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:
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:
Important Notes:
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.