![基于大众交易系统和交易机器人优化点金术的 Expert Advisor(续)](https://c.mql5.com/i/articles/overlay.png)
基于大众交易系统和交易机器人优化点金术的 Expert Advisor(续)
简介
在我之前的本系列文章中(1、2、3、4),我介绍了各种最简单的交易系统,它们的特点是仅处理一个时间范围。因此,此类交易系统在更全局化的时间尺度中完全无法对市场趋势的变化做出反应。这会在市场状况发生变化时导致亏损,因为上述系统无法检测到这些变化。实际上,真实交易中基本不能使用仅以从一个时间范围的图表中获取的数据为基础的系统。正常操作中通常至少要用到两个时间范围。当前趋势通常是在较大时间范围的图表上确定的,而此趋势方向上的入市价位是基于较小时间范围的图表计算得出的。依我看来,之前文章中那些最简单的交易策略示例足以让读者学会如何设计此类系统。那么,现在让我们讨论一下如何根据上述推论改进此类交易系统。
使用两个时间范围的交易系统
从逻辑角度看,无论以之前文章中所述的哪个交易系统为基础,实际上都没有什么区别。我们将构建一个更为复杂的系统。至于其初始本质,每个最简单的交易系统都可用以下形式来表示:
对于多头仓:
对于空头仓:
在使用两个时间范围的交易系统中,这些入市条件将根据在较小时间范围上计算的指标来定义。趋势方向将在较大时间范围上确定。因此,包含这些条件的算法如下所示:
对于多头仓:
对于空头仓:
在这种情况下,Trend 变量仅定义较大时间范围上的当前趋势方向,而入市的其他条件将 Expert Advisor 的交易行为限定至该全局趋势的方向上。从程序代码的角度看,无论使用哪种算法,最终也没有任何区别,都将在较大时间范围上检测当前趋势。所以这完全取决于 EA 编写者决定使用什么算法在较小时间范围上计算入市价位,并在较大时间范围上检测当前趋势。让我们分析早前提过的使用 EA Exp_5.mq4 呈示的 OsMA 振荡指标的算法,为了定义当前趋势,我们使用移动 J2JMA.mq4。在这种情况下,交易定义条件将会非常简单:
那么现在我们要向现有 Exp_5.mq4 添加一些代码,以加入上述逻辑。完成的代码如下所示:
//For the EA operation Metatrader\EXPERTS\indicators folder must //contain indicators 5c_OsMA.mq4 and J2JMA.mq4 //+==================================================================+ //| Exp_11.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern double Money_Management_Up = 0.1; //---- input parameters of the custom indicator J2JMA.mq4 extern int TimeframeX_Up = 240; extern int Length1X_Up = 4; // depth of the first smoothing extern int Phase1X_Up = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Up = 4; // depth of the second smoothing extern int Phase2X_Up = 100; // parameter of the second smoothing, //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Up = 0;/* Selecting prices on which the indicator will be calculated (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.) */ //---- input parameters of the custom indicator 5c_OsMA.mq4 extern int Timeframe_Up = 60; extern double IndLevel_Up = 0; // breakout level of the indicator extern int FastEMA_Up = 12; // quick EMA period extern int SlowEMA_Up = 26; // slow EMA period extern int SignalSMA_Up = 9; // signal SMA period extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern int TRAILINGSTOP_Up = 0; // trailing stop extern int PriceLevel_Up =40; // difference between the current price and // the price of a pending order triggering extern bool ClosePos_Up = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern double Money_Management_Dn = 0.1; //---- input parameters of the custom indicator J2JMA.mq4 extern int TimeframeX_Dn = 240; extern int Length1X_Dn = 4; // smoothing depth extern int Phase1X_Dn = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Dn = 4; // smoothing depth extern int Phase2X_Dn = 100; // parameter of the second smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Dn = 0;/* Selecting prices on which the indicator will be calculated (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.) */ //---- input parameters of the custom indicator 5c_OsMA.mq4 extern int Timeframe_Dn = 60; extern double IndLevel_Dn = 0; // breakout level of the indicator extern int FastEMA_Dn = 12; // quick EMA period extern int SlowEMA_Dn = 26; // slow EMA period extern int SignalSMA_Dn = 9; // signal SMA period extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern int TRAILINGSTOP_Dn = 0; // trailing stop extern int PriceLevel_Dn = 40; // difference between the current price and // the price of a pending order triggering extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBarX_Up, MinBar_Up, MinBarX_Dn, MinBar_Dn; //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("TimeframeCheck: Parameter ",Name, " cannot ", "be equal to", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("Timeframe_Up", Timeframe_Up); //---- Checking the correctness of TimeframeX_Up variable value TimeframeCheck("TimeframeX_Up", TimeframeX_Up); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("Timeframe_Dn", Timeframe_Dn); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); //---- Initialization of variables MinBar_Up = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up; MinBarX_Up = 3 + 30 + 30; MinBar_Dn = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn; MinBarX_Dn = 3 + 30 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of the EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables double J2JMA1, J2JMA2, Osc1, Osc2; //----+ Declaring static variables //----+ +---------------------------------------------------------------+ static double TrendX_Up, TrendX_Dn; static datetime StopTime_Up, StopTime_Dn; static int LastBars_Up, LastBarsX_Up, LastBarsX_Dn, LastBars_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Length2X_Up, Phase1X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Length2X_Up, Phase1X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend TrendX_Up = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 60 * Timeframe_Up; //----+ calculating indicator values Osc1 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 1); //--- Osc2 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 2); //----+ defining signals for trades if (TrendX_Up > 0) if (Osc2 < IndLevel_Up) if (Osc1 > IndLevel_Up) BUY_Sign = true; } //----+ +-------------------+ //----+ EXECUTION OF TRADES | //----+ +-------------------+ if (!OpenBuyLimitOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up, PriceLevel_Up, StopTime_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); if (!Make_TreilingStop(1, TRAILINGSTOP_Up)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //--- Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Dn, "J2JMA", Length1X_Dn, Length2X_Dn, Phase1X_Dn, Phase2X_Dn, 0, IPCX_Dn, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Dn, "J2JMA", Length1X_Dn, Length2X_Dn, Phase1X_Dn, Phase2X_Dn, 0, IPCX_Dn, 0, 2); //----+ defining trend TrendX_Dn = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 60 * Timeframe_Dn; //----+ calculating indicator values Osc1 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 1); //--- Osc2 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 2); //----+ defining signals for trades if (TrendX_Dn < 0) if (Osc2 > IndLevel_Dn) if (Osc1 < IndLevel_Dn) SELL_Sign = true; } //----+ +-------------------+ //----+ EXECUTION OF TRADES | //----+ +-------------------+ if (!OpenSellLimitOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn, PriceLevel_Dn, StopTime_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); if (!Make_TreilingStop(2, TRAILINGSTOP_Dn)) return(-1); } } //----+ +---------------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
尽管方法似乎并不那么复杂,但实际代码看起来比初始 Exp_5mq4 代码大两倍!现在我们来讨论这个结果。我还是只分析 EA 的多头仓部分,空头仓的部分是类似的。用于获取 J2JMA 指标的必要值的额外源代码如下:
//----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend Trend_Up = J2JMA1 - J2JMA2;
因此,EA 开头部分现在包含六个新外部变量的声明,对应于 J2JMA 指标调用:
extern int TimeframeX_Up = 240; extern int Length1X_Up = 4; // depth of the first smoothing extern int Phase1X_Up = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Up = 4; // depth of the second smoothing extern int Phase2X_Up = 100; // parameter of the second smoothing, //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Up = 0;/* Selecting prices on which the indicator will be calculated (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.) */
一个新的类似变量 MinBarX_Up 被添加到全局变量的声明行,以获取计算柱的最小值,它跟在 EA 外部变量的后面:
//---- Integer variables for the minimum of calculation bars int MinBarX_Up, MinBar_Up, MinBarX_Dn, MinBar_Dn;
在 EA 初始化块中,额外检查新外部变量 TimeframeХ_Up 的正确性:
//---- Checking the correctness of TimeframeX_Up variable value TimeframeCheck("TimeframeХ_Up", TimeframeX_Up);
MinBarX_Up = 3 + 30 + 30;
在 EA 的 start() 函数块中执行进一步的代码修改。在本地变量声明行中添加两个新变量:J2JMA1 和 J2JMA2:
//----+ Declaring local variables double J2JMA1, J2JMA2, Osc1, Osc2;
Trend_Up 变量被声明为一个静态变量,因为它仅在柱变更时被初始化一次,它的值用于 start() 函数的进一步价格变动:
static double TrendX_Up, TrendX_Dn;
照此类推,变量 LastBarsX_Up 被声明为静态变量:
static int LastBars_Up, LastBarsX_Up, LastBarsX_Dn, LastBars_Dn;
在多头仓的代码中,检查计算的充分性变得更加复杂:
if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { // CODE FOR LONG POSITIONS } }
并且添加了一个新的块:
//----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend TrendX_Up = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (Trend_Up < 0) BUY_Stop = true; }
在这个必要的块中,对变量 Trend_Up 初始化,此外还在此处定义强制平仓信号(BUY_Stop 变量的初始化)。一般来说,在初始 Exp_5.mq4 中,最后一个变量在“DEFINING SIGNALS FOR MARKET ENTERING”程序块中初始化,但在新 EA 中,更合理的做法是将此初始化放在“DEFINING TREND”块中,并更改其初始化算法。
最重要的是在块“DEFINING SIGNALS FOR MARKET ENTERING”中对信号定义算法做一个小调整:
//----+ defining signals for trades if (TrendX_Up > 0) if (Osc2 < IndLevel_Up) if (Osc1 > IndLevel_Up) BUY_Sign = true;
完成所有修改后,此算法使用变量 Trend_Up 将当前趋势方向考虑在内。
现在来说一些关于 EA 优化的细节。EA 一般都应仅针对多头仓或空头仓进行单独的优化,但即便在这种情况下,要优化的外部变量也非常多。也许同时优化所有这些变量并不合理。尤其是,优化的遗传算法不会优化八个以上的变量!这种情况下,最合适的解决方案是固定某些变量的值,仅优化其余未固定值的变量,即最紧急的变量。优化之后,选择最合适的方法,试着优化其余参数。
例如,对于多头仓,方法如下:
包含测试程序的这些设置的文件 Exp_11.ini 在 TESTER.zip 存档中。这里我们无需优化 Money_Management_Up 和 TimeframeX_Up。至于 TimeframeX_Up 变量,要注意的是,它的值必须大于变量 Timeframe_Up 的值。Length1X_Up 的值的可变范围相当大,而 Phase1X_Up 的值的范围为 -100 至 100。最好在第一次优化时固定参数 Length2X_Up、Phase2X_Up 和 IPCX_Up 的值,我在上一篇文章中介绍 Exp_5.mq4 时提到的 IndLevel_Up 参数也是如此。对于 FastEMA_Up 和 SlowEMA_Up 参数,参数变更的下限值不应太小。当然,它们可以表现出令人惊异的结果,但这种结果有任何意义吗?优化之后还应检查使用追踪止损位是否合理。但在趋势变化时,应始终通过逻辑变量 ClosePos_Up 强制平仓。最好将其值固定为“true”。
优化期间,策略测试程序中的图表周期应等于变量 Timeframe_Up 或 Timeframe_Dn 的值(取决于优化期间的交易方向),在某个帐户上进行最终测试或操作时,图表周期应设为等于这些值的最小值。还有个重要的细节。此 Expert Advisor 使用至少两个时间范围,因此在帐户上下载用于优化、测试和操作的历史数据之时要留心这一点,尤其是你使用在不同经销商开立的多个帐户时更要注意。
在第四篇文章中,我介绍了如何导出 Microsoft Excel 中进一步统计分析的优化结果。在我看来,这篇文章中提供的 EA 最适合此类程序。如果有人要试用这个 EA,我用帐号修改了此 EA 代码,作为本文的推荐 EA (Exp_11_2.mq4)。此代码附于本文之后。
针对不同时间范围的两个图表的计算数据的另一个 EA 使用示例
我想,仅仅一个基于此理念的 EA 示例还不足以供本文使用,所以我会再加一个根据此原理构建的Expert Advisor。我将以我第一篇文章中的第一个 EA Exp_1.mq4 为基础。用于定义入市条件和管理仓位的代码部分已准备就绪。现在我们需要定义较大时间范围的活跃市场趋势。在此 Expert Advisor 中,我使用指标 MAMA_NK.mq4:
在这种情况下,定义趋势方向的条件是第一个柱上两个移动之间的差值:
让我们用类似方式编写一段代码,以 Exp_11.mq4 的代码为模板:
//+==================================================================+ //| Exp_12.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern double Money_Management_Up = 0.1; //---- extern int TimeframeX_Up = 240; extern double FastLimitX_Up = 0.5; extern double SlowLimitX_Up = 0.05; extern int IPCX_Up = 9;/* Selecting prices, upon which the indicator will be calculated (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, 15-Heiken Ashi Open0.) */ //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Up = 60; extern int Length_Up = 4; // smoothing depth extern int Phase_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of a transient process; extern int IPC_Up = 0;/* Selecting prices, upon which the indicator will be calculated (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; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern bool ClosePos_Up = true; // forced position closing is allowed //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern double Money_Management_Dn = 0.1; //---- extern int TimeframeX_Dn = 60; extern double FastLimitX_Dn = 0.5; extern double SlowLimitX_Dn = 0.05; extern int IPCX_Dn = 9;/* Selecting prices, upon which the indicator will be calculated (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, 15-Heiken Ashi Open0.) */ //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Dn = 60; extern int Length_Dn = 4; // smoothing depth extern int Phase_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of a transient process; extern int IPC_Dn = 0;/* Selecting prices, upon which the indicator will be calculated (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; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern bool ClosePos_Dn = true; // forced position closing is allowed //----+ +---------------------------------------------------------------------------+ //---- Integer variables for the minimum of counted bars int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("TimeframeX_Up", TimeframeX_Up); //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("Timeframe_Up", Timeframe_Up); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("Timeframe_Dn", Timeframe_Dn); //---- Initialization of variables MinBarX_Up = 1 + 7; MinBar_Up = 4 + 39 + 30; MinBarX_Dn = 1 + 7; MinBar_Dn = 4 + 39 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of the EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaration of local variables int bar; double Mov[3], dMov12, dMov23, Mama1, Fama1; //----+ declaration of static variables static double TrendX_Up, TrendX_Dn; static int LastBars_Up, LastBars_Dn, LastBarsX_Up, LastBarsX_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values Fama1 = iCustom(NULL, TimeframeX_Up, "MAMA_NK", FastLimitX_Up, SlowLimitX_Up, IPCX_Up, 0, 1); //--- Mama1 = iCustom(NULL, TimeframeX_Up, "MAMA_NK", FastLimitX_Up, SlowLimitX_Up, IPCX_Up, 1, 1); //----+ defining trend TrendX_Up = Mama1 - Fama1; //----+ defining signals for trade closing if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; //----+ calculating indicator values and uploading them into buffer for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Up, "JFatl", Length_Up, Phase_Up, 0, IPC_Up, 0, bar); //----+ defining signals for trades dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (TrendX_Up > 0) if (dMov23 < 0) if (dMov12 > 0) BUY_Sign = true; } //----+ +-------------------+ //----+ EXECUTION OF TRADES | //----+ +-------------------+ if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //----+ Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Stop = false; //----+ calculating indicator values Fama1 = iCustom(NULL, TimeframeX_Dn, "MAMA_NK", FastLimitX_Dn, SlowLimitX_Dn, IPCX_Dn, 0, 1); //--- Mama1 = iCustom(NULL, TimeframeX_Dn, "MAMA_NK", FastLimitX_Dn, SlowLimitX_Dn, IPCX_Dn, 1, 1); //----+ defining trend TrendX_Dn = Mama1 - Fama1; //----+ defining signals for trade closing if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; //----+ calculating indicator values and uploading them into buffer for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Dn, "JFatl", Length_Dn, Phase_Dn, 0, IPC_Dn, 0, bar); //----+ defining signals for trades dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (TrendX_Dn < 0) if (dMov23 > 0) if (dMov12 < 0) SELL_Sign = true; } //----+ +-------------------+ //----+ EXECUTION OF TRADES | //----+ +-------------------+ if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); } } //----+ return(0); } //+------------------------------------------------------------------+
尽管此 EA 的基本算法不同于前一个 EA,但这种情况下,使用两个图表的基本理念看上去仍是绝对可行的。
总结
我认为本文所述的自动交易系统构建方法将帮助已有一些 EA 编写经验的读者用最少的精力构建类似的 Expert Advisor。这里还要说明一点,即此类 Expert Advisor 的实用价值很大程度上取决于其正确的优化。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1525
![非交易 EA 的测试指标](https://c.mql5.com/2/16/627_11.gif)
![基于大众交易策略和交易机器人优化点金术的 Expert Advisor(续)](https://c.mql5.com/2/16/633_39.gif)
![谬误,第 1 部分:资金管理排第二位,并不是很重要](https://c.mql5.com/2/15/601_23.gif)
![图形行-请求的元语言交易和合格交易学习](https://c.mql5.com/2/15/597_26.gif)