trading silver (XAG/USD) requires a slightly different approach than gold. Silver exhibits higher percentage volatility and wider spread-to-range ratios on most CFD brokers.
Because of this, scalping on the 5-minute (M5) timeframe using a trend-pullback system with dynamic ATR risk boundaries yields significantly cleaner results than 1-minute tick chasing.Strategy Blueprint: Silver Pullback Momentum (XAG/USD - M5)
ParameterConfigurationRationaleTimeframeM5Filters out micro-noise and reduces the relative impact of spread costs.Active HoursLondon & NY Overlap (13:00–17:00 UTC)
Highest liquidity window to ensure tight spreads and clean momentum.Trend Baseline200 EMA & (20 EMA / 50 EMA)
Determines long-term bias and local momentum structure.Trigger FilterRSI (14) PullbackIdentifies oversold dips in uptrends and overbought rallies in downtrends.Risk ManagementDynamic ATR (14) SL/TPAdjusts stop-loss and take-profit levels dynamically based on silver's volatility.Entry RulesLong Entry (Buy):Price is above 200 EMA AND 20 EMA is above 50 EMA.RSI (14) drops below 45 and crosses back above 45.Stop Loss: $\text{Entry Price} - (1.5 \times \text{ATR})$.Take Profit: $\text{Entry Price} + (2.5 \times \text{ATR})$ (1:1.67 Risk/Reward).Short Entry (Sell):Price is below 200 EMA AND 20 EMA is below 50 EMA.RSI (14) rises above 55 and crosses back below 55.Stop Loss: $\text{Entry Price} + (1.5 \times \text{ATR})$.Take Profit: $\text{Entry Price} - (2.5 \times \text{ATR})$.Complete MQL4 Expert Advisor CodeBelow is the production-ready MQL4 code for MetaTrader 4. It includes a Max Spread Filter to prevent execution during illiquid market conditions (critical for silver).
Code: Select all
//+------------------------------------------------------------------+
//| SilverScalper_M5.mq4 |
//| Copyright 2026, Scalping System |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026"
#property link ""
#property version "1.00"
#property strict
//--- General Settings
input double InpLotSize = 0.1; // Trade Lot Size
input int InpMagicNumber = 884422; // Magic Number
input int InpMaxSpreadPoints = 50; // Max Allowed Spread (in Points)
//--- Moving Average Parameters
input int InpFastEMA = 20; // Fast EMA Period
input int InpSlowEMA = 50; // Slow EMA Period
input int InpTrendEMA = 200; // Trend Baseline EMA Period
//--- RSI Trigger Settings
input int InpRSI_Period = 14; // RSI Period
input double InpRSI_BuyTrigger = 45.0; // RSI Buy Level (Cross Above)
input double InpRSI_SellTrigger = 55.0; // RSI Sell Level (Cross Below)
//--- Dynamic ATR Risk Settings
input int InpATR_Period = 14; // ATR Period
input double InpSL_ATR_Mult = 1.5; // Stop Loss ATR Multiplier
input double InpTP_ATR_Mult = 2.5; // Take Profit ATR Multiplier
//+------------------------------------------------------------------+
//| Expert Initialization |
//+------------------------------------------------------------------+
int OnInit()
{
Print("SilverScalper_M5 loaded successfully for symbol: ", Symbol());
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert Deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Main Tick Processing |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Maintain single active trade rule per symbol
if(CountOpenTrades() > 0) return;
// 2. Spread Check (Protection against wide Silver spreads)
int currentSpread = (int)MarketInfo(Symbol(), MODE_SPREAD);
if(currentSpread > InpMaxSpreadPoints)
{
return;
}
// 3. Fetch Indicator Data (Evaluated on completed Candle 1)
double fastEMA = iMA(Symbol(), Period(), InpFastEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double slowEMA = iMA(Symbol(), Period(), InpSlowEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double trendEMA = iMA(Symbol(), Period(), InpTrendEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double rsiCurr = iRSI(Symbol(), Period(), InpRSI_Period, PRICE_CLOSE, 1);
double rsiPrev = iRSI(Symbol(), Period(), InpRSI_Period, PRICE_CLOSE, 2);
double atr = iATR(Symbol(), Period(), InpATR_Period, 1);
double close1 = iClose(Symbol(), Period(), 1);
// 4. Trend Evaluation
bool isUptrend = (close1 > trendEMA) && (fastEMA > slowEMA);
bool isDowntrend = (close1 < trendEMA) && (fastEMA < slowEMA);
// 5. Entry Signal Logic
bool buySignal = isUptrend && (rsiPrev < InpRSI_BuyTrigger) && (rsiCurr >= InpRSI_BuyTrigger);
bool sellSignal = isDowntrend && (rsiPrev > InpRSI_SellTrigger) && (rsiCurr <= InpRSI_SellTrigger);
// 6. Execution
if(buySignal)
{
double ask = MarketInfo(Symbol(), MODE_ASK);
double sl = NormalizeDouble(ask - (atr * InpSL_ATR_Mult), Digits);
double tp = NormalizeDouble(ask + (atr * InpTP_ATR_Mult), Digits);
int ticket = OrderSend(Symbol(), OP_BUY, InpLotSize, ask, 3, sl, tp, "Silver Scalp Buy", InpMagicNumber, 0, Blue);
if(ticket < 0) Print("Buy Order Failed. Error code: ", GetLastError());
}
else if(sellSignal)
{
double bid = MarketInfo(Symbol(), MODE_BID);
double sl = NormalizeDouble(bid + (atr * InpSL_ATR_Mult), Digits);
double tp = NormalizeDouble(bid - (atr * InpTP_ATR_Mult), Digits);
int ticket = OrderSend(Symbol(), OP_SELL, InpLotSize, bid, 3, sl, tp, "Silver Scalp Sell", InpMagicNumber, 0, Red);
if(ticket < 0) Print("Sell Order Failed. Error code: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Count Open Positions for Magic Number |
//+------------------------------------------------------------------+
int CountOpenTrades()
{
int count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
{
count++;
}
}
}
return count;
}