MQL4量化交易EA代码逐行解析:三重均线策略深度解读

这篇文章将逐行解读一段基于三重均线策略的MQL4 EA交易代码,帮助你理解量化交易策略的实现过程。MQL4//---#include <Trade\PositionInfo.mqh>#include <Trade\Trade.mqh>#include <Trade\SymbolInfo.mqh>

CPositionInfo m_position; // 交易持仓对象CTrade m_trade; // 交易对象CSymbolInfo m_symbol; // 交易品种信息对象

//--- 输入参数input double Lots = 0.05; // 交易手数input int FastMA = 6; // 快速均线周期input int MedianMA = 16; // 中间均线周期input int SlowMA = 30; // 慢速均线周期input ulong m_magic=42828093; // 魔术数字ulong m_slippage=10; // 滑点

//---int handle_fastMA; // 快速均线指标句柄int handle_medianMA; // 中间均线指标句柄int handle_slowMA; // 慢速均线指标句柄

//+------------------------------------------------------------------+//| EA 初始化函数 |//+------------------------------------------------------------------+int OnInit(){ //--- if(!m_symbol.Name(Symbol())) // 设置交易品种名称 return(INIT_FAILED);

RefreshRates();

string err_text='';    if(!CheckVolumeValue(Lots,err_text))    {        Print(err_text);        return(INIT_PARAMETERS_INCORRECT);    }

//---    m_trade.SetExpertMagicNumber(m_magic);

if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK))        m_trade.SetTypeFilling(ORDER_FILLING_FOK);    else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC))        m_trade.SetTypeFilling(ORDER_FILLING_IOC);    else        m_trade.SetTypeFilling(ORDER_FILLING_RETURN);

m_trade.SetDeviationInPoints(m_slippage);

//--- 创建快速均线指标句柄    handle_fastMA = iMA(m_symbol.Name(), PERIOD_M15, FastMA, 0, MODE_SMA, PRICE_CLOSE);    //--- 创建中间均线指标句柄    handle_medianMA = iMA(m_symbol.Name(), PERIOD_M15, MedianMA, 0, MODE_SMA, PRICE_CLOSE);    //--- 创建慢速均线指标句柄    handle_slowMA = iMA(m_symbol.Name(), PERIOD_M15, SlowMA, 0, MODE_SMA, PRICE_CLOSE);

//--- 检查指标句柄是否创建成功    if(handle_fastMA == INVALID_HANDLE || handle_medianMA == INVALID_HANDLE || handle_slowMA == INVALID_HANDLE)    {        Print('Failed to create moving average indicators for the symbol ', m_symbol.Name());        return(INIT_FAILED);    }

return(INIT_SUCCEEDED);}

//+------------------------------------------------------------------+//| EA 结束函数 |//+------------------------------------------------------------------+void OnDeinit(const int reason){ //---}

//+------------------------------------------------------------------+//| EA 价格变动处理函数 |//+------------------------------------------------------------------+void OnTick(){ //--- 仅在新K线生成时进行交易 static datetime PrevBars=0; datetime time_0=iTime(0); if(time_0==PrevBars) return; PrevBars=time_0;

//--- 获取均线值    double fastMA = iMAGet(0, handle_fastMA);    double medianMA = iMAGet(0, handle_medianMA);    double slowMA = iMAGet(0, handle_slowMA);

//--- 检查当前是否有持仓    for(int i=PositionsTotal()-1;i>=0;i--)    {        if(m_position.SelectByIndex(i))        {            if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)            {                if(m_position.PositionType()==POSITION_TYPE_BUY && fastMA < medianMA && fastMA < slowMA)                {                    //--- 卖出平仓                    m_trade.PositionClose(m_position.Ticket());                    break;                }                else if(m_position.PositionType()==POSITION_TYPE_SELL && fastMA > medianMA && fastMA > slowMA)                {                    //--- 买入平仓                    m_trade.PositionClose(m_position.Ticket());                    break;                }            }        }    }

//--- 如果快速均线上穿中间均线和慢速均线,进行买入交易    if(fastMA > medianMA && fastMA > slowMA && m_position.PositionType() != POSITION_TYPE_BUY && iClose(m_symbol.Name(), PERIOD_M15, 1) > fastMA && iClose(m_symbol.Name(), PERIOD_M15, 1) > medianMA && iClose(m_symbol.Name(), PERIOD_M15, 1) > slowMA)    {        m_trade.Buy(Lots, m_symbol.Name());    }    //--- 如果快速均线下穿中间均线和慢速均线,进行卖出交易    else if(fastMA < medianMA && fastMA < slowMA && m_position.PositionType() != POSITION_TYPE_SELL && iClose(m_symbol.Name(), PERIOD_M15, 1) < fastMA && iClose(m_symbol.Name(), PERIOD_M15, 1) < medianMA && iClose(m_symbol.Name(), PERIOD_M15, 1) < slowMA)    {        m_trade.Sell(Lots, m_symbol.Name());    }}

//+------------------------------------------------------------------+//| 刷新交易品种行情数据 |//+------------------------------------------------------------------+bool RefreshRates(void){ //--- 刷新行情数据 if(!m_symbol.RefreshRates()) { Print('RefreshRates error'); return(false); }

//--- 保护返回值不为'零'    if(m_symbol.Ask()==0 || m_symbol.Bid()==0)        return(false);

return(true);}

//+------------------------------------------------------------------+//| 检查交易手数的正确性 |//+------------------------------------------------------------------+bool CheckVolumeValue(double volume, string &error_description){ //--- 最小允许交易手数 double min_volume = m_symbol.LotsMin(); if(volume < min_volume) { error_description = StringFormat('Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f', min_volume); return(false); }

//--- 最大允许交易手数    double max_volume = m_symbol.LotsMax();    if(volume > max_volume)    {        error_description = StringFormat('Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f', max_volume);        return(false);    }

//--- 获取交易手数变动的最小步长    double volume_step = m_symbol.LotsStep();    int ratio = (int)MathRound(volume / volume_step);    if(MathAbs(ratio * volume_step - volume) > 0.0000001)    {        error_description = StringFormat('Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f',                                     volume_step,ratio * volume_step);        return(false);    }    error_description = 'Correct volume value';    return(true);}

//+------------------------------------------------------------------+ //| 检查指定的成交模式是否允许 | //+------------------------------------------------------------------+ bool IsFillingTypeAllowed(int fill_type){ int filling = m_symbol.TradeFillFlags(); return((filling & fill_type) == fill_type);}

//+------------------------------------------------------------------+ //| 获取指定柱子的时间 | //+------------------------------------------------------------------+ datetime iTime(const int index, string symbol=NULL, ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT){ if(symbol == NULL) symbol = m_symbol.Name(); if(timeframe == 0) timeframe = Period(); datetime Time[1]; datetime time = 0; int copied = CopyTime(symbol, timeframe, index, 1, Time); if(copied > 0) time = Time[0]; return(time);}

//+------------------------------------------------------------------+//| 获取iMA指标缓冲区的值 |//| 缓冲区编号如下: |//| 0 - MAIN_LINE, 1 - SIGNAL_LINE |//+------------------------------------------------------------------+double iMAGet(const int index, const int handle){ double MA[1]; if(CopyBuffer(handle, 0, index, 1, MA) < 0) { Print('Failed to copy data from the moving average indicator'); return(0.0); } return(MA[0]);}

代码解析:

  • 头文件引入 (1-3行): 引入了三个必要的头文件: * Trade\PositionInfo.mqh:提供管理交易持仓信息的类和函数。 * Trade\Trade.mqh: 提供执行交易操作的类和函数。 * Trade\SymbolInfo.mqh:提供获取交易品种信息的类和函数。

  • 全局变量声明 (5-18行): * 声明了三个全局对象:m_position (交易持仓对象), m_trade (交易对象), m_symbol (交易品种信息对象)。 * 定义了五个输入参数:Lots (交易手数), FastMA (快速均线周期), MedianMA (中间均线周期), SlowMA (慢速均线周期), m_magic (EA识别码), m_slippage (滑点)。 * 声明了三个指标句柄: handle_fastMA, handle_medianMA, handle_slowMA, 用于存储不同周期的均线指标数据。

  • OnInit() 函数 (21-47行): EA 初始化函数, 在 EA 加载时执行一次。 * 设置交易品种名称,并检查设置是否成功。 * 调用 RefreshRates() 函数更新价格信息。 * 检查交易手数设置是否合法。 * 设置 EA 的魔术数字, 用于区分不同 EA 的订单。 * 设置订单成交模式。 * 设置允许滑点。 * 创建三个不同周期的均线指标句柄。 * 检查指标句柄是否创建成功。

  • OnDeinit() 函数 (50-52行): EA 结束函数, 在 EA 卸载时执行一次。

  • OnTick() 函数 (55-99行): 每次价格变动时都会调用该函数。 * 仅在新 K 线生成时执行交易逻辑。 * 获取三个均线的当前值。 * 检查当前是否有持仓,如果有,根据当前价格与均线的关系判断是否平仓。 * 判断快速均线与其他两条均线的关系,并根据预设的策略进行开仓操作。

  • RefreshRates() 函数 (102-119行): 刷新交易品种的行情数据。

  • CheckVolumeValue() 函数 (122-150行): 检查交易手数设置是否符合规范。

  • IsFillingTypeAllowed() 函数 (153-165行): 检查指定的成交模式是否允许。

  • iTime() 函数 (168-180行): 获取指定柱子的时间。

  • iMAGet() 函数 (183-197行): 获取 iMA 指标缓冲区的值。

三重均线交易策略:

该 EA 使用了基于三条均线的交易策略:

  • 开仓信号: * 当快速均线上穿中间均线和慢速均线时,产生买入信号。 * 当快速均线下穿中间均线和慢速均线时,产生卖出信号。* 平仓信号: * 当持有多单且快速均线下穿中间均线和慢速均线时,平仓。 * 当持有空单且快速均线上穿中间均线和慢速均线时,平仓。

总结:

这段代码展示了一个简单的基于三重均线的量化交易策略,并详细解释了每行代码的功能。 通过学习这段代码,你可以了解到如何使用 MQL4 语言编写 EA,以及如何将交易策略转化为代码实现。

MQL4量化交易EA代码逐行解析:三重均线策略深度解读

原文地址: https://www.cveoy.top/t/topic/fUXk 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录