下载MetaTrader 5

使用若干中间指标缓存创建多货币指标

6 十二月 2013, 10:37
Alexey Klenov
0
893

简介

这一切开始于当我从 Theoretical Basis of Building Cluster Indicators for FOREX(建立 FOREX 群集指标的理论基础)一文中第一次听到群集指标时。当时我对其非常感兴趣,我决定在多市场分析方面写一点类似的东西。首先,我实施了我自己的指标,代号为 MultiCurrencyIndex,在这个指标中,使用货币指数的计算值来计算经典指标(RSI、MACD、CCI)的值。 

现在,我将告诉您我如何在 MQL5 的帮助下将此指标转移到新的平台 MetaTrader 5,除了代替计算 CCI 以外,我将计算随机动量指标 (Stochastic Oscillator),该指标更具前瞻性(我的个人意见)。

让我们从一些定义开始。

美元指数 - 按照 Neutron 提供给我的公式计算的双精度值。

计算美元指数的公式,

其中,USD / YYY 表示所有方向的直接报价,例如 USD / CHF,而 XXX / USD 表示所有反向报价,例如 EUR / USD。

其他指数通过包含美元的货币对收盘价来计算。

主线 - 指标的两条线,反应计算出来的数据,与当前图形直接相关。例如,在 EURUSD 图形中,它将是 EUR 和 USD 的线条。

补充线 - 其他计算出来的指标线,与当前图形无关。例如,对于相同的 EURUSD 图形,它将是 GBP、CHF、JPY、CAD、AUD 和 NZD 货币的线条。

收盘价 - 必要货币对的当前时间框架的收盘价的值。

让我们开始吧。

问题设置

要开始,我们需要设置问题。

  1. 同步此时间框架内受影响的货币对的图形。
  2. 获得对以下七个货币对的收盘价数据的访问权限:EURUSD、GBPUSD、USDCHF、USDJPY、USDCAD、AUDUSD、NZDUSD,并将数据放入专为计算设计的指标缓存。
  3. 依据在第 2 项中获得的数据计算当前柱的美元指数。
  4. 知道当前柱的货币指数之后,计算余下的货币指数。
  5. 为选择的历史记录时间长度进行所需次数的数据计算(第 3 项和第 4 项)。
  6. 视指标的目的地而定,为每个选择的指数计算货币值:
    • 相对强弱指数 (Relative Strength Index, RSI);
    • 平滑异动移动平均线 (Moving Average Convergence / Divergence, MACD);
    • 随机动量指标 (Stochastic Oscillator);
    • 将来可能补充此列表。

为此,我们需要:

31 个指标缓存:

  • 0-7(含)- 用于呈现最终线条的缓存;
  • 8-14(含)- 包含美元的主货币对的缓存;
  • 15-22(含)- 货币指数缓存;
  • 23-30(含)- 按收盘价/没有平滑的收盘价类型统计的中间数据随机动量的缓存。

为了选择指标的目的地,我们将建立一个枚举类型 enum

enum Indicator_Type
  {
   Use_RSI_on_indexes             = 1, // RSI 索引 
   Use_MACD_on_indexes            = 2, // MACD 索引  
   Use_Stochastic_Main_on_indexes = 3  // Stochastic 索引
  };
接下来,使用 input 命令,在指标参数选择窗口,我们将从这个供用户选择的列表获取值。 
input Indicator_Type ind_type=Use_RSI_on_indexes;  // 索引对应的指标类型

可以用一种更加用户友好的方式,在 "Inputs"(输入)选项卡中显示输入参数的名称。为此,我们使用紧急备注,该备注必须紧跟着输入参数的说明,在同一行中。这样,输入参数的名称更容易被用户理解。

同样的规则也适用于列举命令 enum换言之,如果有助于记忆的名称与备注关联在一起,如我们的例子所示,则将显示此备注的内容,而不是有助于记忆的名称这对编写具有清晰输入参数说明的程序提供了额外的灵活性。

开发人员试图通过让最终用户看到容易理解的参数名称而不是在代码中所写的,向最终用户提供便利的方式来处理 MQL5 程序。可以在此处找到更多信息。

图 1. 指标类型的选择

图 1. 指标类型的选择

我们向用户提供呈现指标所必需的货币及其颜色的选择:

input bool USD=true;
input bool EUR=true;
input bool GBP=true;
input bool JPY=true;
input bool CHF=true;
input bool CAD=true;
input bool AUD=true;
input bool NZD=true;

input color Color_USD = Green;            // USD 线颜色
input color Color_EUR = DarkBlue;         // EUR 线颜色
input color Color_GBP = Red;             // GBP 线颜色
input color Color_CHF = Chocolate;        // CHF 线颜色
input color Color_JPY = Maroon;           // JPY 线颜色
input color Color_AUD = DarkOrange;       // AUD 线颜色
input color Color_CAD = Purple;          // CAD 线颜色
input color Color_NZD = Teal;            // NZD 线颜色

图 2. 指标线颜色的选择

图 2. 指标线颜色的选择

其他一些可配置的参数:

input string rem000        =  ""; // 依据指标类型
input string rem0000       =  ""; // 需要的数值 :
input int rsi_period       =   9; // RSI 周期
input int MACD_fast        =   5; // MACD_fast 周期
input int MACD_slow        =  34; // MACD_slow 周期
input int stoch_period_k   =   8; // Stochastic %K 周期
input int stoch_period_sma =   5; // Stochastics %K 平滑周期
input int shiftbars        = 500; // 指标计算柱线数

图 3. 指标参数

图 3. 指标参数

指标计算的 500 根柱的限制是人为的,但是足以说明计算的概念。但我们必须记住,每个指标缓存都需要内存,显示非常大的可变规模(数以百万计的柱)可能导致计算机没有足够的内存。

指标缓存:

double  EURUSD[], // 报价
        GBPUSD[],
        USDCHF[],
        USDJPY[],
        AUDUSD[],
        USDCAD[],
        NZDUSD[];   
               
double    USDx[], // 指数
          EURx[],
          GBPx[],
          JPYx[],
          CHFx[],
          CADx[],
          AUDx[],
          NZDx[];
                         
double USDplot[], // 货币线结果
       EURplot[],
       GBPplot[],
       JPYplot[],
       CHFplot[],
       CADplot[],
       AUDplot[],
       NZDplot[]; 

double USDStoch[], // 无平滑的 schotastics 的收盘价/收盘价类型中间数据缓存区,
       EURStoch[],
       GBPStoch[],
       JPYStoch[],
       CHFStoch[],
       CADStoch[],
       AUDStoch[],
       NZDStoch[];
我们还需要某些全局(指标级别)变量:
int              i,ii;
int           y_pos=0; // 信息对象的 Y 坐标变量 
datetime   arrTime[7]; // 最后已知时间的零值柱线数组 (需要同步)  
int        bars_tf[7]; // 检查不同货币对的可用柱线数量  
int        countVal=0; // 可执行数量比率  
int           index=0;
datetime  tmp_time[1]; // 柱线时间的中间数组 

现在,我们看到一个相当长的函数 OnInit,使用该函数,我们将依据指标的目的分配指标缓存。

因为初始计算采用美元指数,因此对于 USD,我们简单地建立禁用货币指标缓存呈现的可能性。

它看起来如下所示:

if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);               // 渲染数组
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");              // 指标线名称 (当鼠标选择时)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // 从哪里,我们开始渲染
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // 绘图风格 (线)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // 线的渲染颜色
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // 如果交易品种名称包括 USD 
                                                       // 则画适当宽度的线 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // 按时间序列检索数组   
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // 零值 
   f_draw("USD",Color_USD);                            // 在指标信息窗口渲染 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);            // 计算美元指数的数组
                                                      // (在指标中不会显示) 
ArraySetAsSeries(USDx,true);                            // 按时间序列检索数组
ArrayInitialize(USDx,EMPTY_VALUE);                       // 零值

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);     // 如果指标是 Use_Stochastic_Main_on_indexes,
                                                           // 则需要中间数组
   ArraySetAsSeries(USDstoch,true);                        // 按时间序列检索数组
   ArrayInitialize(USDstoch,EMPTY_VALUE);                  // 零值
  }
对于 EUR 货币,函数代码 OnInit 看起来如下所示:
if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);              // 渲染数组
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");             // 指标线名称 (当鼠标选择时)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // 从哪里,我们开始渲染
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // 绘图风格 (线)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // 线的渲染颜色
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // 如果交易品种名称包括 USD 
                                                       // 则画适当宽度的线 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // 按时间序列检索数组
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // 零值 
   f_draw("USD",Color_USD);                             // 在指标信息窗口渲染 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);             // 计算美元指数的数组
                                                       // (在指标中不会显示) 
ArraySetAsSeries(USDx,true);                             // 按时间序列检索数组
ArrayInitialize(USDx,EMPTY_VALUE);                        // 零值

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);      // 如果指标是 Use_Stochastic_Main_on_indexes,
                                                       // 则需要中间数组
   ArraySetAsSeries(USDstoch,true);                      // 按时间序列检索数组
   ArrayInitialize(USDstoch,EMPTY_VALUE);                 // 零值
  }

if(EUR)
  {
   countVal++;
   SetIndexBuffer(1,EURplot,INDICATOR_DATA);              // 渲染数组
   PlotIndexSetString(1,PLOT_LABEL,"EURplot");             // 指标线名称 (当鼠标选择时)
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,shiftbars);       // 从哪里,我们开始渲染
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);         // 绘图风格 (线)
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,Color_EUR);       // 线的渲染颜色
   if(StringFind(Symbol(),"EUR",0)!=-1)
     {PlotIndexSetInteger(1,PLOT_LINE_WIDTH,wid_main);}    // 如果交易品种名称包括 EUR
                                                       // 则画适当宽度的线 
   else
     {PlotIndexSetInteger(1,PLOT_LINE_STYLE,style_slave);}  // 如果交易品种名称不包括 EUR,
                                                       // 则画适当风格的线(在上交叉)
   ArraySetAsSeries(EURplot,true);                       // 按时间序列检索数组
   ArrayInitialize(EURplot,EMPTY_VALUE);                  // 零值
   SetIndexBuffer(8,EURUSD,INDICATOR_CALCULATIONS);        // 货币对 EURUSD 的收盘数据
   ArraySetAsSeries(EURUSD,true);                        // 按时间序列检索数组
   ArrayInitialize(EURUSD,EMPTY_VALUE);                   // 零值
   SetIndexBuffer(16,EURx,INDICATOR_CALCULATIONS);         // EURO 索引数组用于计算
                                                      // (在指标中不会显示) 
   ArraySetAsSeries(EURx,true);
   ArrayInitialize(EURx,EMPTY_VALUE);
   if(ind_type==Use_Stochastic_Main_on_indexes)
     {
      SetIndexBuffer(24,EURstoch,INDICATOR_CALCULATIONS);   // 如果指标是 Use_Stochastic_Main_on_indexes,
                                                       // 则需要中间数组
      ArraySetAsSeries(EURstoch,true);                   // 按时间序列检索数组
      ArrayInitialize(EURstoch,EMPTY_VALUE);              // 零值
     }
   f_draw("EUR",Color_EUR);                            // 在指标信息窗口渲染
  }
与 EUR 类似,对于 GBP、JPY、CHF、CAD、AUD 和 NZD 等货币,代码也是类似的,移位指标缓存的索引。可在附带的指标文件中找到这些货币的代码。

这样就完成了指标初始化的说明。

接下来,我们需要某些自定义的用户功能:

  • 通过用户缓存计算 RSI
  • 计算 MACD
  • 通过用户缓存计算 SMA
  • 按收盘价/没有平滑的收盘价计算随机动量
  • 呈现对象(信息)
  • 指标右下角中的备注(指标状态)
  • 受影响的 TF 货币对的初始化

以上各项的简短说明:

  • 通过用户缓存计算 RSI

输入参数:

double f_RSI(double &buf_in[], int period,int shift),

其中,buf_in[] - 双精度类型的数组(例如时间序列),period - RSI 指标周期,shift - 我们为其计算指标的指标柱。返回一个双精度类型的值。

  • 计算 MACD

输入参数:

double f_MACD(double &buf_in[], int period_fast,int period_slow,int shift),

其中,buf_in[]  - 双精度类型的数组(例如时间序列),period_fast - 快速移动平均线的周期,period_slow - 慢速移动平均线的周期,shift - 我们为其计算指标的指标柱。返回一个双精度类型的值。

  • 计算 SMA

输入参数:

double SimpleMA(const int position,const int period,const double &price[]),

其中,position - 我们为其计算指标的指标柱。period - SMA 指标的周期,price[] - 双精度类型的时间数组(例如时间序列)。返回一个双精度类型的值。

  • 按收盘价/没有平滑的收盘价计算随机动量

输入参数:

double f_Stoch(double &price[], int period_k, int shift),

其中,price[] - 双精度类型的数组(例如时间序列),period_fast - %K 指标线的周期,shift - 我们为其计算指标的指标柱。返回一个双精度类型的值。

  • 呈现对象

输入参数:

int f_draw(string name, color _color)

其中,name - 对象名称,_color - 对象颜色。该函数仅用于信息显示目的。从窗口的右上角往下,此函数显示受影响的货币的名称。货币文本的颜色和与该货币关联的指标线的颜色相同。

  • 备注位于指标的右下角

输入参数:

int f_comment(string text)

text - 需要放在指标右下角的文本。一种指标工作状态栏。

最后,结束性和最重要的函数之一:

  • 受影响的 TF 货币对的初始化

无输入参数。

在 MetaTrader 5 中,历史记录以针对每一工具的 TF 的分钟数据的形式存储。因此,一旦打开客户端,在启动程序之前,已经依据相同的 TF 分钟数据构建了所有必要的(受影响的)图形。构建还发生在切换当前 TF 或尝试通过 MQL5 程序代码访问 TF 图形期间。

因此:

  • 在第一次启动客户端期间,构建使用的货币对的必要 TF 需要一定的时间(甚至是在后台构建,即用户看不到它们)。
  • 同步所有受影响的货币的零柱,以精确显示指标。换言之,如果在图形中出现新的价格变动,该价格变动打开新的柱(例如一小时柱)。则您需要为其他货币对等待价格变动的出现,该价格变动依次打开新的柱(新的一小时)。之后才继续计算新柱的指标。

此任务的第一部分通过内置的 Bars 函数实施,该函数通过与交易品种的对应周期返回历史记录中柱的数量。使用此版本的函数已经足够,如下所示。

int  Bars(
   string          symbol_name,   // 交易品种名称
   ENUM_TIMEFRAMES   timeframe    // 周期
   );

在专为此数组声明的变量中,我们为所有受影响的货币对收集可用柱数。我们为最低限度的必要历史数据量检查每一个值(指标参数中“用于计算指标的柱的数量”)。如果任何工具的历史记录中的可用柱数小于此变量的值,则我们认为构建不成功,并且重新检查可用数据的数量。一旦针对所有货币对的可用历史记录超过用户请求的数量,则我们认为这部分的初始化已成功完成。

初始化的第二部分通过使用 CopyTime 函数来实施。

我们将每个受影响的工具的零柱的建立复制到一个专为此目的创建的数组。如果此数组的所有元素都相同并且不等于 0,则我们认为我们的零柱已经同步,让我们开始计算。要更加详细地理解这是如何实施的,请查看附带指标的代码。

这样就完成了其他函数的说明,我们转到 OnCalculate 函数的实施。因为这是一个多货币指标,我们将需要此函数请求的第二版本。

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 limit=shiftbars;

   if(prev_calculated>0)
     {limit=1;}
   else
     {limit=shiftbars;}

同步货币对的图形:

   init_tf();

接下来,使用 CopyClose 函数,我们将所有必要货币对的收盘价数据复制到专为此目的寄存的指标缓存。(欲知有关存取当前工具和/或其他工具的其他 TF 数据的更多信息,请浏览帮助

如果出于任何原因,函数未复制数据,并且返回 -1,则我们在备注中显示货币对错误消息,并且等待接收当前工具的新价格变动。

   if (EUR){copied=CopyClose("EURUSD",PERIOD_CURRENT,0,shiftbars,EURUSD); if (copied==-1){f_comment("等待...EURUSD");return(0);}}
   if (GBP){copied=CopyClose("GBPUSD",PERIOD_CURRENT,0,shiftbars,GBPUSD); if (copied==-1){f_comment("等待...GBPUSD");return(0);}}
   if (CHF){copied=CopyClose("USDCHF",PERIOD_CURRENT,0,shiftbars,USDCHF); if (copied==-1){f_comment("等待...USDCHF");return(0);}}
   if (JPY){copied=CopyClose("USDJPY",PERIOD_CURRENT,0,shiftbars,USDJPY); if (copied==-1){f_comment("等待...USDJPY");return(0);}}
   if (AUD){copied=CopyClose("AUDUSD",PERIOD_CURRENT,0,shiftbars,AUDUSD); if (copied==-1){f_comment("等待...AUDUSD");return(0);}}
   if (CAD){copied=CopyClose("USDCAD",PERIOD_CURRENT,0,shiftbars,USDCAD); if (copied==-1){f_comment("等待...USDCAD");return(0);}}
   if (NZD){copied=CopyClose("NZDUSD",PERIOD_CURRENT,0,shiftbars,NZDUSD); if (copied==-1){f_comment("等待...NZDUSD");return(0);}}  

接下来,在循环中(从 0 至限制),我们依据当前柱的收盘价和美元指数进行:

  • 美元指数的计算;
  • 其他货币指数的计算;
for (i=limit-1;i>=0;i--)
   {
      //计算美元指数
      USDx[i]=1.0;
      if (EUR){USDx[i]+=EURUSD[i];}         
      if (GBP){USDx[i]+=GBPUSD[i];}
      if (CHF){USDx[i]+=1/USDCHF[i];}
      if (JPY){USDx[i]+=1/USDJPY[i];}
      if (CAD){USDx[i]+=1/USDCAD[i];}
      if (AUD){USDx[i]+=AUDUSD[i];}
      if (NZD){USDx[i]+=NZDUSD[i];}
      USDx[i]=1/USDx[i];
      //计算其它货币值
      if (EUR){EURx[i]=EURUSD[i]*USDx[i];}
      if (GBP){GBPx[i]=GBPUSD[i]*USDx[i];}
      if (CHF){CHFx[i]=USDx[i]/USDCHF[i];}
      if (JPY){JPYx[i]=USDx[i]/USDJPY[i];}
      if (CAD){CADx[i]=USDx[i]/USDCAD[i];}
      if (AUD){AUDx[i]=AUDUSD[i]*USDx[i];}
      if (NZD){NZDx[i]=NZDUSD[i]*USDx[i];}
   }

数据放入相应的指标缓存。检查在初始化期间用户选择了哪类指标,并且依据此基础进行相应的计算。

如果希望查看指数的 RSI 指标,则执行下面的代码:

if (ind_type==Use_RSI_on_indexes)
   {
      if (limit>1){ii=limit - rsi_period - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=f_RSI(USDx,rsi_period,i);}
            if (EUR){EURplot[i]=f_RSI(EURx,rsi_period,i);}
            if (GBP){GBPplot[i]=f_RSI(GBPx,rsi_period,i);}
            if (CHF){CHFplot[i]=f_RSI(CHFx,rsi_period,i);}
            if (JPY){JPYplot[i]=f_RSI(JPYx,rsi_period,i);}
            if (CAD){CADplot[i]=f_RSI(CADx,rsi_period,i);}
            if (AUD){AUDplot[i]=f_RSI(AUDx,rsi_period,i);}
            if (NZD){NZDplot[i]=f_RSI(NZDx,rsi_period,i);}                  
         }
   }  

如果我们想查看按指数统计的 MACD 指标,则我们的代码如下(但是迄今为止仅仅依据 SimpleMA 实施,以后将依据 EMA 实施):

if (ind_type==Use_MACD_on_indexes)
   {
      if (limit>1){ii=limit - MACD_slow - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDplot[i]=f_MACD(USDx,MACD_fast,MACD_slow,i);}
           if (EUR){EURplot[i]=f_MACD(EURx,MACD_fast,MACD_slow,i);}
           if (GBP){GBPplot[i]=f_MACD(GBPx,MACD_fast,MACD_slow,i);}
           if (CHF){CHFplot[i]=f_MACD(CHFx,MACD_fast,MACD_slow,i);}
           if (JPY){JPYplot[i]=f_MACD(JPYx,MACD_fast,MACD_slow,i);}
           if (CAD){CADplot[i]=f_MACD(CADx,MACD_fast,MACD_slow,i);}
           if (AUD){AUDplot[i]=f_MACD(AUDx,MACD_fast,MACD_slow,i);}
           if (NZD){NZDplot[i]=f_MACD(NZDx,MACD_fast,MACD_slow,i);}                  
         }
   } 

如果是随机动量指标,则您必须首先计算 % K 线,然后通过 SimpleMA 方法对其进行平滑。必须在图表上显示最后经过平滑处理的线条。

if (ind_type==Use_Stochastic_Main_on_indexes)
   {
      if (limit>1){ii=limit - stoch_period_k - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDstoch[i]=f_Stoch(USDx,rsi_period,i);}
           if (EUR){EURstoch[i]=f_stoch(EURx,stoch_period_k,i);}
           if (GBP){GBPstoch[i]=f_stoch(GBPx,stoch_period_k,i);}
           if (CHF){CHFstoch[i]=f_stoch(CHFx,stoch_period_k,i);}
           if (JPY){JPYstoch[i]=f_stoch(JPYx,stoch_period_k,i);}
           if (CAD){CADstoch[i]=f_stoch(CADx,stoch_period_k,i);}
           if (AUD){AUDstoch[i]=f_stoch(AUDx,stoch_period_k,i);}
           if (NZD){NZDstoch[i]=f_stoch(NZDx,stoch_period_k,i);}                  
         }
      if (limit>1){ii=limit - stoch_period_sma - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=SimpleMA(i,stoch_period_sma,USDstoch);}
            if (EUR){EURplot[i]=SimpleMA(i,stoch_period_sma,EURstoch);}
            if (GBP){GBPplot[i]=SimpleMA(i,stoch_period_sma,GBPstoch);}
            if (CHF){CHFplot[i]=SimpleMA(i,stoch_period_sma,CHFstoch);}
            if (JPY){JPYplot[i]=SimpleMA(i,stoch_period_sma,JPYstoch);}
            if (CAD){CADplot[i]=SimpleMA(i,stoch_period_sma,CADstoch);}
            if (AUD){AUDplot[i]=SimpleMA(i,stoch_period_sma,AUDstoch);}
            if (NZD){NZDplot[i]=SimpleMA(i,stoch_period_sma,NZDstoch);}                  
          }                     
   }       

这样就完成了指标的计算。图 4-6 以几张图片说明了不同类型的指标。

图 4. 通过指数统计的 RSI 指标

图 4. 通过指数统计的 RSI 指标

图 5. 通过货币指数统计的 MACD 指标

图 5. 通过货币指数统计的 MACD 指标

图 6. 通过货币指数统计的随机动量指标

图 6. 通过货币指数统计的随机动量指标

总结

在实施 MultiCurrencyIndex 指标时,我在 MQL5 中使用没有数量限制的指标缓存,这样大大简化了代码。本文是此类方法的一个例子。为了获得可靠的指标数据,我说明了一种相对于零柱的不同工具的同步算法。我还示范了一种可能算法,该算法可访问来自与指标附加到的交易品种相关联的其他工具的数据。

因为本文旨在说明处理海量指标缓存的可能性,以上按用户的数据数组计算指标的函数并不是让读者毫无负担的最佳方式。但是它足以执行必需的计算。

Forex 市场的群集分析有利也有弊。可以很容易获取依据此方法的交易系统,并且在各个论坛上,包括 MQL4.Community,都有相关讨论。因此,按这个指标进行交易的原理并不在本文的讨论范围之内。

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

附加的文件 |
从 MQL4 迁移到 MQL5 从 MQL4 迁移到 MQL5

本文是 MQL4 语言函数的快速指南,帮助您将您的程序从 MQL4 迁移到 MQL5。介绍了每个 MQL4 函数(交易函数除外)的说明和 MQL5 实施,从而让您显著减少转换时间。出于方便起见,MQL4 函数被分为组,类似于 MQL4 参考。

遗传算法 - 很简单! 遗传算法 - 很简单!

在本文中,笔者将讨论利用亲自开发的遗传算法进行的进化计算。笔者将通过示例说明算法的功能,并为算法的使用提供实用性的建议。

用 Delphi 为 MQL5 编写 DLL 指南 用 Delphi 为 MQL5 编写 DLL 指南

本文说明在 Delphi 编程环境中使用流行编程语言 ObjectPascal 创建 DLL 模块的机制。本文提供的材料主要针对初学者而设计,这些初学者面临因为连接外部 DLL 模块而突破了嵌入式编程语言 MQL5 边界的问题。

中测试移动平均线计算的性能 中测试移动平均线计算的性能

在创建第一个移动平均线指标之后,已经出现了若干指标。其中很多指标使用类似的平滑方法,但是还没有研究不同的移动平均线算法的性能。在本文中,我们将考虑在 MQL5 中使用移动平均线的若干可能方式并比较它们的性能。