//+------------------------------------------------------------------+
//|                  MovingAverageCrossoverEA.mq5                     |
//|                            Created by ChatGPT                      |
//+------------------------------------------------------------------+
#property copyright 'Created by ChatGPT'
#property link      'https://www.example.com'
#property version   '1.000'
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
//--- input parameters
input double   Lots        = 0.5;              // 交易手数
input int      FastMAPeriod = 6;             // 快速均线周期
input int      MiddleMAPeriod = 15;           // 中期均线周期
input int      SlowMAPeriod  = 30;            // 慢速均线周期
input int      ExitMAFastPeriod = 8;          // 快速出场均线周期
input int      ExitMASlowPeriod = 28;         // 慢速出场均线周期
input ulong    m_magic=42828093;             // 魔术数字
ulong          m_slippage=10;                // 滑点
//---
int         handle_fastMA;                   // 快速均线指标句柄
int         handle_middleMA;                  // 中期均线指标句柄
int         handle_slowMA;                   // 慢速均线指标句柄
int         handle_exitFastMA;                // 快速出场均线指标句柄
int         handle_exitSlowMA;                // 慢速出场均线指标句柄
//+------------------------------------------------------------------+
//|  Expert initialization function                                  |
//+------------------------------------------------------------------+
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, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
    handle_middleMA = iMA(m_symbol.Name(), PERIOD_M15, MiddleMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
    handle_slowMA = iMA(m_symbol.Name(), PERIOD_M15, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
    handle_exitFastMA = iMA(m_symbol.Name(), PERIOD_M15, ExitMAFastPeriod, 0, MODE_SMA, PRICE_CLOSE);
    handle_exitSlowMA = iMA(m_symbol.Name(), PERIOD_M15, ExitMASlowPeriod, 0, MODE_SMA, PRICE_CLOSE);

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

    return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//|  Expert deinitialization function                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    //---
}
//+------------------------------------------------------------------+
//|  Expert tick function                                            |
//+------------------------------------------------------------------+
void OnTick()
{
    //--- 仅在新K线生成时进行交易
    static datetime PrevBars=0;
    datetime time_0=iTime(0);
    if(time_0==PrevBars)
        return;
    PrevBars=time_0;

    //--- 获取均线值
    double fastMA = iMA(m_symbol.Name(), PERIOD_M15, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
    double middleMA = iMA(m_symbol.Name(), PERIOD_M15, MiddleMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
    double slowMA = iMA(m_symbol.Name(), PERIOD_M15, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE); 
    double exitFastMA = iMA(m_symbol.Name(), PERIOD_M15, ExitMAFastPeriod, 0, MODE_SMA, PRICE_CLOSE);
    double exitSlowMA = iMA(m_symbol.Name(), PERIOD_M15, ExitMASlowPeriod, 0, MODE_SMA, PRICE_CLOSE); 
    double closePrice = Close[0];

    //--- 检查当前是否有持仓
    if(m_position.Select(m_symbol.Name()) && m_position.Magic()==m_magic)
    {
        if(m_position.PositionType()==POSITION_TYPE_BUY)
        {
            if (closePrice < exitFastMA) {
                //--- 退出多头仓位
                m_trade.PositionClose(m_position.Ticket());
            }
        }
        else if(m_position.PositionType()==POSITION_TYPE_SELL)
        {
            if (closePrice > exitSlowMA) {
                //--- 退出空头仓位
                m_trade.PositionClose(m_position.Ticket());
            }
        }
    }
    else
    {
        //--- 如果没有持仓,检查是否满足开仓条件
        if (closePrice > fastMA && closePrice > middleMA && closePrice > slowMA && closePrice > exitFastMA)
        {
            //--- 做多
            m_trade.Buy(Lots, m_symbol.Name());
        }
        else if (closePrice < fastMA && closePrice < middleMA && closePrice < slowMA && closePrice < exitSlowMA)
        {
            //--- 做空
            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);
}
//+------------------------------------------------------------------+

代码解读

  • 初始化函数 (OnInit):
    • 设置 EA 的参数,例如交易手数、魔术数字等。
    • 创建所需指标的句柄,包括快速、中期、慢速均线以及出场均线。
    • 检查指标句柄是否创建成功。
  • 主循环函数 (OnTick):
    • 仅在新 K 线生成时执行交易逻辑,避免重复计算。
    • 获取当前 K 线的收盘价以及各条均线的值。
    • 检查当前是否有持仓,如果有,则根据出场条件决定是否平仓。
    • 如果没有持仓,则根据开仓条件决定是否开多或开空。
  • 辅助函数:
    • RefreshRates: 刷新交易品种的行情数据。
    • CheckVolumeValue: 检查交易手数是否符合最小步长和最大最小限制。
    • IsFillingTypeAllowed: 检查指定的成交模式是否允许。
    • iTime: 获取指定柱子的时间。

注意

  • 该代码仅供参考,实际交易中请谨慎使用。
  • 可以根据需要修改 EA 的参数和逻辑。
  • 建议在模拟账户上充分测试 EA 的性能后再进行实盘交易。
  • 交易外汇和差价合约具有高风险,并非适合所有投资者。在决定交易外汇之前,您应该仔细考虑您的投资目标、经验水平和风险承受能力。
MQL5 双向均线交易 EA 代码示例

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

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