© 本贴为 xxtz 原创/首发,严禁抄袭!
用MT5向导建立交易系统好处多多,操作简单,但后面的代码原理异常复杂,了解原理应该对更好的建立放心的交易系统有好处。这里做的是学习笔记,非计算机科班出身,只是爱好编程,所以记录有出入,请善意指出。
通过"Expert Advisor (generate)"产生的交易策略主要通过选择3模块,均存放在“\<client_terminal_directory>\MQL5\Include\Expert\”文件夹下:1.交易信号(Trade Signals),目前系统自带20个,2.移动止损(Trailing),3.资金管理(Money Management)来建立EA。这3个模块选择,是通过向导的3个相对应的页面选择完成的。
向导点击完成后,相应的代码自动产生了。向导产生的EA代码包括如下几个部分,不同交易信号算法有差异代码细节处会有不同,但大体结构差不多。如下以AMAsignals建立的EA为例,该EA设置了两个交易进出场条件,根据资金余额确定下单手数,固定止损。
1. 描述程序的proberties: copyright;link;version.,是向导的第一步的输入信息。
//+------------------------------------------------------------------+
//| wizardAMA.mq5 |
//| xxtz |
//| |
//+------------------------------------------------------------------+
#property copyright "xxtz"
#property link ""
#property version "1.00"
//+--------------------------------
复制代码
2. 包含文件://+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\Signal\SignalAMA.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingFixedPips.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedRisk.mqh>
//+-------------------------------------------
复制代码
3.EA的参数输入,这是在向导(下一步)的第二、三、四步输入的信息。//+------------------------------------------------------------------+
//| Inputs |
//+------------------------------------------------------------------+
//--- inputs for expert
input string Expert_Title ="wizardAMA"; // Document name
ulong Expert_MagicNumber =6964; //
bool Expert_EveryTick =false; //
//--- inputs for main signal
input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100]
input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100]
input double Signal_PriceLevel =0.0; // Price level to execute a deal
input double Signal_StopLevel =50.0; // Stop Loss level (in points)
input double Signal_TakeLevel =50.0; // Take Profit level (in points)
input int Signal_Expiration =4; // Expiration of pending orders (in bars)
input int Signal_0_AMA_PeriodMA =10; // Adaptive Moving Average(10,...) Period of averaging
input int Signal_0_AMA_PeriodFast =2; // Adaptive Moving Average(10,...) Period of fast EMA
input int Signal_0_AMA_PeriodSlow =30; // Adaptive Moving Average(10,...) Period of slow EMA
input int Signal_0_AMA_Shift =0; // Adaptive Moving Average(10,...) Time shift
input ENUM_APPLIED_PRICE Signal_0_AMA_Applied =PRICE_CLOSE; // Adaptive Moving Average(10,...) Prices series
input double Signal_0_AMA_Weight =1.0; // Adaptive Moving Average(10,...) Weight [0...1.0]
input int Signal_1_AMA_PeriodMA =20; // Adaptive Moving Average(20,...) Period of averaging
input int Signal_1_AMA_PeriodFast =2; // Adaptive Moving Average(20,...) Period of fast EMA
input int Signal_1_AMA_PeriodSlow =30; // Adaptive Moving Average(20,...) Period of slow EMA
input int Signal_1_AMA_Shift =0; // Adaptive Moving Average(20,...) Time shift
input ENUM_APPLIED_PRICE Signal_1_AMA_Applied =PRICE_CLOSE; // Adaptive Moving Average(20,...) Prices series
input double Signal_1_AMA_Weight =1.0; // Adaptive Moving Average(20,...) Weight [0...1.0]
//--- inputs for trailing
input int Trailing_FixedPips_StopLevel =300; // Stop Loss trailing level (in points)
input int Trailing_FixedPips_ProfitLevel=500; // Take Profit trailing level (in points)
//--- inputs for money
input double Money_FixRisk_Percent =10.0; // Risk percentage
复制代码
其中前3行(Expert_Title, Expert_MagicNumber and Expert_EveryTick)所有向导产生的EA都是有的。
Expert_MagicNumber:会用在trade requests的参数中(就是下单时候要用到)。
Expert_EveryTick: 设置EA工作模式,如果是true, 会在每个新tick进来都调用句柄函数(检查交易条件,执行交易,仓位的移动止损止盈),他会响应程序最后的OnTick事件产生作用。
//--- inputs for main signal 这个部分是CsignalAMA类实例化时用到的参数。这块是入场核心,未来看是否有时间单篇详解Signal。
//--- inputs for trailing 这个部分是CTrailingStopFixedPips类实例化时用到的参数。移动到指定距离修改止盈和止损位置。
//--- inputs for money 这个部分是执行CMoneyFixedRisk类,重载其父类CExpertMoney一些方法【CheckOpenLong,CheckOpenShort,CheckClose】,CMoneyFixedRisk考虑即将下单如果止损后的资金余额的百分比的下单手数[使用了算法loss=OrderCalcProfit(trade_operation,symbol,1.0,price_open=指定的价格一般根据多空是ASK或BID,price_close=sl,profit),然后lot=MathFloor(m_account.Balance()*m_percent/loss/100.0/stepvol)*stepvol]。换句话说,手数是满足,这单止损后,账户资金还可以同样的单子再损100/risk个单子。
4.声明ExtExper对象,它是CExpert类的实例化。//+------------------------------------------------------------------+
//| Global expert object |
//+------------------------------------------------------------------+
CExpert ExtExpert;
复制代码
ExtExper对象包含了CExpertSignal(trade signals的基类),CExpertMoney(资金和风险管理的基类),CExpertTrailing(仓位的移动的基类)。 该类还包含CExpertTrade(交易),CSymbolnfo(交易品种信息),CAccountInfo(账户的信息),CPositionInfo(已开仓仓位信息),CorderInfo(挂单信息),CIndicators(内置指标的信息)。
5.为了给EA设置参数,需要给对应的类创建实例,在ExExpert类中给创建的对象指定引用。
下面就是在int OnInit()种初始化和配置ExExperts类对象。
5.1.使用了Init方法,对symbol,timeframe,everytick调用方式(是-不加入时间周期,否-加入时间周期),EA的ID(magic),3位或5位小数的位数digits_adjust=10倍调整(m_adjusted_point=m_symbol.Point()*digits_adjust)等。
int OnInit()
{
//--- Initializing expert
if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
{
//--- failed
printf(__FUNCTION__+": error initializing expert");
ExtExpert.Deinit();
return(INIT_FAILED);
}
复制代码
,该阶段也创建了私有类的对象用作signals,trailing and money management对象如下。
//--- trading objects
CExpertTrade *m_trade; // trading object
CExpertSignal *m_signal; // trading signals object
CExpertMoney *m_money; // money manager object
CExpertTrailing *m_trailing; // trailing stops object
bool m_check_volume; // check and decrease trading volume before OrderSend
5.2创建和配置信号Signal(白话就是 进出场条件)对象属性,系统自带20个signal,也可以自己编写signal。//--- Creating signal
CExpertSignal *signal=new CExpertSignal;
if(signal==NULL)
{
//--- failed
printf(__FUNCTION__+": error creating signal");
ExtExpert.Deinit();
return(INIT_FAILED);
}
//---
ExtExpert.InitSignal(signal);
signal.ThresholdOpen(Signal_ThresholdOpen);
signal.ThresholdClose(Signal_ThresholdClose);
signal.PriceLevel(Signal_PriceLevel);
signal.StopLevel(Signal_StopLevel);
signal.TakeLevel(Signal_TakeLevel);
signal.Expiration(Signal_Expiration);
//--- Creating filter CSignalAMA
CSignalAMA *filter0=new CSignalAMA;
if(filter0==NULL)
{
//--- failed
printf(__FUNCTION__+": error creating filter0");
ExtExpert.Deinit();
return(INIT_FAILED);
}
signal.AddFilter(filter0);
//--- Set filter parameters
filter0.PeriodMA(Signal_0_AMA_PeriodMA);
filter0.PeriodFast(Signal_0_AMA_PeriodFast);
filter0.PeriodSlow(Signal_0_AMA_PeriodSlow);
filter0.Shift(Signal_0_AMA_Shift);
filter0.Applied(Signal_0_AMA_Applied);
filter0.Weight(Signal_0_AMA_Weight);
//--- Creating filter CSignalAMA
CSignalAMA *filter1=new CSignalAMA;
if(filter1==NULL)
{
//--- failed
printf(__FUNCTION__+": error creating filter1");
ExtExpert.Deinit();
return(INIT_FAILED);
}
signal.AddFilter(filter1);
//--- Set filter parameters
filter1.PeriodMA(Signal_1_AMA_PeriodMA);
filter1.PeriodFast(Signal_1_AMA_PeriodFast);
filter1.PeriodSlow(Signal_1_AMA_PeriodSlow);
filter1.Shift(Signal_1_AMA_Shift);
filter1.Applied(Signal_1_AMA_Applied);
filter1.Weight(Signal_1_AMA_Weight);
复制代码
配置信号对象:
5.2.1 创建信号对象(New CExpertSignal)和设置该对象的参数(如ExExpert.InitSignal(signal); signal.ThresholdOpen(Signal_ThresholdeOpen);等等);
5.2.2 创建交易信号模块(白话就是 具体的进出场条件,这里有2个,分别是filter0和filter1)(如CSignalAMA *filter0=new CSignalAMA;)并将其加入CExpertSingal类实例总(如signal.AddFilter(filter0););
5.2.3 设置信号模块的参数(白话就是 具体的进出场条件要用到什么指标呢,比如这里要用均线,设置均线周期个数等等)(如filter0.PeriodMA(Signal_0_AMA_PeriodMA);)
5.3 创建和配置仓位的移动trailing属性(trailing白话就是 随着价格变化,移动止盈或移动止损的变化调整),MT5自带选项有:根据固定点数FixedPips,均线MA,抛物线ParabolicSAR设置移动属性,也可以None不设移动属性,
5.3.1 创建trailing对象//--- Creation of trailing object
CTrailingFixedPips *trailing=new CTrailingFixedPips;
if(trailing==NULL)
{
//--- failed
printf(__FUNCTION__+": error creating trailing");
ExtExpert.Deinit();
return(INIT_FAILED);
}
复制代码
5.3.2 将创建的trailing对象加入expert,通过ExtExpert.InitTrailing方法设置了magic,everytick,该方法里也有调用其父类ExpertBase的Init方法,其设置了symbol,adjust_point,period等//--- Add trailing to expert (will be deleted automatically))
if(!ExtExpert.InitTrailing(trailing))
{
//--- failed
printf(__FUNCTION__+": error initializing trailing");
ExtExpert.Deinit();
return(INIT_FAILED);
}
复制代码
5.3.2 设置trailing对象参数//--- Set trailing parameters
trailing.StopLevel(Trailing_FixedPips_StopLevel);
trailing.ProfitLevel(Trailing_FixedPips_ProfitLevel);
复制代码
5.4 创建和配置资金风险管理对象(白话就是 下单手数如何确定),步骤同上。系统自带选项有:FixedLot固定手数,FixMargin固定权益(觉得只是不带杠杆才可能采用这个),FixedRisk固定余额百分比,SizeOptimized根据历史单优化下单手数,None最小下单手数。
5.4.1 创建该对象//--- Creation of money object
CMoneyFixedRisk *money=new CMoneyFixedRisk;
if(money==NULL)
{
//--- failed
printf(__FUNCTION__+": error creating money");
ExtExpert.Deinit();
return(INIT_FAILED);
}
复制代码
5.4.2 将该对象加入Expert中//--- Add money to expert (will be deleted automatically))
if(!ExtExpert.InitMoney(money))
{
//--- failed
printf(__FUNCTION__+": error initializing money");
ExtExpert.Deinit();
return(INIT_FAILED);
}
复制代码
5.4.3 设置该对象的参数//--- Set money parameters
money.Percent(Money_FixRisk_Percent);
//--- Check all trading objects parameters
if(!ExtExpert.ValidationSettings())
{
//--- failed
ExtExpert.Deinit();
return(INIT_FAILED);
}
//--- Tuning of all necessary indicators
复制代码
5.5 初始化类中使用的所有指标。
在上面的交易信号,移动管理,资金风险管理对象初始化后, ExExpert调用InitIndicators成员函数,它初始化之前初始化对象需要使用的指标,获取需要的时间序列数据(检查价格时间序列(开高收低)和其他时间序列(时间、成交量等))
//--- Tuning of all necessary indicators
if(!ExtExpert.InitIndicators())
{
//--- failed
printf(__FUNCTION__+": error initializing indicators");
ExtExpert.Deinit();
return(INIT_FAILED);
}
//--- ok
return(INIT_SUCCEEDED);
复制代码
6. 在 OnDeinit, OnTick, OnTrade and OnTimer 时间句柄总调用相应的ExExpert类中的相应方法实现有关功能。OnTick会处理对于新报价事件出现后,我们之前有关设置Expert_EveryTick工作模式的这儿起作用了,OnTrade会处理订单,仓位等的变化,我们之前有关设置trade检查多空仓位,trailing设置,risk决定的手数等这儿起作用了。 一般编写EA代码,这里是重头戏,但是这里代码多少看,却是最简单的地方了。
//+------------------------------------------------------------------+
//| Deinitialization function of the expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ExtExpert.Deinit();
}
//+------------------------------------------------------------------+
//| "Tick" event handler function |
//+------------------------------------------------------------------+
void OnTick()
{
ExtExpert.OnTick();
}
//+------------------------------------------------------------------+
//| "Trade" event handler function |
//+------------------------------------------------------------------+
void OnTrade()
{
ExtExpert.OnTrade();
}
//+------------------------------------------------------------------+
//| "Timer" event handler function |
//+------------------------------------------------------------------+
void OnTimer()
{
ExtExpert.OnTimer();
}
复制代码
至此,MT5向导代码初步解析完成了,可见向导产生的代码与我们一般手工编写的代码有很大的不同,不符合一般习惯思维方式,但它更加模块化,理论上效率应该更高,熟练后维护更加方便。