当开发交易策略时,第一个任务就是设置入场交易的条件、跟踪仓位的方法和出场点。为此会使用各种数学、统计学和其它分析方法。它们通常被现成的、用于以指标形式评估市场特征的自治系统所强化。在制定任何交易策略时,一个主要问题是缺乏通用性。一个交易系统不能在所有可能的市场条件下以同等的效率运作。所以,交易者在开发EA交易时通常选择条件来侦测某种(潜在获利)的市场条件。
另外,每个交易系统都有自己的缺点,跟随趋势的策略在延长的盘整变化中会亏损,而基于盘整的策略在强方向变化时会错误进场,为了减少错误信号的影响,提高盈利能力,系统变得灵活,这意味着它们有一些特定的设置或输入数据,这是合理的,因为市场行为不断变化。
随着时间的推移,任何交易系统的效率都会降低,因此,有必要调整其参数以适应新的条件。内建的 MetaTrader 5 策略测试器就是解决这个问题的方法,此工具有助于分析历史上任何EA交易的性能,并为其在实际交易中的进一步使用定义最佳设置。
在本文中,我们将在更大范围内探讨策略测试器的应用。显然,大多数交易系统是双向交易(在特定条件下买卖)。图 1 显示了一个实际交易策略的简单例子,想法很简单 - 低买高卖。
图1. 趋势跟踪策略
通常,一组设置用于确定这样一个系统中的上升和下降趋势,并入场条件类似。但关键是,市场增长和下跌的具体情况在许多特征上可能非常不同,例如速度和持续时间。在这方面,我建议考虑一个系统,该系统分别确定上升趋势和下降趋势条件下的入场交易。
为了实现这一点,我们需要两组定义市场进入和退出条件的参数。在这一点上,我们提出了“分离优化”的概念。
分离优化意味着利用策略测试器为上升和下降趋势分别定义交易系统的最佳参数。
为了测试分离优化,我决定选择两个交易系统:跟随趋势的系统和基于盘整的系统。在跟随趋势的策略中,我们将分别优化上升和下降趋势,而在盘整策略中,我们将评估在通道中进行交易的优化。
我将使用 J. F. Ehlers 的重心指标,它表现为彩色的 OSMA 柱形图 (CenterOfGravityOSMA),来测试分离的优化。它的信号是由计算价格平均速度的指标确认的。
参数 | 描述 |
---|---|
使用的指标 | CenterOfGravityOSMA |
使用的指标 | 平均速度 |
时间框架 | H1 |
买入条件 | 重心指标的柱形图显示增长(指标值小于0), 而平均速度指标值高于阈值 (在参数中预设) |
卖出条件 | 重心指标的柱形图显示下跌(指标值大于0), 而平均速度指标值高于阈值 (在参数中预设) |
退场条件 | 获利/止损 |
策略在图2中显示从上表可以看出,交易策略明确了买入和卖出时进入市场的条件。由于这是一种趋势跟随策略,买入条件对应上升趋势,而卖出条件对应下降趋势。
图 2. 跟随趋势策略的入场条件
在 MetaEditor 中实施该策略时,我们应该设置EA工作条件,以便它只能在上升趋势、下降趋势或这两种情况下使用。
我们也应当考虑下面这些:
要满足这些EA开发条件,输入以下代码:
//+------------------------------------------------------------------+ //| 操作模式枚举 | //+------------------------------------------------------------------+ enum Trend_type { UPTREND = 1, //上升趋势 DOWNTREND, //下降趋势 BOTH //两种趋势 };
输入参数集看起来如下:
//+------------------------------------------------------------------+ //| EA 的输入参数 | //+------------------------------------------------------------------+ input string Inp_EaComment="Trend Strategy"; //EA 注释 input double Inp_Lot=0.01; //手数 input MarginMode Inp_MMode=LOT; //资金管理 input Trend_type Inp_Trend_type=3; //趋势类型 //--- 上升趋势参数 input string Inp_Str_label1="===Uptrend parameters==="; //标签 input int Inp_MagicNum1=1111; //幻数 input int Inp_StopLoss1=40; //止损(点数) input int Inp_TakeProfit1=60; //获利(点数) //--- CenterOfGravityOSMA 指标参数 input uint Period_1=9; //平均周期数 input uint SmoothPeriod1_1=3; //平滑周期数1 input ENUM_MA_METHOD MA_Method_1_1=MODE_SMA; //平均方法1 input uint SmoothPeriod2_1=3; //平滑周期数2 input ENUM_MA_METHOD MA_Method_2_1=MODE_SMA; //平均方法2 input Applied_price_ AppliedPrice1=PRICE_OPEN_; //使用的价格 //--- 平均速度指标的参数 input int Inp_Bars1=1; //天数 input ENUM_APPLIED_PRICE Price1=PRICE_CLOSE; //使用的价格 input double Trend_lev1=2; //趋势水平 //--- 下降趋势参数 input string Inp_Str_label2="===Downtrend parameters==="; //标签 input int Inp_MagicNum2=2222; //幻数 input int Inp_StopLoss2=40; //止损(点数) input int Inp_TakeProfit2=60; //获利(点数) //--- CenterOfGravityOSMA 指标参数 input uint Period_2=9; //平均周期数 input uint SmoothPeriod1_2=3; //平滑周期数1 input ENUM_MA_METHOD MA_Method_1_2=MODE_SMA; //平均方法1 input uint SmoothPeriod2_2=3; //平滑周期数2 input ENUM_MA_METHOD MA_Method_2_2=MODE_SMA; //平均方法2 input Applied_price_ AppliedPrice2=PRICE_OPEN_; //使用的价格 //--- 平均速度指标的参数 input int Inp_Bars2=1; //天数 input ENUM_APPLIED_PRICE Price2=PRICE_CLOSE; //使用的价格 input double Trend_lev2=2; //趋势水平
我们可以在代码中看到, Inp_Trend_type 变量是用于选择EA运行模式的, 而针对Uptrend(上升趋势) 和 Downtrend(下降趋势) 模式,分别分离为 'Uptrend parameters(上升趋势参数)' 和 'Downtrend parameters(下降趋势参数)' 。当选择 Both 模式时,两个部分的参数都会使用,而主要逻辑实现的代码在下面提供:
//+------------------------------------------------------------------+ //| EA交易分时函数 | //+------------------------------------------------------------------+ void OnTick() { //--- 取得计算数据 if(!GetIndValue()) return; if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1)) { //--- 如果有买入信号,开启订单 if(BuySignal()) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment); } else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2)) { //--- 如果有卖出信号,开启订单 if(SellSignal()) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment); } else if(Inp_Trend_type==3) { //--- 如果有买入信号,开启订单 if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1)) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment); //--- 如果有卖出信号,开启订单 if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2)) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment); } } //+------------------------------------------------------------------+ //| 买入条件 | //+------------------------------------------------------------------+ bool BuySignal() { return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false; } //+------------------------------------------------------------------+ //| 卖出条件 | //+------------------------------------------------------------------+ bool SellSignal() { return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false; } //+------------------------------------------------------------------+ //| 取得当前指标值 | //+------------------------------------------------------------------+ bool GetIndValue() { return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0 || CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0 || CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 || CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0 )?false:true; } //+------------------------------------------------------------------+
针对上升趋势和下降趋势模式的交易规则都很简单: 在上升趋势时买入而在下降趋势时卖出,也就是跟随趋势。在 Both 模式下,这些系统一起工作并且相互独立使用它们自己的输入参数 — Uptrend+Downtrend。
对于所选策略的测试和单独优化,可以合理地为上升模式选择清晰的上升期,为下降模式选择下降期。所以,我决定选择下面图3中显示的时间段。
图 3. 选择用于测试的时间段
这样,让我们总结以下测试设置。
测试和优化的目标是在策略中使用的指标参数,以及止损和获利值。
上升趋势的优化结果如下:
图 4. 对于上升趋势的测试和优化结果
对于下降趋势的优化结果如下:
图 5. 对于下降趋势的测试和优化结果
在使用对所选模式有利的时间间隔进行优化来定义最佳参数后,是时候在既有向上趋势又有向下趋势的混合间隔上尝试这些参数。这将使我们能够测试交易策略的通用性。
我决定选择以下时间间隔,这非常适合上述要求。
图 6. 为混合测试选择的时间段
我们可以在图6中看到,这个时间段都含有上升和下降趋势以及回滚和盘整的时间段。现在让我们看看EA在这段不熟悉的时间段上的表现。
图 7. 优化趋势跟踪策略在不利区间的检验结果
考虑到这一趋势的测试结果遵循策略,我们可以得出以下结论:
为了在盘整的市场上进行单独的优化,我选择了威廉姆斯的百分比范围来确定超买/超卖状态。此工具将作为搜索入场点的主要指标,ADX 跟随趋势指标将用作没有趋势的确认。
参数 | 描述 |
---|---|
使用的指标 | 威廉姆斯百分比范围(WPR) |
使用的指标 | ADX |
时间框架 | H1 |
买入条件 | WPR 指标在超卖区域 (低于 -80) 而 ADX 在阈值以下。 |
卖出条件 | WPR 指标在超买区域 (高于 -20) 而 ADX 在阈值以下。 |
退场条件 | 获利/止损 |
图 8 为根据这个策略入场提供了一个可视化的例子。
图 8. 根据盘整策略的入场条件
根据选择的策略,将按交易类型进行单独优化:在Buy和Sell模式下。
//+------------------------------------------------------------------+ //| 操作模式枚举 | //+------------------------------------------------------------------+ enum Trend_type { UPTREND = 1, //买入 DOWNTREND, //卖出 BOTH //同时 };
通过这种方法,就能够判断在盘整条件下如何选择策略了。EA 代码在下面提供:
//+------------------------------------------------------------------+ //| EA交易分时函数 | //+------------------------------------------------------------------+ void OnTick() { //--- 取得计算数据 if(!GetIndValue()) return; if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1)) { //--- 如果有买入信号,开启订单 if(BuySignal()) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment); } else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2)) { //--- 如果有卖出信号,开启订单 if(SellSignal()) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment); } else if(Inp_Trend_type==3) { //--- 如果有买入信号,开启订单 if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1)) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment); //--- 如果有卖出信号,开启订单 if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2)) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment); } } //+------------------------------------------------------------------+ //| 买入条件 | //+------------------------------------------------------------------+ bool BuySignal() { return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false; } //+------------------------------------------------------------------+ //| 卖出条件 | //+------------------------------------------------------------------+ bool SellSignal() { return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false; } //+------------------------------------------------------------------+ //| 取得当前的指标值 | //+------------------------------------------------------------------+ bool GetIndValue() { return(CopyBuffer(InpInd_Handle1,0,0,2,wpr1)<=0 || CopyBuffer(InpInd_Handle2,0,0,2,wpr2)<=0 || CopyBuffer(InpInd_Handle3,0,0,2,adx1)<=0 || CopyBuffer(InpInd_Handle4,0,0,2,adx2)<=0 )?false:true; } //+------------------------------------------------------------------+
与测试趋势跟踪策略类似,我们应该首先选择一个历史段进行培训,并优化所选的基于盘整的策略。下面的图片显示了测试时间段:
图 9. 选定的用于盘整策略的时间段
一般的测试条件看起来如下:
获利和止损参数将在测试和优化中使用。在 Buy 模式 下的独立优化结果显示在下面的表格中。
图 10. Buy模式下的基于盘整的策略优化结果
在 Sell 模式下的独立优化结果显示如下:
图 11. Sell模式下的基于盘整策略的优化结果
在使用单独的优化为两种模式定义了最佳参数之后,是时候检查不利区间的策略,并了解它在新条件下的行为。作为一个实验,我们将选择已经被选择用来测试趋势跟踪策略的非盘整市场区间(如图6所示)。我们将其用于两种模式下趋势跟踪策略的混合测试 (Uptrend+Downtrend).
结果如下:
图 12. 基于不利区间的盘整优化策略的测试结果
考虑到该策略是基于盘整的,而测试区间具有较长的趋势运动,取得了良好的效果,并显示出了盈利。
我们将趋势跟踪和基于盘整的策略作为单独优化的示例。两种策略分为两个部分,分别针对有利的市场进行培训和优化。此外,在未知的市场区间内对它们的生存能力进行了测试,结果非常不错。现在,让我们看看在更宽泛的时间间隔内结合上述两种策略的策略。但首先,我们应该把这两种策略结合起来。
在代码中实施该策略后,立即设置趋势跟踪的两种模式和基于盘整的两种模式的优化参数:
//+------------------------------------------------------------------+ //| EA 的输入参数 | //+------------------------------------------------------------------+ input string Inp_EaComment="Universe Strategy"; //EA 注释 input double Inp_Lot=0.01; //手数 input MarginMode Inp_MMode=LOT; //资金管理 //--- 上升趋势参数 input string Inp_Str_label1="===Uptrend parameters==="; //标签 input int Inp_MagicNum1=1111; //幻数 input int Inp_StopLoss1=50; //止损(点数) input int Inp_TakeProfit1=55; //获利(点数) //--- CenterOfGravityOSMA 指标参数 input uint Period_1=9; //平均周期数 input uint SmoothPeriod1_1=3; //平滑周期数1 input ENUM_MA_METHOD MA_Method_1_1=MODE_SMA; //平均方法1 input uint SmoothPeriod2_1=3; //平滑周期数2 input ENUM_MA_METHOD MA_Method_2_1=MODE_SMA; //平均方法2 input Applied_price_ AppliedPrice1=PRICE_TRENDFOLLOW1_; //使用的价格 //--- 平均速度指标的参数 input int Inp_Bars1=1; //天数 input ENUM_APPLIED_PRICE Price1=PRICE_LOW; //使用的价格 input double Trend_lev1=1.6; //趋势水平 //--- 下降趋势参数 input string Inp_Str_label2="===Downtrend parameters==="; //标签 input int Inp_MagicNum2=2222; //幻数 input int Inp_StopLoss2=40; //止损(点数) input int Inp_TakeProfit2=70; //获利(点数) //--- CenterOfGravityOSMA 指标参数 input uint Period_2=15; //平均周期数 input uint SmoothPeriod1_2=3; //平滑周期数1 input ENUM_MA_METHOD MA_Method_1_2=MODE_SMA; //平均方法1 input uint SmoothPeriod2_2=3; //平滑周期数2 input ENUM_MA_METHOD MA_Method_2_2=MODE_SMA; //平均方法2 input Applied_price_ AppliedPrice2=PRICE_HIGH_; //使用的价格 //--- 平均速度指标的参数 input int Inp_Bars2=1; //天数 input ENUM_APPLIED_PRICE Price2=PRICE_WEIGHTED; //使用的价格 input double Trend_lev2=1.0; //趋势水平 //--- Buy parameters input string Inp_Str_label3="===Buy parameters==="; //标签 input int Inp_MagicNum3=3333; //幻数 input int Inp_StopLoss3=40; //止损(点数) input int Inp_TakeProfit3=60; //获利(点数) //--- WPR indicator parameters input int Inp_WPRPeriod1=11; //WPR 周期数 //--- ADX indicator parameters input int Inp_ADXPeriod1=13; //ADX 周期数 input int Inp_FlatLevel1=25; // ADX 盘整水平 //--- Sell parameters input string Inp_Str_label4="===Sell parameters==="; //标签 input int Inp_MagicNum4=4444; //幻数 input int Inp_StopLoss4=30; //止损(点数) input int Inp_TakeProfit4=30; //获利(点数) //--- WPR indicator parameters input int Inp_WPRPeriod2=7; //WPR 周期数 //--- ADX indicator parameters input int Inp_ADXPeriod2=15; //ADX 周期数 input int Inp_FlatLevel2=40; // ADX 盘整水平
此外,由于组合的EA不受培训或优化的影响,因此已取消设置模式的选项。策略本身实现如下:
//+------------------------------------------------------------------+ //| EA交易分时函数 | //+------------------------------------------------------------------+ void OnTick() { //--- 取得计算数据 if(!GetIndValue()) return; //--- 如果有买入信号 (跟随趋势策略) 就开启订单 if(BuySignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum1)) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment); //--- 如果有卖出信号(跟随趋势策略)就开启订单 if(SellSignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum2)) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment); //--- 如果有买入信号 (盘整策略)就开启订单 if(BuySignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum3)) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss3,Inp_TakeProfit3,Inp_MagicNum3,Inp_EaComment); //--- 如果有卖出信号 (盘整策略) 就开启订单 if(SellSignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum4)) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss4,Inp_TakeProfit4,Inp_MagicNum4,Inp_EaComment); } //+------------------------------------------------------------------+ //| 买入条件 (跟随趋势策略) | //+------------------------------------------------------------------+ bool BuySignal_1() { return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false; } //+------------------------------------------------------------------+ //| 卖出条件 (跟随趋势策略) | //+------------------------------------------------------------------+ bool SellSignal_1() { return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false; } //+------------------------------------------------------------------+ //| 买入条件 (基于盘整策略) | //+------------------------------------------------------------------+ bool BuySignal_2() { return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false; } //+------------------------------------------------------------------+ //| 卖出条件 (基于盘整策略) | //+------------------------------------------------------------------+ bool SellSignal_2() { return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false; } //+------------------------------------------------------------------+ //| 取得当前指标值 | //+------------------------------------------------------------------+ bool GetIndValue() { return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0 || CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0 || CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 || CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0 || CopyBuffer(InpInd_Handle5,0,0,2,wpr1)<=0 || CopyBuffer(InpInd_Handle6,0,0,2,wpr2)<=0 || CopyBuffer(InpInd_Handle7,0,0,2,adx1)<=0 || CopyBuffer(InpInd_Handle8,0,0,2,adx2)<=0 )?false:true; } //+------------------------------------------------------------------+
这两种策略的四种模式都是相互独立工作的,训练后都有自己的参数集,不以任何方式相互交叉。为了测试,我决定使用更大的范围——过去三年。全部测试条件列表如下:
测试结果如下:
图 13. 组合策略的测试结果
没有进行对参数新的优化。参数取自在有利区间的单独优化过程中确定的最佳值。考虑到这四个独立的策略在共同的不利条件下运作,其结果是正面的。
通过对比两种策略在上升趋势、下降趋势和盘整条件下的测试结果,得出以下结论:
考虑到我选择了随机交易系统进行测试,并通过单独优化对其进行了改进,对最不利的历史区间进行了最终检查,本研究的结果是积极的。结果表明,分离优化方法具有较好的效率,值得在交易系统的开发和配置中应用。
附加的存档包含所有列出的文件,这些文件位于相应的文件夹中。要执行正确的操作,应将mql5文件夹保存到终端的根目录。
本文使用的程序:
# |
名称 |
类型 |
描述 |
---|---|---|---|
1 |
TrendStrategy.mq5 | EA |
基于跟随趋势策略的EA。 |
2 |
FlatStrategy.mq5 | EA | 基于盘整策略的EA。 |
3 | UniverseStrategy.mql5 | EA | 基于组合策略的EA。 |
4 | Trade.mqh | 库 | 交易函数类。 |
5 |
average_speed.mq5 | 指标 | 在跟随趋势策略中使用的平均价格速度指标。 |
6 | centerofgravityosma.mq5 | 指标 | 用于跟随趋势策略的 Ehlers 的重心指标。 |
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程