下载MetaTrader 5

将指标从 MQL4 迁移到 MQL5

17 十二月 2013, 07:09
Vasily
0
1 265

简介

亲爱的读者们,你们好!

在今天的文章中,我将向你们介绍一个将简单价格计算从 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);

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

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

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

本文译自 MetaQuotes Software Corp. 撰写的俄文原文
原文地址: https://www.mql5.com/ru/articles/66

附加的文件 |
macd_mql4.mq5 (7.83 KB)
mql4_2_mql5.mqh (32.21 KB)
rsi_mql4.mq5 (9.27 KB)
stochastic_mql4.mq5 (10.61 KB)
建立一个频谱分析程序 建立一个频谱分析程序

本文旨在让读者熟悉使用 MQL5 语言图形对象的一种可能变量。它会对一个利用图形对象管理简单频谱分析程序的面板的实施指标进行分析。本文专为熟悉 MQL5 基础的读者编写。

利用标准库类创建您自己的“市场报价” 利用标准库类创建您自己的“市场报价”

新型 MetaTrader 5 客户端与 MQL5 语言提供了向交易者展示可视信息的新机遇。本文中,我们会讲到一系列通用且可扩展的类,处理图表上方任意文本信息的组织与显示工作。“市场报价”指标的示例亦有提供。

针对市场分析的数据库的具体应用 针对市场分析的数据库的具体应用

处理数据成为现代软件的主要任务 - 独立应用程序和网络应用程序都是如此。为解决此问题而创建了专业软件。这些软件被称为数据库管理系统 (DBMS),能够针对它们的计算机存储和处理对数据进行构建、系统化和组织。对于交易,大多数分析师并不在他们的工作中使用数据库。但是对于一些任务,必须使用此类解决方案。本文提供了一个在客户端-服务器和文件-服务器架构中都能将数据保存到数据库或从数据库加载数据的指标例子。

例解 MQL5 中的面向对象编程:处理警告和错误代码 例解 MQL5 中的面向对象编程:处理警告和错误代码

本文以一个例子说明创建一个类用于处理 MQL 程序运行期间交易服务器返回的代码以及所有错误的类。阅读本文之后,您将学习到如何在 MQL5 中处理类和对象。同时,这是一个方便的错误处理工具;并且您可以依据您的具体需要进一步更改此工具。