Охота за трендами

Eryomin Sergey | 10 марта, 2008

Предупреждение

Информация, предоставленная в статье, является исключительно моей точкой зрения. Я, как автор, ни в коем случае никого не призываю действовать согласно данным материалам. Помимо этого, я предупреждаю о возможных убытках, которые могут появиться от использования этой информации.


Введение

В данной статье приведено описание такого приёма в торговле, как наращивание объёма прибыльных сделок. Я считаю, что добавляться можно лишь к прибыльным сделкам. В статье будет рассказано, как это делать оптимальным образом, а также будет приведён код советника, помогающего проводить подобные операции наиболее грамотно.


Концепция алгоритма

Наращивая объём прибыльной сделки, можно получить наибольшую прибыль от движения на рынке, с которым мы столкнулись. Но важно наращивать объём таким образом, чтобы он не мог обернуться увеличением риска. Один из алгоритмов подобного наращивания суммарного объёма сделки приведён в этой статье.

Для начала нужно иметь точку отсчёта, первую, основную сделку. Остальные сделки будут вспомогательные. Основная сделка должна иметь объём, превышающий объём каждой вспомогательной сделки. Допустим, основная сделка будет иметь объём 0.2 лота, а вспомогательные сделки будут иметь объём 0.1 лота. На всех сделках применяется Trailing Stop Loss, например в 50 пунктов. При достижении прибыли на основной сделке в +100 пунктов. Stop Loss, соответственно, будет на +50. В этот момент открывается сделка объёмом 0.1, в том же направлении, с Stop Loss в -50 пунктов. Если цена пойдёт обратно, то обе сделки будут закрыты по приказу Stop Loss. Будет получена прибыль в 50 пунктов лотом 0.2 и убыток в 50 пунктов лотом 0.1. В сумме прибыль будет равной 50 пунктам, лотом 0.1. Таким образом, получена защита от убытков, при увеличении объёма сделки.

В случае если пара продолжит движение в нужном направлении, при достижении прибыли в +50 пунктов на вспомогательной сделке начнёт работать Trailing Stop Loss. При достижении прибыли в 200 пунктов на основной и 100 пунктов на вспомогательной сделке, будет открыта ещё одна вспомогательная сделка. Опять с SL в -50. И так далее.

Таким не хитрым приёмом можно достичь очень не плохих прибылей от наращивания лота. В то же время, риск сводится к минимуму. Фактически, весь риск заключается в том, что будет потеряна часть прибыли основной сделки. Риск от того, что первая вспомогательная сделка понесёт убыток, в случае отката. Но это не риск убытка, а риск недополучения прибыли.

Стандартный Trailing Stop Loss позволяет "тралить" сделки только при наличии прибыли по сделке. Но если это делать на вспомогательных сделках и до достижения необходимой прибыли, то можно увеличить прибыльность подобного подхода к наращиванию лота. Сделать это, а также систематизировать открытие вспомогательных ордеров можно посредством MQL.


Реализация

При разработке робота было решено опираться на советника, представленного в статье "Комфортная пипсовка". В той статье, у советника совмещённые функции: он играет роль тренажёра-игры и роль инструмента для открытия сделок. В советнике для этой статьи была убрана функция игры-тренажёра. Таким образом, этот советник наносит две стрелочки на график – вверх и вниз. Удаление одной из них является сигналом для робота к открытию сделок в нужном направлении. Например, удаляя стрелку вниз, мы оставляем на графике стрелку вверх. Для советника это сигнал к открытию покупки и ряда отложенных Buy Stop ордеров.

Рыночный ордер играет роль основного ордера. Отложенные ордера играют роль вспомогательных сделок, которые по моему замыслу имеют меньший лот, нежели основная. Для расчёта "частоты" открытия вспомогательных сделок и их количества использовано два понятия. Первое – конечная цель, TP. Он устанавливается одинаковым для всех ордеров (и основного и дополнительных). Второе – шаг открытия отложенных ордеров. Исходя из того, какая конечная цель, робот рассчитывает, сколько отложенных ордеров он сможет поставить на интервале от текущей цены до уровня Take Profit.

Например, если использовать TP 400 пунктов, а шаг открытия ордеров 100 пунктов (так по умолчанию), то при покупке будет открыто 4 ордера. Первый – Buy по цене Ask, основной. Второй – Buy Stop вспомогательный, по цене Ask+100 пунктов. Третий – Buy Stop вспомогательный, по цене Ask+200 пунктов. И четвертый – Buy Stop вспомогательный, по цене Ask+300 пунктов. Для всех ордеров будет поставлен Take Profit по цене Ask+400 пунктов, т.е. для первого ордера он будет 400 пунктов, для второго 300, для третьего 200 и для четвёртого 100, соответственно.

Trailing Stop Loss для основной сделки работает только при достижении необходимой прибыли (по умолчанию 50 пунктов). А для вспомогательных сделок – с момента открытия (т.е. может двигать Stop Loss и в области убытка). Величина уровня T-SL одинакова для всех ордеров. Кроме того, размер уровня T-SL является и уровнем Stop Loss для вспомогательных сделок.

В случае закрытия основной сделки оставшиеся отложенные ордера удаляются. После этого на график снова наносятся две стрелки, что сигнализирует о готовности робота снова открывать сделки.

Всё это может показаться достаточно громоздким, но на практике это легко реализуемо. Перейдём к коду советника.
//+------------------------------------------------------------------+
//|                                                   take_trend.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
extern int gap=20;            //уровень, на котором высставляются стрелки 
extern int TP=400;            //уровень Take Profit
extern int SL=0;              //уровень Stop Loss
extern double Lots1=0.2;      //лот основной сделки
extern double Lots2=0.1;      //лот вспомогательных сделок 
extern int slippage=2;        //уровень допустимого реквота
extern int MagicNumber1=5345; //магическое число основной сделки
extern int MagicNumber2=4365; //магическое число вспомогательных сделок
extern int Open_Step=100;     //шаг открытия вспомогательных сделок
 
extern bool UseTrailing = true; //включение/выключение T-SL
extern int TrailingStop = 50;   //уровень Trailing Stop Loss
extern int TrailingStep = 1;    //шаг Trailing Stop Loss
int start()
  {
//------------------------------       
//+----------------------------------------------------------------------------------------------+
//|                              поиск открытых ордеров по паре                                  |
    int pos_sell=0;
  for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
  { 
   if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1   
   &&(OrderType()==OP_SELL))
   {
    pos_sell=1; break;   
   } 
  }
    
    int pos_buy=0;
  for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
  { 
   if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1
   &&(OrderType()==OP_BUY))
   {
    pos_buy=1; break;   
   } 
  }    
//|                              поиск открытых ордеров по паре                                  |
//+----------------------------------------------------------------------------------------------+  
//+------------------------------------------------------------------------------------+
//|                                 работа с объектами                                 |  
 
//+----------------------------------------------------------+
//|                    удаление объектов                     | 
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
  if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point)            
    { 
     ObjectDelete("up"); 
    } 
//|                    удаление объектов                     |   
//+----------------------------------------------------------+ 
 
//+----------------------------------------------------------+
//|                   нанесение объектов                     |   
   if((ObjectFind("down") != 0&&ObjectFind("up") != 0) //если объектов нет
   &&!pos_sell&&!pos_buy)                              //и если нет открытых ордеров
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //рисуем стрелку вниз
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, 234);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //рисуем стрелку вверх
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, 233);
     ObjectSet("up", OBJPROP_COLOR, Blue);
   }    
//|                   нанесение объектов                     |
//+----------------------------------------------------------+   
      
//|                                 работа с объектами                                 |   
//+------------------------------------------------------------------------------------+
 
   
 
 
//+----------------------------------------------------------------------------------------------+ 
//|                                удаление лишних ордеров                                       | 
int cnt_del; 
if(pos_buy==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    {
     if (OrderType()==OP_BUYSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 } 
 
if(pos_sell==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    { 
    if (OrderType()==OP_SELLSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 }  
//|                                удаление лишних ордеров                                       |
//+----------------------------------------------------------------------------------------------+  
 
  
//+------------------------------------------------------------------------------------+ 
//|                                   открытие сделок                                  |
double sl_buy, sl_sell;
 if(!SL)
 { 
  sl_buy=0;
  sl_sell=0;
 }
 else
 {
  sl_buy=Ask-SL*Point;
  sl_sell=Bid+SL*Point;
 }
 int stop_positions=MathFloor(TP/Open_Step-1);
 int i, open_step_2;
  if(
     ObjectGet("up", OBJPROP_PRICE1)==Open[0]+gap*Point
     &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==0
     &&ObjectFind("down") != 0
     &&ObjectFind("up") == 0
     &&!pos_buy  
     )
     {
      OrderSend(Symbol(),OP_BUY, Lots1,Ask,slippage,sl_buy,Ask+TP*Point,"take_trend",MagicNumber1,0,Blue); 
      for(i=stop_positions;i>=0; i--) 
      {
       open_step_2=open_step_2+Open_Step;
       OrderSend(Symbol(),OP_BUYSTOP, Lots2,
       Ask+open_step_2*Point,slippage,
       0,Ask+TP*Point,"take_trend",MagicNumber2,0,Blue);
      }          
     }
  if(
     ObjectGet("down", OBJPROP_PRICE1)==Open[0]-gap*Point
     &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==0
     &&ObjectFind("up") != 0
     &&ObjectFind("down") == 0
     &&!pos_sell
     )
     {
      OrderSend(Symbol(),OP_SELL, Lots1,Bid,slippage,sl_sell,Bid-TP*Point,"take_trend",MagicNumber1,0,Red);
      for(i=stop_positions;i>=0; i--) 
      {
       open_step_2=open_step_2+Open_Step;
       OrderSend(Symbol(),OP_SELLSTOP, Lots2,
       Bid-open_step_2*Point,slippage,
       0,Bid-TP*Point,"take_trend",MagicNumber2,0,Red);
      }        
     }
//|                                   открытие сделок                                  |  
//+------------------------------------------------------------------------------------+   
 
 
//+-------------------------------------------------------------------------------------------------+ 
//|                                      трал открытых ордеров                                      |
if (UseTrailing)
{ 
  for (int trall=0; trall<OrdersTotal(); trall++) {
    if (!(OrderSelect(trall, SELECT_BY_POS, MODE_TRADES))) continue;
    if (OrderSymbol() != Symbol()) continue;       
 
    if (OrderType() == OP_BUY ) {
      if (Bid-OrderOpenPrice() > TrailingStop*Point || OrderMagicNumber()==MagicNumber2) {
        if (OrderStopLoss() < Bid-(TrailingStop+TrailingStep-1)*Point || OrderStopLoss() == 0) {
          OrderModify(OrderTicket(), OrderOpenPrice(), Bid-TrailingStop*Point, OrderTakeProfit(), 0, Blue);
       }
      }
    }
 
    if (OrderType() == OP_SELL) {
     if (OrderOpenPrice()-Ask > TrailingStop*Point || OrderMagicNumber()==MagicNumber2) {
        if (OrderStopLoss() > Ask+(TrailingStop+TrailingStep-1)*Point || OrderStopLoss() == 0) {
          OrderModify(OrderTicket(), OrderOpenPrice(), Ask+TrailingStop*Point, OrderTakeProfit(), 0, Blue);
        }
     }
    }
  }
 }
//|                                      трал открытых ордеров                                      |
//+-------------------------------------------------------------------------------------------------+
     
   return(0);
  }
//+------------------------------------------------------------------+
Код снабжён всем необходимыми комментариями.
Переменные:
gap – уровень, на котором высставляются стрелки 
TP – уровень Take Profit
SL – уровень Stop Loss
Lots1 – лот основной сделки
Lots2 – лот вспомогательных сделок 
slippage – уровень допустимого реквота
MagicNumber1 – магическое число основной сделки
MagicNumber2 – магическое число вспомогательных сделок
Open_Step – шаг открытия вспомогательных сделок


UseTrailing – включение/выключение T-SL
TrailingStop – уровень Trailing Stop Loss
TrailingStep – шаг Trailing Stop Loss

При нанесении советника на график, он нарисует две стрелки:


Оставшаяся стрелка будет находиться на графике до следующей свечи:


Сразу после удаления одной из сделок, советник откроет необходимые сделки:


Как можно заметить, на данном скриншоте уже нет оставшейся стрелки, о чём писалось ранее - она удаляется на следующей свече и стрелки не появляются до закрытия сделок. Когда прибыль на первой сделке достигнет необходимого уровня, начнёт работать T-SL (на вспомогательных сделках он работает всегда). В данном примере, закрылась только первая сделка при откате. Вместе с тем были удалены остальные сделки:




Заключение

В заключение хотелось бы отметить, что уровень Trailing Stop Loss, TP и уровень открытия вспомогательных сделок необходимо подбирать для каждой пары индивидуально. Также стоит отметить, что для продуктивного применения уровень открытия вспомогательных сделок должен быть больше уровня T-SL. Рекомендуется на основной сделке использовать лот превышающий лот вспомогательных сделок.