Modificação de dois estágios de posições abertas

Genkov | 5 fevereiro, 2016


Introdução

O artigo nomeado T.DeMark's Approach to Technical Analysis" contém os coeficientes recomendados do comprimento de correção, particularmente 0,382 e 0,618. Usando esses coeficientes durante a abertura de posições, você pode evitar situações desnecessárias de fechamento e reabertura de posições em situações próximas à tendência. A função funciona bem, especialmente na situação de ocorrência de divergência.

Essa abordagem, contanto que o valor de lucro seja restabelecido, ajuda a detectar o surgimento de uma tendência "favorável". Por exemplo, como é mostrado na Fig. 1 e comparado à Fig. 2.




Algoritmo da função

A primeira modificação da ordem é realizada pelo valor específico de TrailingStop, as subsequentes configuram a StopLoss menor do que o nível de correção possível em 1 ou 2 pontos (nesse caso, o coeficiente de correção = 0,382 "Coeff_"). Aumente o valor de TakeProfit em cada passo em, por exemplo, metade do valor de TrailingStop (você pode escolher outro valor também). O valor de TakeProfit pode ser modificado também. Para esse fim, o valor zero da extern double March = 0; o operador deve ser configurado no início do programa.

Seria mais inteligente para traders que preferem que o suporte por análise de endereço de ações específicas de programa seja realizado diretamente durante o trading, transferir a variável do MagicNumber (número mágico) para o código do próprio Expert Advisor, onde a posição é aberta. Você pode ler informações mais detalhadas sobre o suporte de endereço específico no livro por S. Kovalyov publicado no website MQL4.com.


Vamos examinar o código sugerido da função em perspectiva no EA e os comentários sobre ele em detalhes:

//+------------------------------------------------------------------+
//|      Two-stage variant of TrailingStop       Modify_2step v5.mq4 |
//|   Orders modification: re-placing StopLoss and TakeProfit        |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, GenKov"
#property link      Genkov@bk.ru
//+------------------------------------------------------------------+

/* Magic=N

Magic=N - esse operador deveria ser inserido durante a abertura de posição logo depois do operador de controle de conformidade de condição no próprio programa (Expert Advisor) e na função! Não consegui criar um modificador universal, talvez em vista da imprevisibilidade do mercado, como parece para mim, então a função de tracking (movimento de S/L e T/P) e as condições de fechamento de posição deveriam ser escritas para cada tipo de condição de abertura de posição (por Magic=N).

extern double    March         =  1;  // step of increasing TakeProfit 
                                      // step 0 doesn't increase T/P.

S/L deve ser menor do que TrailingStop em 1 ponto para trazer a S/L para um nível seguro no primeiro triggering (acionamento). De tal forma, nos resguardamos de possíveis prejuízos (gerenciamento de capital).

extern double    StopLoss      = 15;  
extern double    TrailingStop  = 16;  
extern double    TakeProfit    = 60;  // fitting with the tester
//+------------------------------------------------------------------+
//void TrailingStop()
  int start()                                   
   {
   //----------------------------------------------------------------+
   int point  = MarketInfo(Symbol(),MODE_POINT);      // Point size 
   int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL);  
   double half_Trail = MathRound(TrailingStop/2);//half TrailingStop
   double Step = March*half_Trail;  //value of TakeProfit increase
  if (TrailingStop<0) return;
   { 
   for (int i=0; i<OrdersTotal(); i++)
    {
    if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=Magic) continue;
    if (OrderType()==OP_BUY)
     {

Primeiro estágio de modificação de posição BUY (Comprar)

if(OrderStopLoss()<OrderOpenPrice())//if S/L is less than the order open price
      {   // and if the difference between the current price and the position opening price is greater than T/S
      if(Bid-OrderOpenPrice()>TrailingStop*Point) // && 
       {     // and if OrderStopLoss() is less than the difference between the current price and T/S
       if(OrderStopLoss()<Bid-TrailingStop*Point)
        {    // calculate new T/P value
        double Now_T_P=(OrderTakeProfit()+Step*Point);
       { 
       OrderModify(OrderTicket(),OrderOpenPrice(),
       OrderStopLoss()+TrailingStop*Point,
       OrderTakeProfit()+Step*Point,0,Aqua); // increasing T/P value
      return;
      }
     }
    }
   }

Entretanto, a seguinte situação pode ocorrer: a TakeProfit desviada se torna 2-3 pontos maior do que o nível de lucro planejado anteriormente, para e começa a diminuir vagarosamente.



Para evitar perder lucro, vamos inserir o operador de controle de situação que irá fechar a ordem no nível de lucro planejado. Se o preço continuar a crescer, então o desvio da StopLoss e TakeProfit vai continuar.

if(Bid-OrderOpenPrice()>=TakeProfit*Point && (Pr_Op_1-Pr_Op_0)>2*Point) 
   {
    // Print(" Bid= ",Bid," >= ",OrderTakeProfit()," Magic= ",Magic);
    OrderClose(OrderTicket(),Lots,Bid,2,Red);
    }
// Second stage of BUY position modification
 if(OrderStopLoss()>=OrderOpenPrice()) // StopLoss is on a lossless level
   {    // calculate correction coefficient
    double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits);
    // and if the differnece between the current and the open price of the position is greater than corr. coefficient 
    if(Bid-OrderOpenPrice()>Coeff_up) 
     {    // calculate the value of new StopLoss with the margin of 2 points
      double New_S_Loss = Bid-Coeff_up-2*Point;
      // and if the value of new StopLoss is higer than the current one
      if(New_S_Loss-OrderStopLoss()>3*Point)
       {     // move S/L and T/P
        OrderModify(OrderTicket(),OrderOpenPrice(),
        New_S_Loss,OrderTakeProfit()+Step*Point,0,Yellow);
        }
//        Print(" Bid-OrderOpenPrice()= ",Bid-OrderOpenPrice());
//        Print("  2   Coeff_up= ",Coeff_up," Order_S_Los= ",New_S_Loss," Bid= ",Bid);
       return;
       }
      }
     }

A abordagem à posição curta é a mesma da descrita acima, então há menos comentários.

// ---------------------------- 1 stage of modification -----SELL-------------&
   else  if(OrderType()==OP_SELL) 
    {
   if(OrderStopLoss()>OrderOpenPrice())//if S/L is greater than order open price
     {
     if(OrderOpenPrice()-Ask>TrailingStop*Point && 
        OrderStopLoss()>Ask+TrailingStop*Point)
     { 
      OrderModify(OrderTicket(),OrderOpenPrice(),
      Ask+TrailingStop*Point,OrderTakeProfit()-Step*Point,0,SkyBlue);
      return;
      }
     }
if(OrderOpenPrice()-Ask>=TakeProfit*Point && (Pr_Op_0-Pr_Op_1)>2*Point) 
   {
    OrderClose(OrderTicket(),Lots,Bid,2,Red);
    }     
// ---------------------------- 2 stage of modification -----SELL-------------&
   if(OrderStopLoss()<=OrderOpenPrice()) // StopLoss is on a lossless level
    { // calculate correction coefficient
     double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits);
     // and if the difference between the price of position opening and the current price is greater than corr. coefficient 
    if(OrderOpenPrice()-Ask>Coeff_down) 
     {    // calculate the value of new StopLoss with the margin of 2 points
      New_S_Loss = Ask+Coeff_down+2*Point; 
      // and if the value of new StopLoss is less than the current value
      if(New_S_Loss-OrderStopLoss()>3*Point)
       {     // move S/L and T/P   
       OrderModify(OrderTicket(),OrderOpenPrice(),
       New_S_Loss,OrderTakeProfit()-Step*Point,0,Khaki);
      return;
      }
     }
    }
   }
  } 
 //  -----------------------------------------------------------------------------------

Para transformar esse EA em uma função, é necessário comentar a função de início de int especial localizada no início do programa e substituir pela descrição descomentada da função de TrailingStop() localizada no início do programa. Descomentar a solicitação de função:

//TrailingStop();

no final do programa.

Se adicionarmos o bloco representado abaixo, então podemos verificar a função de forma eficiente usando-a como um EA no testador.

// --------------------------------------------------------------------------------
  
   double Macd_m15_0= iMACD(NULL,PERIOD_M15,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
   double Macd_m15_1= iMACD(NULL,PERIOD_M15,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
   
   if(OrdersTotal()<2)
    {
    if(Macd_m15_0<Macd_m15_1)
     {
     OrderSend(Symbol(),OP_SELL,0.1,Bid,3,Ask+StopLoss*Point,Bid-TakeProfit*Point,"",Magic,0,Red);
     }
    if(Macd_m15_0>Macd_m15_1)
     {
     OrderSend(Symbol(),OP_BUY,0.1,Ask,3,Bid-StopLoss*Point,Ask+TakeProfit*Point,"",Magic,0,Blue);
     }
    return(0);
   }
// --------------------------------------------------------------------------------
//  TrailingStop();
  }
   return(0);
  }
// --- end --- &

Agora remova os comentários detalhados do texto código mencionado acima e o formule como uma função de execução: iremos obter o arquivo executável que é recomendado para ser armazenado no diretório terminal_folder\experts\include com a extensão .mqh ou no diretório terminal_folder\libraries com a extensão mq4.

//+------------------------------------------------------------------+
//|                                             Modify_2_Step v5.mq4 |
//|                                         Copyright © 2008, GenKov |
//|                                                     Genkov@bk.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, GenKov"
#property link      "Genkov@bk.ru"
extern double    March         =  1;  // the step of TakeProfit increase
                                      // "0" step doesn't increase T/P.
// S/L must be less than TrailingStop by 1 point to bring the S/L  
// on a safe level in the time of the very first triggering
extern double    StopLoss      = 15;  
extern double    TrailingStop  = 16;
extern double Lots             = 0.1;  
extern double    TakeProfit    = 60;  // fitting with the tester
void TrailingStop()
  {
   int Magic=3090;  //  number of condition that opens position
   int point  = MarketInfo(Symbol(),MODE_POINT);      // Point size 
   int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL);  
   double half_Trail = MathRound(TrailingStop/2);//half TrailingStop
   double Step = March*half_Trail;  //TakeProfit-а increase size
  if (TrailingStop<0) return;
   { 
   for (int i=0; i<OrdersTotal(); i++)
    {//1 +cycle by orders search
    if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=Magic) continue;
    if (OrderType()==OP_BUY)
     {
// --------------------------- 1 stage of modification -----BUY-------------&     
    if(OrderStopLoss()<OrderOpenPrice())//if the S/L is less than the order open price
      {   // and if the difference between the current and the open price is greater than T/S
      if(Bid-OrderOpenPrice()>TrailingStop*Point) // && 
       {     // and if OrderStopLoss() is less than the difference between current price andT/S
       if(OrderStopLoss()<Bid-TrailingStop*Point)
        {    // calculate new T/P value
        double Now_T_P=(OrderTakeProfit()+Step*Point);
       { 
       OrderModify(OrderTicket(),OrderOpenPrice(),
       OrderStopLoss()+TrailingStop*Point,
       OrderTakeProfit()+Step*Point,0,Aqua); // increase T/P value
      return;
      }
     }
    }
   }
  if(Bid-OrderOpenPrice()>=TakeProfit*Point) 
   {
    OrderClose(OrderTicket(),Lots,Bid,2,Red);
    }
//------------------------- 2 stage of modification -----BUY---------------&
  if(OrderStopLoss()>=OrderOpenPrice()) // StopLoss is on the lossless level
   {    // calculate correction coefficient
    double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits);
    // and if the difference between the current and the position price is greater than correction coefficient
    if(Bid-OrderOpenPrice()>Coeff_up) 
     {    // clculate new StopLoss value with the margin of 6 points
      double New_S_Loss = Bid-Coeff_up-6*Point-StopLev*Point;
      // if the value of new StopLoss is greater than the current value
      if((New_S_Loss-OrderStopLoss())<2*Point)
       {     // move S/L and T/P
        OrderModify(OrderTicket(),OrderOpenPrice(),
        OrderStopLoss(),OrderTakeProfit()+Step*Point/2,0,Yellow);
        }
        else
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),
        New_S_Loss+1*Point,OrderTakeProfit()+Step*Point,0,Yellow);
        }
       return;
       }
      }
     }
// ---------------------------- 1 stage of modification -----SELL-------------&
  else if(OrderType()==OP_SELL)
    {
   if(OrderStopLoss()>OrderOpenPrice())//if S/L is greater than the order open price
     {
     if(OrderOpenPrice()-Ask>TrailingStop*Point && 
        OrderStopLoss()>Ask+TrailingStop*Point)
     { 
      OrderModify(OrderTicket(),OrderOpenPrice(),
      Ask+TrailingStop*Point,OrderTakeProfit()-Step*Point,0,SkyBlue);
      return;
      }
     }
if(OrderOpenPrice()-Ask>=TakeProfit*Point) 
   {
    OrderClose(OrderTicket(),Lots,Bid,2,Red);
    }     
// ---------------------------- 2 stage of modification -----SELL-------------&
   if(OrderStopLoss()<=OrderOpenPrice()) // StopLoss is on the lossless level
    if(OrderOpenPrice()-Ask>=OrderTakeProfit()) OrderClose(OrderTicket(),Lots,Ask,2,Red);   
    { // calculate correction coefficient
     double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits);
     // and if the difference between the position open price and the current price is greater than corr. coefficient
    if(OrderOpenPrice()-Ask>Coeff_down) 
     {   // calculate the value of new StopLoss with the margin of 6 points
      New_S_Loss = Ask+Coeff_down+6*Point; 
      // and if the value of new StopLoss is less than the current value
      if((OrderStopLoss()-New_S_Loss-StopLev*Point)>=10*Point)
       {    // move S/L and T/P
       OrderModify(OrderTicket(),OrderOpenPrice(),
       New_S_Loss-5*Point,OrderTakeProfit()-Step*Point,0,Khaki);
      return;
      }
     }
    }
   }
  } 
return(0);
}
}
// ---end----- void TrailingStop()--------------------------------&
  // this block is only for error controlling in the function code
  //  int start()  
  //   {
  //    if(25>26) TrailingStop();
  //    }
  // --------------------------------

Conclusão

Deveria ser dito que, se comparado com a "trailing stop exemplar" descrita no artigo "Trailing Stop padrão e saída de mercado" de Sergey Kravchuk, a versão sugerida é mais fácil de se entender e tem funcionado no meu EA (para dizer a verdade, em uma conta demo) e, como eu penso, se encaixa bem no trailing agressivo e moderado.

As versões em anexo:

v4 - com fechamento por S/L; v5 - com fechamento previsto por T/P; v6 - com um reflexo da previsão e do suporte de endereço pelo número mágico.