我收到上一篇文章的一位读者的提议,对回测过程稍加自动化,以实现同时获得所有优化结果的可能性。此外,手动改变测试周期不是很方便,该过程也应该自动化。这个想法非常棒。而且,MQL4完全可以实现。所以,我将从问题的解决方法开始讲述。
要完成该任务我们需要:
1.在所需的Expert Advisor标头下面写入一行,内容如下:
// + =============================================== =================== + // | 自定义BackTesting功能| // + =============================================== =================== + #include <IsBackTestingTime.mqh>
使用该指令,将IsBackTestingTime()函数加入EA代码。不要忘记将IsBackTestingTime.mqh文件放入INCLUDE文件夹。该函数:
bool IsBackTestingTime() { }
用于定义时间周期,在该时间内进行回测优化或回测。在该时间周期内,函数始终返回'真',在其他时间则返回'假'。除了这个函数,通过以下指令将外部EA变量添加到EA代码:
// 用于回测外部 日期时间的外部变量声明 Start_Time = D'2007.01.01' ; //零优化的开始时间extern int Opt_Period = 3 ; //以月为单位的优化周期,如果小于零,则参数以天为单位extern int Test_Period = 2 ; //测试周期以月为单位extern int Period_Shift = 1 ; //优化周期的步骤以月为单位extern int Opt_Number = 0 ; //优化编号
希望这些变量的含义对于读了我上一篇文章的人都很清楚,这里就不再解释。
2.在EA代码前的开始函数程序块设置调用IsBackTestingTime()函数的最简单的通代代码,根据回测优化的数量将EA运行限制在特定的时间范围。
// + 如果(!IsBackTestingTime()) 返回(0),则执行回测条件 ;
它的示意图如下:
// + =============================================== =================== + // | Exp_BackTest.mq4 | // | 版权所有©2008,Nikolay Kositsin | // | 哈巴罗夫斯克,farria @ mail.redcom.ru | // + =============================================== =================== + #property copyright “Copyright©2008,Nikolay Kositsin” #property link “farria@mail.redcom.ru” // + ==== ================================================== ============ + // | 自定义BackTesting功能| // + =============================================== =================== + #include<IsBackTestingTime.mqh> // EA的输入参数// EA的全球变量// + ==================== ============================================== + // | 用户自定义EA的功能| // + =============================================== =================== + // + =============================================== =================== + // | 自定义专家初始化功能| // + =============================================== =================== + int init() {// + + + // EA初始化的代码// + + + / / 初始化结束 返回(0); }// + =============================================== =================== + // | 自定义专家迭代功能| // + =============================================== =================== + int start() { // + 如果(!IsBackTestingTime()) 返回(0),则执行回测条件 ; // + + - + // + EA算法的代码 // + + - + // + return(0); }// + - - +
如果你对现成EA示例上的详细问题解决方案感兴趣,查看EA代码Exp_5_1.mq4,源于上一篇文章中的Exp_5.mq4,经修改后用于回测。实际上,与简单的EA交易相比,这种EA的优化没有多大不同。但是,我认为除了Opt_Number变量外,回测变量应该进行优化,不过你可能有不同的看法。
重要的是记住:在测试优化后,我们得到的不是优化期间的结果,而是在其之后(右侧边界之外)的结果使用遗传算法在一次运行内进行所有的回测优化并非最好的决定,在没有优化输入变量Opt_Number的情况下,单独深入分析每个回测优化更加有趣。
但即使在这种情况下,这种方法也促进了对EA行为的理解。应该记住,外部变量Opt_Number的值可以从零变化到某个最大值,该最大值可以使用以下方式定义:从执行所有回测优化的总周期(月数)减去回测优化周期的月数(Opt_Period)和减去回测周期(Test_Period)。获得的值加一。如果Period_Shift等于一,获得的结果将是Opt_Number变量的最大值。
这种交易系统的变体非常普遍现在我们来分析奠定这种策略的算法对于做多头寸,输入的算法如下。:
对于做空头寸,则如下:
可以使用在指标中定义平均线的具有不同参数的两条相同移动线。假设定义MovA移动平均线的参数始终小于MovB移动平均线的同一参数。这样,在该交易系统中,MovA是快速移动线,MovB是慢速线。下面是基于两条JMA移动线的交易系统的实现变体:
// + =============================================== =================== + // | Exp_6.mq4 | // | 版权所有©2007,Nikolay Kositsin | // | 哈巴罗夫斯克,farria @ mail.redcom.ru | // + =============================================== =================== + #property copyright “Copyright©2007,Nikolay Kositsin” #property link “farria@mail.redcom.ru” // + + - + // EA INPUT参数购买交易extern bool Test_Up = true ;//交易计算方向过滤器extern int Timeframe_Up = 240 ;extern double Money_Management_Up = 0.1 ;extern int LengthA_Up = 4 ; //快速移动的extern int的平滑深度 PhaseA_Up = 100 ; //参数改变的范围内 // - 100 ... 100,影响快速移动的瞬态过程的质量的extern INT IPCA_Up = 0 ; / *选择指标所在的价格通过快速移动计算(0-CLOSE,1-OPEN,2-HIGH,3-LOW,4-MEDIAN,5-TYPICAL, 6-WEIGHTED,7-Heiken Ashi Close,8-SIMPL,9-TRENDFOLLOW,10-0.5 * TRENDFOLLOW, 11-Heiken Ashi Low,12-Heiken Ashi High,13-Heiken Ashi Open, 14-Heiken Ashi Close。)* / extern int LengthB_Up = 4 ; //平滑深度增量缓慢移动到快速一个外部 int PhaseB_Up = 100 ; //参数在 // - 100 ... +100 范围内变化,影响慢速运动瞬态过程的质量; extern int IPCB_Up = 0 ; / *选择指标所在的价格缓慢移动计算(0-CLOSE,1-OPEN,2-HIGH,3-LOW,4-MEDIAN,5-TYPICAL, 6-WEIGHTED,7-Heiken Ashi Close,8-SIMPL,9-TRENDFOLLOW,10-0.5 * TRENDFOLLOW, 11-Heiken Ashi Low,12-Heiken Ashi High,13-Heiken Ashi Open, 14-Heiken Ashi Close。)* / extern int STOPLOSS_Up = 50 ; //止损extern int TAKEPROFIT_Up = 100 ; //获取利润extern bool ClosePos_Up = true ; //允许强制关闭位置// + + - + // 出售交易的EA输入参数extern bool Test_Dn = true ; //交易计算方向过滤器extern int Timeframe_Dn = 240 ;EXTERN double Money_Management_Dn = 0.1 ;extern int LengthA_Dn = 4 ; //快速移动的extern int的平滑深度 PhaseA_Dn = 100 ; //参数在 // -100 ... +100 范围内变化,影响快速移动瞬态过程的质量; extern int IPCA_Dn = 0 ; / *选择指标所在的价格通过快速移动计算(0-CLOSE,1-OPEN,2-HIGH,3-LOW,4-MEDIAN,5-TYPICAL, 6-WEIGHTED,7-Heiken Ashi Close,8-SIMPL,9-TRENDFOLLOW,10-0.5 * TRENDFOLLOW, 11-Heiken Ashi Low,12-Heiken Ashi High,13-Heiken Ashi Open, 14-Heiken Ashi Close。)* / extern int LengthB_Dn = 4 ; //平滑深度增量缓慢移动到快速一个外部 int PhaseB_Dn = 100 ; //参数在 // -100 ... +100 范围内变化,影响慢速运动的瞬态过程质量; extern int IPCB_Dn = 0 ; / *选择指标所在的价格缓慢移动计算(0-CLOSE,1-OPEN,2-HIGH,3-LOW,4-MEDIAN,5-TYPICAL, 6-WEIGHTED,7-Heiken Ashi Close,8-SIMPL,9-TRENDFOLLOW,10-0.5 * TRENDFOLLOW, 11-Heiken Ashi Low,12-Heiken Ashi High,13-Heiken Ashi Open, 14-Heiken Ashi Close。)* / extern int STOPLOSS_Dn = 50 ; //止损extern int TAKEPROFIT_Dn = 100 ; //获取利润extern bool ClosePos_Dn = true ; //允许强制关闭位置// + + - + // 最小计算条的整数变量int MinBar_Up,MinBar_Dn;// + =============================================== =================== + // | 自定义专家功能|// + =============================================== =================== + #include <Lite_EXPERT1.mqh> // + ==================== ============================================== + // | 自定义专家初始化功能| // + =============================================== =================== + int init() {// 检查Timeframe_Up变量值的正确性 if(Timeframe_Up!= 1) if(Timeframe_Up!= 5) if(Timeframe_Up!= 15) if(Timeframe_Up!= 30) if(Timeframe_Up!= 60)if(Timeframe_Up!= 60) if( Timeframe_Up!= 240) if(Timeframe_Up!= 1440) Print(StringConcatenate(“参数Timeframe_Up不能”, “等于”,Timeframe_Up,“!!!” ));// 检查Timeframe_Dn变量值的正确性 if(Timeframe_Dn!= 1) if(Timeframe_Dn!= 5) if(Timeframe_Dn!= 15) if(Timeframe_Dn!= 30) if(Timeframe_Dn!= 60)if(Timeframe_Dn!= 60) if( Timeframe_Dn!= 240) if(Timeframe_Dn!= 1440) Print(StringConcatenate(“参数Timeframe_Dn不能”), “等于”,Timeframe_Dn,“!!!” )); // 变量的初始化 MinBar_Up = 4 + 30 ; MinBar_Dn = 4 + 30 ; // 初始化结束 返回(0); }// + =============================================== =================== + // | 专家取消初始化功能| // + =============================================== =================== + int deinit() {// + // EA deinitialization 返回结束(0);// + }// + =============================================== =================== + // | 自定义专家迭代功能| // + =============================================== =================== + int start() { // +声明局部变量 int bar; 双 MovA [ 2 ],MovB [ 2 ]; // +声明静态变量 static int LastBars_Up,LastBars_Dn; static bool BUY_Sign,BUY_Stop,SELL_Sign,SELL_Stop; // ++ 长期位置代码if(Test_Up) { int IBARS_Up = iBars(NULL,Timeframe_Up); if(IBARS_Up> = MinBar_Up) { if(LastBars_Up!= IBARS_Up) { // +变量的初始化 BUY_Sign = false ; BUY_Stop = false ; LastBars_Up = IBARS_Up; // +计算指示符值和上载他们BUFFERS 为(巴= 1 ;栏< 3 ;巴++) MovA [bar - 1 ] = iCustom(NULL,Timeframe_Up, “JJMA”,LengthA_Up,PhaseA_Up, 0,IPCA_Up,0,bar); for(bar = 1 ; bar < 3 ; bar ++) MovB [bar - 1 ] = iCustom(NULL,Timeframe_Up, “JJMA”,LengthA_Up + LengthB_Up,PhaseB_Up, 0,IPCB_Up,0,bar); // +定义交易信号 if(MovA [ 1 ] <MovB [ 1 ]) if(MovA [ 0 ]> MovB [ 0 ]) BUY_Sign = true ; if(MovA [ 0 ]> MovB [ 0 ]) BUY_Stop = true ; } // +交易的执行 if(!OpenBuyOrder1(BUY_Sign,1,Money_Management_Up, STOPLOSS_Up,TAKEPROFIT_Up)) 返回( - 1); if(ClosePos_Up ) if(!CloseOrder1(BUY_Stop,1)) return( - 1); } } // ++用于短位置的代码 if(Test_Dn) { int IBARS_Dn = iBars(NULL,Timeframe_Dn); if(IBARS_Dn> = MinBar_Dn) { if(LastBars_Dn!= IBARS_Dn) { // +变量的初始化 SELL_Sign = false ; SELL_Stop = false ; LastBars_Dn = IBARS_Dn; // +计算指示符值和上载他们BUFFERS 为(巴= 1 ;栏< 3 ;巴++) MovA [bar - 1 ] = iCustom(NULL,Timeframe_Dn, “JJMA”,LengthA_Dn,PhaseA_Dn, 0,IPCA_Dn,0,bar); for(bar = 1 ; bar < 3 ; bar ++) MovB [bar - 1 ] = iCustom(NULL,Timeframe_Dn, “JJMA”,LengthA_Dn + LengthB_Dn,PhaseB_Dn, 0,IPCB_Dn,0,bar); // +定义交易信号 if(MovA [ 1 ]> MovB [ 1 ]) if(MovA [ 0 ] <MovB [ 0 ]) SELL_Sign = true ; if(MovA [ 0 ] <MovB [ 0 ]) SELL_Stop = true ; } // +交易的执行 if(!OpenSellOrder1(SELL_Sign,2,Money_Management_Dn, STOPLOSS_Dn,TAKEPROFIT_Dn)) 返回( - 1); if(ClosePos_Dn ) if(!CloseOrder1(SELL_Stop,2)) return( - 1); } }// + return(0); }// + - - +
这种交易策略不仅可以使用移动线,还可以使用震荡指标,但对于后者,根据上一篇文章所写,最好设置挂单,而不是在收到信号后立即进入市场。可以使用NACD图表作为生动的示例。
要设置BuyLimit挂单,算法如下:
下面是用于SellLimit类型订单的算法:
该EA的代码跟之前EA的代码类似:
// + =============================================== =================== + // | Exp_7.mq4 | // | 版权所有©2007,Nikolay Kositsin | // | 哈巴罗夫斯克,farria @ mail.redcom.ru | // + =============================================== =================== + #property copyright “Copyright©2007,Nikolay Kositsin” #property link “farria@mail.redcom.ru” // + + - + // EA INPUT参数购买交易extern bool Test_Up = true ;//交易计算方向过滤器extern int Timeframe_Up = 240 ;extern double Money_Management_Up = 0.1 ;extern int FST_period_Up = 12 ; //快速移动的时间段extern int SLO_period_Up = 22 ; //缓慢移动到快速一个外部的 句点增量int SIGN_period_Up = 8 ; //信号线的周期extern int Price_Up = 0 ; //选择计算MACD的价格extern int STOPLOSS_Up = 50 ; //止损extern int TAKEPROFIT_Up = 100 ; // take profit extern int PriceLevel_Up = 40 ; // 触发extern bool 的当前价格和//挂单价格之间的差异 ClosePos_Up = true ; //允许强制关闭位置// + + - + // EA INPUT PARAMETERS FOR卖出交易的extern 布尔 Test_Dn = 真 ;//交易计算方向过滤器extern int Timeframe_Dn = 240 ;extern double Money_Management_Dn = 0.1 ;extern int FST_period_Dn = 12 ; //快速移动的时间段extern int SLO_period_Dn = 22 ; //缓慢移动到快速一个外部的 句点增量int SIGN_period_Dn = 8 ; //信号线的周期extern int Price_Dn = 0 ; //选择计算MACD的价格extern int STOPLOSS_Dn = 50 ; //止损extern int TAKEPROFIT_Dn = 100 ; //获取利润extern int PriceLevel_Dn = 40 ; //当前价格和 //挂单的价格之间的差异触发extern bool ClosePos_Dn = true ; //允许强制关闭位置// + + - + // 整数变量的计算条最小诠释 MinBar_Up,MinBar_Dn;// + =============================================== =================== + // | 自定义专家功能| // + =============================================== =================== + #include <Lite_EXPERT1.mqh> // + ==================== ============================================== + // | 自定义专家初始化功能| // + =============================================== =================== + int init() {// 检查Timeframe_Up变量值的正确性 if(Timeframe_Up!= 1) if(Timeframe_Up!= 5) if(Timeframe_Up!= 15) if(Timeframe_Up!= 30) if(Timeframe_Up!= 60)if(Timeframe_Up!= 60) if( Timeframe_Up!= 240) if(Timeframe_Up!= 1440) Print(StringConcatenate(“参数Timeframe_Up不能”, “等于”,Timeframe_Up,“!!!” ));// 检查Timeframe_Dn变量值的正确性 if(Timeframe_Dn!= 1) if(Timeframe_Dn!= 5) if(Timeframe_Dn!= 15) if(Timeframe_Dn!= 30) if(Timeframe_Dn!= 60)if(Timeframe_Dn!= 60) if( Timeframe_Dn!= 240) if(Timeframe_Dn!= 1440) Print(StringConcatenate(“参数Timeframe_Dn不能”), “等于”,Timeframe_Dn,“!!!” )); // 变量的初始化 MinBar_Up = 4 + FST_period_Up + SLO_period_Up + SIGN_period_Up; MinBar_Dn = 4 + FST_period_Dn + SLO_period_Dn + SIGN_period_Dn; // 初始化结束 返回(0); }// + =============================================== =================== + // | 专家取消初始化功能| // + =============================================== =================== + int deinit() {// + // EA deinitialization 返回结束(0);// + }// + =============================================== =================== + // | 自定义专家迭代功能| // + =============================================== =================== + int start() { // +声明局部变量 int bar; 双 MovA [ 2 ],MovB [ 2 ]; // +声明静态变量 static int LastBars_Up,LastBars_Dn; static datetime StopTime_Up,StopTime_Dn; static bool BUY_Sign,BUY_Stop,SELL_Sign,SELL_Stop; // ++ 长期位置代码if(Test_Up) { int IBARS_Up = iBars(NULL,Timeframe_Up); if(IBARS_Up> = MinBar_Up) { if(LastBars_Up!= IBARS_Up) { // +变量的初始化 BUY_Sign = false ; BUY_Stop = false ; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL,Timeframe_Up,0) + 60 * Timeframe_Up; // +计算指示符值和上载他们BUFFERS 为(巴= 1 ;栏< 3 ;巴++) MovA [bar - 1 ] = iMACD(NULL,Timeframe_Up, FST_period_Up,FST_period_Up + SLO_period_Up, SIGN_period_Up,Price_Up,0,bar); for(bar = 1 ; bar < 3 ; bar ++) MovB [bar - 1 ] = iMACD(NULL,Timeframe_Up, FST_period_Up,FST_period_Up + SLO_period_Up, SIGN_period_Up,Price_Up,1,bar); // +定义交易信号 if(MovA [ 1 ] <MovB [ 1 ]) if(MovA [ 0 ]> MovB [ 0 ]) BUY_Sign = true ; if(MovA [ 0 ]> MovB [ 0 ]) BUY_Stop = true ; } // +交易的执行 if(!OpenBuyLimitOrder1(BUY_Sign,1, Money_Management_Up,STOPLOSS_Up,TAKEPROFIT_Up, PriceLevel_Up,StopTime_Up)) 返回( - 1); if(ClosePos_Up ) if(!CloseOrder1(BUY_Stop,1)) return( - 1); } } // ++用于短位置的代码 if(Test_Dn) { int IBARS_Dn = iBars(NULL,Timeframe_Dn); if(IBARS_Dn> = MinBar_Dn) { if(LastBars_Dn!= IBARS_Dn) { // +变量的初始化 SELL_Sign = false ; SELL_Stop = false ; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL,Timeframe_Dn,0) + 60 * Timeframe_Dn; // +计算指示符值和上载他们BUFFERS 为(巴= 1 ;栏< 3 ;巴++) MovA [bar - 1 ] = iMACD(NULL,Timeframe_Dn, FST_period_Dn,FST_period_Dn + SLO_period_Dn, SIGN_period_Dn,Price_Dn,0,bar); for(bar = 1 ; bar < 3 ; bar ++) MovB [bar - 1 ] = iMACD(NULL,Timeframe_Dn, FST_period_Dn,FST_period_Dn + SLO_period_Dn, SIGN_period_Dn,Price_Dn,1,bar); // +定义交易信号 if(MovA [ 1 ]> MovB [ 1 ]) if(MovA [ 0 ] <MovB [ 0 ]) SELL_Sign = true ; if(MovA [ 0 ] <MovB [ 0 ]) SELL_Stop = true ; } // +执行交易 if(!OpenSellLimitOrder1(SELL_Sign,2, Money_Management_Dn,STOPLOSS_Dn,TAKEPROFIT_Dn, PriceLevel_Dn,StopTime_Dn)) 返回( - 1); if(ClosePos_Dn ) if(!CloseOrder1(SELL_Stop,2)) return( - 1); } }// + return(0); }// + - - +
另一篇文章也已完成。在Expert Advisor中基于绝对不同的指标变体实现了另一个交易系统。希望本文能够对EA编程新手有用,以进一步培养将正确形式化的算法转化为Expert Advisor可用和绝对有效的代码。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程