量化机器人吧 关注:855贴子:10,728
  • 0回复贴,共1

期货量化交易软件:测试移动平均类型以了解它们的洞察力。

只看楼主收藏回复

在我之前的文章中,赫兹期货量化软件探讨了最流行的移动平均线类型(简单、加权、指数):了解如何设计不同的移动平均系统。我们将在本文中继续这个主题,并使用简单类型将其结果与其他类型的移动平均线进行比较。许多交易者根据自己的偏好使用不同类型的移动平均线,因此,在本文中,我们将详细探讨它们的不同类型,测试它们的性能,并比较结果,以确定哪种类型的性能更好。出于本文的目的,我们将创建一个简单的应用程序,以便在内置的赫兹期货量化软件中执行平均指标的回测。要了解我们在研究测试结果时需要关注的内容,请查看我之前的文章理解并有效地使用 MQL5 策略测试器;它提供了很多有用的信息。为了探讨不同类型的移动平均线并了解它们的表现,我们将研究以下主题:请注意,尽管我会尝试优化每个移动平均线的设置以获得最佳结果,但您需要自己做更多的检查和测试,因为这里的目的只是教学。因此,您应该测试、优化并找到更好的设置,以便获得更好的结果。这种情况可能会发生,因此这些类型中的任何一种或全部都不适合您的交易风格。但我希望你能找到有助于改善交易的见解。一般来说,无论你遇到什么理想情况,在实际账户中使用任何交易策略之前,衡量其效果都很重要。免责声明:所有信息均按原样提供,仅用于教育目的,不用于交易目的或建议。这些信息不能保证任何结果。如果您选择在任何交易账户上使用这些材料,您将自行承担风险,并且您将承担唯一责任。简单移动平均(SMA)系统测试在这一部分中,我将分享简单系统的结果,该系统仅基于简单的一次移动平均策略。它寻找价格和简单移动平均线之间的交叉点,这将产生买入和卖出信号。赫兹期货量化软件将创建一个能够自动执行这些信号的系统,我们将使用以下信号进行交易操作:买入信号:收盘价高于简单移动平均值而且,之前的收盘价低于之前的简单移动平均值卖出信号:收盘价低于简单移动平均值而且,之前的收盘价高于之前的简单移动平均值如果你想了解简单均线和其他流行的均线类型,我建议你阅读我之前的文章了解如何设计不同的均线系统,这将有助于你很好地了解它们,也有助于很好地理解这篇文章。以下是创建这种类型的交易系统的步骤,该系统能够根据上述信号自动执行买卖订单。在全局范围内,我们将把Trade包含文件包括在软件中,该软件允许使用预处理器#include根据我们的信号执行订单。如果您想了解更多关于预处理器的信息,可以阅读文章有关MQL5程序结构的所有信息了解更多详细信息。#include <Trade\Trade.mqh>创建三个用户输入参数,分别为 double 型变量 lotSize、ENUM_TIMEFRAMES 变量 timeFrame、和整数变量 MAPeriod,根据用户需求进行更改,并启动它们的默认值:input double lotSize = 1;input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;input int MAPeriod= 50;创建两个整数变量 simpleMA 和 barsTotal 而不进行赋值,因为我们稍后将在OnInit()部分中定义它们。int simpleMA;int barsTotal;创建 CTrade 类的 trade 对象,以便轻松访问交易函数。CTrade trade;在OnInit()部分,我们将使用iMA函数来定义simpleMA,以返回移动平均指标的句柄,其参数为:
symbol:用于指定交易品种名称,我们将使用 _Symbol 作为当前交易品种
period:用于指定时间框架,我们将使用默认值为1小时的用户输入,但用户可以进行调整
ma_period:用于指定简单的移动平均周期,我们将使用默认值为50的用户输入,但用户也可以调整它
ma_shift:用于指定水平偏移,我们将使用0
applied_price:用于指定价格类型,我们将使用收盘价进行简单的移动平均线计算。
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);barsTotal 通过使用 iBars 函数返回柱数,其参数为:
symbol:用于指定交易品种,我们将使用(_Symbol)应用于当前交易品种
timeframe:用于指定时间框架,我们将使用创建的默认值为1小时的用户输入时间框架,用户可以对其进行调整
barsTotal=iBars(_Symbol,timeFrame);添加图片注释,不超过 140 字(可选)在OnTick()部分中,赫兹期货量化软件将创建两个数组,一个用于使用MqlRates存储价格、数量和价差信息的价格,另一个用于简单移动平均值: MqlRates priceArray[]; double mySMAArray[];使用 ArraySetAsSeries 函数为这两个创建的数组设置AS_SERIES标志,其参数为:
array[]: 使用引用方式指定数组
flag: 用于指定数组的索引方向
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);在创建两个 double 型变量后定义卖家出价和买家出价 double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);使用 CopyRates 函数获取 MqlRates 的历史数据,其参数为:
symbol_name: 用于确定交易品种名称
timeframe: 用于确定时间框架
start_pos: 用于指定起始位置
count: 用于指定要复制的数据量
rates_array[]: 用于指定复制的目标数组
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);使用 CopyBuffer 函数获取指标缓冲区的数据,其参数为:
indicator_handle: 用于指定指标句柄,此处为 simpleMA
buffer_num: 用于指定指标缓冲区编号,此处为0
start_pos: 用于确定起始位置,0表示当前烛形
count: 用于指定我们需要复制的数据量,此处为3
buffer[]: 用于指定我们需要复制的目标数组,此处为 mySMAArray
CopyBuffer(simpleMA,0,0,3,mySMAArray);创建两个 double 型变量,用于定义同一烛形的最后收盘价和简单移动平均值 double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);创建另外两个 double 型变量,用于定义上一个收盘价和同一蜡烛的简单移动平均值 double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);创建一个整型 bars 变量,用于和创建的 barsTotal 作比较int bars=iBars(_Symbol,timeFrame);通过检查 bars 和 barsTotal 是否相等来检查是否有新柱生成if(barsTotal != bars)如果 barsTotal 不等于 bars,我们需要用 bars 的值来更新 barsTotalbarsTotal=bars;如果 barsTotal 不等于 bars,我们还需要检查我们的策略条件,如果最后一次收盘的前一次低于同一烛形的简单移动平均值,并且同时最后一次的收盘价高于同一个烛形的简单运动平均值。我们需要该程序来关闭当前打开的头寸并打开买入头寸 if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); }如果最后一次收盘的前一个收盘价高于同一烛形的简单移动平均值,同时最后一次的收盘价低于同一个烛形的简单运动平均值。我们需要该程序来关闭当前打开的头寸并打开卖出头寸 if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); }然后我们将编译代码,我们会发现它编译后没有任何错误或警告。以下是一个代码块中的完整代码://+------------------------------------------------------------------+//| SMA_System.mq5 |//+------------------------------------------------------------------+#include <Trade\Trade.mqh>input double lotSize = 1;input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;input int MAPeriod= 50;int simpleMA;int barsTotal;CTrade trade;//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+int OnInit() { simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); }//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } }//+------------------------------------------------------------------+


IP属地:浙江1楼2024-04-30 16:13回复