English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Перенос индикаторов из MQL4 в MQL5

Перенос индикаторов из MQL4 в MQL5

MetaTrader 5Примеры | 21 июля 2010, 21:22
11 990 2
Vasily
Vasily

Введение

Доброго дня, дорогие читатели!

В сегодняшней статье я предоставлю вам алгоритм переноса простейших ценовых расчетов с MQL4 на MQL5. С учетом отличий MQL5 от MQL4, добавлена библиотека функций mql4_2_mql5.mqh, которой мы научимся пользоваться после прочтения этой статьи.

1. Подготовка индикатора к переносу

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

Для начала нужно подготовить mql4-код для переноса. Рассмотрим, что для этого нужно сделать.

Открываем редактор MetaEditor 4 с необходимым индикатором, например, MACD,  и начинаем редактировать входные параметры:

//---- indicator parameters
extern int FastEMA=12;
extern int SlowEMA=26;
extern int SignalSMA=9;
//---- indicator buffers
double     MacdBuffer[];
double     SignalBuffer[];

нам нужно привести это всё к виду:

double &MacdBuffer[],double &SignalBuffer[],int FastEMA,int SlowEMA,int SignalSMA

Cначала в строчке идут буферы индикатора с добавлением символа & перед названием буфера, так как нам нужно передать ссылки на массив, в котором будут происходить все изменения, но не сам массив!!!

Далее входные параметры. В нашем mql4-индикаторе заменяем строчку:

int start()

на

int start(int rates_total,
         int prev_calculated,
         double &MacdBuffer[],
         double &SignalBuffer[],
         int FastEMA,
         int SlowEMA,
         int SignalSMA)

Как мы видим, добавились ещё 2 обязательных элемента:

int rates_total, int prev_calculated,

Дальнейшая часть представляет ранее сформированную нами строчку.

Теперь копируем весь блок до последнего символа.

//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
int start(int rates_total
         ,int prev_calculated
         ,double &MacdBuffer[]
         ,double &SignalBuffer[]
         ,int FastEMA
         ,int SlowEMA
         ,int SignalSMA)
  {
   int limit;
   int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- macd counted in the 1-st buffer
   for(int i=0; i<limit; i++)
      MacdBuffer[i]=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i)
                     -iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_CLOSE,i);
//---- signal line counted in the 2-nd buffer
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArray(MacdBuffer,Bars,SignalSMA,0,MODE_SMA,i);
//---- done
   return(0);
  }
//+------------------------------------------------------------------

2. Создание шаблона MQL5 для MQL4 программ

Теперь нам необходимо подготовить среду для нашего блока.

Для этого в редакторе MetaEditor 5 выбираем пункт меню "Создать...", далее выбираем "Пользовательский индикатор".

Входные параметры (рис.1) создаём согласно входным параметрам mql4-индикатора:

//---- indicator parameters
extern int FastEMA=12;
extern int SlowEMA=26;
extern int SignalSMA=9;

Рисунок 1. Входные параметры MACD_MQL4

Рисунок 1. Входные параметры индикатора MACD

Далее создаём индикаторные буферы (рис. 2) согласно записям о них в mql4-программе:

//---- indicator buffers
double     MacdBuffer[];
double     SignalBuffer[];

Рисунок 2. Индикаторные буферы MACD

У нас сформировался шаблон для нашего нового индикатора.

В нем необходимо сделать модификации: добавить строчки выше входных параметров

#include <mql4_2_mql5.mqh>
//--- input parameters

внести в функцию:

int OnInit()

строчку

    InitMql4();
и добавить в теле программы строку, которая отвечает за запуск среды для mql4 программ:
int bars=MQL4Run(rates_total,prev_calculated);
// bars - количество баров, доступных mql4 программам

Как видим данная функция вернёт нам количество баров, доступных для MQL4 среды, также здесь появляется новая переменная 

int CountedMQL4;

эта переменая является аналогом mql5-переменной

 prev_calculated,

Переменная CountedMQL4 обьявлена в подключаемом файле и передаёт количество рассчитанных данных.

Далее вставляем наш обработанный блок mql4 в сформированный шаблон на mql5 после последнего символа.

Теперь нам необходимо запустить наш индикатор.

Для этого в теле программы нужно добавить строчку:

Start(bars,
      CountedMQL4,
      MacdBuffer,
      SignalBuffer,
      FastEMA,
      SlowEMA,
      SignalSMA);

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

Должно получиться вот так:

//+------------------------------------------------------------------+
//|                                                     MACD_MQ4.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot MacdBuffer
#property indicator_label1  "MacdBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot SignalBuffer
#property indicator_label2  "SignalBuffer"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- input parameters
#include <mql4_2_mql5.mqh>
input int      FastEMA=12;
input int      SlowEMA=26;
input int      SignalSMA=9;
//--- indicator buffers
double         MacdBuffer[];
double         SignalBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
//---
   InitMql4();
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
//---
int bars=MQL4Run(rates_total,prev_calculated);
// bars - количество баров доступных mql4 программам

   Start(bars,
         CountedMQL4,
         MacdBuffer,
         SignalBuffer,
         FastEMA,
         SlowEMA,
         SignalSMA);//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
int Start(int rates_total,
         int prev_calculated,
         double &MacdBuffer[],
         double &SignalBuffer[],
         int FastEMA,
         int SlowEMA,
         int SignalSMA)
  {
   int limit;
   int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- macd counted in the 1-st buffer
   for(int i=0; i<limit; i++)
      MacdBuffer[i]=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i)
                       -iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_CLOSE,i);
//---- signal line counted in the 2-nd buffer
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArray(MacdBuffer,Bars,SignalSMA,0,MODE_SMA,i);
//---- done
   return(0);
  }

это только первая часть переноса, теперь приступаем к отладке индикатора.

3. Особенности работы с индикаторными буферами в MQL5

Так как многие предопределенные переменные языка MQL4 совпадают с именами предопределенных переменных в MQL5, необходимо совершить следующие замены в переносимом блоке MQL4:

MQL4
MQL5
IndicatorCounted()
prev_calculated
 Bars  rates_total
 iMA(  iMAMql4(
 iMAOnArray(  iMAOnArrayMql4(

//+--------------------+------------------+
//|              MQL4  | MQL5             |
//+--------------------+------------------+
//|IndicatorCounted()  | prev_calculated  |
//|              Bars  | rates_total      |
//|              iMA(  | iMAMql4(         |
//|       iMAOnArray(  | iMAOnArrayMql4(  |
//+--------------------+------------------+ 

По поводу особенностей организации хранения данных в MQL5 в справке к SetIndexBuffer() указано:

Примечание

После связывания динамический массив buffer[]  будет иметь индексацию как в обычных массивах, даже если для связываемого массива будет предварительно установлена индексация как в таймсериях. Если необходимо изменить порядок доступа к элементам индикаторного массива, необходимо применить функцию ArraySetAsSeries() после связывания массива функцией SetIndexBuffer().

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

   ArraySetAsSeries(MacdBuffer,true);
   ArraySetAsSeries(SignalBuffer,true);

В результате у нас получается вот такой код:

//+------------------------------------------------------------------+
//|                                                    MACD_MQL4.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot MacdBuffer
#property indicator_label1  "MacdBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot SignalBuffer
#property indicator_label2  "SignalBuffer"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#include <mql4_2_mql5.mqh>
//--- input parameters
input int      FastEMA=12;
input int      SlowEMA=26;
input int      SignalSMA=9;
//--- indicator buffers
double         MacdBuffer[];
double         SignalBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
//---   
   InitMql4();
//---
   ArraySetAsSeries(MacdBuffer,true);
   ArraySetAsSeries(SignalBuffer,true);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int bars=MQL4Run(rates_total,prev_calculated);
// bars - количество баров, доступных mql4 программам   
   Start(bars,
         CountedMQL4,
         MacdBuffer,
         SignalBuffer,
         FastEMA,
         SlowEMA,
         SignalSMA);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
//+--------------------+------------------+
//|              MQL4  | MQL5             |
//+--------------------+------------------+
//|IndicatorCounted()  | prev_calculated  |
//|              Bars  | rates_total      |
//|              iMA(  | iMAMql4(         |
//|       iMAOnArray(  | iMAOnArrayMql4(  |
//+--------------------+------------------+ 
int Start(int rates_total,
         int prev_calculated,
         double &MacdBuffer[],
         double &SignalBuffer[],
         int FastEMA,
         int SlowEMA,
         int SignalSMA)
  {
   int limit;
   int counted_bars=prev_calculated;
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=rates_total-counted_bars;
//---- macd counted in the 1-st buffer
   for(int i=0; i<limit; i++)
      MacdBuffer[i]=iMAMql4(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i)
                    -iMAMql4(NULL,0,SlowEMA,0,MODE_EMA,PRICE_CLOSE,i);
//---- signal line counted in the 2-nd buffer
   for(int i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArrayMql4(MacdBuffer,rates_total,SignalSMA,0,MODE_SMA,i);
//---- done
   return(0);
  }
//+------------------------------------------------------------------+

Результат его выполнения приведен на рис. 3:

Рисунок 3. Сравнение индикатора MACD, переписанного с MQL4 и стандартного индикатора MACD в MQL5.


4. Пример перенесения индикатора Stochastic

Создадим в MetaEditor 5 новый шаблон для нашего индикатора (рис. 4-5):

Рисунок 4. Входные параметры

Рисунок 5. Буферы

В процессе отладки выяснилось, что необходимо перенести внутрь функции start некоторые расчеты из функции "OnInit" mql4 простым копированием:

int draw_begin1=KPeriod+Slowing;
int draw_begin2=draw_begin1+DPeriod;
Также необходи изменить количество буферов прорисовки, так как в нашей mql4 программе 2 буфера используется для внутренних расчетов и 2 - для отрисовки:
#property indicator_plots   2

И статус буферов, которые будет использовать наша mql4 программа для внутренних расчетов:

   SetIndexBuffer(2,HighesBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,LowesBuffer,INDICATOR_CALCULATIONS);
Проведем необходимые замены:
//+------------------------------------------------------------------+
//|                                              Stochastic_MQL4.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 4
#property indicator_plots   2
//--- plot MainBuffer
#property indicator_label1  "MainBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot SignalBuffer
#property indicator_label2  "SignalBuffer"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#include <mql4_2_mql5.mqh>
//--- input parameters
input int      Kperiod=14;
input int      Dperiod=5;
input int      Slowing=5;
//--- indicator buffers
double         MainBuffer[];
double         SignalBuffer[];
double         HighesBuffer[];
double         LowesBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MainBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,HighesBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,LowesBuffer,INDICATOR_CALCULATIONS);
//---
    InitMql4();
//---
   ArraySetAsSeries(MainBuffer,true);
   ArraySetAsSeries(SignalBuffer,true);
   ArraySetAsSeries(HighesBuffer,true);
   ArraySetAsSeries(LowesBuffer,true);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int bars=MQL4Run(rates_total,prev_calculated);
// bars - количество баров, доступных mql4-программам
   start(bars,
         CountedMQL4,
         MainBuffer,
         SignalBuffer,
         HighesBuffer,
         LowesBuffer,
         Kperiod,
         Dperiod,
         Slowing);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+--------------------+------------------+
//|              MQL4  | MQL5             |
//+--------------------+------------------+
//|IndicatorCounted()  | prev_calculated  |
//|              Bars  | rates_total      |
//|              iMA(  | iMAMql4(         |
//|       iMAOnArray(  | iMAOnArrayMql4(  |
//+--------------------+------------------+ 
int start(int rates_total,
          int prev_calculated,
          double &MainBuffer[],
          double &SignalBuffer[],
          double &HighesBuffer[],
          double &LowesBuffer[],
          int KPeriod,
          int DPeriod,
          int Slowing)
  {
   int draw_begin1=KPeriod+Slowing;
   int draw_begin2=draw_begin1+DPeriod;
   int    i,k;
   int    counted_bars=prev_calculated;
   double price;
//----
   if(rates_total<=draw_begin2) return(0);
//---- initial zero
   if(counted_bars<1)
     {
      for(i=1;i<=draw_begin1;i++) MainBuffer[rates_total-i]=0;
      for(i=1;i<=draw_begin2;i++) SignalBuffer[rates_total-i]=0;
     }
//---- minimums counting
   i=rates_total-KPeriod;
   if(counted_bars>KPeriod) i=rates_total-counted_bars-1;
   while(i>=0)
     {
      double min=1000000;
      k=i+KPeriod-1;
      while(k>=i)
        {
         price=Low[k];
         if(min>price) min=price;
         k--;
        }
      LowesBuffer[i]=min;
      i--;
     }
//---- maximums counting
   i=rates_total-KPeriod;
   if(counted_bars>KPeriod) i=rates_total-counted_bars-1;
   while(i>=0)
     {
      double max=-1000000;
      k=i+KPeriod-1;
      while(k>=i)
        {
         price=High[k];
         if(max<price) max=price;
         k--;
        }
      HighesBuffer[i]=max;
      i--;
     }
//---- %K line
   i=rates_total-draw_begin1;
   if(counted_bars>draw_begin1) i=rates_total-counted_bars-1;
   while(i>=0)
     {
      double sumlow=0.0;
      double sumhigh=0.0;
      for(k=(i+Slowing-1);k>=i;k--)
        {
         sumlow+=Close[k]-LowesBuffer[k];
         sumhigh+=HighesBuffer[k]-LowesBuffer[k];
        }
      if(sumhigh==0.0) MainBuffer[i]=100.0;
      else MainBuffer[i]=sumlow/sumhigh*100;
      i--;
     }
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   int limit=rates_total-counted_bars;
//---- signal line is simple moving average
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArrayMql4(MainBuffer,rates_total,DPeriod,0,MODE_SMA,i);
//----
   return(0);
  }
//+------------------------------------------------------------------+

В результате получили полноценный стохастик на MQL5 с ценовыми конструкциями MQL4.

Результат его работы представлен на рис. 6:


Рисунок 6. Сравнение индикатора Stochastic, переписанного с MQL4 и стандартного индикатора Stochastic в MQL5.

5. Пример перенесения индикатора RSI

Соберём информацию о нашем индикаторе:
//---- input parameters
extern int RSIPeriod=14;
//---- buffers
double RSIBuffer[];
double PosBuffer[];
double NegBuffer[];

И создадим в MetaEditor 5 его шаблон (рис. 7-8).

Рисунок 7. Входной параметр индикатора RSI

Рисунок 8. Буферы индикатора RSI

Общее количество буферов - 3:

#property indicator_buffers 3

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

#property indicator_plots   1

Задаем статус расчетных буферов:

   SetIndexBuffer(1,PosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,NegBuffer,INDICATOR_CALCULATIONS)

Cкомпонуем и проведем необходимые замены:

//+------------------------------------------------------------------+
//|                                                     RSI_MQL4.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1
//--- plot RSIBuffer
#property indicator_label1  "RSIBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Green
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot PosBuffer
#property indicator_label2  "PosBuffer"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot NegBuffer
#property indicator_label3  "NegBuffer"
#property indicator_type3   DRAW_LINE
#property indicator_color3  Red
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

#include <mql4_2_mql5.mqh>
//--- input parameters
input int      RSIPeriod=14;
//--- indicator buffers
double         RSIBuffer[];
double         PosBuffer[];
double         NegBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,RSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,PosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,NegBuffer,INDICATOR_CALCULATIONS);
//---
   InitMql4(3);

   ArraySetAsSeries(RSIBuffer,true);
   ArraySetAsSeries(PosBuffer,true);
   ArraySetAsSeries(NegBuffer,true);

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int bars=MQL4Run(rates_total,prev_calculated);
// bars - количество баров, доступных mql4 программам
   RSImql4(bars,
           CountedMQL4,
           RSIBuffer,
           PosBuffer,
           NegBuffer,
           RSIPeriod);
   return(rates_total);
  }
//+--------------------+------------------+
//|              MQL4  | MQL5             |
//+--------------------+------------------+
//|IndicatorCounted()  | prev_calculated  |
//|              Bars  | rates_total      |
//|              iMA(  | iMAMql4(         |
//|       iMAOnArray(  | iMAOnArrayMql4(  |
//+--------------------+------------------+ 
int RSImql4(int rates_total,
            int prev_calculated,
            double &RSIBuffer[],
            double &PosBuffer[],
            double &NegBuffer[],
            int RSIPeriod)
  {
   int    i,counted_bars=prev_calculated;
   double rel,negative,positive;
//----fd
   if(rates_total<=RSIPeriod) return(0);
//---- initial zero
   if(counted_bars<1)
      for(i=1;i<=RSIPeriod;i++) RSIBuffer[rates_total-i]=0.0;
//----
   i=rates_total-RSIPeriod-1;
   if(counted_bars>=RSIPeriod) i=rates_total-counted_bars-1;
   while(i>=0)
     {
      double sumn=0.0,sump=0.0;
      if(i==rates_total-RSIPeriod-1)
        {
         int k=rates_total-2;
         //---- initial accumulation
         while(k>=i)
           {
            rel=Close[k]-Close[k+1];
            if(rel>0) sump+=rel;
            else      sumn-=rel;
            k--;
           }
         positive=sump/RSIPeriod;
         negative=sumn/RSIPeriod;
        }
      else
        {
         //---- smoothed moving average
         rel=Close[i]-Close[i+1];
         if(rel>0) sump=rel;
         else      sumn=-rel;
         positive=(PosBuffer[i+1]*(RSIPeriod-1)+sump)/RSIPeriod;
         negative=(NegBuffer[i+1]*(RSIPeriod-1)+sumn)/RSIPeriod;
        }
      PosBuffer[i]=positive;
      NegBuffer[i]=negative;
      if(negative==0.0) RSIBuffer[i]=0.0;
      else RSIBuffer[i]=100.0-100.0/(1+positive/negative);
      i--;
     }
//----
   return(0);
  }
//+------------------------------------------------------------------+

Здесь, в отличие от предыдущего индикатора, заменили название: теперь вместо привычной функции int Start() в MQL4

int start()
  {

в MQL5 мы используем

int RSImql4(

Переименованы как имя самой функции, так и строка, вызывающая ее, в теле MQL5-программы.

Результат работы библиотечки приведен на рис. 9.


Рисунок 9. Сравнение индикатора RSIc, переписанного с MQL4 и стандартного индикатора RSI в MQL5.

6. Установка

Для установки данного модуля необходимо поместить файл mql4_2_mql5.mqh в папку MQL5\Include\.

Тестовые файлы поместить в папку MQL5\Indicators.

7. Дополнение

При желании можно расширить функционал модуля путем подключения библиотеки из статьи Переход с MQL4 на MQL5. Добавьте файл InitMQL4.mqh из этой статьи в каталог MQL5\Include и следующие строчки перед входными параметрами:

#include <InitMQL4.mqh>

Cо списком необходимых замен вы можете ознакомится в статье Переход с MQL4 на MQL5.

Заключение

В данной статье представлен алгоритм переноса простейших ценовых конструкций из MQL4 в среду MQL5 с использованием специальной библиотеки mql4_2_mql5.mqh.

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

Учитывая особенности доступа к данным в среде MQL5, пересчет индикаторов может занять некоторое время, поскольку приходится создавать и пересчитывать необходимые данные для программ из среды MQL4. Для полноценного переноса индикатора в среду MQL5 его стоит переписать с учетом особенностей хранения и доступа к данным среды MQL5.

Post Scriptum

Прошу обратить внимание на фразу: "Учитывая особенности доступа к данным в среде mql5 пересчет индикаторов может занять некоторое время, поскольку приходиться создавать и пересчитывать необходимые данные для программ из среды mql4.". Иногда такое ожидание может занять до нескольких секунд (см. рис. 10-11):

  

Рисунок 10. Данные не просчитались                                                                                                  Рисунок 11. Данные доступны

Это связано с особенностью терминала MetaTrader 5, которая проявляется в том, что при создании хендла индикатора в кеше терминала создается расчетная часть только в одном экземпляре.  Если такого индикатора в кеше терминала еще нет (с такими входными параметрами), вызов 

iMA(Symb,TimFram,iMAPeriod,ma_shift,ma_method,applied_price);

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

Соответственно, расчет индикатора будет произведен только один раз, и не сразу после того, как создан хендл индикатора.

Прикрепленные файлы |
rsi_mql4.mq5 (4.77 KB)
macd_mql4__1.mq5 (4.07 KB)
mql4_2_mql5.mqh (16.44 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (2)
Serge
Serge | 31 июл. 2013 в 16:00

Видимо опечатка:

int CountedMQL4;
эта переменая является аналогом mql4-переменной
prev_calculated,

Следует читать аналогом mql5-переменной

Rashid Umarov
Rashid Umarov | 1 авг. 2013 в 14:31
Спасибо, исправили.
Оптимальный метод подсчета объема совокупной позиции по заданному магическому номеру Оптимальный метод подсчета объема совокупной позиции по заданному магическому номеру
В статье рассматривается проблема необходимости подсчета совокупной позиции по заданному символу и магическому номеру. Предложенный метод подсчета объема позиции в процессе работы загружает только минимально необходимую часть истории сделок. В процессе же самой работы обработка происходит только по последним сделкам. Дополнительно рассматривается метод формирования уникальных имен глобальных переменных.
Как написать индикатор на основе другого индикатора Как написать индикатор на основе другого индикатора
На MQL5 можно не только создать новый пользовательский индикатор с чистого листа, но и написать индикатор на базе другого, уже существующего индикатора, встроенного в терминал или пользовательского. И тут существует два способа: первый - доработать индикатор, добавить к нему новые вычисления и графические стили, второй - использовать встроенный в терминал индикатор или существующий пользовательский индикатор при помощи функций iCustom() или IndicatorCreate().
Конкурс советников внутри советника Конкурс советников внутри советника
С помощью виртуальной торговли можно создать адаптивный советник, который будет выполнять включение/отключение сделок на реальном рынке. Соберите несколько стратегий в одном эксперте! Ваш мультисистемный советник будет автоматически выбирать торговую стратегию, которой стоит торговать на реальном рынке по результатам успешности виртуальных сделок. Такой метод позволяет снизить просадку и увеличить прибыльность Вашей работы на рынке. Экспериментируйте и делитесь результатами с другими! Думаю, будет интересно многим узнать о вашем портфеле стратегий.
Исследование быстродействия скользящих средних в MQL5 Исследование быстродействия скользящих средних в MQL5
Со времён создания первого индикатора простой скользящей средней появилась масса разнообразных индикаторов. Многие из них построены именно на схожем принципе или используют в своих расчётах те или иные способы обработки ценового ряда. При этом зачастую за бортом остаётся вопрос скорости вычислений таких индикаторов и оптимальности алгоритмов, заложенных в них. В статье рассмотрены все возможные варианты использования скользящих средних и проведён сравнительный анализ быстродействия каждого.