Summary: 提供完整的MQL4多周期均线交叉EA源码,含双均线交叉信号、高周期过滤、保本止损和风险管理功能。帮助交易者快速掌握EA编程和策略优化。




本文提供一套完整的、可直接编译运行的MQL4专家顾问源码,基于多周期移动平均线交叉策略构建。均线交叉是外汇交易中最经典且广泛使用的趋势跟踪策略之一。本EA在传统双均线交叉的基础上,增加了更高时间周期的趋势过滤功能,能够有效减少震荡行情中的虚假信号,提高交易胜率。

该EA的核心运作机制为:在当前图表时间周期上计算两条均线(快线和慢线),并可选地通过更高时间周期的第三条均线来确认大趋势方向。当快线自下而上穿越慢线,且高周期趋势为多头时,触发买入信号;反之,当快线自上而下穿越慢线,且高周期趋势为空头时,触发卖出信号。这种多周期融合确认机制大幅提升了策略的鲁棒性,使其能够适应不同市场环境。

核心功能亮点:
  • 双均线交叉信号,均线类型、周期均可灵活调整

  • 可选高时间周期趋势过滤器,过滤逆势噪音

  • 支持固定手数或基于账户净值的风险比例资金管理

  • 内置止损、止盈及保本止损移动功能

  • 可分别控制允许开多、开空或双向交易

  • 适用于所有货币对及各种时间框架


  • 以下是该EA的完整源码。请将代码复制到MetaEditor中,编译后挂载到图表即可使用。注意本EA不使用DLL,运行安全稳定。

    ```mql4
    //+------------------------------------------------------------------+
    //| MA_Crossover_MTF_EA.mq4 |
    //| Copyright 2025, ForexSourceLab |
    //| https://www.example.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2025, ForexSourceLab"
    #property link "https://www.example.com"
    #property version "1.00"
    #property strict

    //+------------------------------------------------------------------+
    //| 输入参数 |
    //+------------------------------------------------------------------+
    input int FastMAPeriod = 10; // 快速均线周期
    input int SlowMAPeriod = 30; // 慢速均线周期
    input int SignalMAPeriod = 50; // 信号均线周期(高周期过滤用)
    input int MA_Shift = 0; // 均线偏移
    input int MA_Method = MODE_SMA; // 均线方法 (0=SMA,1=EMA,2=SMMA,3=LWMA)
    input int AppliedPrice = PRICE_CLOSE; // 应用价格
    input bool UseHigherTF = true; // 启用高周期趋势过滤
    input ENUM_TIMEFRAMES HigherTF = PERIOD_H1; // 高时间周期
    input double LotSize = 0.1; // 固定交易手数
    input bool UseRiskManagement = false; // 启用风险比例资金管理
    input double RiskPercent = 2.0; // 每笔交易风险比例(%)
    input int StopLoss = 60; // 止损点数
    input int TakeProfit = 120; // 止盈点数
    input int BreakevenTrigger = 30; // 保本激活点数
    input int BreakevenPips = 5; // 保本偏移点数
    input int MagicNumber = 202507; // EA魔术编号
    input bool AllowBuy = true; // 允许买入
    input bool AllowSell = true; // 允许卖出
    input int MaxOrders = 1; // 最大同时持仓数

    //+------------------------------------------------------------------+
    //| 全局变量 |
    //+------------------------------------------------------------------+
    datetime lastBarTime = 0;

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    if(FastMAPeriod <= 0 || SlowMAPeriod <= 0 || FastMAPeriod >= SlowMAPeriod)
    return(INIT_PARAMETERS_INCORRECT);
    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| EA反初始化函数 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    Comment("");
    }

    //+------------------------------------------------------------------+
    //| EA核心Tick函数 |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    //--- 检查新K线,避免同一K线重复触发
    if(Time[0] == lastBarTime) return;
    lastBarTime = Time[0];

    //--- 统计当前EA已开订单数量
    int totalOrders = CountTotalOrders(MagicNumber);
    if(totalOrders >= MaxOrders) return;

    //--- 计算当前图表周期的两条均线值
    double fastMA_0 = iMA(NULL, 0, FastMAPeriod, MA_Shift, MA_Method, AppliedPrice, 0);
    double fastMA_1 = iMA(NULL, 0, FastMAPeriod, MA_Shift, MA_Method, AppliedPrice, 1);
    double slowMA_0 = iMA(NULL, 0, SlowMAPeriod, MA_Shift, MA_Method, AppliedPrice, 0);
    double slowMA_1 = iMA(NULL, 0, SlowMAPeriod, MA_Shift, MA_Method, AppliedPrice, 1);

    //--- 计算更高时间周期的信号均线趋势(如果启用)
    bool higherTrendBull = true;
    bool higherTrendBear = true;
    if(UseHigherTF)
    {
    double signalMA_0 = iMA(NULL, HigherTF, SignalMAPeriod, MA_Shift, MA_Method, AppliedPrice, 0);
    double signalMA_1 = iMA(NULL, HigherTF, SignalMAPeriod, MA_Shift, MA_Method, AppliedPrice, 1);
    double signalMA_2 = iMA(NULL, HigherTF, SignalMAPeriod, MA_Shift, MA_Method, AppliedPrice, 2);
    //--- 通过信号均线的斜率定义趋势方向
    higherTrendBull = (signalMA_0 > signalMA_1 && signalMA_1 > signalMA_2);
    higherTrendBear = (signalMA_0 < signalMA_1 && signalMA_1 < signalMA_2);
    }

    //--- 检测金叉(看涨交叉)
    if(AllowBuy && higherTrendBull && fastMA_1 <= slowMA_1 && fastMA_0 > slowMA_0)
    {
    if(CountOrdersByType(MagicNumber, OP_BUY) == 0)
    {
    OpenOrder(OP_BUY);
    }
    }
    //--- 检测死叉(看跌交叉)
    if(AllowSell && higherTrendBear && fastMA_1 >= slowMA_1 && fastMA_0 < slowMA_0)
    {
    if(CountOrdersByType(MagicNumber, OP_SELL) == 0)
    {
    OpenOrder(OP_SELL);
    }
    }

    //--- 订单管理(保本止损)
    ManageOrders();
    }

    //+------------------------------------------------------------------+
    //| 开仓函数 |
    //+------------------------------------------------------------------+
    void OpenOrder(int cmd)
    {
    double price = (cmd == OP_BUY) ? Ask : Bid;
    double sl = 0, tp = 0;

    //--- 如果启用风险资金管理,动态计算手数
    double tradeLot = LotSize;
    if(UseRiskManagement)
    {
    double riskAmount = AccountBalance() * RiskPercent / 100.0;
    double pipValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double riskPips = StopLoss;
    tradeLot = riskAmount / (riskPips * pipValue * 10);
    tradeLot = MathMax(tradeLot, MarketInfo(Symbol(), MODE_MINLOT));
    tradeLot = MathMin(tradeLot, MarketInfo(Symbol(), MODE_MAXLOT));
    tradeLot = NormalizeDouble(tradeLot, 2);
    }

    if(StopLoss > 0)
    {
    sl = (cmd == OP_BUY) ? price - StopLoss * Point * 10 : price + StopLoss * Point * 10;
    }
    if(TakeProfit > 0)
    {
    tp = (cmd == OP_BUY) ? price + TakeProfit * Point * 10 : price - TakeProfit * Point * 10;
    }

    int ticket = OrderSend(Symbol(), cmd, tradeLot, price, 5, sl, tp, "MA Crossover EA", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    {
    Print("OrderSend failed with error #", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| 统计总订单数量 |
    //+------------------------------------------------------------------+
    int CountTotalOrders(int magic)
    {
    int count = 0;
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == magic)
    {
    count++;
    }
    }
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| 按类型统计订单数量 |
    //+------------------------------------------------------------------+
    int CountOrdersByType(int magic, int type)
    {
    int count = 0;
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == magic && OrderType() == type)
    {
    count++;
    }
    }
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| 订单管理(保本止损) |
    //+------------------------------------------------------------------+
    void ManageOrders()
    {
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    double openPrice = OrderOpenPrice();
    double currentSL = OrderStopLoss();

    if(OrderType() == OP_BUY)
    {
    //--- 保本止损逻辑
    if(BreakevenTrigger > 0 && currentSL < openPrice)
    {
    if(Bid - openPrice >= BreakevenTrigger * Point * 10)
    {
    double newSL = openPrice + BreakevenPips * Point * 10;
    if(newSL > currentSL)
    {
    if(!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE))
    Print("保本止损修改错误: ", GetLastError());
    }
    }
    }
    }
    else if(OrderType() == OP_SELL)
    {
    //--- 保本止损逻辑
    if(BreakevenTrigger > 0 && (currentSL > openPrice || currentSL == 0))
    {
    if(openPrice - Ask >= BreakevenTrigger * Point * 10)
    {
    double newSL = openPrice - BreakevenPips * Point * 10;
    if(newSL < currentSL || currentSL == 0)
    {
    if(!OrderModify(OrderTicket(), openPrice, newSL, OrderTakeProfit(), 0, clrNONE))
    Print("保本止损修改错误: ", GetLastError());
    }
    }
    }
    }
    }
    }
    }
    }
    //+------------------------------------------------------------------+
    ```

    详细使用说明:
    1. 在MT4中按F4打开MetaEditor。
    2. 新建专家顾问,将上述代码完整粘贴进去。
    3. 按F7编译代码,确保没有任何错误提示。
    4. 将EA拖拽到您选择的货币对图表上。
    5. 在“输入参数”选项卡中根据个人交易策略调整各项参数。
    6. 启用“允许实时交易”,并确保MT4工具栏上的自动交易按钮处于激活状态。

    参数详细解读:
  • `FastMAPeriod` / `SlowMAPeriod`:快速均线和慢速均线的计算周期,两者交叉形成交易信号。

  • `SignalMAPeriod`:高周期过滤所用的均线周期,仅在`UseHigherTF`启用时生效。

  • `MA_Method`:均线计算方法,可选SMA(简单移动平均)、EMA(指数移动平均)、SMMA(平滑移动平均)、LWMA(线性加权移动平均)。

  • `UseHigherTF`:是否启用更高时间周期的趋势确认。启用后,只有当高周期趋势与交叉信号方向一致时才会开仓。

  • `HigherTF`:用于趋势过滤的更高时间周期,例如H1、H4。

  • `LotSize`:每笔交易的固定手数。

  • `UseRiskManagement` / `RiskPercent`:启用后,EA将根据账户余额的百分比自动计算每笔交易的手数,实现动态资金管理。

  • `StopLoss` / `TakeProfit`:止损和止盈点数,设为0则代表不设置。

  • `BreakevenTrigger` / `BreakevenPips`:当价格朝着有利方向移动达到`BreakevenTrigger`点数时,将止损移动至保本位置(即开仓价加/减`BreakevenPips`偏移点)。

  • `MagicNumber`:该EA所下订单的专属魔术编号,用于区分不同EA的订单,防止相互干扰。

  • `AllowBuy` / `AllowSell`:分别控制是否允许开多单和空单,可灵活组合。

  • `MaxOrders`:同一时间内EA允许持有的最大订单数量,防止过度加仓。


  • 策略优化与扩展思路:
    为了使本EA更好地适应不同的市场环境,您可以考虑以下增强方向:
  • 引入ATR(平均真实波幅)指标实现动态止损止盈,而非固定点数。

  • 增加交易时段过滤器,限制只在流动性较高的主要交易时段开仓。

  • 添加移动止损功能,与保本止损形成互补,让利润充分奔跑。

  • 集成邮件或推送通知功能,实时获取交易状态更新。


  • 本EA是一个极佳的学习和实战起点,能够帮助您深入理解MQL4编程中多周期数据调用、订单管理、资金管理和风险控制等核心模块。在实际投入实盘之前,请务必在模拟账户上进行充分的回测和前瞻测试,以验证策略的有效性并优化参数组合。

    如果您希望获得更强大的交易工具,例如集成机器学习信号过滤、多币种组合管理、以及高级风险分散策略的付费版EA,欢迎关注我们的付费会员体系,我们将为您提供持续的策略升级和专业的技术支持,助您在交易之路上更进一步。

    参考来源:自主编译,基于标准MQL4均线交叉逻辑与多周期趋势过滤技术。