Скачать MetaTrader 5

Двухэтапный вариант модификации открытых позиций

9 мая 2008, 11:51
Genkov
10
1 496

Введение

В статье "Подход Т. Демарка к техническому анализу" есть рекомендованные коэффициенты длины коррекции, в частности 0,382 и 0,618. Применяя эти коэффициенты при отслеживании открытых позиций, можно избежать ненужных ситуаций закрытия и переоткрытия позиций в ситуациях близких к трендовым. Функция хорошо работает особенно в ситуациях возникновения дивергенций.

Этот подход с учетом переустановки величины профита помогает уловить и возникновение "хорошего" тренда. Например, как показано на рис1 по сравнению с рис2.




Алгоритм функции

1-ая модификация ордера по заданному значению TrailingStop, последующие - устанавливают StopLoss на 1 или 2 пункта ниже возможного уровня коррекции (в данном случае коэффициент коррекции = 0.382 "Coeff_ "). Значение TakeProfit при каждом шаге увеличиваем, например на половину величины TrailingStop-а (можно выбрать и другую величину!). Можно так же и не менять величину TakeProfit. Для этого в начале программы в операторе extern double March = 0; установить значение ноль.

Для тех трейдеров, которые предпочитают адресный анализ-поддержку выполнения конкретных действий программы непосредственно в ходе торгов, целесообразнее будет переменную MagicNumber перенести в код самого советника в то место, где происходит открытие позиции. Более подробно о конкретной адресной поддержке можно прочитать в Учебнике, опубликованного на сайте MQL4.com (автор С.Ковалев).


Рассмотрим поподробнее предлагаемый код и комментарии к нему будущей функции в советнике:

//+------------------------------------------------------------------+
//|      Двухэтапный вариант TrailingStop        Modify_2step v5.mq4 |
//|  Модификация ордеров: переустановка StopLoss и TakeProfit        |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, GenKov"
#property link      Genkov@bk.ru
//+------------------------------------------------------------------+
/* Magic=N

Magic=N - такой оператор надо вставлять при открытии позиции сразу же после операторов контроля выполнения условий в самой программе (советнике), и в функцию! Наверное, в связи с непредсказуемостью рынка, как мне кажется, универсального модификатора мне создать не удалось, а поэтому для каждого вида условий открытия позиций (по Magic=N) надо писать функцию отслеживания (передвижения S/L и T/P) и условия закрытия позиции.

extern double    March         =  1;  // шаг увеличения TakeProfit-а 
                                      // "0" шаг не увеличивает T/P.

S/L должен быть на 1 пункт меньше TrailingStop-а, чтобы при первом же срабатывании S/L оказался на безубыточном уровне. Таким образом мы страхуем себя от возможных потерь (управление капиталом).

extern double    StopLoss      = 15;  
extern double    TrailingStop  = 16;  
extern double    TakeProfit    = 60;  // подбор по тестеру
//+------------------------------------------------------------------+
//void TrailingStop()
  int start()                                   
   {
   //----------------------------------------------------------------+
   int point  = MarketInfo(Symbol(),MODE_POINT);      // Размер пункта 
   int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL);  
   double half_Trail = MathRound(TrailingStop/2);//половина TrailingStop-а
   double Step = March*half_Trail;  //величина увеличения TakeProfit-а
  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)
     {

Первый этап модификации позиций BUY

if(OrderStopLoss()<OrderOpenPrice())//если S/L ниже цены открытия ордера
      {   // и если разность между текущей ценой и ценой открытия поз больше T/S
      if(Bid-OrderOpenPrice()>TrailingStop*Point) // && 
       {     // и если OrderStopLoss() меньше разницы текущей цены и T/S
       if(OrderStopLoss()<Bid-TrailingStop*Point)
        {    // расчитаем новое значение T/P
        double Now_T_P=(OrderTakeProfit()+Step*Point);
       { 
       OrderModify(OrderTicket(),OrderOpenPrice(),
       OrderStopLoss()+TrailingStop*Point,
       OrderTakeProfit()+Step*Point,0,Aqua); // повышаем значение T/P 
      return;
      }
     }
    }
   }

Однако, может возникнуть ситуация, когда передвигаемый TakeProfit станет на 2-3 пункта выше ранее запланированного уровня прибыли, остановится и

начнет медленно снижаться.


Чтобы избежать упущенной прибыли, введем оператор контроля над этой ситуацией, который и закроет ордер на запланированном уровне прибыли. Если же цена продолжит рост, то будет продолжено продвижение стоп-лоса и тейк-профита.

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);
    }
// второй этап модификации поз.BUY
  if(OrderStopLoss()>=OrderOpenPrice()) // Стор лос на безубыточном уровне
   {    // посчитаем коэффициент коррекции
    double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits);
    // и если разность между текущей ценой и ценой открытия поз больше коэфф. коррекции 
    if(Bid-OrderOpenPrice()>Coeff_up) 
     {    // посчитаем значение нового StopLoss с запасом в 2-а пункта
      double New_S_Loss = Bid-Coeff_up-2*Point;
      // и если значение нового StopLoss-a выше текущего значения 
      if(New_S_Loss-OrderStopLoss()>3*Point)
       {     // передвинем S/L и 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;
       }
      }
     }

Подход к короткой позиции аналогичен предыдущим рассуждениям и поэтому комментариев поменьше.

// ---------------------------- 1 этап модификации -----SELL-------------&
   else  if(OrderType()==OP_SELL) 
    {
   if(OrderStopLoss()>OrderOpenPrice())//если S/L выше цены открытия ордера
     {
     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 этап модификации -----SELL-------------&
   if(OrderStopLoss()<=OrderOpenPrice()) // Стор лос на безубыточном уровне
    { // посчитаем коэффициент коррекции
     double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits);
     // и если разность между ценой открытия поз и текущей ценой больше коэфф. коррекции 
    if(OrderOpenPrice()-Ask>Coeff_down) 
     {    // посчитаем значение нового StopLoss с запасом в 2-а пункта
      New_S_Loss = Ask+Coeff_down+2*Point; 
      // и если значение нового StopLoss-a ниже текущего значения 
      if(New_S_Loss-OrderStopLoss()>3*Point)
       {     // передвинем S/L и T/P   
       OrderModify(OrderTicket(),OrderOpenPrice(),
       New_S_Loss,OrderTakeProfit()-Step*Point,0,Khaki);
      return;
      }
     }
    }
   }
  } 
 //  -----------------------------------------------------------------------------------

Для превращения этого советника в функцию надо закомментировать специальную функцию int start(), стоящую в начале программы, заменив ее на раскомментированное определение функции TrailingStop() в начале программы, закомментированный вызов функции в конце программы

//TrailingStop();

раскомментировать.


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

// --------------------------------------------------------------------------------
  
   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 --- &

Теперь убираем из вышеприведенного текста кода подробные комментарии, и оформляем код в виде исполнительной функции: получим следующий фай, который рекомендуется хранить в директории каталог_терминал\experts\include с расширением .mqh или каталог_терминал\libraries с расширением 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;  // шаг увеличения TakeProfit-а 
                                      // "0" шаг не увеличивает T/P.
// S/L должен быть на 1 пункт меньше TrailingStop-а, чтобы при 
// первом же срабатывании S/L оказался на безубыточном уровне  
extern double    StopLoss      = 15;  
extern double    TrailingStop  = 16;
extern double Lots             = 0.1;  
extern double    TakeProfit    = 60;  // подобрать по тестеру
void TrailingStop()
  {
   int Magic=3090;  //  номер условия открывшего позицию
   int point  = MarketInfo(Symbol(),MODE_POINT);      // Размер пункта 
   int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL);  
   double half_Trail = MathRound(TrailingStop/2);//половина TrailingStop-а
   double Step = March*half_Trail;  //величина увеличения TakeProfit-а
  if (TrailingStop<0) return;
   { 
   for (int i=0; i<OrdersTotal(); i++)
    {//1 +цикл по перебору ордеров
    if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=Magic) continue;
    if (OrderType()==OP_BUY)
     {
// --------------------------- 1 этап модификации -----BUY-------------&     
    if(OrderStopLoss()<OrderOpenPrice())//если S/L ниже цены открытия ордера
      {   // и если разность между текущей ценой и ценой открытия поз больше T/S
      if(Bid-OrderOpenPrice()>TrailingStop*Point) // && 
       {     // и если OrderStopLoss() меньше разницы текущей цены и T/S
       if(OrderStopLoss()<Bid-TrailingStop*Point)
        {    // расчитаем новое значение T/P
        double Now_T_P=(OrderTakeProfit()+Step*Point);
       { 
       OrderModify(OrderTicket(),OrderOpenPrice(),
       OrderStopLoss()+TrailingStop*Point,
       OrderTakeProfit()+Step*Point,0,Aqua); // повышаем значение T/P 
      return;
      }
     }
    }
   }
  if(Bid-OrderOpenPrice()>=TakeProfit*Point) 
   {
    OrderClose(OrderTicket(),Lots,Bid,2,Red);
    }
//------------------------- 2-ой этап модификации -----BUY---------------&
  if(OrderStopLoss()>=OrderOpenPrice()) // Стор лос на безубыточном уровне
   {    // посчитаем коэффициент коррекции
    double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits);
    // и если разность между текущей ценой и ценой поз. больше коэфф. коррекции 
    if(Bid-OrderOpenPrice()>Coeff_up) 
     {    // посчитаем значение нового StopLoss с запасом в 6-и пункта
      double New_S_Loss = Bid-Coeff_up-6*Point-StopLev*Point;
      // и если значение нового StopLoss-a выше текущего значения 
      if((New_S_Loss-OrderStopLoss())<2*Point)
       {     // передвинем S/L и 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 этап модификации -----SELL-------------&
  else if(OrderType()==OP_SELL)
    {
   if(OrderStopLoss()>OrderOpenPrice())//если S/L выше цены открытия ордера
     {
     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 этап модификации -----SELL-------------&
   if(OrderStopLoss()<=OrderOpenPrice()) // Стор лос на безубыточном уровне
    if(OrderOpenPrice()-Ask>=OrderTakeProfit()) OrderClose(OrderTicket(),Lots,Ask,2,Red);   
    { // посчитаем коэффициент коррекции
     double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits);
     // и если разность между ценой открытия поз и текущей ценой больше коэффициента коррекции 
    if(OrderOpenPrice()-Ask>Coeff_down) 
     {   // посчитаем значение нового StopLoss с запасом в 6-и пункта
      New_S_Loss = Ask+Coeff_down+6*Point; 
      // и если значение нового StopLoss-a ниже текущего значения 
      if((OrderStopLoss()-New_S_Loss-StopLev*Point)>=10*Point)
       {    // передвинем S/L и T/P
       OrderModify(OrderTicket(),OrderOpenPrice(),
       New_S_Loss-5*Point,OrderTakeProfit()-Step*Point,0,Khaki);
      return;
      }
     }
    }
   }
  } 
return(0);
}
}
// ---end----- void TrailingStop()--------------------------------&
  // этот блок только для контроля ошибок в коде функции
  //  int start()  
  //   {
  //    if(25>26) TrailingStop();
  //    }
  // --------------------------------


В заключении нужно сказать, что в отличие от "образцова трейлинг-стопа", описанного 21.04.2008 Сергеем Кравчуком в статье "Образцовый трейлинг-стоп и выход с рынка", предлагаемый вариант попроще в понимании, и в моем советнике срабатывал, правда на демо-счете, и, по моему, подходит для агрессивного и умеренного трейлинга.

Прикреплены варианты версий:

v4 - с закрытием по S/L; v5 - с упреждающим закрытием по T/P; v6 - с учетом упреждения и адресной поддержке по Magic померу.

Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (10)
Genkov
Genkov | 18 май 2008 в 05:21
gareev:

В Modify_2step v4.mq4  и Modify_2step v5.mq4 

// ---------------------------- 2 этап модификации -----SELL-------------&
   if(OrderStopLoss()<=OrderOpenPrice()) // Стор лос на безубыточном уровне
    { // посчитаем коэффициент коррекции
     double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits);
     // и если разность между ценой открытия поз и текущей ценой больше коэфф. коррекции
    if(OrderOpenPrice()-Ask>Coeff_down)
     {   // посчитаем значение нового StopLoss с запасом в 2-а пункта
      New_S_Loss = Ask+Coeff_down+2*Point;
      // и если значение нового StopLoss-a ниже текущего значения
      if(New_S_Loss-OrderStopLoss()>3*Point)/*здусь ошибка*/if(OrderStopLoss()-New_S_Loss>3*Point)



Да Рамиль, Вы правы! В v 6 эта ошибка была исправлена, а в двух предыдущих ..увы! Большое спасибо за Ваш внимательный анализ. Удачного Вам профита!
Martes
Martes | 5 июн 2008 в 07:06

Заметил, что в программе вычисляется значение переменной point (с маленькой буквы), а фактически все равно используется стандартная переменная Point (с большой буквы).

Martes
Martes | 5 июн 2008 в 10:10
Прикрутил такой метод модификации к паре советников, но особенно лучше не стало.
Genkov
Genkov | 6 июн 2008 в 18:54
Martes:

Заметил, что в программе вычисляется значение переменной point (с маленькой буквы), а фактически все равно используется стандартная переменная Point (с большой буквы).


         Относительно большой и маленькой буквы в переменной Point - дело в том, что в моем компе при тестировании (не на Демо) на некоторых модификациях MQL4 переменная с маленькой буквы не определяется, а с большой - сбоев не наблюдал. 

        Относительно метода модификации "....., но особенно лучше не стало." - спасибо за приятное для меня сообщение, т.к. можно понять, что небольшое усовершествование дает такую-то пользу, по принципу "лучше 40 раз по разу, чем ниразу 40 раз".

MQL4 Comments
MQL4 Comments | 14 ноя 2008 в 23:41

Как прикрутить его к советнику?

Образцовый трейлинг-стоп и выход с рынка Образцовый трейлинг-стоп и выход с рынка

У разработчиков алгоритмов модификаций и закрытия ордеров есть одна непроходящая головная боль - как сравнивать результаты, получаемые по различным методикам? Механизм проверок известен - тестер стратегий. А вот как сделать так, чтобы эксперт всегда работал одинаково по открытию/закрытию ордеров? В статье описывается инструмент, обеспечивающий строгую повторяемость открытий ордеров, позволяющую обеспечить математически корректную платформу для сравнения результатов различных алгоритмов трейлинг-стопов и выходов с рынка.

Заблуждения, Часть 1: Управление капиталом вторично и не слишком важно Заблуждения, Часть 1: Управление капиталом вторично и не слишком важно

Первичная демонстрация результатов тестирования стратегии на лоте 0.1, кажется, начинает превращаться в стандарт де-факто на форуме. Новичок, получив одобрительное "угу, не так и плохо" от бывалых, видит, что тестирование "0.1" приносит относительно скромные результаты, и решается на введение агрессивного управления капиталом, считая, что положительное матожидание сделки автоматически обеспечит ему все остальное. Посмотрим, что из этого может получиться, попутно построив несколько искусственных, но очень поучительных графиков баланса.

Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота (Продолжение) Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота (Продолжение)

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

Заблуждения, Часть 2: Статистика - лженаука, или Хроника пикирующего бутерброда Заблуждения, Часть 2: Статистика - лженаука, или Хроника пикирующего бутерброда

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