Советники: Diff_TF_MA_EA

 

Diff_TF_MA_EA:

Советник на основе индикатора Diff_TF_MA. В основе сигналов советника лежит обычное пересечение двух линий скользящих средних:

  • Если МА с текущего таймфрейма пересекает вверх линию МА старшего таймфрейма, то это сигнал на открытие длинной позиции;
  • Если МА с текущего таймфрейма пересекает вниз линию МА старшего таймфрейма, то это сигнал на открытие короткой позиции.

На одном сигнале открывается одна соответствующая позиция. Противоположная закрывается.

Советник предназначен для работы на счетах с хэджингом. При запуске на неттинговом счете советник выдаст об этом предупреждение и выгрузится.

Сам индикатор для работы советника не требуется - все расчеты скользящих средних сделаны непосредственно в коде советника.

Советник позволяет реверсировать сигналы индикатора - открывать вместо покупок продажи, и наоборот. Так же можно задать стоп лосс и тейк профит в пунктах. При ошибочно заданных размерах стоп лосс или тейк профит советник их автоматически корректирует под минимальный размер StopLevel, установленный для символа.

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

Стоит понимать, что этот советник предназначен для учебных целей.

Советник имеет девять настраиваемых параметров:

  • Experts magic nember - уникальный идентификатор (магик) позиций советника;
  • Period of MA - период расчета скользящей средней старшего таймфрейма (период МА текущего таймфрейма рассчитывается автоматически);
  • Timeframe of MA - таймфрейм скользящей средней старшего таймфрейма;
  • Reverse trade - выбор "реверса" сделок (Yes, No): для Yes при сигнале на открытие длинной позиции будет открываться короткая, и наоборот;
  • Lots - объем открываемых позиций;
  • Stop loss in points - размер StopLoss открываемой позиции в пунктах;
  • Take profit in points - размер TakeProfit открываемой позиции в пунктах;
  • Slippage of price - величина дозволенного проскальзывания цены при открытии позиции;
  • Multiplier spread for stops - число, на которое советник будет умножать спред при расчете корректной дистанции стоп-приказов.
При выставлении стоп лосс или тейк профит (а так же отложенных ордеров) существует минимально разрешенная дистанция установки стоп-приказов - StopLevel. Т.е., стоп лосс или тейк профит (или отложенный ордер) должны быть выставлены не ближе этой дистанции к цене. Если же StopLevel задан нулевым, то, в основном, это не говорит об его отсутствии, а говорит о том, что StopLevel плавающий. В этом случае минимальной дистанцией чаще всего является спред*2, но иногда двойного спреда не достаточно. Поэтому и введен параметр - число, на которое советник будет умножать спред для расчета минимальной дистанции установки стопов.

Для проверки стратегии был проведен тест с настройками по умолчанию на промежутке дат с 2017.01.02 по 2018.01.19. К сожалению, с настройками по умолчанию советник не показал никаких интересных результатов. Поэтому был проведен тест в режиме реверса сделок. Тут результаты были поинтереснее, и была проведена минимальная оптимизация всего одного параметра - Period of MA - в диапазоне от 1 до 20 с шагом 1. Лучшим вариантом при оптимизации на максимальный баланс оказался период 8.

Рис.1 Результат тестирования 2017.01.02 - 2018.01.19, период 8, реверс сделок включен

Рис.2 График тестирования 2017.01.02 - 2018.01.19, период 8, реверс сделок включен

Автор: Scriptor

 

Местами резануло в коде.

//+------------------------------------------------------------------+
//| Returns the name timeframe                                       |
//+------------------------------------------------------------------+
string NameTimeframe(int timeframe=PERIOD_CURRENT)
  {
   if(timeframe==PERIOD_CURRENT) timeframe=Period();
   switch(timeframe)
     {
      case 1      : return "M1";
      case 2      : return "M2";
      case 3      : return "M3";
      case 4      : return "M4";
      case 5      : return "M5";
      case 6      : return "M6";
      case 10     : return "M10";
      case 12     : return "M12";
      case 15     : return "M15";
      case 20     : return "M20";
      case 30     : return "M30";
      case 16385  : return "H1";
      case 16386  : return "H2";
      case 16387  : return "H3";
      case 16388  : return "H4";
      case 16390  : return "H6";
      case 16392  : return "H8";
      case 16396  : return "H12";
      case 16408  : return "D1";
      case 32769  : return "W1";
      case 49153  : return "MN1";
      default     : return (string)(int)Period();
     }
  }
Попробуйте так
string NameTimeframe( const ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT )
{
  return(StringSubstr(EnumToString(timeframe == PERIOD_CURRENT ? Period() : timeframe), 7));
}
 
//+------------------------------------------------------------------+
//| Заполняет массивы тикетов позиций                                |
//+------------------------------------------------------------------+
void FillingListTickets(void)
  {
   list_tickets_buy.Clear();
   list_tickets_sell.Clear();
   total_volume_buy=0;
   total_volume_sell=0;
//---
   int total=PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      ulong ticket=PositionGetTicket(i);
      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
      if(PositionGetInteger(POSITION_MAGIC)!=InpMagic)   continue;
      if(PositionGetString(POSITION_SYMBOL)!=symb)       continue;
      double volume=PositionGetDouble(POSITION_VOLUME);
      if(type==POSITION_TYPE_BUY)
        {
         list_tickets_buy.Add(ticket);
         total_volume_buy+=volume;
        }
      else if(type==POSITION_TYPE_SELL)
        {
         list_tickets_sell.Add(ticket);
         total_volume_sell+=volume;
        }
     }
  }

Нет проверки PositionGetTicket.

"else if" может быть просто "else".

type берется не после continue.

 

В советнике нет отложенных ордеров, поэтому такое

double price=(order_type==ORDER_TYPE_BUY ? symbol_info.Ask() : symbol_info.Bid());

Такое условие корректно только для POSITION_TYPE_BUY.

 
fxsaber:

В советнике нет отложенных ордеров, поэтому такое

Такое условие корректно только для POSITION_TYPE_BUY.

Почему?

Вызов этой функции присутствует в двух местах кода:

   //--- Открытие позиций по сигналам
      if(open_long)
        {
         if(num_s>0) CloseSell();
         if(num_b==0)
           {
            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_BUY,InpStopLoss));
            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_BUY,InpTakeProfit));
            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_BUY);
            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_BUY,ll))
              {
               if(trade.Buy(ll,symb,0,sl,tp))
                  FillingListTickets();
              }
           }
        }
      if(open_short)
        {
         if(num_b>0) CloseBuy();
         if(num_s==0)
           {
            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_SELL,InpStopLoss));
            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_SELL,InpTakeProfit));
            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_SELL);
            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_SELL,ll))
              {
               if(trade.Sell(ll,symb,0,sl,tp))
                  FillingListTickets();
              }
           }
        }

Соответственно, если только сам программист, писавший этот код, сдуру отправит в функцию не тот тип ордера, то да, будет ошибка. В случае этого кода - её не будет.

 
Artyom Trishkin:

Почему?

Вызов этой функции присутствует в двух местах кода:

Соответственно, если только сам программист, писавший этот код, сдуру отправит в функцию не тот тип ордера, то да, будет ошибка. В случае этого кода - её не будет.

Потому что может быть разный взгляд на КБ

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

МТ4 или МТ5. Какие преимущества и недостатки?

Renat Fatkhullin, 2018.01.31 14:28

  1. 4300 программ и 870 экспертов включительно, в исходниках, заведомо достаточно для обучения и развития собственных идей

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

Можно, конечно, сквозь пальцы это пропустить. Но мне видится здесь, что лучше предупредить.

 
fxsaber:

Потому что может быть разный взгляд на КБ


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

Можно, конечно, сквозь пальцы это пропустить. Но мне видится здесь, что лучше предупредить.

Вы правы, предупредить - это верно.
Автор наверняка имел в виду убрать лишние ненужные проверки - в некоторых случаях универсальность - лишнее. Тут наверное вас сбило с толку перечисление ENUM_ORDER_TYPE. Если бы там было ENUM_POSITION_TYPE, то и вопросов бы не возникло.

Равно как и ваше предложение резать текст. Разве switch не быстрее?

 
Artyom Trishkin:

Автор наверняка имел в виду убрать лишние ненужные проверки - в некоторых случаях универсальность - лишнее. Тут наверное вас сбило с толку перечисление ENUM_ORDER_TYPE. Если бы там было ENUM_POSITION_TYPE, то и вопросов бы не возникло.

Здесь и саму функцию и ее вызовы нужно было поправить. Автор еще с MT4 не осознал этого до конца.

Равно как и ваше предложение резать текст. Разве switch не быстрее?

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

 
fxsaber:

Здесь и саму функцию и ее вызовы нужно было поправить. Автор еще с MT4 не осознал этого до конца.

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

Интересно. А в чём по вашему мнению не верность подхода к стандартному расчёту минимальной дистанции установки стоп-приказов?

//+------------------------------------------------------------------+
//| Возвращает корректный StopLoss относительно StopLevel            |
//+------------------------------------------------------------------+
double CorrectStopLoss(const ENUM_ORDER_TYPE order_type,const int stop_loss)
  {
   if(stop_loss==0) return 0;
   double pt=symbol_info.Point();
   double price=(order_type==ORDER_TYPE_BUY ? symbol_info.Ask() : symbol_info.Bid());
   int lv=StopLevel(),dg=symbol_info.Digits();
   return
   (order_type==ORDER_TYPE_BUY ?
    NormalizeDouble(fmin(price-lv*pt,price-stop_loss*pt),dg) :
    NormalizeDouble(fmax(price+lv*pt,price+stop_loss*pt),dg)
    );
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает рассчитанный StopLevel                                |
//+------------------------------------------------------------------+
int StopLevel(void)
  {
   int sp=symbol_info.Spread();
   int lv=symbol_info.StopsLevel();
   return(lv==0 ? sp*size_spread : lv);
  }
//+------------------------------------------------------------------+

Я не вижу тут ошибок. Поясните. И в чём разница расчёта минимальной дистанции для MT4 и МТ5 ?

 

В коде на самом деле есть еще ошибки. Например, хорошо показано, что использовать CSymbolInfo лишь ради СБ-style - зло.

Закрывать позиции через ранее собранный список тикетов - зло. Это очень распространенная ошибка.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

fxsaber, 2018.01.23 09:39

Это неправильная логика. После неудачного и удачного OrderSend должно быть заново полностью считано текущее торговое окружение. Это правило должно действовать всегда.

Насчет кодов возврата. В своих советниках никак не анализирую их. По-моему, торговая логика не должна от них зависеть.

 
Artyom Trishkin:

Интересно. А в чём по вашему мнению не верность подхода к стандартному расчёту минимальной дистанции установки стоп-приказов?

Я не вижу тут ошибок. Поясните. И в чём разница расчёта минимальной дистанции для MT4 и МТ5 ?

Там ошибка в enum-входе и вызове, а не в мин. дистанции. Но и она рассчитывается неверно, потому что

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Советники: Diff_TF_MA_EA

fxsaber, 2018.02.01 21:38

хорошо показано, что использовать CSymbolInfo лишь ради СБ-style - зло.