Summary: This article provides complete MQL4 source code of a moving average crossover EA, including usage instructions and parameter explanation. Perfect for beginners learning automated trading.




This article shares a complete Moving Average Crossover Expert Advisor (EA) for MetaTrader 4 (MT4). The EA generates buy/sell signals when a fast moving average crosses above or below a slow moving average. It is ideal for learning EA programming basics and can be compiled directly in MetaEditor.

Key Features:
  • Two moving averages (fast and slow)

  • Configurable periods, methods, and apply-to prices

  • Built-in money management (fixed lot or risk percent)

  • Simple trailing stop and take profit / stop loss


  • Complete MQL4 Source Code:
    ```cpp
    //+------------------------------------------------------------------+
    //| MACrossoverEA.mq4 |
    //| Copyright 2025, AutoTrader |
    //| https://www.example.com |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2025, AutoTrader"
    #property link "https://www.example.com"
    #property version "1.00"
    #property strict

    //--- input parameters
    input double LotSize = 0.1; // Fixed lot size
    input bool UseRiskPercent = false; // Use risk percent instead of fixed lot
    input double RiskPercent = 2.0; // Risk % of balance per trade
    input int FastMAPeriod = 5; // Fast MA period
    input int SlowMAPeriod = 20; // Slow MA period
    input int MAMethod = MODE_SMA; // MA method: 0=SMA,1=EMA,2=SMMA,3=LWMA
    input int MAPrice = PRICE_CLOSE; // Apply to price
    input int MagicNumber = 12345; // EA identifier
    input int Slippage = 3; // Slippage in points
    input int StopLoss = 300; // Stop loss in points (0 = disabled)
    input int TakeProfit = 600; // Take profit in points (0 = disabled)
    input int TrailingStop = 200; // Trailing stop points (0 = disabled)

    //--- global variables
    double fastMA, slowMA;
    int ticket;

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    if(FastMAPeriod >= SlowMAPeriod)
    {
    Print("Error: Fast MA period must be less than Slow MA period");
    return(INIT_PARAMETERS_INCORRECT);
    }
    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| Expert deinitialization function |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    }

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // Calculate MA values
    fastMA = iMA(Symbol(), PERIOD_CURRENT, FastMAPeriod, 0, MAMethod, MAPrice, 1);
    slowMA = iMA(Symbol(), PERIOD_CURRENT, SlowMAPeriod, 0, MAMethod, MAPrice, 1);
    double fastMA_prev = iMA(Symbol(), PERIOD_CURRENT, FastMAPeriod, 0, MAMethod, MAPrice, 2);
    double slowMA_prev = iMA(Symbol(), PERIOD_CURRENT, SlowMAPeriod, 0, MAMethod, MAPrice, 2);

    // Check for existing position
    if(CountPositions() == 0)
    {
    // Buy signal: fast crosses above slow
    if(fastMA_prev <= slowMA_prev && fastMA > slowMA)
    {
    double lot = CalculateLotSize();
    ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage,
    StopLoss>0 ? Ask - StopLoss*Point : 0,
    TakeProfit>0 ? Ask + TakeProfit*Point : 0,
    "MA Cross Buy", MagicNumber, 0, clrGreen);
    if(ticket < 0) Print("Buy order failed: ", GetLastError());
    }
    // Sell signal: fast crosses below slow
    else if(fastMA_prev >= slowMA_prev && fastMA < slowMA)
    {
    double lot = CalculateLotSize();
    ticket = OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage,
    StopLoss>0 ? Bid + StopLoss*Point : 0,
    TakeProfit>0 ? Bid - TakeProfit*Point : 0,
    "MA Cross Sell", MagicNumber, 0, clrRed);
    if(ticket < 0) Print("Sell order failed: ", GetLastError());
    }
    }
    else
    {
    // Trailing stop management
    if(TrailingStop > 0) TrailingStopLoss();
    }
    }

    //+------------------------------------------------------------------+
    //| Count open positions with MagicNumber |
    //+------------------------------------------------------------------+
    int CountPositions()
    {
    int count = 0;
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    count++;
    }
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| Calculate lot size based on risk percent |
    //+------------------------------------------------------------------+
    double CalculateLotSize()
    {
    if(!UseRiskPercent) return LotSize;
    double balance = AccountBalance();
    double riskMoney = balance * RiskPercent / 100.0;
    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double stopPoints = StopLoss;
    if(stopPoints <= 0) return LotSize;
    double lot = riskMoney / (stopPoints * tickValue);
    lot = NormalizeDouble(lot, 2);
    double minLot = MarketInfo(Symbol(), MODE_MINLOT);
    double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
    if(lot < minLot) lot = minLot;
    if(lot > maxLot) lot = maxLot;
    return lot;
    }

    //+------------------------------------------------------------------+
    //| Trailing stop loss function |
    //+------------------------------------------------------------------+
    void TrailingStopLoss()
    {
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    if(OrderType() == OP_BUY)
    {
    double newSL = Bid - TrailingStop * Point;
    if(OrderStopLoss() < newSL - Point)
    if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrBlue))
    Print("Trailing stop modify failed: ", GetLastError());
    }
    else if(OrderType() == OP_SELL)
    {
    double newSL = Ask + TrailingStop * Point;
    if(OrderStopLoss() > newSL + Point || OrderStopLoss() == 0)
    if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrBlue))
    Print("Trailing stop modify failed: ", GetLastError());
    }
    }
    }
    }
    }
    //+------------------------------------------------------------------+
    ```

    Usage Instructions:
    1. Copy the code into MetaEditor (MT4: Tools → MetaQuotes Language Editor).
    2. Save the file as `MACrossoverEA.mq4`.
    3. Compile (F7) and fix any errors if present.
    4. Attach the EA to a chart in MT4 (Navigator → Expert Advisors → drag onto chart).
    5. Adjust input parameters according to your risk preference.

    Parameter Explanation:
  • `LotSize`: Base lot size when risk management is off.

  • `UseRiskPercent`: If true, calculates lot based on RiskPercent and StopLoss.

  • `RiskPercent`: Percentage of balance to risk per trade.

  • `FastMAPeriod` & `SlowMAPeriod`: Lengths of two moving averages. Fast must be smaller.

  • `MAMethod`: 0=SMA,1=EMA,2=SMMA,3=LWMA.

  • `MAPrice`: Price constant (0=close,1=open,2=high,3=low,4=median,5=typical,6=weighted).

  • `StopLoss`/`TakeProfit`: Distance in points from entry.

  • `TrailingStop`: Activates trailing stop if >0.


  • Important Notes:
  • Always backtest before live trading. Use Visual Mode in Strategy Tester.

  • This EA works on any timeframe, but H1 or M15 is recommended for MA crossovers.

  • Ensure your broker allows expert advisors and has no restrictions on stop levels.


  • Reference: *Autocompiled by ForexEA Studio, 2025. Original design based on classic moving average crossover strategy.*

    For more advanced EA strategies, premium indicators, and professional automation tools, kindly check our Premium EA Collection – updated monthly with verified source code and dedicated support. Click "Subscribe" in the sidebar to access the latest releases.