English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Склейка фьючерсов в MetaTrader 5

Склейка фьючерсов в MetaTrader 5

MetaTrader 5Индикаторы | 12 марта 2014, 08:31
6 742 8
Vladimir Karputov
Vladimir Karputov

Введение

В MetaTrader 5 пользователю нельзя создавать собственные графики, так как график может строиться только на основе символов, которые поставляет ваш брокер. В случае с фьючерсами трейдеру для анализа нужен синтетический инструмент – склеенный непрерывный фьючерс. Беда в том, что такую склейку проводит только брокер, а значит, только брокер решает, будет ли он производить склейку по данному символу или нет.

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


Принятые условности:

  1. Все данные и выкладки, а также рисунки и скриншоты в статье основываются на реальных значениях фьючерса на индекс Украинской биржи.
  2. Участки кода, которые были изменены или добавлены в статье будут выделяться цветом. Например:
    //+------------------------------------------------------------------+
    //|                                                       Это пример |
    //|                                            редактированного кода |
    //+------------------------------------------------------------------+

Проблема первая: перекрытие по датам

Соседние фьючерсы торгуются с перекрытием по датам.

То есть, когда до последнего дня исполнения по текущему фьючерсу остаётся ещё около 2 месяцев, следующий фьючерс уже начинает торговаться.

Рис. 1. Перекрытие по датам фьючерсов

Рис. 1. Перекрытие по датам фьючерсов

На рисунке видно, что 2013.09.16 – дата начала обращения следующего фьючерса UX-3.14, хотя в это время еще существует текущий фьючерс UX-12.13.


Проблема вторая: выбираем тип склейки

Склейки бывают следующих типов:

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

Рис. 2. Склейка. Простое добавление.

Рис. 2. Склейка. Простое добавление

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

Рис. 3. Склейка. Добавление со смещением

Рис. 3. Склейка. Добавление со смещением


Необходимые настройки в терминале

В окне «Обзор рынка» следует расположить фьючерсы в порядке убывания:

Рис. 4. Обзор рынка 

Рис. 4. Обзор рынка


Создаём индикатор

По умолчанию индикатор должен находиться в папке terminal_data_folder\MQL5\Indicators. Чтобы не засорять папку ...\Indicators Стандартной библиотеки, а также для дальнейшего удобства синхронизации своих индикаторов с помощью MQL5 Storage, создадим в директории ...\Indicators свою папку MyIndicators и в ней папку Synthetics. Итоговый путь к папке будет выглядеть так: terminal_data_folder\MQL5\Indicators\MyIndicators\Synthetics.

В папке Synthetics создадим новый файл:

Рис. 5. Создаём новый файл индикатора

Рис. 5. Создаём новый файл индикатора

Укажем тип нового файла - "Пользовательский индикатор":

Рис. 3. Тип нового файла - "Пользовательский индикатор" 

Рис. 6. Тип нового файла - "Пользовательский индикатор"

После выбора типа нового файла, следует нажать "Далее" и откроется окно "Общие параметры пользовательского индикатора". В этом окне следует ввести название индикатора - "SYNT", а также добавить два параметра. Первый параметр "Количество фьючерсов для склейки" определяет количество инструментов, которые будут склеиваться. Замечу, что минимально возможное значение параметра "Количество фьючерсов для склейки" равно 2. Второй параметр "Тип склейки" определяет тип склейки в индикаторе по умолчанию - "простое добавление":

Рис. 7. Параметры пользовательского индикатора 

Рис. 7. Параметры пользовательского индикатора

Обратите внимание на параметр "тип склейки": тип склейки может быть "простое добавление" или "добавление со смещением". Но на этапе добавления параметров мы не можем добавить эти два типа склейки списком. Поэтому оставим по умолчанию значение "простое добавление". Возможность видеть выпадающий список типов склейки в свойствах индикатора мы реализуем позже, при написании кода индикатора "SYNT".

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

Рис. 8. Обработчики событий для индикатора 

Рис. 8. Обработчики событий для индикатора

Обратите внимание, в индикаторе "SYNT" будет использоваться функция OnTimer(). В OnTimer() будет организован основной функционал индикатора. Индикатор можно будет прикрепить как на график символа, на котором торговля прекращена (соответственно, на таком символе не будет событий OnCalculate), так и на график символа, по которому торговля активна.

Нажимаем "Далее" и в следующем окне "Параметры отображения пользовательского индикатора" поставим галочку "Индикатор в отдельном окне":

Рис. 9. Выбор опции индикатор в отдельном окне

Рис. 9. Выбор опции "индикатор в отдельном окне"

Нажимаем кнопку "Готово" и у нас появилась заготовка индикатора "SYNT".


Организация выпадающего списка типа склейки

Чтобы список типов склейки можно было видеть как выпадающий список, в параметрах индикатора нужно объявить перечисление ENUM_GLUING_TYPE.

Указанное перечисление объявим в глобальной области в начале блока входных параметров:

#property indicator_separate_window
//+------------------------------------------------------------------+
//|  перечисление способов склейки                                   |
//+------------------------------------------------------------------+
enum ENUM_GLUING_TYPE
  {
   simple_addition,        // простое добавление||simple addition
   addition_with_shift     // добавление со смещением||addition with shift
  };  
//--- input parameters || входные параметры
input ENUM_GLUING_TYPE  gluing_type=simple_addition;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

Сейчас можно проверить, как отображается выпадающий список.

Следует компилировать файл индикатора (F7). Теперь при прикреплении индикатора в параметрах можно увидеть, что выпадающий список работает:

Рис. 10. Теперь в параметрах есть выпадающий список

Рис. 10. Теперь в параметрах есть выпадающий список
 

Добавим описание индикатора, которое будет видно во вкладке "Общие" при первом присоединении индикатора к графику или при изменении свойств индикатора:

#property version   "1.00"
//+------------------------------------------------------------------+
//| version   "1.00": Подкачка истории по таймеру                    |
//+------------------------------------------------------------------+
#property description "Индикатор для склейки нескольких фьючерсов."
#property description "Рисуется в отдельном окне самого молодого фьючерса."
#property description "Для отрисовки использует N первых символов"
#property description "взятых из окна \"Обзор рынка\"."

#property indicator_separate_window 

Стиль построения индикатора - DRAW_COLOR_CANDLES - разноцветные свечи.

Для этого стиля необходимо 4 индикаторных буфера и 1 буфер для хранения индекса цвета. Стиль линии, индикатора - STYLE_SOLID - сплошная линия. Отобразим все это в коде индикатора:

#property description "взятых из окна \"Обзор рынка\"."

//--- indicator settings || настройки индикатора
#property indicator_separate_window
#property indicator_buffers 5 
#property indicator_plots   1
//--- plot Bars || отрисовка баров
#property indicator_label1    "SYNT"
#property indicator_type1     DRAW_COLOR_CANDLES
#property indicator_style1    STYLE_SOLID
#property indicator_width1    1
//+------------------------------------------------------------------+
//|  перечисление способов склейки                                   |
//+------------------------------------------------------------------+

Введём входной параметр "numder_futures_gluing" - количество инструментов для построения. Значение "numder_futures_gluing" по умолчанию равно 2:

//--- input parameters || входные параметры
input int               numder_futures_gluing=2;
input ENUM_GLUING_TYPE  gluing_type=simple_addition;

Объявим 4 индикаторных буфера и 1 буфер для хранения индекса цвета, а также вспомогательный массив LoadHistory[]:

#property indicator_style1    STYLE_SOLID
#property indicator_width1    1
//--- indicator buffers || индикаторные буферы
double            OpenBuffer[];
double            HighBuffer[];
double            LowBuffer[];
double            CloseBuffer[];
double            ColorCandlesColors[];
double            LoadHistory[];
//+------------------------------------------------------------------+
//|  перечисление способов склейки                                   |
//+------------------------------------------------------------------+

Свяжем индикаторные буферы с одномерными динамическими массивами, а также для массивов установим индексацию как в таймсериях:

//--- indicator buffers mapping
//--- связывание индикаторных буферов
   SetIndexBuffer(0,OpenBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,LowBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,CloseBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,ColorCandlesColors,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5,LoadHistory,INDICATOR_CALCULATIONS);
//--- set buffer indexing as timeseries
//--- установим индексацию для буфера как в таймсерии
   ArraySetAsSeries(OpenBuffer,true);
   ArraySetAsSeries(HighBuffer,true);
   ArraySetAsSeries(LowBuffer,true);
   ArraySetAsSeries(CloseBuffer,true);
   ArraySetAsSeries(ColorCandlesColors,true);
//---
   return(INIT_SUCCEEDED);

Для отображения имени индикаторных серий ("Open", "High", "Low" и "Close") в окне "Окно данных" нужна переменная s_symbol:

input int               numder_futures_gluing=2;
input ENUM_GLUING_TYPE  gluing_type=simple_addition;
//--- symbol name
string s_symbol;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

Для работы индикатора также понадобятся переменная shft_array и два флага good_history и indicator_rendered:

input ENUM_GLUING_TYPE  gluing_type=simple_addition;
//--- symbol name
string   s_symbol;
int      shift_array=0;
bool     good_history=false;        // история не подготовлена||history not prepared
bool     indicator_rendered=false;  // индикатор не отрисован
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

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

   ArraySetAsSeries(CloseBuffer,true);
   ArraySetAsSeries(ColorCandlesColors,true);
//--- set accuracy || точность отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS,0);
//--- set drawing line empty value || пустое значение для построения, для которого нет отрисовки
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- set labels for the line || имя для отображения в окне DataWindow
   PlotIndexSetString(0,PLOT_LABEL,s_symbol+" Open;"+s_symbol+" High;"+s_symbol+" Low;"+s_symbol+" Close");
   IndicatorSetString(INDICATOR_SHORTNAME,"SYNT");
//--- set number of colors in color buffer || кол-во цветов в буфере
   PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,9);
//--- set line color || установка цвета линии
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrOrange);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,3,clrGreen);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,4,clrPink);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,5,clrIndigo);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,6,clrPaleVioletRed);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,7,clrDarkViolet);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,8,clrDimGray);
//---
   return(INIT_SUCCEEDED);

Также в функцию инициализации OnInit() добавим инициализацию таймера с периодичностью 3 секунды и инициализацию генератора случайных чисел:

   PlotIndexSetInteger(0,PLOT_LINE_COLOR,7,clrDarkViolet);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,8,clrDimGray);
//---
   EventSetTimer(3);
//--- инициализируем генератор случайных чисел
   MathSrand(GetTickCount());
//---
   return(INIT_SUCCEEDED);

Для операции склейки нужно минимум два символа.

В функции OnCalculate() выполним проверку на количество инструментов, участвующих в склейке:

                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- checking the number of instruments || проверка количества инструментов
   if(numder_futures_gluing<=1)
     {
      //--- сформируем строку сообщения
      string comm=StringFormat("Для работы индикатора необходимо выбрать не менее %d символов",numder_futures_gluing);
      //--- выведем сообщение в комментарий на главное окно графика
      Comment(comm);
      return(0);
     }
//--- return value of prev_calculated for next call
   return(rates_total);

После проверки на достаточное количество символов для склейки проверим, был ли индикатор уже отрисован. Если индикатор уже отрисован, значит из OnCalculate() можно выходить:

      Comment(comm);
      return(0);
     }
   if(indicator_rendered==true) return(rates_total);
//--- return value of prev_calculated for next call
   return(rates_total);

Так как индикатор "SYNT" используется, по большей части, для анализа развития тенденции дневных баров, то считаю, что нет необходимости пересчета на каждом тике. То есть, индикатор "SYNT" не будет пересчитываться на каждом тике.

Более того, пересчитывать индикатор необходимо только в следующих случаях:

  • если это первый запуск индикатора;
  • если произошло изменение в истории (например, была подкачана история).
   if(indicator_rendered==true) return(rates_total);
//--- если это первый запуск вычислений нашего индикатора
//--- или если необходимо рассчитать индикатор для двух или более баров (значит что-то изменилось в истории)
//--- помним, что бар под номером "0" - самый левый
   if(prev_calculated==0 || rates_total>prev_calculated+1)
     {
     }
//--- return value of prev_calculated for next call
   return(rates_total);


Принудительная инициализация индикаторных буферов

Индикаторные буферы индикатора "SYNT" - это связанные динамические массивы.

При первом запуске индикатора такие буферы в обязательном порядке должны быть инициализированы принудительно. Инициализацию нужно проводить в OnCalculate(). Почему в OnCalculate(), а не в OnInit? Пояснение в рисунке ниже:

Рис. 11. Почему инициализация массива именно в OnCalculate

Рис. 11. Почему инициализация массива именно в OnCalculate()

Как видно на рис.11, событие OnCalculate() произойдет в любом случае, тогда как событие OnInit() в случае обновления графика через команду "Обновить" не происходит. Поэтому инициализацию массивов проведем в OnCalculate():

//--- помним, что бар под номером "0" - самый левый
   if(prev_calculated==0 || rates_total>prev_calculated+1)
     {
      //--- инициализируем массивы
      ArrayInitialize(OpenBuffer,0);
      ArrayInitialize(HighBuffer,0);
      ArrayInitialize(LowBuffer,0);
      ArrayInitialize(CloseBuffer,0);
     }
//--- return value of prev_calculated for next call
   return(rates_total);

Функция  ArrayInitialize() выполняет инициализацию индикаторного буфера. В данном случае инициализация идет нулями.

При попытке инициализации индикаторного буфера значением EMPTY_VALUE на индикатор "SYNT" нельзя будет наложить индикаторы.


Алгоритм простого добавления

Рис. 10. Алгоритм простого добавления

Рис. 12. Алгоритм простого добавления

 

Даты на рисунке - это даты начала обращения и даты последнего дня обращения для фьючерсов UX-9.13, UX-12.13 и UX-3.14. Эти же данные в виде таблицы:

СимволНачало обращенияПоследний день обращения
UX-9.132013.03.152013.09.16
UX-12.132013.06.172013.12.16
UX-3.142013.09.162014.03.17

 

На рис. 10 дата 2013.12.25 - это реальная дата на календаре. То есть, символ UX-3.14 еще действует.

Метод склейки "Простое добавление" будет реализован в функции SimpleAddition:

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
  }
//+------------------------------------------------------------------+
//| Simple addition                                                  |
//| Простое добавление. В индикаторный массив добавляем только       |
//| символ sibmUP                                                    |
//+------------------------------------------------------------------+
bool SimpleAddition(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color)
  {
  }
//+------------------------------------------------------------------+

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

Полный код функции SimpleAddition() приведен ниже:

//+------------------------------------------------------------------+
//| Simple addition                                                  |
//| Простое добавление. В индикаторный массив добавляем только       |
//| символ sibmUP                                                    |
//+------------------------------------------------------------------+
bool SimpleAddition(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color)//////
  {
   datetime expiration_time_UP;     // дата окончания обращения символа simbUP
   datetime expiration_time_DOWN;   // дата окончания обращения символа simbDOWN

   expiration_time_UP=int(SymbolInfoInteger(simbUP,SYMBOL_EXPIRATION_TIME));
   if(expiration_time_UP>TimeLocal())
     {
      expiration_time_UP=TimeLocal();
     }
   if(simbDOWN!="")
     {
      expiration_time_DOWN=int(SymbolInfoInteger(simbDOWN,SYMBOL_EXPIRATION_TIME));
     }
   else
     {
      expiration_time_DOWN=int(SymbolInfoInteger(simbUP,SYMBOL_START_TIME));
     }
//--- в массив rates[] будем копировать цены Open, High, Low и Close
   MqlRates rates[];
   ArraySetAsSeries(rates,true);
   int copied=0;           //--- сколько скопировано
   copied=CopyRates(simbUP,period,expiration_time_DOWN,expiration_time_UP,rates);
   if(copied>0)
     {
      for(int j=shift_array;j<shift_array+copied;j++)
        {
         //--- записываем цены в буферы
         OpenBuffer[j]=rates[j-shift_array].open;
         HighBuffer[j]=rates[j-shift_array].high;
         LowBuffer[j]=rates[j-shift_array].low;
         CloseBuffer[j]=rates[j-shift_array].close;
         ColorCandlesColors[j]=Color;
        }
      shift_array=shift_array+copied;
      indicator_rendered=true;
      ChartRedraw();
     }
   else
     {
      Print("Не удалось получить исторические данные по символу ",simbUP);
      indicator_rendered=false;
      return(false);
     }
//---  Simple addition end
   return(true);
  }
//+------------------------------------------------------------------+


Алгоритм добавления со смещением


Рис. 11. Алгоритм склейки добавление со смещением

Рис. 13. Алгоритм склейки добавление со смещением 

Главное отличие от алгоритма простого добавления - склейка начинается за 10 дней до последнего дня обращения символа. Метод склейки "Добавление со смещением" будет реализован в функции AdditionWithShift():

//--- Simple addition end
   return(true);
  }
//+------------------------------------------------------------------+
//| Addition With Shift                                              |
//| Добавление со смещением. В индикаторный массив добавляем только       |
//| символ sibmUP                                                    |
//+------------------------------------------------------------------+
bool AdditionWithShift(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color)
  {
//--- 
   return(true);
  }
//+------------------------------------------------------------------+

Функции AdditionWithShift() отличается от функции SimpleAddition() всего двумя строчками - от дат отнимается 10 дней:

   .
   .
   .
   expiration_time_UP=int(SymbolInfoInteger(simbUP,SYMBOL_EXPIRATION_TIME))-86400*10;
   .
   .
   .
   expiration_time_DOWN=int(SymbolInfoInteger(simbDOWN,SYMBOL_EXPIRATION_TIME))-86400*10;
   .
   .
   .

Из-за такого небольшого отличия в коде я не буду приводить полный код функции AdditionWithShift(), код можно посмотреть в файле индикатора в конце статьи.

Несмотря на такое небольшое отличие в коде функций AdditionWithShift() и SimpleAddition(), лучше их не объединять в одну универсальную функцию (на случай дальнейшего изменения алгоритма или, например, введения проверок).


Предварительная загрузка истории по символам

Функция CheckLoadHistory() выполняет копирование всей истории по символу во вспомогательный буфер tmp_rates.

При удачном копировании флагу good_history присваивается значение true - это значит, что теперь можно отрисовывать индикатор:

//--- Addition With Shift end
   return(true);
  }
//+------------------------------------------------------------------+
//| Request to receive all history from a trade server               |
//| Получение всей истории с торгового сервера                       |
//+------------------------------------------------------------------+
bool CheckLoadHistory(string symbol,ENUM_TIMEFRAMES period)
  {
   MqlRates tmp_rates[];      // в массив rates[] будем копировать цены Open, High, Low и Close
   datetime start_time;       // дата начала торгов по инструменту
   datetime expiration_time;  // дата окончания торгов по инструменту
   start_time=int(SymbolInfoInteger(symbol,SYMBOL_START_TIME));
   expiration_time=int(SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_TIME));
   if(CopyRates(symbol,period,start_time,expiration_time,tmp_rates)>0)
     {
      good_history=true;
     }
   else
     {
      good_history=false;
     }
//--- 
   return(true);
  }
//+------------------------------------------------------------------+

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


OnTimer - основная функция индикатора

Теперь, когда есть код для двух видов склейки и код предварительной загрузки истории, можно изменить функцию OnTimer():

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(indicator_rendered==true) return;
   if(good_history==true)
     {
      int t=0;       // color || цвет
      int number;
      switch(gluing_type)
        {
         case simple_addition:
            for(int n=0;n<numder_futures_gluing;n++)
              {
               //--- получим случайное число
               number=MathRand();
               //--- получим индекс цвета, как остаток от целочисленного деления
               t=number%(PlotIndexGetInteger(0,PLOT_COLOR_INDEXES)-1);
               SimpleAddition(SymbolName(n,true),SymbolName(n+1,true),PERIOD_D1,t);
              }
            break;
         case addition_with_shift:
            for(int n=0;n<numder_futures_gluing;n++)
              {
               //--- получим случайное число
               number=MathRand();
               //--- получим индекс цвета, как остаток от целочисленного деления
               t=number%(PlotIndexGetInteger(0,PLOT_COLOR_INDEXES)-1);
               AdditionWithShift(SymbolName(n,true),SymbolName(n+1,true),PERIOD_D1,t);
              }
            break;
        }
     }
   else
     {
      for(int n=0;n<numder_futures_gluing;n++)
        {
         CheckLoadHistory(SymbolName(n,true),PERIOD_D1);
        }
     }
  }
//+------------------------------------------------------------------+

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


Предварительные результаты работы индикатора "SYNT"

Прикрепив на график два экземпляра индикатора "SYNT" с разными вариантами типа склейки, можно визуально сравнить два метода склейки:

Рис. 12. Сравнение двух методов склейки фьючерсов

  Рис. 14. Сравнение двух методов склейки фьючерсов


Возможность наложить на индикатор другие (стандартные и пользовательские) индикаторы

На индикатор "SYNT" можно прикрепить пользовательские индикаторы, которые имеют первую форму вызова OnCalculate:

int OnCalculate (const int rates_total,      // размер массива price[]
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const int begin,            // откуда начинаются значимые данные
                 const double& price[]       // массив для расчета
   );

Для этого нужно в окне "Навигатор" раскрыть список "Пользовательские индикаторы", далее раскрыть список "Examples" в котором выбрать индикатор и перенести его на "SYNT". Далее во вкладке "Параметры" в выдающем списке выбрать применить к "Данные предыдущего индикатора". 

Список индикаторов, которые можно прикрепить на индикатор "SYNT", и которые корректно работают на индикаторе "SYNT":

Пример индикатора "SYNT", склеившего три фьючерса с наложенным на него индикатором Custom Moving Average:

Рис. 15. Пример склейки трех символов

Рис. 15. Пример склейки трех символов


Заключение

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


Прикрепленные файлы |
synt.mq5 (12.55 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (8)
Valerii Mazurenko
Valerii Mazurenko | 4 мая 2014 в 14:05
forexman77:

То есть возможно ли в одном тесте протестить один график, а потом переключиться на другой и так далее?  

Можно (но это нужно делать самому в коде)
Vladimir Karputov
Vladimir Karputov | 4 мая 2014 в 14:08
forexman77:

Хорошая статья. Не претендую на оригинальность. Но, вот мои мысли: начало и обращение фьючерса всегда волатильно и не отражает реальной картины, где происходят основные объемы.

Не знаю на сколько это возможно. Но, скажу. Что, если задать для каждого фьючерса интервал по датам(где происходит нормальная торговля) и оптимизировать эти участки, как одно целое.

То есть возможно ли в одном тесте протестировать один график, а потом переключиться на другой и так далее?  

Если Вы спрашиваете: "Можно-ли тестировать склейку в тестере стратегий?" - то ответ - нет. Т.е. по простому не получится, так как склейка - это пользовательский индикатор
forexman77
forexman77 | 4 мая 2014 в 14:20
barabashkakvn:
Если Вы спрашиваете: "Можно-ли тестировать склейку в тестере стратегий?" - то ответ - нет. Т.е. по простому не получится, так как склейка - это пользовательский индикатор

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

Мысль про то, что можно задать интервал дат каждого фьючерса и протестировать все на протежении № лет, как единое целое. 

Vladimir Karputov
Vladimir Karputov | 4 мая 2014 в 14:28
forexman77:

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

Мысль про то, что можно задать интервал дат каждого фьючерса и протестировать все на протежении № лет, как единое целое. 

Это называется "тип склейки". Конкретно в статье рассмотрены два типа склейки - "Простое добавление" и "Добавление со смещением".

Andrey Khatimlianskii
Andrey Khatimlianskii | 23 янв. 2021 в 01:52

Уже давно появились кастумные инструменты.

Может, и продукт, генерирующий и обновляющий склейку, есть? Никто не встречал?

На таком инструменте можно было бы и тестировать, и советников запускать (назначая правильный символ для торговли, естественно).

Типичные ошибки в программах на MQL4 и методы их устранения Типичные ошибки в программах на MQL4 и методы их устранения
В старой версии компилятора во избежание критического завершения программ многие ошибки обрабатывались средой исполнения. Например, деление на ноль или выход за пределы массива являются критическими ошибками и обычно приводят к аварийному завершению работы программ. Новый компилятор позволяет обнаружить реальные или потенциальные источники ошибок и повысить качество кода. В этой статье мы рассмотрим возможные ошибки, возникающие при компиляции старых программ и методы их устранения.
Индикатор для построения графика "Ренко" Индикатор для построения графика "Ренко"
В статье рассказывается о графике "Ренко" и приведен один из вариантов его реализации на языке MQL5 в виде индикатора. Индикатор имеет множество модификаций, отличающих его от классического графика. Реализовано построение не только в окне индикатора, но и на главном графике. Кроме того, реализовано представление индикатора в виде линий "ZigZag". Приведено несколько примеров стратегий работы с графиком.
Рецепты MQL5 - Мультивалютный советник и работа с отложенными ордерами на MQL5 Рецепты MQL5 - Мультивалютный советник и работа с отложенными ордерами на MQL5
На этот раз рассмотрим создание мультивалютного советника, торговый алгоритм которого строится на работе с отложенными ордерами Buy Stop и Sell Stop. В статье будут рассмотрены следующие вопросы: торговля в указанном временном диапазоне, установка/модификация/удаление отложенных ордеров, проверка закрытия последней позиции по Тейк Профит или Стоп Лосс, контроль истории сделок на каждом символе.
Видео: Как работают торговые сигналы на платформе MetaTrader Видео: Как работают торговые сигналы на платформе MetaTrader
Короткий видеоролик за 15 минут расскажет и покажет, что такое торговые сигналы, как оформить на них подписку и как самому стать Поставщиком. В видео максимально подробно показаны все особенности нашего сервиса. После внимательного просмотра материала вы сможете самостоятельно подписаться на любой Сигнал из обширной базы или начать продавать собственные сигналы.