Summary: 提供专业级MQL4 EA源码,融合RSI、MACD、EMA三种信号,支持投票开仓、固定比例资金管理、新闻过滤和时间过滤。完整可编译,适合进阶交易者。




本文提供一套专业级MQL4 EA源码,融合了RSI、MACD和EMA交叉三种信号类型,并集成了高级资金管理与新闻过滤器。适合希望通过多信号源分散风险并进行智能仓位管理的交易者。

策略逻辑:
  • 信号1(RSI):超卖(<30)做多,超买(>70)做空

  • 信号2(MACD):主线上穿信号线做多,下穿做空

  • 信号3(EMA):快线(12)上穿慢线(26)做多,下穿做空

  • 投票机制:需要至少2个信号一致才开仓(可配置)

  • 可选:要求3个信号完全一致


  • 高级功能:
  • 固定比例资金管理(基于账户净值计算仓位)

  • 时间过滤器(仅指定时间段交易)

  • 新闻过滤器(避开重大新闻前后时段)

  • 移动止损、保本止损、最大点差保护


  • 参数详解:
  • `SignalVoteRequirement` – 0=任一信号,1=至少2个,2=全部3个

  • `RSI_Period` / `RSI_Overbought` / `RSI_Oversold` – RSI参数

  • `MACD_Fast` / `MACD_Slow` / `MACD_Signal` – MACD参数

  • `EMA_Fast` / `EMA_Slow` – 均线参数

  • `UseFixedRatioMM` – 是否启用固定比例资金管理,`RiskPercent` – 每笔风险百分比

  • `UseNewsFilter` – 是否启用新闻过滤,`NewsAvoidHours` – 新闻前后避开小时数

  • `StartHour` / `EndHour` – 交易时段

  • `MaxSpread` – 最大允许点差


  • MQL4源码:

    ```mql4
    //+------------------------------------------------------------------+
    //| MultiStrategyEA_MoneyManagement.mq4 |
    //| 自主编译 / Self-compiled |
    //+------------------------------------------------------------------+
    #property copyright "外汇高级工具"
    #property link ""
    #property version "2.00"
    #property strict

    //--- 信号设置
    input int SignalVoteRequirement = 1; // 0=任一,1=至少2个,2=全部3个
    input int RSI_Period = 14;
    input double RSI_Overbought = 70;
    input double RSI_Oversold = 30;
    input int MACD_Fast = 12;
    input int MACD_Slow = 26;
    input int MACD_Signal = 9;
    input int EMA_Fast = 12;
    input int EMA_Slow = 26;

    //--- 资金管理
    input bool UseFixedRatioMM = true;
    input double RiskPercent = 2.0; // 每笔风险占净值百分比
    input double FixedLotSize = 0.1;
    input int StopLoss = 50;
    input int TakeProfit = 150;

    //--- 过滤器
    input bool UseNewsFilter = true;
    input int NewsAvoidHours = 2; // 新闻前后2小时不开仓
    input bool UseTimeFilter = true;
    input int StartHour = 8;
    input int EndHour = 20;
    input int MaxSpread = 30; // 最大点差
    input int TrailingStop = 40;
    input int BreakEvenPips = 30;

    //--- EA设置
    input int MagicNumber = 202411;
    input int Slippage = 3;

    double currentSpread;
    datetime lastNewsCheck = 0;
    string highImpactNewsSymbols[] = {"USD","EUR","GBP","JPY","AUD","CAD","CHF","NZD"};

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    if(EMA_Fast >= EMA_Slow)
    {
    Print("错误:EMA快线周期必须小于慢线周期");
    return(INIT_PARAMETERS_INCORRECT);
    }
    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| EA核心tick函数 |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // 点差检查
    currentSpread = (Ask - Bid) / _Point;
    if(currentSpread > MaxSpread && MaxSpread > 0)
    {
    Comment("点差过高:", currentSpread);
    return;
    }

    // 时间过滤
    if(UseTimeFilter && !IsTradingTime())
    {
    Comment("非交易时段");
    return;
    }

    // 新闻过滤
    if(UseNewsFilter && IsNewsTime())
    {
    Comment("新闻过滤激活 - 暂停交易");
    return;
    }

    // 移动止损和保本处理
    ManageOpenPositions();

    // 检查新开仓信号
    if(CountOpenOrders() == 0)
    {
    int signal = GetCombinedSignal();
    if(signal == 1) OpenOrder(OP_BUY);
    if(signal == -1) OpenOrder(OP_SELL);
    }
    }

    //+------------------------------------------------------------------+
    //| 组合信号投票系统 |
    //+------------------------------------------------------------------+
    int GetCombinedSignal()
    {
    int buyVotes = 0, sellVotes = 0;

    // RSI信号
    double rsi = iRSI(_Symbol,0,RSI_Period,PRICE_CLOSE,1);
    double rsi_prev = iRSI(_Symbol,0,RSI_Period,PRICE_CLOSE,2);
    if(rsi < RSI_Oversold && rsi_prev <= RSI_Oversold) buyVotes++;
    if(rsi > RSI_Overbought && rsi_prev >= RSI_Overbought) sellVotes++;

    // MACD信号
    double macd_main = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_MAIN,1);
    double macd_signal = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_SIGNAL,1);
    double macd_main_prev = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_MAIN,2);
    double macd_signal_prev = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_SIGNAL,2);
    if(macd_main > macd_signal && macd_main_prev <= macd_signal_prev) buyVotes++;
    if(macd_main < macd_signal && macd_main_prev >= macd_signal_prev) sellVotes++;

    // EMA交叉信号
    double ema_fast = iMA(_Symbol,0,EMA_Fast,0,MODE_EMA,PRICE_CLOSE,1);
    double ema_slow = iMA(_Symbol,0,EMA_Slow,0,MODE_EMA,PRICE_CLOSE,1);
    double ema_fast_prev = iMA(_Symbol,0,EMA_Fast,0,MODE_EMA,PRICE_CLOSE,2);
    double ema_slow_prev = iMA(_Symbol,0,EMA_Slow,0,MODE_EMA,PRICE_CLOSE,2);
    if(ema_fast > ema_slow && ema_fast_prev <= ema_slow_prev) buyVotes++;
    if(ema_fast < ema_slow && ema_fast_prev >= ema_slow_prev) sellVotes++;

    // 投票逻辑
    if(SignalVoteRequirement == 0)
    {
    if(buyVotes > 0) return 1;
    if(sellVotes > 0) return -1;
    }
    else if(SignalVoteRequirement == 1)
    {
    if(buyVotes >= 2) return 1;
    if(sellVotes >= 2) return -1;
    }
    else if(SignalVoteRequirement == 2)
    {
    if(buyVotes == 3) return 1;
    if(sellVotes == 3) return -1;
    }
    return 0;
    }

    //+------------------------------------------------------------------+
    //| 固定比例资金管理 - 动态计算手数 |
    //+------------------------------------------------------------------+
    double CalculateLotSize()
    {
    if(!UseFixedRatioMM) return FixedLotSize;

    double riskMoney = AccountBalance() * RiskPercent / 100;
    double tickValue = MarketInfo(_Symbol,MODE_TICKVALUE);
    double stopPoints = StopLoss * 10;
    if(stopPoints <= 0) return FixedLotSize;

    double lot = riskMoney / (stopPoints * tickValue);
    double minLot = MarketInfo(_Symbol,MODE_MINLOT);
    double maxLot = MarketInfo(_Symbol,MODE_MAXLOT);
    double stepLot = MarketInfo(_Symbol,MODE_LOTSTEP);

    lot = MathFloor(lot / stepLot) * stepLot;
    lot = MathMax(minLot, MathMin(maxLot, lot));

    return NormalizeDouble(lot, 2);
    }

    //+------------------------------------------------------------------+
    //| 开仓函数(动态手数) |
    //+------------------------------------------------------------------+
    void OpenOrder(int cmd)
    {
    double lot = CalculateLotSize();
    double price, sl, tp;

    if(cmd == OP_BUY)
    {
    price = Ask;
    if(StopLoss > 0) sl = price - StopLoss * _Point * 10;
    if(TakeProfit > 0) tp = price + TakeProfit * _Point * 10;
    }
    else
    {
    price = Bid;
    if(StopLoss > 0) sl = price + StopLoss * _Point * 10;
    if(TakeProfit > 0) tp = price - TakeProfit * _Point * 10;
    }

    int ticket = OrderSend(_Symbol,cmd,lot,price,Slippage,sl,tp,"多策略EA",MagicNumber,0,clrNONE);
    if(ticket < 0)
    {
    Print("开仓失败,错误码:", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| 统计当前持仓数量 |
    //+------------------------------------------------------------------+
    int CountOpenOrders()
    {
    int count = 0;
    for(int i=0; i {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol)
    count++;
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| 移动止损和保本管理 |
    //+------------------------------------------------------------------+
    void ManageOpenPositions()
    {
    for(int i=0; i {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    {
    if(OrderMagicNumber() != MagicNumber || OrderSymbol() != _Symbol) continue;

    double newSL = OrderStopLoss();
    double profitPips = 0;

    if(OrderType() == OP_BUY)
    {
    profitPips = (Bid - OrderOpenPrice()) / _Point / 10;
    // 保本止损
    if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() < OrderOpenPrice())
    newSL = OrderOpenPrice();
    // 移动止损
    if(TrailingStop > 0 && profitPips > TrailingStop)
    {
    double trailSL = Bid - TrailingStop * _Point * 10;
    if(trailSL > OrderStopLoss()) newSL = trailSL;
    }
    }
    else if(OrderType() == OP_SELL)
    {
    profitPips = (OrderOpenPrice() - Ask) / _Point / 10;
    if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() > OrderOpenPrice())
    newSL = OrderOpenPrice();
    if(TrailingStop > 0 && profitPips > TrailingStop)
    {
    double trailSL = Ask + TrailingStop * _Point * 10;
    if(trailSL < OrderStopLoss() || OrderStopLoss() == 0) newSL = trailSL;
    }
    }

    if(newSL != OrderStopLoss())
    OrderModify(OrderTicket(),OrderOpenPrice(),newSL,OrderTakeProfit(),0,clrNONE);
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 时间过滤函数 |
    //+------------------------------------------------------------------+
    bool IsTradingTime()
    {
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    return (hour >= StartHour && hour < EndHour);
    }

    //+------------------------------------------------------------------+
    //| 新闻过滤函数(简化版,生产环境需接入真实财经日历API) |
    //+------------------------------------------------------------------+
    bool IsNewsTime()
    {
    // 生产环境请接入新闻日历API
    // 此处为占位示例:周一早盘和周五晚盘避开
    datetime now = TimeCurrent();
    if(TimeDayOfWeek(now) == 1 && TimeHour(now) < NewsAvoidHours) return true;
    if(TimeDayOfWeek(now) == 5 && TimeHour(now) > 24 - NewsAvoidHours) return true;
    return false;
    }

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

    编译与修改教程:
    1. 在MetaEditor中编译(F7)– 确保无错误
    2. 调整`SignalVoteRequirement`改变信号严格程度
    3. 资金管理调优:修改`RiskPercent`(建议1-3%)
    4. 新闻过滤器为占位代码,生产环境需接入真实经济日历API
    5. 使用MT4策略测试器进行回测,验证参数有效性

    常见调试技巧:
  • 若编译报错,检查是否`#property strict`已声明

  • 开仓手数为0?检查`MarketInfo`返回值和`StopLoss`是否为正数

  • 新闻过滤器不生效?这是示例代码,替换为真实新闻API即可


  • 参考来源: 自主编译,多策略逻辑参考专业基金管理技术。

    需要持续更新、高级技术支持以及访问我们完整的高胜率EA库?欢迎订阅我们的付费EA套餐,获取独家策略和一对一指导。