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

量化交易吧 /  量化策略 帖子:3364712 新帖:0

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

你在说什么呢发表于:4 月 17 日 18:53回复(1)

简介

移动平均线的使用在市场时间序列的分析中、在指标和 EA 交易的编程中都是一种常见的实践方法。它是最流行的价格数据平滑方法。在新版本的 MQL 语言中,有成打的移动平均线算法可供使用。

它们之间有何差异?计算速度确实取决于某些移动平均线的算法吗?哪种算法最快?

与 MetaTrader 4 相比,在 MetaTrader 5 中移动平均线的计算速度加快了吗?有很多此类问题出现。因此,让我们探讨一下其中的大多数问题。

当然,新平台的速度令人印象深刻,但是最好通过实验检查一下。

1. 测试条件

计算速度取决于很多因素。因此,本研究作为结果获得的数据在其他测试条件下可能有所不同。换言之,性能的绝对值将有所不同,但是相对值将是类似的(针对某个平台)。

因此 MQL5 中的 iMA 函数本身不返回计算结果(它返回指标的句柄),我们将测试两个函数的速度:iMA 和 CopyBuffer。

测试条件:
  • CPU:Core i7 965
  • 交易品种:"EURUSD"
  • 价格数据大小:10000 个元素
  • 客户端:自主交易,图表中的最大柱数设置为 10000
  • 移动平均线模型:MODE_SMA、MODE_EMA、MODE_SMMA、MODE_LWMA
  • 计算速度的精确度限制为两位有效数字
  • 移动平均线函数的可能调用数量:7


2. 如何测试

要测量移动平均线的计算时间,我们使用 GetTickCount() 函数,该函数运行于毫秒级别。此精确度还不足够,因此我们需要组织某些循环以提高测量的质量。

但是,如果我们用相同的计算和相同的输入数据多次重复循环,则结果会失真。该事实的原因如下:iMA 函数在客户端的全局缓存中创建相应技术指标的一个副本。如果在全局缓存中已经存在一个指标的副本(具有相同的参数),则不创建新的副本,指标副本的引用计数器增大。

换言之,整个缓存指标仅在第一次调用时计算一次,所有后续的调用仅采用已经存在的值,它仅重新计算新的数据。

因此,应按这样的方式组织循环:指标的输入参数在循环期间是唯一的。我们已经选择了三个这样的参数:平均周期、时间框架和应用的价格。

参数
 值范围
 平均周期
 从 1 至 100
 时间框架
 М1、М5、М15、М30
 应用的价格
 PRICE_CLOSE、PRICE_OPEN、PRICE_HIGH、PRICE_LOW、PRICE_MEDIAN、PRICE_TYPICAL、PRICE_WEIGHTED

表 1. 输入参数的范围

我们将使用七种不同的调用方法计算含有 10000 个元素的数组的移动平均值(详情见第 4 节)。


3. 研究结果

我们已经将所有结果组合在表 1 中,使用以秒为单位的计算时间来评估计算性能(见表 1)。程序计算了 100х4х7=2800 类移动平均线,并且我们确定含有 10000 个元素的价格数组的计算时间。单次循环的计算时间约等于总时间除以 2800。例如,对于案例 1 和 SMA 模式,它约等于 0.0028/2800。

模式
MODE_SMA MODE_EMA MODE_SMMA MODE_LWMA 平台
0  (见第 4.1 节)
0,0041 0,0040 0,0043 0,0041  MetaTrader 4
1  (见第 4.2 节) 0,0028 0,00023 0,00027 0,0045  MetaTrader 5
2  (见第 4.3 节) 0,0029 0,0029 0,0029 0,0029  MetaTrader 5
3  (见第 4.4 节) 0,0998 0,0997 0,0998 0,0998  MetaTrader 5
4  (见第 4.5 节) 0,0996 0,0996 0,0996 0,0996  MetaTrader 5
5  (见第 4.6 节) 0,0030 0,0029 0,0029 0,0029  MetaTrader 5
6  (见第 4.7 节) 0,000140 0,000121 0,000117 0,0035  MetaTrader 5

表 2. 结果

将在下文讨论测试案例的意义(第 4.1-4.7 节)。让我们评估移动平均线计算性能的整个画面。 

为方便起见,在图表中表示结果(见图 1-5)。移动平均线的调用类型在 X 轴上表示(见表 2),用对数刻度 -1 表示 Y 轴的值,因此,值越大,性能越快。每个计算模型(SMA、EMA、SMMA、LWMA)对应于图表中的一根柱。

图 1 不同移动平均线算法的性能测试结果

图 1. 不同移动平均线算法的性能测试结果

可以看到在不同的移动平均线计算案例中计算速度出现显著差异。这意味着什么?由 MQL5 开发人员提供的几种移动平均线算法具有不同的计算性能:有很快的算法(案例 6)和较慢的算法(案例 3 和 4)。因此,在用 MQL5 编写使用移动平均线的程序时,必须选择正确的算法。

在以下的图中详细说明了各个移动平均线模型 (0-6) 的计算时间,见表 2。

图 2. MODE_SMA 模式的移动平均线计算性能

图 2. MODE_SMA 模式的移动平均线计算性能

图 3. MODE_EMA 模式的移动平均线计算性能

图 3. MODE_EMA 模式的移动平均线计算性能

图 4. MODE_SMMA 模式的移动平均线计算性能

图 4. MODE_SMMA 模式的移动平均线计算性能

图 5. MODE_LWMA 模式的移动平均线计算性能

图 5. MODE_LWMA 模式的移动平均线计算性能

比较两个平台的计算性能非常有趣:MetaTrader 4 和 MetaTrader 5。表 2 中的案例 0 (MQL4) 和案例 1 (MQL5) 显示了结果。

为方便起见,让我们将 iMA 标准指标的计算结果组合到单独的图和表中(见图 6)。测试的计算时间以 Y 轴表示。

图 6. MetaTrader 4 和 MetaTrader 5 计算性能的比较图

图 6. MetaTrader 4 和 MetaTrader 5 计算性能的比较图

结论

  1. 新的 MetaTrader 5 平台比以前的 MetaTrader 4 快 40%。
  2. SMA、EMA 和 SMMA 模型(案例 6),以及 LWMA(案例 2 和 5)实现了更快的性能。
  3. 对于测试案例,在使用标准指标 iMA 时,不同模型的计算性能实际上是相同的。对于 MovingAverages.mqh 库函数而言,事实并非如此。对于不同的模型,性能几乎相差一个量级 (0.00023~0.0045)。
  4. 表示的结果对应于“冷启动”,在客户端的全局缓存中没有任何预先计算的数据。


4. 案例研究

MQL5 开发人员建议使用以下获取标准技术指标的值的方法:

//--- 指标缓冲区
double      MA[];                // 用于存放 iMA 指标数值的数组
//---- 指标句柄
int         MA_handle;           // iMA 指标句柄
//+------------------------------------------------------------------
//| EA 初始化函数                                                     |
//+------------------------------------------------------------------
int OnInit()
  {
   //--- 创建 iMA 指标句柄
   MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
   //--- 如果出错,打印消息
   if(MA_handle<0)
      {
      Print("此 iMA 对象不能创建: MA_handle= ",INVALID_HANDLE);
      Print("运行时错误 = ",GetLastError());
      //--- 强迫中断程序
      return(-1);
      }
   return(0);
  }
//+------------------------------------------------------------------
//| EA 即时价格处理函数                                                |
//+------------------------------------------------------------------
void OnTick()
  {
   //--- 以 iMA 指标当前值填充 MA[] 数组
   //--- 我们将复制 100 个元素, 或如果出错则返回
   if(CopyBuffer(MA_handle,0,0,100,MA)<=0) return;
   //--- 设置 MA[] 顺序为时间序列
   ArraySetAsSeries(MA,true);  
   //--- 此处我们可以利用数据做任何事
  }

在“MQL5 初学者:在‘EA 交易’中使用技术指标的指南”一文中详细说明了此方法。

要测试移动平均线的计算性能,最好使用脚本,因为它能执行所有计算而不必等待事件(例如新的价格变动事件等)。

没有必要针对所有测试案例测试一个单独的通用程序,因此我们将为每个移动平均线计算案例创建单独的脚本。

那么,让我们详细考虑移动平均线计算的每个案例。


4.1. 案例 0

在这个案例中,我们测量 MQL4 的技术指标 iMA 的计算性能。计算在 MetaTrader4 中进行并且计算所有数据。

模型 结果 最佳结果
MODE_SMA 0,0041 0.000140(案例 6)
MODE_EMA 0,0040 0.000121(案例 6)
MODE_SMMA 0,0043 0.000117(案例 6)
MODE_LWMA 0,0041 0.0029(案例 2、5)

此案例的代码如下 (MQL4):

int         M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
int         P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int start()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   Print("开始 ");
   startGTC=GetTickCount();
//----
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
           Test0();
           }
        }
     }
//----
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   Print("总计时间 [msec] ",time);
   time=time/1000/m/p/periodMA;
   Print("性能 [sec] ",DoubleToStr(time, 10));
   return(0);
  }
//+------------------------------------------------------------------
void Test0()
  {
//--- 模式: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   for(int i=0;i<count;i++)
     {
      buf[i]=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p],i);
     }
  }

注:此代码不能在 MetaTrader 5 中运行,因为它是用 MQL4 编写的。应该在 MetaTrader 4 客户端中执行它。


4.2. 案例 1

在这个案例中,我们执行了 4 个模型的计算:案例 1 (SMA)、案例 2 (EMA)、案例 3 (SMMA) 和案例 4 (LWMA) 使用 MovingAverages.mqh 库函数。

用所有数据数组执行计算。

模型
 结果 最佳结果
MODE_SMA
0,0028
0.000140(案例 6)
MODE_EMA
0,00023
0.000121(案例 6)
MODE_SMMA
0,00027 0.000117(案例 6)
MODE_LWMA
0,0045 0.0029(案例 2、5)
#include <MovingAverages.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[],close[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   ArraySetAsSeries(close,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         CopyClose(_Symbol,M[m],0,count,close);
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test1(); // 测试在此
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test1()
  {
   for(int i=0;i<count;i++)
     {
      buf[i]=SimpleMA(i,periodMA,close);
     }
  }
//+------------------------------------------------------------------
void Test2()
  {
   buf[0]=close[0];
   for(int i=1;i<count;i++)
     {
      buf[i]=ExponentialMA(i,periodMA,buf[i-1],close);
     }
  }
//+------------------------------------------------------------------
void Test3()
  {
   buf[0]=close[0];
   for(int i=1;i<count;i++)
     {
      buf[i]=SmoothedMA(i,periodMA,buf[i-1],close);
     }
  }
//+------------------------------------------------------------------
void Test4()
  {
   for(int i=0;i<count;i++)
     {
      buf[i]=LinearWeightedMA(i,periodMA,close);
     }
  }

注:我们已经计划在数组中使用几种类型的数据,但是为了简单起见,我们仅使用一个含有收盘价数据的数组(这不影响计算性能)。


4.3. 案例 2

在这个案例中,我们使用 iMA 标准技术指标和测试 5。

用所有数据数组执行计算。

模型 结果 最佳结果
MODE_SMA 0,0029 0.000140(案例 6)
MODE_EMA 0,0029 0.000121(案例 6)
MODE_SMMA 0,0029 0.000117(案例 6)
MODE_LWMA 0,0029 0.0029(案例 2、5)
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
double      MA[];                // 用于存放 iMA 指标数组
int         MA_handle;           // iMA 指标句柄
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test5();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test5()
  {
//--- 模式: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   MA_handle=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   while(BarsCalculated(MA_handle)<count){}
   CopyBuffer(MA_handle,0,0,count,MA);
  }


4.4. 案例 3

在案例 3 中,使用标准库类中的指标处理类。

使用元素对元素的数据复制。用所有数据数组执行计算。

模型 结果 最佳结果
MODE_SMA 0,0998 0.000140(案例 6)
MODE_EMA 0,0997 0.000121(案例 6)
MODE_SMMA 0,0998 0.000117(案例 6)
MODE_LWMA 0,0998 0.0029(案例 2、5)
#include <Indicators\Trend.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
CiMA        objMA;
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test6();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test6()
  {
//--- 模式: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   objMA.BuffSize(count);
   objMA.Refresh(1);
   for(int i=0;i<count;i++)
     {
      buf[i]=objMA.Main(i);
     }
  }

4.5. 案例 4

在案例 4 中,使用标准库类中的指标处理类。

作为整体复制指标缓存的数组。用所有数据数组执行计算。

模型 结果 最佳结果
MODE_SMA 0,0996 0.000140(案例 6)
MODE_EMA 0,0996 0.000121(案例 6)
MODE_SMMA 0,0996 0.000117(案例 6)
MODE_LWMA 0,0996 0.0029(案例 2、5)
#include <Indicators\Trend.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
CiMA        objMA;
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test7();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test7()
  {
//--- 模式: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   objMA.BuffSize(count);
   objMA.Refresh(1);
   objMA.GetData(0,count,0,buf);          
  }

4.6. 案例 5

使用测试 8:使用 IndicatorCreate 函数创建指标句柄。

用所有数据数组执行计算。
模型 结果 最佳结果
MODE_SMA 0,0030 0.000140(案例 6)
MODE_EMA 0,0029 0.000121(案例 6)
MODE_SMMA 0,0029 0.000117(案例 6)
MODE_LWMA 0,0029 0.0029(案例 2、5)
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
double      MA[];                // 用于存放 iMA 指标数组
int         MA_handle;           // iMA 指标句柄
MqlParam    params[];
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   ArrayResize(params,4);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test8();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test8()
  {
//--- 模式: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
//--- 设置 ma_period
   params[0].type         =TYPE_INT;
   params[0].integer_value=periodMA;
//--- 设置 ma_shift
   params[1].type         =TYPE_INT;
   params[1].integer_value=0;
//--- 设置 ma_method
   params[2].type         =TYPE_INT;
   params[2].integer_value=MODE_SMA;
//--- 设置 applied_price
   params[3].type         =TYPE_INT;
   params[3].integer_value=P[p];
//--- 创建 MA
   MA_handle=IndicatorCreate(NULL,M[m],IND_MA,4,params);
   while(BarsCalculated(MA_handle)<count){}
   CopyBuffer(MA_handle,0,0,count,MA);
  }


4.7. 案例 6

在这个案例中,我们执行了 4 个模型的计算:案例 9 (SMA)、案例 10 (EMA)、案例 11 (SMMA) 和案例 12 (LWMA) 使用 MovingAverages.mqh 库函数(与来自 MQL4 的 iMAOnArray 类似的缓存函数)。

用所有数据数组执行计算。

模型 结果 最佳结果
MODE_SMA 0,000140 0.000140(案例 6)
MODE_EMA 0,000121 0.000121(案例 6)
MODE_SMMA 0,000117 0.000117(案例 6)
MODE_LWMA 0,00350 0.0029(案例 2、5)
#include <MovingAverages.mqh>
ENUM_TIMEFRAMES         M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE         P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[],arr[];
double      close[];
double      time;
int         count=10000,total;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------
//| 脚本程序初始函数                                                   |
//+------------------------------------------------------------------
int OnStart()
  {
   CopyClose(_Symbol,_Period,0,count,close);
   total=ArrayCopy(arr,close);
   if(ArrayResize(buf,total)<0) return(-1);
//---
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(arr,false);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         CopyClose(_Symbol,M[m],0,count,close);
         total=ArrayCopy(arr,close);
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test9();    // 测试在此
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------
void Test9()
  {
   SimpleMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
void Test10()
  {
   ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
void Test11()
  {
   SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
void Test12()
  {
   LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }

注: 我们已经计划在数组中使用几种类型的数据,但是为了简单起见,我们仅使用一个含有收盘价数据的数组(这不影响计算性能)。


5. 结果的输出

为了输出结果并检查移动平均线,我使用了 PrintTest 函数:

void PrintTest(const int position, const double &price[])
{
   Print("总计时间 [msec] ",(endGTC-startGTC));
   Print("性能 [sec] ",time);
   Print(position," - 数组元素 = ",price[position]);
}

可以按以下方式调用它(柱的位置和数据数组是函数的参数):

//---
   ArraySetAsSeries(buf,false);
   ArraySetAsSeries(close,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//--- 输出结果
   ArraySetAsSeries(buf,true);
   ArraySetAsSeries(close,true);
   PrintTest(0,buf);
   PrintTest(0,close);
//---

注意,数组索引在计算之前和计算之后是不同的。

重要须知:在计算期间,AsSeries 标记被设置为 false,在打印结果时,被设置为 true。


6. 其他调查

为了回答有关初始参数对计算性能的影响的问题,进行了某些其他测量。

如我们所记住的,案例 6 具有最佳性能,因此我们将使用它。

测试参数:

模式
时间框架
 平均周期
1
М1
144
2
М5
144
3
М15
144
4
М30
144
5
М1 21
6
М1 34
7
М1 55
8
М1 89
9
М1 233
10
М1 377
11
М1 610
12
М1 987

表 3. 其他调查

测试的源代码:

//+------------------------------------------------------------------
//| Test_SMA                                       Model: MODE_SMA   |
//+------------------------------------------------------------------
void Test_SMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   SimpleMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
//| Test_EMA                                       Model: MODE_EMA   |
//+------------------------------------------------------------------
void Test_EMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
//| Test_SMMA                                      Model: MODE_SMMA  |
//+------------------------------------------------------------------
void Test_SMMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------
//| Test_LWMA                                      Model: MODE_LWMA  |
//+------------------------------------------------------------------
void Test_LWMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }

对于其他测试,我们将使用自动测试程序,其图形用户界面如图 7 所示。

图 7. 用于自动测试的自动测试程序

图 7. 用于自动测试的自动测试程序

结果:(X 轴具有对数时间序列)

图 8. 时间框架参数 (Y) 和移动平均线计算性能 (X)

图 8. 时间框架参数 (Y) 和移动平均线计算性能 (X)

图 9. 周期参数 (Y) 和移动平均线计算性能 (X)

图 9. 周期参数 (Y) 和移动平均线计算性能 (X)

从其他调查的结果得出的结论

  1. 时间框架参数并不重要,它不影响计算性能(见图 8)。
  2. 对于模型 SMA、EMA 和 SMMA 的移动平均线计算的性能,周期并不是重要的参数。但是相反,它显著减慢 LWMA 模型的计算(从 0.00373 秒到 0.145 秒)。


总结

不正确地选择移动平均线算法会降低程序的计算性能。

全部回复

0/140

量化课程

    移动端课程