Summary: Complete MQL4 source code for a multi-strategy EA combining RSI, MACD, and EMA. Features fixed-ratio money management, time filter, and news filter. Compilable and customizable.




This article presents a professional-grade MQL4 EA源码 that combines three signal types – RSI, MACD, and EMA crossover – with advanced money management and an integrated news filter. Perfect for serious traders looking to diversify signal sources and manage risk intelligently.

Strategy Logic:
  • Signal 1 (RSI): Oversold (<30) for buy, overbought (>70) for sell

  • Signal 2 (MACD): Main line crosses above signal line for buy, below for sell

  • Signal 3 (EMA): Fast EMA (12) crosses above slow EMA (26) for buy, below for sell

  • Voting system: 2 out of 3 signals required to trigger a trade

  • Optional: Require all 3 signals (configurable)


  • Advanced Features:
  • Fixed Ratio Money Management (position sizing based on account equity)

  • Time filter (trading only within specified hours)

  • News filter (avoids trading before/after high-impact news)

  • Trailing stop, break-even, and max spread protection


  • Parameters Explanation:
  • `SignalVoteRequirement` – 0=any,1=at least 2 signals,2=all 3 signals

  • `RSI_Period` / `RSI_Overbought` / `RSI_Oversold`

  • `MACD_Fast` / `MACD_Slow` / `MACD_Signal`

  • `EMA_Fast` / `EMA_Slow`

  • `UseFixedRatioMM` – true/false, `RiskPercent` – % of equity to risk per trade

  • `UseNewsFilter` – true/false, `NewsAvoidHours` – hours to avoid before/after news

  • `StartHour` / `EndHour` – trading session filter

  • `MaxSpread` – maximum allowed spread in points


  • MQL4 Source Code:

    ```mql4
    //+------------------------------------------------------------------+
    //| MultiStrategyEA_MoneyManagement.mq4 |
    //| 自主编译 / Self-compiled |
    //+------------------------------------------------------------------+
    #property copyright "Forex Advanced Tools"
    #property link ""
    #property version "2.00"
    #property strict

    //--- Signal settings
    input int SignalVoteRequirement = 1; // 0=any,1=at least 2,2=all 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;

    //--- Money Management
    input bool UseFixedRatioMM = true;
    input double RiskPercent = 2.0; // % of equity to risk per trade
    input double FixedLotSize = 0.1;
    input int StopLoss = 50;
    input int TakeProfit = 150;

    //--- Filters
    input bool UseNewsFilter = true;
    input int NewsAvoidHours = 2; // avoid trading 2h before/after news
    input bool UseTimeFilter = true;
    input int StartHour = 8;
    input int EndHour = 20;
    input int MaxSpread = 30; // max spread in points
    input int TrailingStop = 40;
    input int BreakEvenPips = 30;

    //--- EA settings
    input int MagicNumber = 202411;
    input int Slippage = 3;

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

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    if(EMA_Fast >= EMA_Slow)
    {
    Print("Error: EMA_Fast must be less than EMA_Slow");
    return(INIT_PARAMETERS_INCORRECT);
    }
    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // Spread check
    currentSpread = (Ask - Bid) / _Point;
    if(currentSpread > MaxSpread && MaxSpread > 0)
    {
    Comment("Spread too high: ", currentSpread);
    return;
    }

    // Time filter
    if(UseTimeFilter && !IsTradingTime())
    {
    Comment("Outside trading hours");
    return;
    }

    // News filter (simplified - checks if within avoid period)
    if(UseNewsFilter && IsNewsTime())
    {
    Comment("News filter active - no trading");
    return;
    }

    // Trailing stop & break-even
    ManageOpenPositions();

    // Check for new trade signals
    if(CountOpenOrders() == 0)
    {
    int signal = GetCombinedSignal();
    if(signal == 1) OpenOrder(OP_BUY);
    if(signal == -1) OpenOrder(OP_SELL);
    }
    }

    //+------------------------------------------------------------------+
    //| Combined signal voting system |
    //+------------------------------------------------------------------+
    int GetCombinedSignal()
    {
    int buyVotes = 0, sellVotes = 0;

    // RSI signal
    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 signal
    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 crossover signal
    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++;

    // Voting logic
    if(SignalVoteRequirement == 0) // any signal
    {
    if(buyVotes > 0) return 1;
    if(sellVotes > 0) return -1;
    }
    else if(SignalVoteRequirement == 1) // at least 2 votes
    {
    if(buyVotes >= 2) return 1;
    if(sellVotes >= 2) return -1;
    }
    else if(SignalVoteRequirement == 2) // all 3 votes
    {
    if(buyVotes == 3) return 1;
    if(sellVotes == 3) return -1;
    }
    return 0;
    }

    //+------------------------------------------------------------------+
    //| Fixed Ratio Money Management |
    //+------------------------------------------------------------------+
    double CalculateLotSize()
    {
    if(!UseFixedRatioMM) return FixedLotSize;

    double riskMoney = AccountBalance() * RiskPercent / 100;
    double tickValue = MarketInfo(_Symbol,MODE_TICKVALUE);
    double stopPoints = StopLoss * 10; // convert to points
    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);
    }

    //+------------------------------------------------------------------+
    //| Open order with dynamic lot size |
    //+------------------------------------------------------------------+
    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,"Multi-Strategy EA",MagicNumber,0,clrNONE);
    if(ticket < 0)
    {
    Print("OrderSend failed: ", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| Count open orders |
    //+------------------------------------------------------------------+
    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;
    }

    //+------------------------------------------------------------------+
    //| Trailing stop and break-even management |
    //+------------------------------------------------------------------+
    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;
    // Break-even
    if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() < OrderOpenPrice())
    newSL = OrderOpenPrice();
    // Trailing stop
    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);
    }
    }
    }

    //+------------------------------------------------------------------+
    //| Time filter |
    //+------------------------------------------------------------------+
    bool IsTradingTime()
    {
    datetime now = TimeCurrent();
    int hour = TimeHour(now);
    return (hour >= StartHour && hour < EndHour);
    }

    //+------------------------------------------------------------------+
    //| Simplified news filter (placeholder - requires external news API)|
    //+------------------------------------------------------------------+
    bool IsNewsTime()
    {
    // In production, integrate with a news calendar API
    // This is a placeholder checking last Monday (no real news data)
    datetime now = TimeCurrent();
    if(TimeDayOfWeek(now) == 1 && TimeHour(now) < NewsAvoidHours) return true;
    if(TimeDayOfWeek(now) == 5 && TimeHour(now) > 24 - NewsAvoidHours) return true;
    return false;
    }

    //+------------------------------------------------------------------+
    //| Expert deinitialization |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    Comment("");
    }
    //+------------------------------------------------------------------+
    ```

    Compilation & Modification Guide:
    1. Compile in MetaEditor (F7) – ensure no errors
    2. Adjust `SignalVoteRequirement` to change signal strictness
    3. For money management tuning, modify `RiskPercent` (recommended 1-3%)
    4. News filter is a placeholder – integrate with a real economic calendar API for production use
    5. Backtest before live trading (Strategy Tester in MT4)

    Reference: 自主编译 / Self-compiled. Multi-strategy logic inspired by professional fund management techniques.

    For ongoing updates, premium support, and access to our complete EA library with high-probability setups, subscribe to our paid EA package.