English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
거래 로봇 이야기: 더 적은 것이 더 많은 것인가요?

거래 로봇 이야기: 더 적은 것이 더 많은 것인가요?

MetaTrader 5트레이딩 | 12 10월 2021, 13:58
107 0
Roman Zamozhnyy
Roman Zamozhnyy

문제를 풀려면 먼저 제 자신에게 말해야 해요. 내가 해결책을 찾았다고 생각할 때, 내가 옳다는 것을 증명해야 합니다.

저는 이것을 증명할 수 있는 유일한 방법을 알고 있습니다. 그것은 제 돈으로 하는 것입니다.

Jesse Livermore


프롤로그

'마지막 십자군'에서 우리는 꽤 흥미롭지만 현재 널리 사용되지 않는 시장 정보 표시 방법인 포인트 및 피겨 차트를 검토했습니다. 제공된 스크립트는 차트를 표시할 수 있습니다. 하지만 거래 자동화를 제안하지는 않았습니다. 이제 포인트 및 그림 차트를 사용하여 거래 프로세스를 자동화하고 거래 방향과 규모에 대한 결정을 내릴 수 있습니다.

여기에 기본적인 그리기 원리를 쓰지는 않겠습니다. 일반적인 차트를 보십시오:

Copyright (c) 2012-2014 Roman Rich
Euro vs US Dollar, Box-20, Reverse-3


    1.4588 | \.....\.................................................................... | 1.4588
    1.4521 | X\....X\................................................................... | 1.4521
    1.4454 | XO\.\.XO\.................................................................. | 1.4454
    1.4388 | XOX\X\XO.\................................................................. | 1.4388
    1.4322 | XOXOXOXO..\................................................................ | 1.4322
    1.4256 | XOXOXOXO...\....\.......................................................... | 1.4256
    1.4191 | XOXO/OXO....\...X\......................................................... | 1.4191
    1.4125 | XOX/.O/O.....\..XO\........................................................ | 1.4125
    1.4060 | XO/../.O......\.XO.\....................................................... | 1.4060
    1.3996 | ./.....O.......\XO..\...................................................... | 1.3996
    1.3932 | .......OX.......XO...\....................................................X | 1.3932
    1.3868 | .......OXO..X.X.XOX...\.................................................X.X | 1.3868
    1.3804 | .......OXO..XOXOXOXOX..\..............................................X.XOX | 1.3804
    1.3740 | .......OXO..XOXOXOXOXO..\.................................\...........XOXOX | 1.3740
    1.3677 | .......OXOX.XO.O.OXOXO...\................................X\..........XOXOX | 1.3677
    1.3614 | .......OXOXOX....O.OXO....\...............................XO\.........XOXOX | 1.3614
    1.3552 | .......O.OXOX...../OXO.....\..............................XO.\........XOXOX | 1.3552
    1.3490 | .........OXOX..../.O.OX.....\.............................XO..\.......XOXO. | 1.3490
    1.3428 | .........OXOX.../....OXO.....\X.\.........................XO...\\...X.XOX.. | 1.3428
    1.3366 | .........O.OX../.....OXO......XOX\........................XO....X\..XOXOX.. | 1.3366
    1.3305 | ...........OX./......OXO....X.XOXO\.....................X.XO....XO\.XOXO... | 1.3305
    1.3243 | ...........OX/.......O.O....XOXOXOX\....................XOXO....XO.\XOX.../ | 1.3243
    1.3183 | ...........O/..........OX...XOXOXOXO\...................XOXOX.X.XOX.XOX../. | 1.3183
    1.3122 | .........../...........OXO..XOXOXOXO.\..........X...X.X.XOXOXOXOXOXOXO../.. | 1.3122
    1.3062 | .......................OXOX.XOXO.OXO..\.........XOX.XOXOXOXOXOXOXOXOX../... | 1.3062
    1.3002 | .......................O.OXOXO...O/O...\........XOXOXOXOXO.OXO.OXOXO../.... | 1.3002
    1.2942 | .........................OXOX..../.O....\.......XOXOXOXOX..OX..OXOX../..... | 1.2942
    1.2882 | .........................O.OX.../..O.....\......XOXO.OXO...OX..OXOX./...... | 1.2882
    1.2823 | ...........................OX../...OX.....\.....XO...OX.../OX..O/OX/....... | 1.2823
    1.2764 | ...........................OX./....OXO.....\....X....OX../.O.../.O/........ | 1.2764
    1.2706 | ...........................OX/.....OXO..X...\...X....O../......../......... | 1.2706
    1.2647 | ...........................O/......O.OX.XOX..\..X....../................... | 1.2647
    1.2589 | .........................../.........OXOXOXO..\.X...../.................... | 1.2589
    1.2531 | .....................................OXOXOXO...\X..../..................... | 1.2531
    1.2474 | .....................................OXO.OXO....X.../...................... | 1.2474
    1.2417 | .....................................OX..O.O..X.X../....................... | 1.2417
    1.2359 | .....................................OX....OX.XOX./........................ | 1.2359
    1.2303 | .....................................O.....OXOXOX/......................... | 1.2303
    1.2246 | ...........................................OXOXO/.......................... | 1.2246
    1.2190 | ...........................................OXO./........................... | 1.2190
    1.2134 | ...........................................OX.............................. | 1.2134
    1.2078 | ...........................................O............................... | 1.2078
    1.2023 | ........................................................................... | 1.2023

             222222222222222222222222222222222222222222222222222222222222222222222222222
             000000000000000000000000000000000000000000000000000000000000000000000000000
             111111111111111111111111111111111111111111111111111111111111111111111111111
             111111111111111111111111112222222222222222222222222222222333333333333333344
             ...........................................................................
             000000000001111111111111110000000000000000000000011111111000000000000011100
             788888899990000001111112221122233445566666677888900001222123444567778901213
             ...........................................................................
             200011211220111220011231220101212121201112222001100010001002123110112020231
             658801925683489071404504193396436668111288937260415979579417630739120547713
                                                                                        
             000100001012111111110111111100112010210001111101101101011111111101011101110
             910501876933613095500253237788652909250001557626626824655375907538165785367
             :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
             550433251023230204310404232105354323532031240033315125241340044324523153453
             000000000000000000000000000000000000000000000000000000000000000000000000000
-->

저는 이 차트에서 거래 기회가 명확하게 보인다고 주장하지는 않겠습니다. 저는 단지 두 가지 거래 가설을 확인하는 것을 제안할 뿐입니다:

주요 추세와의 거래 — 강세장에서 사고 약세장에서 팔립니다.

손실 중지 사용, 시장에 진입하기 전에 정의된 손실을 중지합니다.

  • 이전 X열의 고점보다 위의 중지-주문을 사용하여, 지지 레벨 위에서 구매하며, 이전 O열 의 저점 보다 아래의 중지 주문을 사용하여 저항선 아래에서 판매합니다; 피벗(pivot) 레벨에서 후행 중지(trailing stop)를 사용합니다.

수익이 증가하도록 놔두세요.

손실을 만드는 거래를 닫습니다(우량 거래는 대개 즉시 이익을 나타냅니다).

  • 저항선을 돌파할 때 구입하고, 지지선을 돌파할 때 판매하며, 피벗 레벨에서 손실 중지를 설정하고, 추세선에서 후행 중지를 설정합니다.


볼륨을 선택하는 방법

위의 주식 투자 마스터에 대한 인용에 주목하십시오: 중지 주문을 사용하십시오. 저는 손실 중지 주문이 촉발될 때 잔액 손실은 제가 받아들일 수 있는 잔액의 퍼센트를 넘지 않도록 특정 볼륨으로 시장에 진입하는 것을 선호합니다(랠프 빈스가 그의 "돈 관리의 수학"에서 최적 F라고 부르는 것). 거래당 손실 위험은 최적화 가능한 변수입니다(아래 코드의 opt_f).

따라서 거래당 허용 가능한 위험에 따라 달라지는 대량 계산 메커니즘으로 매수/매도 주문을 하는 기능이 있습니다.

//+------------------------------------------------------------------+
//| The function places an order with a precalculated volume         |
//+------------------------------------------------------------------+
void PlaceOrder()
  {
//--- Variables for calculating the lot
   uint digits_2_lot=(uint)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
   double trade_risk=AccountInfoDouble(ACCOUNT_EQUITY)*opt_f;
   double one_tick_loss_min_lot=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS)*SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
//--- Fill out the main fields of the request
   trade_request.magic=magic;
   trade_request.symbol=symbol;
   trade_request.action=TRADE_ACTION_PENDING;
   trade_request.tp=NULL;
   trade_request.comment=NULL;
   trade_request.type_filling=NULL;
   trade_request.stoplimit=NULL;
   trade_request.type_time=NULL;
   trade_request.expiration=NULL;
   if(is_const_lot==true)
     {
      order_vol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
     }
   else
     {
      order_vol=trade_risk/(MathAbs(trade_request.price-trade_request.sl)*MathPow(10,digits_2_lot)*one_tick_loss_min_lot)*SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
      order_vol=MathMax(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN));
      if(SymbolInfoDouble(symbol,SYMBOL_VOLUME_LIMIT)!=0) order_vol=MathMin(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_LIMIT));
      order_vol=NormalizeDouble(order_vol,(int)MathAbs(MathLog10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP))));
     }
//--- Place an order
   while(order_vol>0)
     {
      trade_request.volume=MathMin(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX));
      if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
      order_vol=order_vol-SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
     };
   ticket=trade_result.order;
  };
-->


사용할 최적화 기준은 무엇입니까?

실제로 최적화 기준은 두 가지입니다. 즉, 주어진 수익 수준에서 최소화 또는 드로우다운하거나, 주어진 드로우다운 수준에서 균형을 최대화하는 것입니다. 저는 두 번째 기준으로 최적화하는 것을 선호합니다:

//+------------------------------------------------------------------+
//| Result of strategy run in the testing mode                       |
//+------------------------------------------------------------------+
double OnTester()
  {
   if(TesterStatistics(STAT_EQUITY_DDREL_PERCENT)>(risk*100))
      return(0);
   else
      return(NormalizeDouble(TesterStatistics(STAT_PROFIT),(uint)SymbolInfoInteger(symbol,SYMBOL_DIGITS)));
  };
-->

여기서 위험은 전략을 받아들일 수 없는 수준 이상의 하강 단계입니다. 이 변수도 최적화해야 할 변수 중 하나입니다.


언제 다시 최적화해야 합니까?

누군가는 시간 간격(예: 일주일에 한 번, 한 달에 한 번), 거래 간격(50건, 100건의 거래 이후)에 따라 전략을 다시 최적화하고, 누군가는 시장이 바뀔 때 새로운 최적화를 시작합니다. 사실, 재최적화의 필요성은 앞 단락에서 선택한 최적화 기준에 의해서만 결정됩니다. 드로다운이 허용된 최대 위험 매개 변수 아래로 떨어지면 전략을 다시 최적화합니다. 모든 것이 정상이면 그대로 작동합니다. 10%를 초과하는 인하는 허용되지 않습니다. 따라서 작업 중에 시스템이 더 큰 그리기 작업을 수행할 경우 시스템을 다시 최적화합니다.


한 번에 모든 것을 최적화할 수 있습니까?

안타깝게도 전략 테스터에서는 "마켓 워치에서 선택한 모든 기호" 모드에 대해 외부 변수를 최적화할 수 없습니다. 따라서 다음과 같이 다른 외부 최적화 가능 변수와 함께 마켓 상품을 선택하겠습니다.

//+------------------------------------------------------------------+
//| Enumeration of symbols                                           |
//+------------------------------------------------------------------+
enum  SYMBOLS
  {
   AA=1,
   AIG,
   AXP,
   BA,
   C,
   CAT,
   DD,
   DIS,
   GE,
   HD,
   HON,
   HPQ,
   IBM,
   IP,
   INTC,
   JNJ,
   JPM,
   KO,
   MCD,
   MMM,
   MO,
   MRK,
   MSFT,
   PFE,
   PG,
   QQQ,
   T,
   SPY,
   UTX,
   VZ,
   WMT,
   XOM
  };
//+------------------------------------------------------------------+
//| Symbol selection function                                        |
//+------------------------------------------------------------------+
void  SelectSymbol()
  {
   switch(selected_symbol)
     {
      case  1: symbol="#AA";   break;
      case  2: symbol="#AIG";  break;
      case  3: symbol="#AXP";  break;
      case  4: symbol="#BA";   break;
      case  5: symbol="#C";    break;
      case  6: symbol="#CAT";  break;
      case  7: symbol="#DD";   break;
      case  8: symbol="#DIS";  break;
      case  9: symbol="#GE";   break;
      case 10: symbol="#HD";   break;
      case 11: symbol="#HON";  break;
      case 12: symbol="#HPQ";  break;
      case 13: symbol="#IBM";  break;
      case 14: symbol="#IP";   break;
      case 15: symbol="#INTC"; break;
      case 16: symbol="#JNJ";  break;
      case 17: symbol="#JPM";  break;
      case 18: symbol="#KO";   break;
      case 19: symbol="#MCD";  break;
      case 20: symbol="#MMM";  break;
      case 21: symbol="#MO";   break;
      case 22: symbol="#MRK";  break;
      case 23: symbol="#MSFT"; break;
      case 24: symbol="#PFE";  break;
      case 25: symbol="#PG";   break;
      case 26: symbol="#QQQ";  break;
      case 27: symbol="#T";    break;
      case 28: symbol="#SPY";  break;
      case 29: symbol="#UTX";  break;
      case 30: symbol="#VZ";   break;
      case 31: symbol="#WMT";  break;
      case 32: symbol="#XOM";  break;
      default: symbol="#SPY";  break;
     };
  };
-->

필요한 경우, 기호 선택 기능 및 열거에 필요한 기기를 추가할 수 있습니다 (OnInit()에서 호출됩니다).


우리가 만든 로봇은 무엇일까요?

틱 핸들러:

//+------------------------------------------------------------------+
//| A typical ticks handler OnTick()                                 |
//|     Draw the chart only based on complete bars but first         |
//|     check if it is a new bar.                                    |
//|     If the bar is new and there is a position, check             |
//|     whether we need to move the stop loss,                       |
//|     if the bar is new and no position, check                     |
//|     if we have conditions for opening a deal.                    |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- If the bar is new
   if(IsNewBar()==true)
     {
      RecalcIndicators();
      //--- Tester/optimizer mode?
      if((MQLInfoInteger(MQL_TESTER)==true) || (MQLInfoInteger(MQL_OPTIMIZATION)==true))
        {
         //--- Is it the testing period?
         if(cur_bar_time_dig[0]>begin_of_test)
           {
            //--- If there is an open position on the symbol
            if(PositionSelect(symbol)==true)
               //--- check if we need to move SL; if need, move it
               TrailCondition();
            //--- If there are no positions
            else
            //--- check if we need to open a position; if we need, open it
               TradeCondition();
           }
        }
      else
        {
         //--- if there is an oprn position on the symbol
         if(PositionSelect(symbol)==true)
            //--- check if we need to move SL; if need, move it
            TrailCondition();
         //--- If there are no positions
         else
         //---  check if we need to open a position; if we need, open it
            TradeCondition();
        }

     };
  };
-->

전략 1의 경우: "이전 X열의 고점보다 위의 중지-주문을 사용하여 지지 레벨 위에서 구매하고, 이전 O열의 저점보다 아래의 판매 중지 주문을 사용하여 저항선 아래에서 판매합니다; 피벗 레벨에서 후행 중지(trailing stop)를 사용합니다.':

//+------------------------------------------------------------------+
//| Function checks trade conditions for opening a deal              |
//+------------------------------------------------------------------+
void TradeCondition()
  {
   if(order_col_number!=column_count)
      //--- Are there any orders on the symbol?
     {
      if(OrdersTotal()>0)
        {
         //--- Delete them!
         for(int loc_count_1=0;loc_count_1<OrdersTotal();loc_count_1++)
           {
            ticket=OrderGetTicket(loc_count_1);
            if(!OrderSelect(ticket)) Print("Failed to select order #",ticket);
            if(OrderGetString(ORDER_SYMBOL)==symbol)
              {
               trade_request.order=ticket;
               trade_request.action=TRADE_ACTION_REMOVE;
               if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
              };
           };
         order_col_number=column_count;
         return;
        }
      else
        {
         order_col_number=column_count;
         return;
        }
     }
   else
      if((MathPow(10,pnf[column_count-1].resist_price)<SymbolInfoDouble(symbol,SYMBOL_ASK)) && 
         (pnf[column_count-1].column_type=='X') && 
         (pnf[column_count-1].max_column_price<=pnf[column_count-3].max_column_price))
        {
         //--- Conditions for BUY met; let's see if there are any pending Buy orders for the symbol with the price we need?
         trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-3].max_column_price+double_box),digit_2_orders);
         trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-3].max_column_price-(reverse-1)*double_box),digit_2_orders);
         trade_request.type=ORDER_TYPE_BUY_STOP;
         if(OrderSelect(ticket)==false)
            //--- No pending orders - place an order
           {
            PlaceOrder();
            order_col_number=column_count;
           }
         else
         //--- If there is a pending order
           {
            //--- what is the type and price of the pending order?
            if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) || 
               ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price)))
              {
               //--- The wrong type or the price differs - close the order
               trade_request.order=ticket;
               trade_request.action=TRADE_ACTION_REMOVE;
               if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
               //--- open with the desired price
               PlaceOrder();
               order_col_number=column_count;
              };
           };
         return;
        }
   else
      if((MathPow(10,pnf[column_count-1].resist_price)>SymbolInfoDouble(symbol,SYMBOL_ASK)) && 
         (pnf[column_count-1].column_type=='O') && 
         (pnf[column_count-1].min_column_price>=pnf[column_count-3].min_column_price))
        {
         //--- Conditions for SELL met; let's see if there are any pending Sell orders for the symbol with the price we need?
         trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-3].min_column_price-double_box),digit_2_orders);
         trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-3].min_column_price+(reverse-1)*double_box),digit_2_orders);
         trade_request.type=ORDER_TYPE_SELL_STOP;
         if(OrderSelect(ticket)==false)
            //--- No pending orders, place an order
           {
            PlaceOrder();
            order_col_number=column_count;
           }
         else
         //--- or there is a pending order
           {
            //--- what is the type and price of the pending order?
            if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) || 
               ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price)))
              {
               //--- The wrong type or the price differs - close the order
               trade_request.order=ticket;
               trade_request.action=TRADE_ACTION_REMOVE;
               if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
               //--- and open with the desired price
               PlaceOrder();
               order_col_number=column_count;
              };
           };
         return;
        }
   else
      return;
  };
//+------------------------------------------------------------------+
//| The function checks conditions for moving Stop Loss              |
//+------------------------------------------------------------------+
void TrailCondition()
  {
   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
      trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].max_column_price-reverse*double_box),digit_2_orders);
   else
      trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].min_column_price+reverse*double_box),digit_2_orders);
   if(PositionGetDouble(POSITION_SL)!=trade_request.sl)
      PlaceTrailOrder();
  };
-->

전략 2의 경우, "저항선을 돌파할 때 구매하고, 지지선을 돌파할 때 판매하며, 피벗 수준에서 손실 중지를 설정하고, 추세선에서 후행 중지를 설정합니다.":

//+------------------------------------------------------------------+
//| The function checks trade conditions for opening a deal          |
//+------------------------------------------------------------------+
void TradeCondition()
  {
   if(order_col_number!=column_count)
      //--- Are there any orders for the symbol?
     {
      if(OrdersTotal()>0)
        {
         //--- Delete them!
         for(int loc_count_1=0;loc_count_1<OrdersTotal();loc_count_1++)
           {
            ticket=OrderGetTicket(loc_count_1);
            if(!OrderSelect(ticket)) Print("Failed to select order #",ticket);
            if(OrderGetString(ORDER_SYMBOL)==symbol)
              {
               trade_request.order=ticket;
               trade_request.action=TRADE_ACTION_REMOVE;
               if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
              };
           };
         order_col_number=column_count;
         return;
        }
      else
        {
         order_col_number=column_count;
         return;
        }
     }
   else
   if(MathPow(10,pnf[column_count-1].resist_price)>SymbolInfoDouble(symbol,SYMBOL_ASK))
     {
      //--- Conditions for BUY met; let's see if there are any pending Buy orders for the symbol with the price we need?
      trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-1].resist_price),digit_2_orders);
      trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].resist_price-(reverse-1)*double_box),digit_2_orders);
      trade_request.type=ORDER_TYPE_BUY_STOP;
      if(OrderSelect(ticket)==false)
         //--- No pending orders - place an order
        {
         PlaceOrder();
         order_col_number=column_count;
        }
      else
      //--- or there is a pending order
        {
         //--- what is the type and price of the pending order?
         if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) || 
            ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price)))
           {
            //--- The wrong type or the price differs - close the order
            trade_request.order=ticket;
            trade_request.action=TRADE_ACTION_REMOVE;
            if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
            //--- open with the desired price
            PlaceOrder();
            order_col_number=column_count;
           };
        };
      return;
     }
   else
   if(MathPow(10,pnf[column_count-1].resist_price)<SymbolInfoDouble(symbol,SYMBOL_ASK))
     {
      //--- Conditions for SELL met; let's see if there are any pending Sell orders for the symbol with the price we need?
      trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-1].supp_price),digit_2_orders);
      trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].supp_price+(reverse-1)*double_box),digit_2_orders);
      trade_request.type=ORDER_TYPE_SELL_STOP;
      if(OrderSelect(ticket)==false)
         //--- No pending orders - place an order
        {
         PlaceOrder();
         order_col_number=column_count;
        }
      else
      //--- If there is a pending order
        {
         //--- what is the type and price of the pending order?
         if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) || 
            ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price)))
           {
            //--- The wrong type or the price differs - close the order
            trade_request.order=ticket;
            trade_request.action=TRADE_ACTION_REMOVE;
            if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order);
            //--- open with the desired price
            PlaceOrder();
            order_col_number=column_count;
           };
        };
      return;
     }
   else
      return;
  };
//+------------------------------------------------------------------+
//| The function checks conditions for moving Stop Loss              |
//+------------------------------------------------------------------+
void TrailCondition()
  {
   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
      trade_request.sl=NormalizeDouble(MathMax(SymbolInfoDouble(symbol,SYMBOL_ASK),MathPow(10,pnf[column_count-1].max_column_price-reverse*double_box)),digit_2_orders);
   else
      trade_request.sl=NormalizeDouble(MathMin(SymbolInfoDouble(symbol,SYMBOL_BID),MathPow(10,pnf[column_count-1].min_column_price+reverse*double_box)),digit_2_orders);
   if(PositionGetDouble(POSITION_SL)!=trade_request.sl)
      PlaceTrailOrder();
  };
-->

독자 여러분, 몇 가지 사항을 메모해 두세요.

  • 시장 상품의 가격은 센트에서 수만 개(예: 일본 증권 거래소의 주식 및 CFD)까지 상당히 광범위한 범위에서 다양합니다. 따라서 상자 크기에 대해 1에서 수만 개의 pip 값을 설정하지 않기 위해 포인트 및 그림 차트의 가격 로그를 사용합니다.
  • 포인트 및 그림 차트의 배열 인덱스는 0에서 시작되므로 마지막 열의 인덱스는 열 수에서 1을 뺀 값과 같습니다.
  • 지지선 값이 사용되는 경우 -10.0보다 크지만 가격의 가격 로그보다 작습니다. 지지선(또는 저항)을 사용하지 않는 경우 차트 배열의 값은 -10.0입니다. 따라서, 지지/저항 라인을 통과하는 조건은 위의 전략 2의 코드와 동일한 형태로 작성됩니다.

아래 첨부파일의 보조기능 코드를 참조하십시오. 차트의 코드가 너무 커서 기사에 작성하지 않습니다. 아래 첨부파일의 코멘트를 참조하십시오.


EA 트레이딩 결과

최적화를 위해 symbol_list_1.mhq 및 symbol_list_2.mhq 파일에 시장 기호 두 세트를 준비했습니다. 여기에는 다우지수의 통화 쌍과 주식 CFD가 포함됩니다.

설정 창:

테스트 옵션

첫 번째 경우 전략 테스터의 설정 창은 다음과 같습니다:

최적화 매개 변수

Testing Start(테스트 시작) 줄을 참고합니다. 로봇에는 분석 및 의사 결정을 위해 최소 몇 개의 차트 열이 필요합니다. 상자 크기를 50pips 이상으로 설정하면 한 개의 열에도 1년 이력이 충분하지 않은 경우가 많습니다. 따라서 상자 크기가 50pips 이상인 차트의 경우 로봇 작동 시작 후 약 3년 이상의 간격을 사용하여 설정 창의 테스트 시작 매개 변수에 로봇 작동 시작을 설정합니다. 이 예에서는 01.01.2012 이후 100pips의 상자 크기로 테스트하기 위해 설정 탭에서 01.01.2009 이후 간격을 지정하고 매개 변수 탭에서 01.01.2012 이후 간격을 설정합니다.

매개 변수 "거래 최소 로트?"의 잘못된 값은 로트 크기가 잔액과 "거래당 리스크, %" 변수에 따라 달라진다는 것을 나타냅니다(이 경우 거래당 1%이지만 최적화할 수도 있습니다). "최대 하강률, %"는 OnTester() 함수의 최적화 기준입니다. 이 문서에서는 최적화에 두 개의 변수만 사용합니다; 기호 및 상자 크기(pips).

최적화 기간: 2012-2013. EA는 EURUSD 차트에서 가장 잘 실행됩니다. 그 기호는 최고의 틱 커버리지를 제공하기 때문입니다. 아래 표에는 첫 번째 전략에 따라 상자 크기가 10인 다양한 통화 쌍을 테스트하기 위한 전체 보고서가 나와 있습니다.

패스 결과 이익 예상되는 지급 이익 요인 복구 요인 샤프 지수 사용자 정의 지분 DD % 거래들 selected_symbol 상자
0,00 0,00 -1 002,12 -18,91 0,54 -0,79 -0,24 0,00 12,67 53,00 AUDCAD 10,00
1,00 886,56 886,56 14,53 1,40 1,52 0,13 886,56 5,76 61,00 AUDCHF 10,00
2,00 0,00 -1 451,63 -10,60 0,77 -0,70 -0,09 0,00 19,92 137,00 AUDJPY 10,00
3,00 -647,66 -647,66 -17,50 0,57 -0,68 -0,24 -647,66 9,46 37,00 AUDNZD 10,00
4,00 -269,22 -269,22 -3,17 0,92 -0,26 -0,03 -269,22 9,78 85,00 AUDUSD 10,00
5,00 0,00 -811,44 -13,52 0,72 -0,64 -0,14 0,00 12,20 60,00 CADCHF 10,00
6,00 0,00 1 686,34 16,53 1,36 1,17 0,12 0,00 11,78 102,00 CHFJPY 10,00
7,00 356,68 356,68 5,66 1,13 0,40 0,06 356,68 8,04 63,00 EURAUD 10,00
8,00 0,00 -1 437,91 -25,68 0,53 -0,92 -0,25 0,00 15,47 56,00 EURCAD 10,00
9,00 0,00 -886,66 -46,67 0,34 -0,74 -0,46 0,00 11,56 19,00 EURCHF 10,00
10,00 0,00 -789,59 -21,93 0,54 -0,75 -0,26 0,00 10,34 36,00 EURGBP 10,00
11,00 0,00 3 074,86 28,47 1,62 1,72 0,20 0,00 12,67 108,00 EURJPY 10,00
12,00 0,00 -1 621,85 -19,78 0,55 -0,97 -0,25 0,00 16,75 82,00 EURNZD 10,00
13,00 152,73 152,73 2,88 1,07 0,21 0,03 152,73 6,90 53,00 EURUSD 10,00
14,00 0,00 -1 058,85 -14,50 0,65 -0,66 -0,16 0,00 15,87 73,00 GBPAUD 10,00
15,00 0,00 -1 343,47 -25,35 0,43 -0,64 -0,34 0,00 20,90 53,00 GBPCAD 10,00
16,00 0,00 -2 607,22 -44,19 0,27 -0,95 -0,59 0,00 27,15 59,00 GBPCHF 10,00
17,00 0,00 1 160,54 11,72 1,27 0,81 0,10 0,00 12,30 99,00 GBPJPY 10,00
18,00 0,00 -1 249,91 -14,70 0,69 -0,85 -0,15 0,00 14,41 85,00 GBPNZD 10,00
19,00 208,94 208,94 5,36 1,12 0,25 0,05 208,94 7,81 39,00 GBPUSD 10,00
20,00 0,00 -2 137,68 -21,17 0,53 -0,79 -0,24 0,00 25,62 101,00 NZDUSD 10,00
21,00 0,00 -1 766,80 -38,41 0,30 -0,97 -0,53 0,00 18,10 46,00 USDCAD 10,00
22,00 -824,69 -824,69 -11,95 0,73 -0,90 -0,13 -824,69 9,11 69,00 USDCHF 10,00
23,00 2 166,53 2 166,53 26,10 1,58 2,40 0,18 2 166,53 7,13 83,00 USDJPY 10,00

2 029,87 -10 213,52




13,40 1 659,00

다음은 다양한 기호 및 상자 크기 값에 대한 요약 표입니다:

전략 기호 상자 크기 거래들 지분 DD % 이익 결과 기대 잔액
1 통화 10 1 659 9월 -10 214 2 030 2 030
1 통화 20 400 5 1 638 2 484 2 484
1 주식 50 350 60 7 599 7 599 15 199
1 주식 100 81 2 4 415 4 415 17 659
2 통화 10 338 20 -4 055 138 138
2 통화 20 116 8 4 687 3 986 3 986
2 주식 50 65 6 6 770 9 244 9 244
2 주식 100 12 1 -332 -332 -5 315

뭐가 보이죠?

항상 나쁜 짓을 하는 바보들이 있어요.

그리고 당신이 항상 거래해야 한다고 믿는 월스트리트의 바보들이 있습니다.

주식을 사고파는 데 필요한 모든 정보를 가지고 있고 그것을 상당히 합리적으로 하는 사람은 세상에 없습니다.

결론은 이상하게 보일 수 있습니다: 당신의 예치금은 거래가 적을수록 더 높을 가능성이 높습니다. 만약 2년 전에 우리가 박스 크기 100과 거래당 위험을 1%로 하는 EA 거래 주식을 허용했다면, EA는 그 이후 (기호당 연간 평균 1.25건의 거래) 우리의 예치금은 44% 증가했을 것이고 평균 주식 인출은 2%를 약간 상회했을 것입니다. 10%의 가능한 하강률을 받아들이면 거래당 4%의 위험을 감수할 수 있으며, 예치금은 2년 동안 177% 증가했을 것입니다. 즉, 미국에서 연간 90% 증가했을 것입니다. 달러!


에필로그

구입을 시작하기에는 가격이 결코 너무 높지 않으며 판매를 시작하기에는 결코 너무 낮지 않습니다.

큰 돈을 버는 것은 생각하지 않습니다. 앉아 있는거죠.

위에서 설명한 전략을 수정할 수 있으며 10% 이하의 드로다운으로 훨씬 더 큰 수익률을 보일 수 있습니다. 너무 자주 거래하려고 하지 말고, 24개의 통화 쌍과 34개의 주식으로 구성된 "표준 세트"의 기호뿐만 아니라 최소한 3, 400개의 상징(주식, 선물)을 제공하는 중개인을 찾는 것이 좋습니다. 기호가 서로 연관되지 않고 예치금이 더 안전할 가능성이 높습니다. 한 마디 더 하자면, 주식은 통화 쌍보다 더 나은 결과를 보여줍니다.


추신 (광고 멘트)

저의 PnF Chartist 스크립트를 시중에서 구입할 수 있습니다. MT4, MT5 또는 Yahoo 금융에서 제공하는 견적을 사용하여 텍스트 파일에 포인트 및 그림 차트를 그립니다. 여러분의 두뇌보다 더 좋은 테스터/최적화 기기는 없기 때문에 가격 패턴을 시각적으로 검색하는 데 사용합니다. 패턴을 찾는 즉시 이 기사의 EA 템플릿을 사용하여 아이디어의 증거를 찾으십시오.

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/910

파일 첨부됨 |
licence.txt (1.05 KB)
strategy_one.mq5 (37.87 KB)
strategy_two.mq5 (37.39 KB)
symbol_list_1.mqh (2.43 KB)
symbol_list_2.mqh (2.17 KB)
소셜 테크놀로지 스타트업을 구축하기, 1부: MetaTrader 5 신호를 트윗하세요 소셜 테크놀로지 스타트업을 구축하기, 1부: MetaTrader 5 신호를 트윗하세요
오늘은 EA의 거래 신호를 트윗할 수 있도록 MetaTrader 5 단말기를 트위터와 연결하는 방법에 대해 알아보겠습니다. 우리는 RESTful 웹 서비스를 기반으로 PHP의 사회적 의사결정 지원 시스템을 개발하고 있습니다. 이 아이디어는 컴퓨터 지원 거래라고 불리는 자동 거래의 특별한 개념에서 나온 것입니다. 우리는 휴먼 거래자들의 인지 능력이 Expert Advisor가 자동으로 시장에 내놓는 거래 신호를 걸러내기를 원합니다.
세줄 브레이크 차트(Three Line Break Chart)를 구성하기 위한 지시자 세줄 브레이크 차트(Three Line Break Chart)를 구성하기 위한 지시자
이 기사는 스티브 니슨이 그의 책 "캔들스틱 그 너머"에서 제안한 3행 브레이크 차트(Three Line Break Chart)에 관한 것입니다. 이 차트의 가장 큰 장점은 이전 이동과 관련하여 가격의 사소한 변동을 필터링할 수 있다는 것입니다. 우리는 차트 구성의 원칙, 지표의 코드, 그리고 그것을 기반으로 한 거래 전략의 몇 가지 예를 논의할 것입니다.
MQL5(MQL4)에서 MySQL 데이터베이스에 액세스하는 방법 MQL5(MQL4)에서 MySQL 데이터베이스에 액세스하는 방법
이 문서에서는 MQL과 MySQL 데이터베이스 간의 인터페이스 개발에 대해 설명합니다. 기존의 실용적인 솔루션에 대해 설명하고 데이터베이스 작업을 위한 라이브러리를 보다 편리하게 구현할 수 있는 방법을 제공합니다. 이 문서에는 기능, 인터페이스 구조, 예제 및 MySQL 사용 시 특정 기능에 대한 자세한 설명이 포함되어 있습니다. 소프트웨어 솔루션의 경우 문서 첨부 파일에는 동적 라이브러리 파일, MQL4 및 MQL5 언어의 설명서 및 스크립트 예가 포함됩니다.
SQL 및 MQL5: SQLite 데이터베이스로 작업하기 SQL 및 MQL5: SQLite 데이터베이스로 작업하기
이 문서는 프로젝트에서 SQL을 사용하는 데 관심이 있는 개발자를 대상으로 합니다. SQLite의 기능과 장점을 설명합니다. 이 문서에서는 SQLite 기능에 대한 특별한 지식이 필요하지 않지만 SQL에 대한 최소한의 이해만으로도 유용합니다.