请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3364704 新帖:25

如何快速创建一个"2010 年自动交易锦标赛"专用"EA 交易"

有事您说话发表于:4 月 17 日 17:11回复(1)

简介

为了开发出一种参与“2010 自动交易锦标赛”的“EA 交易”,我们使用一个即用的、来自《交易机器人的原型》一文的“EA 交易”模板。 即便是 MQL5 程序员初哥也能胜任此任务,因为您策略的基类、函数和模板都已经开发完毕。 编写少量的代码来实现您的交易理念就足够了。  

我们需要准备的内容:
  • 策略选择
  • 编写“EA 交易”
  • 测试
  • 策略测试程序中的优化
  • 策略优化
  • 以不同时间间隔测试

1. 策略选择

人们相信随势交易比区间交易更有利可图,而且盘中量发生的反弹,要比通道边界的崩溃更加频繁。

基于上述假设,我们会向着通道边界(轨道线)反弹的当前趋势建仓。 我们会根据平仓信号或在达到 Stop Loss(止损)或 Take Profit(获利)水平时平仓。

  与趋势信号一样,我们会利用 MACD 增长或在日线图上的减少,还会根据小时时间表上的通道边界反弹进行交易。  

图 1. EURUSD 日线图上的 MACD 指标

图 1. EURUSD 日线图上的 MACD 指标

如果 MACD 指标连续于两个柱上增长 - 此为买入信号。 如连续在两个柱上减少 - 则为卖出信号。

图 2. 轨道线边界价格反弹

图 2. 轨道线边界价格反弹


2. 编写“EA 交易”

2.1. 包含的模块

专家会采用来自 ExpertAdvisor.mqh 模块的“EA 交易”类。

#include <ExpertAdvisor.mqh>

2.2. 输入变量

input int    SL        =  50; // 止损距离
input int    TP        = 100; // 获利距离
input int    TS        =  50; // 追踪止损距离
input int    FastEMA   =  15; // 快速 EMA
input int    SlowEMA   =  26; // 慢速 EMA
input int    MACD_SMA  =   1; // MACD 信号线
input int    EnvelPer  =  20; // 轨道线周期
input double EnvelDev  = 0.4; // 轨道线方差
input double Risk      = 0.1; // 风险

2.3. 创建一个继承自 CExpertAdvisor 的类

class CMyEA : public CExpertAdvisor
  {
protected:
   double            m_risk;          // 风险大小
   int               m_sl;            // 止损
   int               m_tp;            // 获利
   int               m_ts;            // 追踪止损
   int               m_pFastEMA;      // 快速 EMA
   int               m_pSlowEMA;      // 慢速 EMA
   int               m_pMACD_SMA;     /// MACD 信号线
   int               m_EnvelPer;      // 轨道线周期
   double            m_EnvelDev;      // 轨道线方差
   int               m_hmacd;         // MACD指标句柄
   int               m_henvel;        // 轨道线指标句柄
public:
   void              CMyEA();
   void             ~CMyEA();
   virtual bool      Init(string smb,ENUM_TIMEFRAMES tf); // 初始化
   virtual bool      Main();                              // 主函数
   virtual void      OpenPosition(long dir);              // 根据信号开仓
   virtual void      ClosePosition(long dir);             // 根据信号平仓
   virtual long      CheckSignal(bool bEntry);            // 检查信号
  };
//------------------------------------------------------------------

2.4. 删除指标
//------------------------------------------------------------------    
void CMyEA::~CMyEA()
  {
   IndicatorRelease(m_hmacd);  // 删除MACD指标
   IndicatorRelease(m_henvel); // 删除轨道线指标
  
}
//------------------------------------------------------------------    

2.5. 初始化变量
//------------------------------------------------------------------    Init
bool CMyEA::Init(string smb,ENUM_TIMEFRAMES tf)
  {
   if(!CExpertAdvisor::Init(0,smb,tf)) return(false);    // initialize parent class
   // 复制参数
    m_risk=Risk; 
   m_tp=TP; 
   m_sl=SL; 
   m_ts=TS;
   m_pFastEMA=FastEMA; 
   m_pSlowEMA=SlowEMA; 
   m_pMACD_SMA=MACD_SMA;
   m_EnvelPer = EnvelPer;
   m_EnvelDev = EnvelDev;
   m_hmacd=iMACD(m_smb,PERIOD_D1,m_pFastEMA,m_pSlowEMA,m_pMACD_SMA,PRICE_CLOSE);      // 创建MACD指标
   m_henvel=iEnvelopes(m_smb,PERIOD_H1,m_EnvelPer,0,MODE_SMA,PRICE_CLOSE,m_EnvelDev); // 创建轨道线指标
   if(m_hmacd==INVALID_HANDLE ||m_henvel==INVALID_HANDLE ) return(false);             //如果报错,则退出
   m_bInit=true; 
   return(true);                                                                      // 允许交易
  
} 


2.6. 交易函数

//------------------------------------------------------------------    CheckSignal
long CMyEA::CheckSignal(bool bEntry)
  {
   double macd[4],   // MACD 指标值数组
         env1[3],    // 轨道线上轨值数组
         env2[3];    // 轨道线下轨值数组
   MqlRates rt[3];   // 最近3个柱形的价格数组
   
   if(CopyRates(m_smb,m_tf,0,3,rt)!=3) // 将最近3个柱形的价格值复制到数组中
     {
       Print("CopyRates ",m_smb," history is not loaded"); 
        return(WRONG_VALUE);
     
}
   // 将指标值复制到数组
   if(CopyBuffer(m_hmacd,0,0,4,macd)<4 || CopyBuffer(m_henvel,0,0,2,env1)<2 ||CopyBuffer(m_henvel,1,0,2,env2)<2)
     { 
        Print("CopyBuffer - no data"); 
       return(WRONG_VALUE);
     
}
   // 如果MACD在增长并且价格从轨道线下轨反弹,买入
   if(rt[1].open<env2[1] && rt[1].close>env2[1] && macd[1]<macd[2] &&  macd[2]<macd[3])
      return(bEntry ?ORDER_TYPE_BUY:ORDER_TYPE_SELL); // 买入的条件
   // 如果MACD在下降并且价格从轨道线上轨向下反弹,卖出
   if(rt[1].open>env1[1] && rt[2].close<env1[1]&& macd[1]>macd[2] &&  macd[2]>macd[3])
      return(bEntry ?ORDER_TYPE_SELL:ORDER_TYPE_BUY); // 卖出条件

   return(WRONG_VALUE); // 如果没有信号
  
}

CMyEA ea; // 类的实例

所以,编写代码后,将作为结果的“EA 交易”发送至策略测试程序。


3. 测试

在策略测试程序中,周期为 "去年" ,货币对为 EURUSD 时 ,我们得到下述图表:

图 3. 带初始化参数的交易系统的测试结果

图 3. 带初始化参数的交易系统的测试结果

结果不是那么令人满意,所以我们开始优化 Stop Loss 和 Take Profit 的水平。


4. 策略测试程序中的优化

我们会以 10-500 的间隔、50 的步幅,优化 Stop Loss 和 Take Profit 参数。

最佳结果: Stop Loss = 160,Take Profit = 310。优化 Stop Loss 与 Take Profit 之后,我们收到 67% 的可盈利交易(之前是 36%)和 $1522.97 的净利润。 由此,通过简单的处理,我们升级好的系统已经实现了收支平衡,甚至还有一些盈利。

图 4. 带有优化 Stop Loss 与 Take Profit 的交易系统的测试结果

图 4. 带有优化 Stop Loss 与 Take Profit 的交易系统的测试结果

接下来,我们来优化轨道线周期与方差。

轨道线周期会以 4 为步幅,从 10 变到 40,而方差则从 0.1 变到 1,步幅为 0.1。

最佳优化结果为: 轨道线周期 = 22,轨道线方差 = 0.3。 即使现在,我们已经获得了 $14418.92 的净利润和 79% 的可盈利交易。

图 5. 带有优化轨道线周期与方差的交易系统的测试结果

图 5. 带有优化轨道线周期与方差的交易系统的测试结果

如果我们将风险加到 0.8,我们就会获得 $77330.95 的净利润。

图 6. 带有优化风险的交易系统的测试结果

图 6. 带有优化风险的交易系统的测试结果

 

5. 策略优化

策略优化可能包含下述步骤:

  • 更改趋势指标
  • 选择另一条轨道线
  • 选择另一个时间表
  • 更改交易条件

5.1. 更改趋势指标

通过《在 MQL5 中寻找趋势的几种方法》一文我们可以看出,最佳的趋势指标是移动平均线和移动平均“扇形图”。

我们用简单的移动平均线来替代 MACD 指标。 EA 代码请见随附的 Macena.mq5 文件。

5.2. 选择另一条轨道线

Envelopes (轨道线)旁边,您也可以自行选择另一条轨道线。 例如:Price Channel(价格通道)、Bollinger Bands (布林带)或是某条基于移动平均线的轨道线。

随附的 Maboll.mq5 文件中,有一份使用 MA 与布林带的 EA 示例。

5.3. 选择另一个时间表

我们将时间表改大或改小。 大时间表用 H4,小时间表则用 M15,然后测试并优化您的系统。

为达此目的,只需替换代码中的一行:

m_henvel=iEnvelopes(m_smb,PERIOD_H1,m_EnvelPer,0,MODE_SMA,PRICE_CLOSE,m_EnvelDev);  // 创建轨道线指标

如是 H4 时间表:

m_henvel=iEnvelopes(m_smb,PERIOD_H4,m_EnvelPer,0,MODE_SMA,PRICE_CLOSE,m_EnvelDev);  // 创建轨道线指标 

如是 M15 时间表:

m_henvel=iEnvelopes(m_smb,PERIOD_M15,m_EnvelPer,0,MODE_SMA,PRICE_CLOSE,m_EnvelDev);  // 创建轨道线指标

5.4. 更改交易条件

作为一次试验,我们还要更改交易条件。  

  1. 让系统具备反向的能力。 我们会在从轨道线下边界反弹时买入,并在从轨道线上边界反弹时卖出。
  2. 不按日趋势检查系统。 也很简单,只需将下述代码插入交易块即可:
    //------------------------------------------------------------------ 检查信号
    long CMyEA::CheckSignal(bool bEntry)
      {
       double env1[3],   // 轨道线上轨值数组
             env2[3];    // 轨道线下轨值数组
       MqlRates rt[3];   // 最近3个柱形的价格数组
    
       if(CopyRates(m_smb,m_tf,0,3,rt)!=3) // 将最近3个柱形的价格值复制到数组中
         {
          Print("CopyRates ",m_smb," history is not loaded");
          return(WRONG_VALUE);
         
    }
    // 将指标值复制到数组
       if(CopyBuffer(m_henvel,0,0,2,env1)<2 || CopyBuffer(m_henvel,1,0,2,env2)<2)
         {
          Print("CopyBuffer - no data");
          return(WRONG_VALUE);
         
    }
    // 如果MACD在增长并且价格从轨道线下轨反弹,买入
       if(rt[1].open<env2[1] && rt[1].close>env2[1])
          return(bEntry ?ORDER_TYPE_BUY:ORDER_TYPE_SELL); // 买入的条件
    // 如果MACD在下降并且价格从轨道线上轨向下反弹,卖出
       if(rt[1].open>env1[1] && rt[2].close<env1[1])
          return(bEntry ?ORDER_TYPE_SELL:ORDER_TYPE_BUY); // 卖出条件
    
       return(WRONG_VALUE); // 如果没有信号
      
    }
    
    CMyEA ea; // 类的实例
    //------------------------------------------------------------------    OnInit
    
    

     3. 如果价格未大幅下滑、而是转而向上,我们就会平卖出持仓。

     4. 如果价格未大幅上扬、而是转而向下,我们就会平买入持仓。

您可以自创方法来优化交易策略,相关文献中也有一些介绍。

更深入的研究,就靠您自己了。


6. 以不同时间间隔测试

按相同的时间间隔测试我们的“EA 交易”,每次 1 个月。 我们将 "去年" 作为一个测试周期。 时间周期 - 3 个月。

测试间隔
利润,以美元计
可盈利交易
 1.01.2010 - 30.03.2010
7239.50 76.92%
 1.02.2010 - 30.04.2010 -6577.50 0%
 1.03.2010 - 30.05.2010 -8378.50 50%
 1.04.2010 - 30.06.2010 -6608.00 0%
 1.05.2010 - 30.07.2010  41599.50 80%
  1.06.2010 - 30.08.2010  69835.50  85%
总结: 将“EA 交易”搭配如此一种进取性资金管理使用,并不可取。 降低风险。


总结

简要总结: 以此模板为基础,您可以用最少的时间和精力,快速实现您的交易理念。

对于系统参数和交易标准的优化也没有任何问题。

要创建一套稳定性更高的交易系统,有必要在更长的时间间隔内对所有参数进行优化。

参考资源列表:
  1. 《用 MQL5 语言编写的 20 种交易信号》。
  2. 《交易机器人的原型》。
  3. 《在 MQL5 中寻找趋势的几种方法》。
  4. 《基于流行交易系统的“EA 交易”以及交易机器人优化点石成金》。
  5. 《“EA 交易”中的限制和验证》。
  6. 《利用 MQL5 面向对象编程法编写“EA 交易”》。
  7. 《“EA 交易”中的资金管理函数》。  

全部回复

0/140

量化课程

    移动端课程