在外汇交易中,MQL5向导为我们提供了一个便捷的方式,以创建基于晨星和暮星图形的专家顾问(EA)。这个向导结合了客户端终端提供的标准库类,帮助我们快速验证交易思路。
创建自己的交易信号类是关键。我们可以在文章MQL5向导:如何创建交易信号模块中找到相关结构和示例。
基本思路是:交易信号类继承自CExpertSignal,接下来需要重写LongCondition()和ShortCondition()虚方法。
我们将关注反转蜡烛图模式,这些模式需要通过RSI等指标进行确认。
1. “晨星”和“暮星”反转蜡烛图模式
1.1. 晨星
晨星形态通常出现在下跌趋势的底部,由三根蜡烛组成(见图1)。首先是一根长黑蜡烛,接着是一根小实体的蜡烛(颜色无所谓),其实体位于黑蜡烛的下方。小实体意味着多空双方力量均衡,市场即将反转。
第三根蜡烛为看涨蜡烛,其实体不与第二根蜡烛重叠,且收盘价位于第一根(看跌)蜡烛的实体内。图1显示了该模式的形成。

图1. 晨星和晨星十字蜡烛图模式
“晨星”模式的识别可以在CCandlePattern类中的CheckPatternMorningStar()和CheckPatternMorningDoji()方法中实现。
//+------------------------------------------------------------------+ //| 检查“晨星”模式的形成 | //+------------------------------------------------------------------+ bool CCandlePattern::CheckPatternMorningStar() { //--- 晨星 if((Open(3)-Close(3)>AvgBody(1)) && // 看跌蜡烛,其实体大于平均蜡烛实体 (MathAbs(Close(2)-Open(2)<AvgBody(1)*0.5) && // 第二根蜡烛小于平均蜡烛的一半 (Close(2)<Close(3)) && // 第二根蜡烛收盘价低于第一根蜡烛 (Open(2)<Open(3)) && // 第二根蜡烛开盘价低于第一根蜡烛 (Close(1)>MidOpenClose(3))) // 最后一根蜡烛收盘价高于第一根蜡烛的中间价 return(true); //--- return(false); } //+------------------------------------------------------------------+
1.2. 暮星
暮星形态通常出现在上涨趋势的顶部,同样由三根蜡烛组成(见图2)。首先是一根长白蜡烛,接着是一根小实体的蜡烛,最后是看跌蜡烛,其实体不与第二根蜡烛重叠。

图2. 暮星和暮星十字蜡烛图模式
“暮星”的识别可以通过CheckPatternEveningStar()和CheckPatternEveningDoji()方法实现。
//+------------------------------------------------------------------+ //| 检查“暮星”模式的形成 | //+------------------------------------------------------------------+ bool CCandlePattern::CheckPatternEveningStar() { //--- 暮星 if((Close(3)-Open(3)>AvgBody(1)) && // 看涨蜡烛,其实体大于平均蜡烛实体 (MathAbs(Close(2)-Open(2)<AvgBody(1)*0.5) && // 第二根蜡烛小于平均蜡烛的一半 (Close(2)>Close(3)) && // 第二根蜡烛收盘价高于第一根蜡烛 (Open(2)>Open(3)) && // 第二根蜡烛开盘价高于第一根蜡烛 (Close(1)<MidOpenClose(3))) // 最后一根蜡烛收盘价低于第一根蜡烛的中间价 return(true); //--- return(false); } //+------------------------------------------------------------------+
2. 通过RSI指标确认的交易信号
开多或开空的交易信号必须由RSI指标确认。RSI的值需低于40(开多)或高于60(开空)。
平仓则取决于RSI的值,主要有两个条件:
- 当RSI到达相反的临界水平时(开多时为70,开空时为30)
- 当反向信号未得到确认时(RSI到达的水平为开多时的30和开空时的70)

图3. 被RSI指标确认的晨星模式
- int CMS_ES_RSI::LongCondition() - 检查开多仓的条件(返回80)和关闭空仓的条件(返回40);
- int CMS_ES_RSI::ShortCondition() - 检查开空仓的条件(返回80)和关闭多仓的条件(返回40)。
2.1. 开多仓/平空仓
- 晨星模式需被RSI确认:RSI(1)<40(最近一根已完成蜡烛的RSI值需小于40)。
- 如果RSI指标向上穿越70或30的临界水平,则需平空仓。
//+------------------------------------------------------------------+ //| 检查市场进入和退出条件 | //| 1) 市场进入(开多仓,结果=80) | //| 2) 市场退出(平空仓,结果=40) | //+------------------------------------------------------------------+ int CMS_ES_RSI::LongCondition() { int result=0; //--- idx可以用来确定专家顾问的工作模式 //--- idx=0 - 在这种情况下,EA在每个波动中检查交易条件 //--- idx=1 - 在这种情况下,EA仅在新闻蜡烛上检查交易条件 int idx =StartIndex(); //--- 检查开多仓的条件 //--- 晨星形态和RSI<30 if(CheckCandlestickPattern(CANDLE_PATTERN_MORNING_STAR) && (RSI(1)<40)) result=80; //--- 检查平空仓的条件 //--- 信号线穿越超买/超卖水平(向上穿越30,向上穿越70) if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) result=40; //--- 返回结果 return(result); }
2.2. 开空仓/平多仓
- 暮星模式需被RSI确认:RSI(1)>60(最近一根已完成蜡烛的RSI值需大于60)。
- 如果RSI指标向下穿越70或30的临界水平,则需平多仓。
//+------------------------------------------------------------------+ //| 检查市场进入和退出条件 | //| 1) 市场进入(开空仓,结果=80) | //| 2) 市场退出(平多仓,结果=40) | //+------------------------------------------------------------------+ int CMS_ES_RSI::ShortCondition() { int result=0; //--- idx可以用来确定专家顾问的工作模式 //--- idx=0 - 在这种情况下,EA在每个波动中检查交易条件 //--- idx=1 - 在这种情况下,EA仅在新闻蜡烛上检查交易条件 int idx =StartIndex(); //--- 检查开空仓的条件 //--- 暮星形态和RSI>60 if(CheckCandlestickPattern(CANDLE_PATTERN_EVENING_STAR) && (RSI(1)>60)) result=80; //--- 检查平多仓的条件 //--- 信号线穿越超买/超卖水平(向下穿越70,向下穿越30) if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) result=40; //--- 返回结果 return(result); }
2.3. 使用MQL5向导创建专家顾问
CMS_ES_RSI类并不包含在标准库类中,使用前需下载acms_es_rsi.mqh文件(见附件)并保存在客户端数据文件夹
要创建一个专家顾问,启动MQL5向导:

图4. 使用MQL5向导创建专家顾问
为专家顾问指定名称:

图5. 专家顾问的一般属性
接下来,我们需要选择使用的交易信号模块。

图6. 专家顾问的信号属性
在我们的案例中,只使用一个交易信号模块。
添加“基于晨星/暮星的交易信号,确认由RSI”交易信号模块:

图7. 专家顾问的信号属性
信号模块已添加:

图8. 专家顾问的信号属性
您可以选择任意的跟踪属性,但我们将使用“不使用跟踪止损”:

图9. 专家顾问的跟踪属性
关于资金管理属性,我们将使用“固定交易量交易”:

图10. 专家顾问的资金管理属性
点击“完成”按钮后,我们将获得生成的专家顾问代码,位于Expert_AMS_ES_RSI.mq5中,保存于terminal_data_folder\MQL5\Experts\下。
生成的专家顾问默认输入参数:
//--- 主要信号的输入 input int Signal_ThresholdOpen =10; // 开仓信号阈值[0...100] input int Signal_ThresholdClose =10; // 平仓信号阈值[0...100] input double Signal_PriceLevel =0.0; // 执行交易的价格水平 input double Signal_StopLevel =50.0; // 止损水平(以点为单位) input double Signal_TakeLevel =50.0; // 止盈水平(以点为单位)
需替换为:
//--- 主要信号的输入 input int Signal_ThresholdOpen =40; // 开仓信号阈值[0...100] input int Signal_ThresholdClose =20; // 平仓信号阈值[0...100] input double Signal_PriceLevel =0.0; // 执行交易的价格水平 input double Signal_StopLevel =0.0; // 止损水平(以点为单位) input double Signal_TakeLevel =0.0 // 止盈水平(以点为单位)
Signal_ThresholdOpen/Signal_ThresholdClose输入参数允许您为开仓和平仓指定阈值。
在交易信号类的LongCondition()和ShortCondition()方法的代码中,我们指定了固定的阈值:
- 开仓:80;
- 平仓:40。
由MQL5向导生成的专家顾问通过交易信号模块的“投票”来开仓和平仓。主模块的投票结果也会被使用,但它的LongCondition()和ShortCondition()方法始终返回0。
在我们的案例中,我们有:主模块 + 1个交易信号模块,因此在设定阈值时需考虑这一点。由于这种情况,ThresholdOpen和ThresholdClose应设置为40=(0+80)/2和20=(0+40)/2。
Signal_StopLevel和Signal_TakeLevel输入参数的值设置为0,这意味着平仓仅在平仓条件真实时才会执行。
2.4. 历史回测结果
让我们来看一下基于历史数据(EURUSD H1,测试周期:2010.01.01-2011.03.04,PeriodK=47,PeriodD=9,PeriodSlow=13,MA_period=5)的专家顾问的回测结果。
在创建专家顾问时,我们使用了固定的交易量(固定手数交易,0.1),不使用跟踪止损算法(不使用跟踪)。

图11. 基于晨星/暮星与RSI的专家顾问测试结果
您可以使用MetaTrader 5客户端终端的策略测试器来找到最佳的输入参数。
使用策略测试器的3D可视化模式大大简化了参数的研究,该功能从419版本开始添加(见图12):

图12. 平衡作为PeriodRSI和MA_period输入参数的函数
由MQL5向导创建的专家顾问的代码已附在expert_ms_es_rsi.mq5中。