
基于大众交易系统和交易机器人优化点金术的 Expert Advisor(续)
简介
因此,MetaQuotes Software Corp. 于 2008 年 7 月 1 日为 2008 年自动交易锦标赛的参赛者开放注册!如果我错过这个机会,中止我撰写表示 EA 构建原理的系列文章,那就太不合逻辑了。所构建 EA 可满足 2008 年自动交易锦标赛的所有规则,且不会容许竞赛中可能导致失去资格的重大错误!
我自然而然地使用了最简单的建仓算法来实现该事件,在本文中,它的交易因素并不有趣,然而最基础的细微事物可能会成为寻找测试的最重要因素,因为他们可以参加多年后的锦标赛!
编写 EA 的总体思路
在我看来,在我们的例子中,通过详细描述 Expert Advisor 的构造可在其与交易服务器互动时提供正确行为,对 Expert Advisor 做出如此概述最具说服力。锦标赛的规则决定了建仓时的金额和同时等于三的挂单。因此,在一个 EA 内使用三种策略,且每个仓位对应一个策略是相当合理的。
我们将针对开立多头和空头仓位使用带有不同参数的相同算法,每次仅使用这些算法开立一个仓位时,需要我们向其分配相同的幻数。因此,我们将拥有六种算法来进入市场,且仅有三种幻数!我将使用基于本系列文章中 第一篇 的移动平均线方向变化的交易系统作为进入算法。为了让算法各不相同,我在其中使用了不同的移动平均数!
Expert Advisor 代码
以下是 EA 代码的一个版本:
//+==================================================================+ //| Exp_16_Champ.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR BUY TRADES extern bool Test_Up1 = true;//a filter for trades calculation direction extern int Timeframe_Up1 = 60; extern double Money_Management_Up1 = 0.1; extern int Length_Up1 = 4; // smoothing depth extern int Phase_Up1 = 100; // parameter ranging within //-100 ... +100, it affects the quality of the transient process; extern int IPC_Up1 = 0;/* Choosing prices to calculate the indicator on (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_Up1 = 50; // StopLoss extern int TAKEPROFIT_Up1 = 100; // TakeProfit extern bool ClosePos_Up1 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR SELL TRADES extern bool Test_Dn1 = true;//a filter for trades calculation direction extern int Timeframe_Dn1 = 60; extern double Money_Management_Dn1 = 0.1; extern int Length_Dn1 = 4; // smoothing depth extern int Phase_Dn1 = 100; // parameter ranging within // -100 ... +100, it affects the quality of the transient process; extern int IPC_Dn1 = 0;/* Choosing prices to calculate the indicator on (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_Dn1 = 50; // StopLoss extern int TAKEPROFIT_Dn1 = 100; // TakeProfit extern bool ClosePos_Dn1 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR BUY TRADES extern bool Test_Up2 = true;//a filter for trades calculation direction extern int Timeframe_Up2 = 60; extern double Money_Management_Up2 = 0.1; extern int Length1_Up2 = 4; // first smoothing depth extern int Phase1_Up2 = 100; // parameter of the first smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int Length2_Up2 = 4; // second smoothing depth extern int Phase2_Up2 = 100; // parameter of the second smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int IPC_Up2 = 0;/* Choosing prices to calculate the indicator on (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_Up2 = 50; // StopLoss extern int TAKEPROFIT_Up2 = 100; // TakeProfit extern bool ClosePos_Up2 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR SELL TRADES extern bool Test_Dn2 = true;//a filter for trades calculation direction extern int Timeframe_Dn2 = 60; extern double Money_Management_Dn2 = 0.1; extern int Length1_Dn2 = 4; // smoothing depth extern int Phase1_Dn2 = 100; // parameter of the first smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int Length2_Dn2 = 4; // smoothing depth extern int Phase2_Dn2 = 100; // parameter of the second smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int IPC_Dn2 = 0;/* Choosing prices to calculate the indicator on (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_Dn2 = 50; // StopLoss extern int TAKEPROFIT_Dn2 = 100; // TakeProfit extern bool ClosePos_Dn2 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR BUY TRADES extern bool Test_Up3 = true;//a filter for trades calculation direction extern int Timeframe_Up3 = 60; extern double Money_Management_Up3 = 0.1; extern int Period_Up3 = 10; // LSMA period extern int Length_Up3 = 4; // smoothing depth extern int Phase_Up3 = 100; // parameter of smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int IPC_Up3 = 0;/* Choosing prices to calculate the indicator on (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_Up3 = 50; // StopLoss extern int TAKEPROFIT_Up3 = 100; // TakeProfit extern bool ClosePos_Up3 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- EXPERT ADVISOR'S INPUTS FOR SELL TRADES extern bool Test_Dn3 = true;//a filter for trades calculation direction extern int Timeframe_Dn3 = 60; extern double Money_Management_Dn3 = 0.1; extern int Period_Dn3 = 10; // LSMA period extern int Length_Dn3 = 4; // smoothing depth extern int Phase_Dn3 = 100; // parameter smoothing, //ranging within -100 ... +100, it affects the quality //of the averaging transient; extern int IPC_Dn3 = 0;/* Choosing prices to calculate the indicator on (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_Dn3 = 50; // StopLoss extern int TAKEPROFIT_Dn3 = 100; // TakeProfit extern bool ClosePos_Dn3 = true; // enable forcible closing the position //----+ +-----------------------------------------------------------------------+ //---- Integer variables for the minimum of estimated bars int MinBar_Up1, MinBar_Up2, MinBar_Up3; int MinBar_Dn1, MinBar_Dn2, MinBar_Dn3; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT_Champ.mqh> //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the value of the 'Timeframe' variable for correctness 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 values of short-position timeframe variables for correctness TimeframeCheck("Timeframe_Up1", Timeframe_Up1); TimeframeCheck("Timeframe_Up2", Timeframe_Up2); TimeframeCheck("Timeframe_Up3", Timeframe_Up3); //---- Checking the values of long-position timeframe variables for correctness TimeframeCheck("Timeframe_Dn1", Timeframe_Dn1); TimeframeCheck("Timeframe_Dn2", Timeframe_Dn2); TimeframeCheck("Timeframe_Dn3", Timeframe_Dn3); //---- Initialization of variables MinBar_Up1 = 4 + 39 + 30; MinBar_Up2 = 4 + 30; MinBar_Up3 = 4 + Period_Up3 + 30; MinBar_Dn1 = 4 + 39 + 30; MinBar_Dn2 = 4 + 30; MinBar_Dn3 = 4 + Period_Dn3 + 30; //---- initialization complete return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- Expert Advisor initialization complete return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaration of local variables int bar; double Mov[3], dMov12, dMov23; //----+ Declaration of static variables static int LastBars_Up1, LastBars_Dn1; static int LastBars_Up2, LastBars_Dn2; static int LastBars_Up3, LastBars_Dn3; static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1; static bool BUY_Sign2, BUY_Stop2, SELL_Sign2, SELL_Stop2; static bool BUY_Sign3, BUY_Stop3, SELL_Sign3, SELL_Stop3; //+------------------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS if (Test_Up1) { int IBARS_Up1 = iBars(NULL, Timeframe_Up1); if (IBARS_Up1 >= MinBar_Up1) { if (LastBars_Up1 != IBARS_Up1) { //----+ Initialization of variables BUY_Sign1 = false; BUY_Stop1 = false; LastBars_Up1 = IBARS_Up1; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Up1, "JFatl", Length_Up1, Phase_Up1, 0, IPC_Up1, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 < 0) if (dMov12 > 0) BUY_Sign1 = true; if (dMov12 < 0) BUY_Stop1 = true; } //----+ MAKING TRADES if (!OpenBuyOrder_Ch(BUY_Sign1, 1, Money_Management_Up1, STOPLOSS_Up1, TAKEPROFIT_Up1)) return(-1); if (ClosePos_Up1) if (!CloseOrder_Ch(BUY_Stop1, 1)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn1) { int IBARS_Dn1 = iBars(NULL, Timeframe_Dn1); if (IBARS_Dn1 >= MinBar_Dn1) { if (LastBars_Dn1 != IBARS_Dn1) { //----+ Initialization of variables SELL_Sign1 = false; SELL_Stop1 = false; LastBars_Dn1 = IBARS_Dn1; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Dn1, "JFatl", Length_Dn1, Phase_Dn1, 0, IPC_Dn1, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 > 0) if (dMov12 < 0) SELL_Sign1 = true; if (dMov12 > 0) SELL_Stop1 = true; } //----+ MAKING TRADES if (!OpenSellOrder_Ch(SELL_Sign1, 1, Money_Management_Dn1, STOPLOSS_Dn1, TAKEPROFIT_Dn1)) return(-1); if (ClosePos_Dn1) if (!CloseOrder_Ch(SELL_Stop1, 1)) return(-1); } } //+------------------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS if (Test_Up2) { int IBARS_Up2 = iBars(NULL, Timeframe_Up2); if (IBARS_Up2 >= MinBar_Up2) { if (LastBars_Up2 != IBARS_Up2) { //----+ Initialization of variables BUY_Sign2 = false; BUY_Stop2 = false; LastBars_Up2 = IBARS_Up2; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Up2, "J2JMA", Length1_Up2, Length2_Up2, Phase1_Up2, Phase2_Up2, 0, IPC_Up2, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 < 0) if (dMov12 > 0) BUY_Sign2 = true; if (dMov12 < 0) BUY_Stop2 = true; } //----+ MAKING TRADES if (!OpenBuyOrder_Ch(BUY_Sign2, 2, Money_Management_Up2, STOPLOSS_Up2, TAKEPROFIT_Up2)) return(-1); if (ClosePos_Up2) if (!CloseOrder_Ch(BUY_Stop2, 2)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn2) { int IBARS_Dn2 = iBars(NULL, Timeframe_Dn2); if (IBARS_Dn2 >= MinBar_Dn2) { if (LastBars_Dn2 != IBARS_Dn2) { //----+ Initialization of variables SELL_Sign2 = false; SELL_Stop2 = false; LastBars_Dn2 = IBARS_Dn2; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Dn2, "J2JMA", Length1_Dn2, Length2_Dn2, Phase1_Dn2, Phase2_Dn2, 0, IPC_Dn2, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 > 0) if (dMov12 < 0) SELL_Sign2 = true; if (dMov12 > 0) SELL_Stop2 = true; } //----+ MAKING TRADES if (!OpenSellOrder_Ch(SELL_Sign2, 2, Money_Management_Dn2, STOPLOSS_Dn2, TAKEPROFIT_Dn2)) return(-1); if (ClosePos_Dn2) if (!CloseOrder_Ch(SELL_Stop2, 2)) return(-1); } } //+------------------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS if (Test_Up3) { int IBARS_Up3 = iBars(NULL, Timeframe_Up3); if (IBARS_Up3 >= MinBar_Up3) { if (LastBars_Up3 != IBARS_Up3) { //----+ Initialization of variables BUY_Sign3 = false; BUY_Stop3 = false; LastBars_Up3 = IBARS_Up3; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Up3, "JLSMA", Period_Up3, Length_Up3, Phase_Up3, 0, IPC_Up3, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 < 0) if (dMov12 > 0) BUY_Sign3 = true; if (dMov12 < 0) BUY_Stop3 = true; } //----+ MAKING TRADES if (!OpenBuyOrder_Ch(BUY_Sign3, 3, Money_Management_Up3, STOPLOSS_Up3, TAKEPROFIT_Up3)) return(-1); if (ClosePos_Up3) if (!CloseOrder_Ch(BUY_Stop3, 3)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn3) { int IBARS_Dn3 = iBars(NULL, Timeframe_Dn3); if (IBARS_Dn3 >= MinBar_Dn3) { if (LastBars_Dn3 != IBARS_Dn3) { //----+ Initialization of variables SELL_Sign3 = false; SELL_Stop3 = false; LastBars_Dn3 = IBARS_Dn3; //----+ CALCULATING THE INDICATORS' VALUES AND LOADING THEM TO BUFFERS for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Dn3, "JLSMA", Period_Dn3, Length_Dn3, Phase_Dn3, 0, IPC_Dn3, 0, bar); //----+ DETERMINING SIGNALS FOR TRADES dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (dMov23 > 0) if (dMov12 < 0) SELL_Sign3 = true; if (dMov12 > 0) SELL_Stop3 = true; } //----+ MAKING TRADES if (!OpenSellOrder_Ch(SELL_Sign3, 3, Money_Management_Dn3, STOPLOSS_Dn3, TAKEPROFIT_Dn3)) return(-1); if (ClosePos_Dn3) if (!CloseOrder_Ch(SELL_Stop3, 3)) return(-1); } } //+------------------------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
想获得不受锦标赛规则限制的 EA 的人,可以前往 Exp_16.mq4。实际上,我们可以看到三种算法的交易策略相互之间在某一方面有所区别。总体而言,我们在一个 Expert Advisor 内有完全独立的三个自动化交易策略。编写代码时,我在每个自动交易系统(ATS)中修改了变量名称以避免出现一致。
为进行交易,我使用文件 Lite_EXPERT1.mqh 中的相似函数,这些函数由文件 Lite_EXPERT_Champ.mqh 表示。这些函数要求对他们的代码进行微小更改和纠正,以符合锦标赛的要求。单独在其他参赛者的 EA 代码中使用这些函数的代码是合乎法规的,因为这些代码只是 EA 的执行元素,且和实际控制该等元素的智能填充无关!
所以,并没有特别需求来获得这些函数的所有细节或创建属于你自己的相似函数。阅读我此系列中的早前文章,便足以让你使用这些函数了。总体而言,使用编写 EA 的这些函数和使用芯片进行电子设备开发和制造一样有效。
以下是对构建这些函数时应考虑的要点的简要概述。
1.所有用于建仓和下挂单的函数会检测已开立仓位和已下挂单的数量,如果该数量超过两个,则不会采取任何行动。
2.订单的开仓价位与函数 OpenBuyOrder_Ch(), OpenSellOrder_Ch(), OpenBuyLimitOrder_Ch(), OpenBuyStopOrder_Ch(), OpenSellLimitOrder_Ch() 和 OpenSellStopOrder_Ch() 设置获利位之间的最小距离,总是超出锦标赛规则对剥头皮的规定范围。StopLoss 的最小距离由已交易品种的属性所决定,并由服务器提出申请。这也与挂单相关。然而,你应考虑到有时挂单所处理的价位会比申请价位糟糕的事实。在此情况下,你的获利位可能会进入剥头皮策略的“范围”!所以获利位最好呆在远离剥头皮策略的地方。否则,鉴于许多缺口(很有可能出现在年底),你会发现你的 EA 已直接归入了剥头皮策略的定义!
然而,需要给出启发性提醒的是,如果获利位过大,则 EA 的交易可能过少,从而可能导致 EA 也失去资格!
3.待开立的最大和最小的仓位,以及受锦标赛规则决定的最小更改步骤,都和需要初始化的变量值一同写入所有这些函数中。因此,这些错误已经规避!
4.开立仓位前,函数 OpenBuyOrder_Ch() 和 OpenSellOrder_Ch() 检查仓位的大小并检查仓位本身的保证金金额是否足以匹配其大小,并降低手数至可接受的值。因此,处理这些函数时,你的 EA 在任何情况下都可避免出现诸如“无效交易量”这样的错误。遗憾的是,以这种方式纠正挂单的手数大小是不可能的,因为无法预测从挂单触发起保证金的自由资产量是多少。因此 EA 编写者必须在初始化函数 OpenBuyLimitOrder_Ch(), OpenBuyStopOrder_Ch(), OpenSellLimitOrder_Ch() 和 OpenSellStopOrder_Ch() 外部变量时非常专心,尤其是对于 StopLosses 的大数值。
5.所有用于仓位管理的函数在交易之间根据错误发生代码进行正确暂停。
6.平仓或删除挂单,或移动 StopLosses 前,函数 CloseOrder_Ch(), CloseOrder_Ch() 和 Make_TreilingStop_Ch() 将检查冻结的仓位,如果仓位被冻结,则无需进行任何操作。
7.平仓前,函数 CloseOrder_Ch() 将检查其净盈余没有剥头皮特征。如果发现仓位在剥头皮范围内,则无需进行任何操作。
8.函数 Make_TreilingStop_Ch() 没有将 StopLoss 移入价格范围内,在此范围内由 StopLoss 平仓的盈利可能会进入“剥头皮范围”内。
总结
以上便是所有我想说的关于自动交易锦标赛中 EA 的典型行为。当然,还有一个和 EA 对 CPU 资源过分消耗相关的实际问题。在多数情况下,这个问题通常取决于 EA 在操作过程中调用的无效编写指标。但这是另一个主题了。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1542
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.

