Предложение: добавить IndicatorCreate в MetaTrader 4

 
  • 44% (17)
  • 21% (8)
  • 36% (14)
Всего проголосовало: 39
 

Не секрет, что MQL4 и MQL5 это один и тот же язык, с разным набором функций. При этом большинство этих функций одинаково работают как в MQL4 так и в MQL5. Различий немного, но они есть и они принципиальны. Это накладывает существенные ограничения на кросплатформенность, переносимость кодов и в конечном счете миграцию пользователей на MetaTrader 5.

Здесь хотелось бы обсудить конкретную несовместимость МТ4 и МТ5, связанную с вызовом индикаторов. в MetaTrader 4 данные индикатора получают через функцию iCustom, либо специализированную функцию с префиксом i, например iMA, получает значения индикатора Movin Average, а iBands - значения индикатора полос Боллинждера. В MetaTrader 5 действуют одноименные функции, но работают они иначе: вместо конкретного значения индикатора, возвращается хендл (ака указатель) на индикатор, которые эти значения может предоставить. Поэтому напрямую совместимости платформ в обработке значений индикаторов нет. В MetaTrader 4 можно использовать значение индикатора сразу, в MetaTrader 5 в советнике дополнительно потребуется описать процедуру копирования данных конкретного буфера этого индикатора.

Что бы решить вопрос кросплатформенности на форуме предлагается следующее:

...
#ifdef __MQL4__
      ValMA[1]=iMA(NULL,PERIOD_CURRENT,14,0,MODE_EMA,PRICE_CLOSE,1);
#endif
#ifdef __MQL5__
      CopyBuffer(ind_handleMA,0,1,2,ValMA);
#endif
...

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

Какая альтернатива может быть предложенному варианту? Можно пойти по пути написания универсального интерфейса индикатора. Т.е. написать некий универсальный класс, который будет создавать любой индикатор:

//+------------------------------------------------------------------+
//| Базовый класс индикатора                                         |
//+------------------------------------------------------------------+
class CUnIndicator
{
private:
   MqlParam m_params[];
   int      m_params_count;
   int      m_current_buffer;
   int      m_handle;
   static   CLog*    Log;
   bool     m_invalid_handle;
public:
            CUnIndicator(void);
            CUnIndicator(string ind_name);
   void     SetBuffer(int index);
   template <typename T>
   bool     SetParameter(T value);
   int      Create(string symbol, ENUM_TIMEFRAMES period, string name = NULL);
   int      Create(string symbol, ENUM_TIMEFRAMES period, string name, const MqlParam& params[]);
   void     CreateOnHandle(int handle);
   void     IndicatorRelease(void);
   double   operator[](int index);
   double   operator[](datetime time);
};

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

   ...
   // Create indicator MACD
   CUnIndicator MACD;
   MACD.SetParameter(10);           // Fast EMA
   MACD.SetParameter(13);           // Slow EMA
   MACD.SetParameter(8);            // Signal MA
   MACD.SetParameter(PRICE_CLOSE);  // Type Price
   MACD.Create("EURUSD"PERIOD_M1);
   // Work with indicator MACD
   MACD.SetBuffer(0);               // Set fast ema buffer
   double fast_ema = MACD[0];       // Get fast ema
   MACD.SetBuffer(1);               // Set slow ema buffer
   double fast_ema = MACD[0];       // Get slow ema
   // Release Indicator
   MACD.IndicatorRelease();
   ...

Что это означает на практике? То что мы избавились от платформозависимой компоненты. Этот код платформонезависим, и будет компилироваться в обоих платформах. Но не все так просто. В MetaTrader 4 нет возможности создать универсальный индикатор. Вместо этого, еще на этапе компиляции нужно точно сконфигурировать функцию iCustom. Сама она содержит переменный набор параметров. Но в MQL нет возможности создавать свои пользовательские функции с произвольным набором параметров.

Проблему решило бы добавление функции IndicatorCreate и соответствующей структуры MqlParam. При этом не изменяя формату МТ4, данная функция вполне может возвращать конкретное значение индикатора:

double  IndicatorCreate
   string           symbol,                            // имя символа 
   ENUM_TIMEFRAMES  period,                            // период 
   ENUM_INDICATOR   indicator_type,                    // тип индикатора из перечисления ENUM_INDICATOR 
   int              parameters_cnt=0,                  // количество параметров 
   const MqlParam&  parameters_array[]=NULL,           // массив параметров 
   int              mode;                              // источник данных
   int              shift;                             // сдвиг

   );

 

Что даст такой вариант вызова пользователям:

  1. Платформонезависимость и универсальность. Будет возможно создать универсальный код для МТ4 и МТ5 работающий с одним единственным IndicatorCreate, вместо непараметризированным iCustom.
  2. Нет ограничений на количество передаваемых параметров. Сейчас оно составляет 64 параметра. Это кажется больше чем достаточно, но это не так. Например, некоторые индикаторы, продаваемые в Маркете имеют больше 64 параметров, что делает их невозможным для тестирования в экспертах (!).
  3. Можно создавать программы определенных типов. Например, можно сделать панель, которая бы показывала бы сигналы пользовательских индикаторов в виде значков. Для ее работы достаточно было бы указать шаблон, с описанием того, какие индикаторы с какими параметрами необходимо загрузить.

Вот несколько ссылок по теме: 

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

Как можно легко писать программы работающие в MT4 и в MT5 кроссплатформенный код , стимул изучать ООП

Yuriy Zaytsev, 2017.01.26 11:59

Были кончено не спорю, но это был мизер в сравнении с потоком заказов на mql4,  он и сейчас меньше.


Зато сейчас я уговариваю клиентов переходить на мт5  , некоторые соглашаются менять платформу.  Разницы  между платформами уже нет,  при том  еще и  MQL4 MQL5  прекрасно идут друг другу навстречу сливаясь в одно единое.  Разница минимальна, а применяя ООП можно легко писать эксперта прекрасно работающего на обоих платформах. 

Достаточно влепить

// к примеру
   CTrade            trade;
...
dBid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
dAsk = SymbolInfoDouble(_Symbol,SYMBOL_ASK);


   trade.Sell(0.1,_Symbol,dBid ,dAsk +0.0020,dBid -0.0010,""); // и в MQL5 и MQL4 работает

с индикаторами примерно так
...
#ifdef __MQL4__
      ValMA[1]=iMA(NULL,PERIOD_CURRENT,14,0,MODE_EMA,PRICE_CLOSE,1);
#endif
#ifdef __MQL5__
      CopyBuffer(ind_handleMA,0,1,2,ValMA);
#endif
...

и все чудесно работает на обоих платформах

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

Еще о кроссплатформенном коде. Вызов индикатора

Dmitry Fedoseev, 2017.01.26 14:43

Классы для вызова iMA:

//+------------------------------------------------------------------+
//|                                                     CMT45_MA.mqh |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"

class CMT45_IndMA{
   protected:
      int m_handle;
      //---
      int m_period;
      int m_shift;
      ENUM_MA_METHOD m_method;
      ENUM_APPLIED_PRICE m_price;  
   public:
   virtual bool Value(double & val,CMT45_IndMA * & z,int shift){
      return(true);
   }
   void SetHandle(int h,int period,int shift,ENUM_MA_METHOD method,ENUM_APPLIED_PRICE price){
      m_handle=h;
      m_period=period;
      m_shift=shift;
      m_method=method;
      m_price=price;        
   }
};

...

Использование:

#include <CMT45_MA.mqh>

CMT45_MA ma(15,0,MODE_SMA,PRICE_CLOSE);

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){

  
   Alert("== Start ==");
  
   double v=0;
   if(ma.Value(v,0)){
      Alert("v1=",v);
   }
   else{
      Alert("er1");
   }

   if(ma.Value(v,0)){
      Alert("v2=",v);
   }
   else{
      Alert("er2");
   }


}
//+------------------------------------------------------------------+

От необходимости загружать индикатор удалось избавиться, но все равно надо объект создавать. Параметры МА передаются в конструктор при создании объекта.

Из-за того, что в МТ5 надо проверять результаты загрузки индикатора и результаты работы CopyBufer()  то получилось скорее МТ4 подогнать под МТ5, а не наоборот. Разве что в МТ4 можно не проверять результаты вызова ma.Value(). Значение индикатора возвращается по ссылке в переменной v. Что касается МТ4 - ведь проще один раз создать объект с передачей ему параметров, а потом обращаться к методу объекта передавая ему всего два параметра (переменную для значения и шифт).

Но стоит ли этим пользоваться... вот вопрос... 

---

Сварганил все это на скоряк, так что, если какие ошибочки, извиняйте. 


Даже есть вот такой вариант советника:

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

...

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

iCustom функция

Алексей Тарабанов, 2015.05.19 21:26

Алексей Тарабанов:
Vasyl Nosal:

Какое количество параметров максимальное можно передавать через iCustom?

64? Почему? 

Так сложилось.  

 Ну в общем довольно много инфы, если присмотреться.

 
Можно навелосипедить, но очень жесткое ограничение -- не больше 8 параметров
 
Хоть я и проголосовал "нужна", но что-то сомневаюсь что обратят на это внимание. Да и кроссплатформенный код не что иное как забава. По-любому МТ4 загонят в ...
 
Комбинатор:
Можно навелосипедить, но очень жесткое ограничение -- не больше 8 параметров
Не соображу даже на восемь параметров. Подсказку в студию) 
 
Vasiliy Sokolov:
Не соображу даже на восемь параметров. Подсказку в студию) 

шаблоны и много мороки. для пользователя оно будет выглядеть как конфетка, внутри будет ад. Хотя нет, даже не ад, просто много кода.

Если тема ничем не закончится, скорее всего напишу и выложу.

 
Василий, при всём уважении, не туда копаете. МТ4 скоро не будет. И MQ не будет ничего дополнять, улучшать и расширять. Короче, бесперспективно...
 
В СД пробовал?
 
Dennis Kirichenko:
Василий, при всём уважении, не туда копаете. МТ4 скоро не будет. И MQ не будет ничего дополнять, улучшать и расширять. Короче, бесперспективно...
Копаю туда, где можно заработать (извиняюсь за меркантелизм). А заработать можно пока только на МТ4. Работать в Маркете в сегменте MetaTrader 5 - экономическое самоубийство.
 
Комбинатор:
В СД пробовал?
Пока нет. По результатам обсуждения накатаю заявку. Но думаю действительно будет глухо.
 
Комбинатор:
Можно навелосипедить, но очень жесткое ограничение -- не больше 8 параметров

Я такую штуку велосипедил для iCustom (проблемы там те же, что будут и с затычкой IndicatorCreate). Генерил исходники шаблонного класса с методами вроде следующего (для случая 2-х параметров):

    double CallCustom2(int buffer, int bar)
    {
      switch(mask)
      {
        case 0:
          return iCustom(symbol, tf, indicator, params[0].getValue(), params[1].getValue(), buffer, bar);
        case 1:
          return iCustom(symbol, tf, indicator, params[0].getString(), params[1].getValue(), buffer, bar);
        case 2:
          return iCustom(symbol, tf, indicator, params[0].getValue(), params[1].getString(), buffer, bar);
        case 3:
          return iCustom(symbol, tf, indicator, params[0].getString(), params[1].getString(), buffer, bar);
      }
      return EMPTY_VALUE;
    }

Основная проблема в разделении параметров по типам на строковые и числовые (все взаимно преобразуемые). Ограничения в 8 параметров нет. Но проявляется косвенное ограничение на размер кода - при увеличении параметров скомпилированный индюк весит неподъемно и вешает терминал.

Причина обращения: