请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3364747 新帖:11

将指标从 MQL4 迁移到 MQL5

我是小编发表于:4 月 17 日 16:16回复(1)

简介

亲爱的读者们,你们好!

在今天的文章中,我将向你们介绍一个将简单价格计算从 MQL4 迁移到 MQL5 的算法。在快速查看 MQL5 和 MQL4 之间的差异之后,我添加了函数库 mql4_2_mql5.mqh;在读完本文之后,我们将学会如何使用它。

1. 准备要迁移的指标

本文仅仅围绕指标计算的迁移;如果您一个指标包含图形元素或更加复杂的价格计算,则您会遇到困难。

首先,我们需要准备一个要迁移的 MQL4 代码。让我们看一看为此我们需要什么。

打开 MetaEditor 4 及必要的指标,例如 MACD;开始修改其输入参数:

//---- 指标参数
extern int FastEMA=12;
extern int SlowEMA=26;
extern int SignalSMA=9;
//---- 指标缓存
double     MacdBuffer[];
double     SignalBuffer[];

我们需要将它们全部置于以下状态:

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

在代码行的开头指定了指标缓存,并且在它们的名称前面有符号 &。原因在于我们需要传递在其中执行所有变化的数组的链接,而不是数组本身!!!

接着是输入参数。在我们的 MQL4 指标中,将以下代码行:

int start()

改为

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

如您所见,添加了另外两个必需的元素:

int rates_total, int prev_calculated,

下一部分是我们以前生成的代码行。

现在,将整个部分复制到最后一个交易品种。

//+------------------------------------------------------------------
//| 移动平均的收敛/发散指标(MACD)                                       |
//+------------------------------------------------------------------
int start(int rates_total
         ,int prev_calculated
         ,double &MacdBuffer[]
         ,double &SignalBuffer[]
         ,int FastEMA
         ,int SlowEMA
         ,int SignalSMA)
  {
   int limit;
   int counted_bars=IndicatorCounted();
//---- 最近一次计算的柱形将被重算
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- macd的计算结果在第一个指标缓存中
   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);
//---- 信号线的计算结果在第二个指标缓存中
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArray(MacdBuffer,Bars,SignalSMA,0,MODE_SMA,i);
//---- 完成
   return(0);
  
}
//+------------------------------------------------------------------

2. 为 MQL5 程序创建一个 MQL4 模板

现在,我们需要为我们的部分准备环境。

为此,在 MetaEditor 5 中选择菜单项 "New"(新建),然后选择 "Custom indicator"(自定义指标)。

依据 MQL4 指标的输入参数创建输入参数(图 1):

//---- 指标参数
extern int FastEMA=12;
extern int SlowEMA=26;
extern int SignalSMA=9;

MACD 指标的输入参数

图 1. MACD 指标的输入参数

然后,依据在 MQL4 程序中所写的创建指标缓存(图 2):

//---- 指标缓存
double     MacdBuffer[];
double     SignalBuffer[];

MACD 的指标缓存

图 2. MACD 的指标缓存

现在,我们已经为我们的新指标创建了一个模板。

您需要对其进行几处修改。在输入参数上方添加一行:

#include <mql4_2_mql5.mqh>
//--- 输入参数

向函数:

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
//---绘制 MacdBuffer
#property indicator_label1  "MacdBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- 绘制 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 int      FastEMA=12;
input int      SlowEMA=26;
input int      SignalSMA=9;
//--- 指标缓存
double         MacdBuffer[];
double         SignalBuffer[];
//+------------------------------------------------------------------
//| 自定义指标初始化函数                                               |
//+------------------------------------------------------------------
int OnInit()
  {
//--- 指标缓存映射
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
//---
   InitMql4();
//---
   return(0);
  
}
//+------------------------------------------------------------------
//| 自定义指标迭代函数                                                 |
//+------------------------------------------------------------------
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);//--- 返回prev_calculated的值用于下一次调用 
   return(rates_total);
  
}
//+------------------------------------------------------------------
//| 移动平均的收敛/发散指标(MACD)                                       |
//+------------------------------------------------------------------
int Start(int rates_total,
         int prev_calculated,
         double &MacdBuffer[],
         double &SignalBuffer[],
         int FastEMA,
         int SlowEMA,
         int SignalSMA)
  {
   int limit;
   int counted_bars=IndicatorCounted();
//---- 最近一次计算的柱形将被重算
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- macd的计算结果在第一个指标缓存中
   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);
//---- 信号线的计算结果在第二个指标缓存中
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArray(MacdBuffer,Bars,SignalSMA,0,MODE_SMA,i);
//---- 完成
   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[] 将被作为公共数组编制索引,即使为已绑定数组预安装了时间序列的索引。如果您要更改指标数组的存取顺序,在使用 SetIndexBuffer() 函数绑定数组之后使用 ArraySetAsSeries() 函数。

因此,存取指标缓存的初始政策现在与处理普通数组对应,因而您应始终添加绑定:

   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
//---绘制 MacdBuffer
#property indicator_label1  "MacdBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- 绘制 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 int      FastEMA=12;
input int      SlowEMA=26;
input int      SignalSMA=9;
//--- 指标缓存
double         MacdBuffer[];
double         SignalBuffer[];
//+------------------------------------------------------------------
//| 自定义指标初始化函数                                               |
//+------------------------------------------------------------------
int OnInit()
  {
//--- 指标缓存映射
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
//---   
   InitMql4();
//---
   ArraySetAsSeries(MacdBuffer,true);
   ArraySetAsSeries(SignalBuffer,true);
//---
   return(0);
  
}
//+------------------------------------------------------------------
//| 自定义指标迭代函数                                                 |
//+------------------------------------------------------------------
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);
//--- 返回prev_calculated的值用于下一次调用
   return(rates_total);
  
}
//+------------------------------------------------------------------
//| 移动平均的收敛/发散指标(MACD)                                       |
//+------------------------------------------------------------------
//+--------------------+------------------+
//|              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;
//---- 最近一次计算的柱形将被重算
   if(counted_bars>0) counted_bars--;
   limit=rates_total-counted_bars;
//---- macd的计算结果在第一个指标缓存中
   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);
//---- 信号线的计算结果在第二个指标缓存中
   for(int i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArrayMql4(MacdBuffer,rates_total,SignalSMA,0,MODE_SMA,i);
//---- 完成
   return(0);
  
}
//+------------------------------------------------------------------

图 3 显示了执行结果:

图 3. 用 MQL4 重写的 MACD 指标与用 MQL5 写的标准 MACD 指标的比较。


4. 迁移随机动量指标的例子

让我们在 MetaEditor 5 中为我们的指标创建新的模板(图 4-5):

输入参数

图 4. 输入参数

缓存

图 5. 缓存

在调试期间,我们指出应通过简单的复制,将 MQL4 "OnInit" 函数中的几个计算移到 "Start" 函数内:

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
//--- 绘制 MainBuffer
#property indicator_label1  "MainBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- 绘制 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 int      Kperiod=14;
input int      Dperiod=5;
input int      Slowing=5;
//--- 指标缓存
double         MainBuffer[];
double         SignalBuffer[];
double         HighesBuffer[];
double         LowesBuffer[];
//+------------------------------------------------------------------
//| 自定义指标初始化函数                                               |
//+------------------------------------------------------------------
int OnInit()
  {
//--- 指标缓存映射
   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);
  
}
//+------------------------------------------------------------------
//| 自定义指标迭代函数                                                 |
//+------------------------------------------------------------------
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);
//--- 返回prev_calculated的值用于下一次调用
   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);
//---- 用0初始化
   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;
     
}
//---- 最少的计数
   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--;
     
}
//---- 最大计数
   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线
   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--;
     
}
//---- 最近一次计算的柱形将被重算
   if(counted_bars>0) counted_bars--;
   int limit=rates_total-counted_bars;
//---- 信号线是移动平均
   for(i=0; i<limit; i++)
      SignalBuffer[i]=iMAOnArrayMql4(MainBuffer,rates_total,DPeriod,0,MODE_SMA,i);
//----
   return(0);
  
}
//+------------------------------------------------------------------

结果,我们得到一个用 MQL5 编写的,具有 MQL4 价格结构的完全成熟的随机动量指标。

图 6 显示了其运行结果:

用 MQL4 重写的随机动量指标与用 MQL5 写的标准随机动量指标的比较。

图 6. 用 MQL4 重写的随机动量指标与用 MQL5 写的标准随机动量指标的比较。

5. 迁移 RSI 指标的例子

收集有关我们的指标的信息:
//---- 输入参数
extern int RSIPeriod=14;
//---- 缓存
double RSIBuffer[];
double PosBuffer[];
double NegBuffer[];

并且在 MetaEditor 5 中为其创建一个模板(图 7-8)。

RSI 指标的输入参数

图 7. RSI 指标的输入参数

RSI 指标的缓存

图 8. RSI 指标的缓存

缓存总数为 3:

#property indicator_buffers 3

用于绘图的缓存数量为 1:

#property indicator_plots   1

设定用于计算的缓存的状态:

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

安排各个部分并进行必要的更改:

//+------------------------------------------------------------------
//|                                                     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
//--- 绘制 RSIBuffer
#property indicator_label1  "RSIBuffer"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Green
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- 绘制 PosBuffer
#property indicator_label2  "PosBuffer"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- 绘制 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 int      RSIPeriod=14;
//--- 指标缓存
double         RSIBuffer[];
double         PosBuffer[];
double         NegBuffer[];
//+------------------------------------------------------------------
//| 自定义指标初始化函数                                               |
//+------------------------------------------------------------------
int OnInit()
  {
//--- 指标缓存映射
   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);
  
}
//+------------------------------------------------------------------
//| 自定义指标迭代函数                                                 |
//+------------------------------------------------------------------
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);
//---- 用0初始化
   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;
         //---- 初始累加
         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
        {
         //---- 平滑移动平均
         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);
  
}
//+------------------------------------------------------------------

在这里,与前一个指标不同,我们更改名称:现在,代替在 MQL4 中有用的 int Start() 函数

int start()
  {

我们在 MQL5 中使用

int RSImql4(

函数本身的名称以及在 MQL5 中的调用位置都出现改变。

图 9 显示了库的运行结果。

用 MQL4 重写的 RSIc 指标与用 MQL5 写的标准 RSI 指标的比较。

图 9. 用 MQL4 重写的 RSIc 指标与用 MQL5 写的标准 RSI 指标的比较。

6. 设置

要设置此模块,您需要将 mql4_2_mql5.mqh 文件复制到 MQL5\Include\ 文件夹。

测试文件应放于 MQL5\Indicators 文件夹中。

7. 改进

如果您愿意,您可以通过依据“从 MQL4 迁移到 MQL5”一文,连接一个库来扩展模块的功能。将 InitMQL4.mqh 文件添加到 MQL5\Include 文件夹,并且在输入参数之前添加以下代码行:

#include <InitMQL4.mqh>

您可以在“从 MQL4 迁移到 MQL5”一文中熟悉必要的更改。

总结

本文介绍了使用特殊的 mql4_2_mql5.mqh 库将简单价格结构从 MQL4 迁移到 MQL5 的算法。

在调试期间您可能会遇到一些麻烦,但是对于熟悉 MQL4 的人而言,复制它们并不会成为一个问题。

考虑到在 MQL5 环境中存取数据的特性,指标的重新计算可能要用一些时间。原因在于我们必须针对来自 MQL4 环境的程序创建和重新计算必要的数据。对于到 MQL5 环境的完全成熟的指标迁移,在重写时应考虑到在 MQL5 中存储和存取数据的特性。

附注

我想提醒您注意“考虑到在 MQL5 环境中存取数据的特性,指标的重新计算可能要用一些时间。原因在于我们必须针对来自 MQL4 环境的程序创建和重新计算必要的数据。”这两句。有时等待可能会持续几秒钟(见图 10-11):

  

图 10. 未计算出数据                                                                                                  图 11. 有数据可用

这与客户端的一个特点有关 - 在创建指标句柄时,在客户端的高速缓存中只创建计算部分的一个副本。如果尚未创建此类指标(具有相同的输入参数),则 

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

函数的调用将创建一个移动平均线指标,但是仅创建一次。

下一次尝试创建已经存在的指标时,客户端将仅返回其句柄。

因此,指标的计算仅执行一次,而不是刚刚在创建其句柄之后。

全部回复

0/140

达人推荐

量化课程

    移动端课程