Различные виды трала

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Различные виды трала

Сообщение Haos » 11 авг 2018, 21:00

В этой теме рассмотрим разные виды трала (подтягивание СЛ вслед за движением цены). Метод (алгоритм) осуществления трала может быть простой или сложный. Обычно, сложные виды трала основаны на индикаторах или оригинальных методах расчета. Эффективность их сложно оценить без тестирования. Всё зависит от конкретной ТС. Простой же вид трала основан на перемещении СЛ вслед за ценой на количество пунктов, которая цена движется в профит на каждом тике. Когда же она движется против направления сделки, трал останавливается.
Каждый имеющийся у меня функционал трала использует ряд дополнительных функций, который можно привести вначале:

Функция модификации предварительно выбранного ордера
Код: выделить все
bool f__ModifyOrder(int ti, double sl, double tp)
{
/*
   Описание: модификация предварительно выбранного ордера
   Используется функция: f__ProcessError()
   Параметры:                                                               
   ti - OrderTicket()
   sl - новый СЛ ордера (-1 - не менять)
   tp - новый ТП ордера (-1 - не менять)             
*/
   int int_Try = 5; // rоличество попыток
   if (OrderSelect(ti, SELECT_BY_TICKET) == true)
   {
      int i = 0;
      double dbl_SL = sl; if(sl == -1) dbl_SL = OrderStopLoss();
      double dbl_TP = tp; if(tp == -1) dbl_TP = OrderTakeProfit();
      if((OrderStopLoss()== dbl_SL) && (OrderTakeProfit() == dbl_TP)) return(true);
      GetLastError();
      while(i < int_Try)
      {
         if(OrderModify(OrderTicket(), OrderOpenPrice(), dbl_SL, dbl_TP, 0)) return(true);
         else
         {
            i++;
            if(!f__ProcessError(GetLastError())) return(false);
         }
      }
   }

return(false);
}


Другие вспомогательные функции, направленные на обработку ошибок
Код: выделить все
bool f__ProcessError(int err)
{
/*
   Описание : Обработка ошибок
   Используется функция: f__PrintError()
   Параметры:                                                               
   err - номер ошибки           
*/
   int iteration;

   if(err > 1) f__PrintError(err);
   switch(err)
   {
   // Некритические ошибки
   case 0:     // ERR_NO_ERROR
   case 135:   // ERR_PRICE_CHANGED
   case 138:   // ERR_REQUOTE
      return(true);
   // Некритические ошибки, требующие таймаута
   case 4:     // ERR_SERVER_BUSY
   case 128:   // ERR_TRADE_TIMEOUT
      Sleep(1000 * 60);
      return(true);   
   case 129:   // ERR_INVALID_PRICE
   case 130:   // ERR_INVALID_STOPS
      //if (WorkMode==ModeManual && ShowConfirm) MessageBox("Неправильные стопы", VISITCARD, MB_OK);
      return(false);
   case 136:   // ERR_OFF_QUOTES
      Sleep(1000 * 5);
      return(true);   
   case 137:   // ERR_BROKER_BUSY
   case 145:   // ERR_TRADE_MODIFY_DENIED
      Sleep(1000 * 15);
      return(true);   
   // Нет связи с сервером. Пытаемся восстановить связь
   case 6:     // ERR_NO_CONNECTION
   {
      bool connect = false;
      iteration = 0;
      while((!connect) || (iteration < 60)) // в течение 5 минут пытаемся подконнектиться к серверу
      {
         Sleep(1000 * 5);
         connect = IsConnected();
         if(connect)
         {
            Print("Связь восстановлена");
            return(true);
         }
         iteration++;
         Print("Связь не восстановлена, прошло ", iteration * 5, " секунд.");
      }
      Print("Соединение в течение ", iteration * 5, " секунд восстановить не удалось.");
      return(false);
   }
   // Подсистема торговли занята. Ждем, пока освободится
   case 146:   // ERR_TRADE_CONTEXT_BUSY
   {
      bool tradecontextbusy = true;
      iteration = 0;
      while((tradecontextbusy) || (iteration < 60)) // в течение 5 минут ждем освобождения подсистемы торговли
      {
         Sleep(1000 * 5);
         tradecontextbusy = IsTradeContextBusy();
         if(!tradecontextbusy)
         {
            Print("Подсистема торговли освободилась.");
            return(true);
         }
         iteration++;
         Print("Подсистема торговли все еще занята, прошло ", iteration * 5, " секунд.");
      }
      Print("Подсистема торговли в течение ", iteration * 5, " секунд не освободилась.");
      return(false);
   }
   // Критические ошибки. Прекращаем попытки открытия ордера
   case 1:     // ERR_NO_RESULT
   case 2:     // ERR_COMMON_ERROR
   case 3:     // ERR_INVALID_TRADE_PARAMETERS
   case 5:     // ERR_OLD_VERSION
   case 7:     // ERR_NOT_ENOUGH_RIGHTS
   case 8:     // ERR_TOO_FREQUENT_REQUESTS
   case 9:     // ERR_MALFUNCTIONAL_TRADE
   case 64:    // ERR_ACCOUNT_DISABLED
   case 65:    // ERR_INVALID_ACCOUNT
   case 131:   // ERR_INVALID_TRADE_VOLUME
   case 132:   // ERR_MARKET_CLOSED
   case 133:   // ERR_TRADE_DISABLED
   case 134:   // ERR_NOT_ENOUGH_MONEY
   case 139:   // ERR_ORDER_LOCKED
   case 140:   // ERR_LONG_POSITIONS_ONLY_ALLOWED
   case 141:   // ERR_TOO_MANY_REQUESTS
   case 142:
   case 143:
   case 144:
   case 147:   // ERR_TRADE_EXPIRATION_DENIED
   case 148:   // ERR_TRADE_TOO_MANY_ORDERS
   case 4110:  // ERR_LONGS_NOT_ALLOWED
   case 4111:  // ERR_SHORTS_NOT_ALLOWED
      return(false);
   case 4109:  // ERR_TRADE_NOT_ALLOWED
      //MessageBox("Для совершения операций необходимо поставить галочку \"Разрешить советнику торговать\" в настройках терминала", VISITCARD, MB_OK);
      return(false);
   }
   return(false);
}

//*********************************************************************************************

int f__PrintError(int err)
{
   Print("ERROR ", err, ":  ", f__Err2str(err));
   return(0);
}

//*********************************************************************************************

//+------------------------------------------------------------------+
//| Получение описания ошибки по ее номеру                           |
//+------------------------------------------------------------------+
string f__Err2str(int err)
{
   switch(err)
   {
   case 0:
      return("Нет ошибки");
   case 1:
      return("Функция модификации ордера пытается изменить уже установленные значения такими же значениями");
   case 2:
      return("Общая ошибка");
   case 3:
      return("В торговую функцию переданы неправильные параметры");
   case 4:
      return("Торговый сервер занят");
   case 5:
      return("Старая версия клиентского терминала");
   case 6:
      return("Нет связи с торговым сервером");
   case 7:
      return("Недостаточно прав");
   case 8:
      return("Слишком частые запросы");
   case 9:
      return("Недопустимая операция нарушающая функционирование сервера");
   case 64:
      return("Счет заблокирован");
   case 65:
      return("Неправильный номер счета");
   case 128:
      return("Истек срок ожидания совершения сделки");
   case 129:
      return("Неправильная цена");
   case 130:
      return("Неправильные стопы");
   case 131:
      return("Неправильный объем сделки");
   case 132:
      return("Рынок закрыт");
   case 133:
      return("Торговля запрещена");
   case 134:
      return("Недостаточно денег для совершения операции");
   case 135:
      return("Цена изменилась");
   case 136:
      return("Нет цен");
   case 137:
      return("Брокер занят");
   case 138:
      return("Реквот! Новые цены");
   case 139:
      return("Ордер заблокирован и уже обрабатывается");
   case 140:
      return("Разрешена только покупка");
   case 141:
      return("Слишком много запросов");
   case 142:
      return("Ордер поставлен в очередь");
   case 143:
      return("Ордер принят дилером к исполнению");
   case 144:
      return("Ордер аннулирован самим клиентом при ручном подтверждении сделки");
   case 145:
      return("Модификация запрещена, так как ордер слишком близок к рынку");
   case 146:
      return("Подсистема торговли занята");
   case 147:
      return("Использование даты истечения ордера запрещено брокером");
   case 148:
      return("Количество открытых и отложенных ордеров достигло предела, установленного брокером");
   case 4109:
      return("Торговля не разрешена. Необходимо включить опцию \"Разрешить советнику торговать\" в свойствах эксперта");
   case 4110:
      return("Длинные позиции не разрешены");
   case 4111:
      return("Короткие позиции не разрешены");
   }
   return("Описание ошибки не известно");
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Различные виды трала

Сообщение Haos » 11 авг 2018, 21:01

1. Сопровождение позиции простым тралом
Код: выделить все
void f_SimpleTral(string sy, int op, int mn, int tst, int tde)
{
/*
  Описание : Сопровождение позиций простым тралом
  11.08.2018
  Используется функция f__ModifyOrder()                             
  Параметры:                                                               
  sy - наименование инструмента   ( ""  - любой символ,                   
                                    "0" - текущий символ)                 
  op    - операция                ( -1  - любая позиция)                 
  mn    - MagicNumber             ( -1  - любой магик) 
  tst   - Шаг трала в пунктах (1 пнт., например)
  tde   - Размер профита в пунктах (5 пнт., например) после кот. нач. тралить
*/
   double   Ysl,  // новый уровень установки СЛ
            Po,   // величина пункта
            Y1;   // текущая котировка цены
   int      Di,   // Количество цифр после запятой в цене инструмента
            Sp;   // спред в пнт.
   
   if(sy == "0") sy = Symbol();
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if((OrderSymbol() == sy || sy == "") && (op < 0 || OrderType() == op))
         {
            Sp = (int) MarketInfo(OrderSymbol(), MODE_SPREAD);
            Po = MarketInfo(OrderSymbol(), MODE_POINT);
            Di  = (int) MarketInfo(OrderSymbol(), MODE_DIGITS);           
            if(tde < Sp) tde = Sp;
            if(mn < 0 || OrderMagicNumber() == mn)
            {
               // ---------- начало работы со сделкой на покупку:
               if(OrderType() == OP_BUY)
               {
                  Y1 = MarketInfo(OrderSymbol(), MODE_BID);
                  if(Y1 - OrderOpenPrice() > tde * Po)
                  {
                     if(OrderStopLoss() < Y1 - (tde + tst - 1) * Po)
                     {
                        Ysl = NormalizeDouble(Y1 - tde * Po, Di);
                     
                        if(f__ModifyOrder(OrderTicket(), Ysl, -1))
                        {
                           Print(Symbol(), "Modify Trailing ok");         
                        }
                        else Print(Symbol(), " Modify Trailing fail");                     
                     }
                  }
               }   
               //------------окончание работы со сдлекой на покупку --------------------
               // ---------- начало работы со сделкой на продажу:
               if(OrderType() == OP_SELL)
               {
                  Y1 = MarketInfo(OrderSymbol(), MODE_ASK);
                  if(OrderOpenPrice() - Y1 > tde * Po)
                  {
                     if(OrderStopLoss() > Y1 +(tde + tst - 1) * Po || OrderStopLoss() == 0)
                     {
                        Ysl = NormalizeDouble(Y1 + tde * Po, Di);
                        if(f__ModifyOrder(OrderTicket(), Ysl, -1))
                        {
                           Print(Symbol(), "Modify Trailing ok");         
                        }
                        else Print(Symbol(), " Modify Trailing fail");
                     }
                  }
               }
               //---конец работы со сделкой на продажу
            }
         }
      }
   }
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Различные виды трала

Сообщение Haos » 23 ноя 2018, 09:47

2. Трал по Параболику (SAR).
Код: выделить все
void f_SARTral(int op, int mn, double pste, double pmax, int offs)
{
/*
   Трал по Параболику
   pste - шаг изменения цены - коэффициент ускорения (Параболик)
   pmax - максимальный шаг (Параболик)
   offs - отступ от точки Пабалика при установке СЛ (пнт.)
*/
   double dbl_SL1, dbl_SAR0;
   double dbl_SL0;
   double dbl_StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if((OrderSymbol() == _Symbol) && (op < 0 || OrderType() == op))
         {
            if(OrderType() == OP_BUY || OrderType() == OP_SELL)
            {       
               if(mn < 0 || OrderMagicNumber() == mn)   
               {           
                  dbl_SL1 = OrderStopLoss(); // уже установленный у сделки СЛ (может и 0 быть)
                  dbl_SAR0 = iSAR(NULL, 0, pste, pmax, 0);
         
                  if(OrderType() == OP_BUY)
                  {
                     dbl_SL0 = dbl_SAR0 - offs * _Point;
                     if((dbl_SL1 < dbl_SL0) && (Bid - dbl_StopLevel > dbl_SAR0)) 
                     {                   
                        if(f__ModifyOrder(OrderTicket(), dbl_SL0, -1))
                        {
                           Print(Symbol(), " Modify Trailing ok");         
                        }
                        else Print(Symbol(), " Modify Trailing fail");
                     }
                   }
                   if(OrderType() == OP_SELL)
                   {
                      dbl_SL0 = dbl_SAR0 + offs * _Point;
                      if(((dbl_SL1 > dbl_SL0) || dbl_SL1 == 0) && (Ask + dbl_StopLevel < dbl_SAR0))
                      {
                         if(f__ModifyOrder(OrderTicket(), dbl_SL0, -1))
                         {
                            Print(Symbol(), " Modify Trailing ok");         
                         }
                         else Print(Symbol(), " Modify Trailing fail");
                      }
                   }
               }
            }
         }
      }
   }
}

Также используется упомянутая выше функция f__ModifyOrder().

Далее будет рассмотрен Трал по ATR
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Различные виды трала

Сообщение Haos » 24 ноя 2018, 09:41

В функции, описанной выше, предварительный СЛ не требуется, т.е. если сделка имеет СЛ, то трал будет при более лучшей цене, а если СЛ нет, то он будет выставлен согласно показанию Параболика. Также, как обычно, есть фильтр по имени торгового актива и мэджику сделок. Остальные параметры функции определены параболическим расчетом.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Различные виды трала

Сообщение Haos » 24 дек 2018, 10:01

Рассмотрим трейлинг стоп по индикатору ATR. Это один из самых распространенных видов трала после простого.

Код: выделить все
void f_ATRTral(int tf, int mn, int pe, double kk, int sh)
{
/*
   Описание : Трал по ATR   
   Используется функция f__ModifyOrder()
   Параметры:                                                               
   tf  - таймфрейм   (0 - текущий таймфрейм)       
   pe  - период ATR  (14, например)
   kk  - коэффициент, на который умножаем ATR
   sh  - сдвиг относительно текущего бара на указанное количество периодов назад
   // результат умножения ATR на коэффициент
   double dblATR = iATR(NULL, tf, pe, sh) * kk;
*/
   double dblSLOld, dblSLNew;
   double dblStLev = MarketInfo(_Symbol, MODE_STOPLEVEL) * Point;
   double dblATR = NormalizeDouble(iATR(NULL, tf, pe, sh) * kk, _Digits);
   
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == _Symbol && (mn < 0 || OrderMagicNumber() == mn))
         {
            if(OrderType() == OP_BUY || OrderType() == OP_SELL)
            {       
               // уже установленный у сделки СЛ (может и 0 быть)
               dblSLOld = OrderStopLoss();
               if(OrderType() == OP_BUY)
               {
                  dblSLNew = Low[sh] - dblATR;
                  if((dblSLOld < dblSLNew) && (Bid - dblStLev > dblSLNew)) 
                  {                   
                     if(f__ModifyOrder(OrderTicket(), dblSLNew, -1))
                     {
                        Print(_Symbol, "Modify Trailing ok");         
                     }
                     else Print(_Symbol, "Modify Trailing fail");
                  }
               }
               if(OrderType() == OP_SELL)
               {
                  dblSLNew = High[sh] + dblATR;
                  if(((dblSLOld > dblSLNew) || dblSLOld == 0) && (Ask + dblStLev < dblSLNew))
                  {
                     if(f__ModifyOrder(OrderTicket(), dblSLNew, -1))
                     {
                        Print(Symbol(), " Modify Trailing ok");         
                     }
                     else Print(Symbol(), " Modify Trailing fail");
                  }
                }
            }
         }
      }
   }
}

Параметрами функции являются ТФ, мэджик ордеров (таким образом мы выделяем нужные нам ордера, отрытые заданным экспертом от всех остальных) и параметры для расчета АТР. В цикле мы пробегаем по всем ордерам на предмет положения уже имеющегося СЛ в сравнении с рассчитанным АТР и в случае возможности подтягивания СЛ по АТР в сторону цены, подтягиваем его.
Также в функции реализована возможность расчета АТР для указанного номера бара (а не только для последнего закрытого).
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 64

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения