IC Markets

How i scalp silver? My own trading strategy.

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
Post Reply
FTtrader
Posts: 151
Joined: Mon Aug 03, 2026 2:43 pm

How i scalp silver? My own trading strategy.

Post by FTtrader »

Hi traders,

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;
}
FTtrader
Posts: 151
Joined: Mon Aug 03, 2026 2:43 pm

Re: How i scalp silver? My own trading strategy.

Post by FTtrader »

Deployment & Calibration Checklist
Compilation: Open MT4, press F4 to open MetaEditor, create a new Expert Advisor (Template), paste the code, and click Compile (F7).

Spread Calibration: Check your broker's typical spread on XAGUSD. If your broker's spread is 30 points (3 cents), leave InpMaxSpreadPoints at 50. If the spread spikes during high volatility, the EA will automatically pause trading.

Lot Sizing: Test initially on a demo account with InpLotSize = 0.01 or 0.10 to observe tick speed and fill behavior before increasing risk parameters.
FTtrader
Posts: 151
Joined: Mon Aug 03, 2026 2:43 pm

Re: How i scalp silver? My own trading strategy.

Post by FTtrader »

And here i added there trailing stops, which should more improve profitabilty.

Here is the updated MQL4 code for the Silver scalping strategy. I have integrated a dynamic ATR trailing stop mechanism that continuously adjusts your stop loss to lock in profits once the trade moves in your favor.

What's New in This Version:
InpUseTrailingStop: A toggle to turn the trailing feature on or off.

InpTrailingStart_ATR_Mult: Defines how much profit (measured in ATR multiples) the trade must be in before the trailing stop activates. For example, setting this to 1.0 means the trade must be in profit by at least 1 ATR before the stop loss begins moving.

InpTrailingStep_ATR_Mult: Defines how far behind the current price the stop loss should trail once activated. Setting this to 0.5 trails the stop at half an ATR distance behind the current Bid/Ask price.

Complete Updated MQL4 Code

Code: Select all

//+------------------------------------------------------------------+
//|                                    SilverScalper_M5_Trailing.mq4 |
//|                                  Copyright 2026, Scalping System |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026"
#property link      ""
#property version   "1.10"
#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;       // Initial Stop Loss ATR Multiplier
input double   InpTP_ATR_Mult     = 2.5;       // Take Profit ATR Multiplier

//--- Trailing Stop Settings
input bool     InpUseTrailingStop        = true; // Enable ATR Trailing Stop
input double   InpTrailingStart_ATR_Mult = 1.0;  // Profit distance (ATR) to start trailing
input double   InpTrailingStep_ATR_Mult  = 0.5;  // Distance (ATR) to trail behind price

//+------------------------------------------------------------------+
//| Expert Initialization                                            |
//+------------------------------------------------------------------+
int OnInit()
{
   Print("SilverScalper_M5 with ATR Trailing loaded successfully for symbol: ", Symbol());
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert Deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();
}

//+------------------------------------------------------------------+
//| Main Tick Processing                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 1. Manage existing open trades (Trailing Stop)
   if(InpUseTrailingStop)
   {
      ManageTrailingStop();
   }

   // 2. Maintain single active trade rule per symbol
   if(CountOpenTrades() > 0) return;

   // 3. Spread Check (Protection against wide Silver spreads)
   int currentSpread = (int)MarketInfo(Symbol(), MODE_SPREAD);
   if(currentSpread > InpMaxSpreadPoints)
   {
      return;
   }

   // 4. Fetch Indicator Data
   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);

   // 5. Trend Evaluation
   bool isUptrend   = (close1 > trendEMA) && (fastEMA > slowEMA);
   bool isDowntrend = (close1 < trendEMA) && (fastEMA < slowEMA);

   // 6. Entry Signal Logic
   bool buySignal  = isUptrend   && (rsiPrev < InpRSI_BuyTrigger)  && (rsiCurr >= InpRSI_BuyTrigger);
   bool sellSignal = isDowntrend && (rsiPrev > InpRSI_SellTrigger) && (rsiCurr <= InpRSI_SellTrigger);

   // 7. 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());
   }
}

//+------------------------------------------------------------------+
//| Manage ATR Trailing Stop                                         |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
   double atr = iATR(Symbol(), Period(), InpATR_Period, 1);
   double trailStartDist = atr * InpTrailingStart_ATR_Mult;
   double trailStepDist  = atr * InpTrailingStep_ATR_Mult;
   
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            if(OrderType() == OP_BUY)
            {
               double bid = MarketInfo(Symbol(), MODE_BID);
               // Check if the trade is in enough profit to start trailing
               if(bid - OrderOpenPrice() > trailStartDist)
               {
                  double newSL = NormalizeDouble(bid - trailStepDist, Digits);
                  // Only modify if the new SL is tighter than the current SL 
                  // (Adding a 10-point buffer prevents MT4 error 1 - modifying without changes)
                  if(newSL > OrderStopLoss() + (Point * 10)) 
                  {
                     bool res = OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, Blue);
                     if(!res) Print("Error modifying Buy order trailing stop: ", GetLastError());
                  }
               }
            }
            else if(OrderType() == OP_SELL)
            {
               double ask = MarketInfo(Symbol(), MODE_ASK);
               // Check if the trade is in enough profit to start trailing
               if(OrderOpenPrice() - ask > trailStartDist)
               {
                  double newSL = NormalizeDouble(ask + trailStepDist, Digits);
                  // Only modify if the new SL is tighter than the current SL or if no SL exists
                  if(newSL < OrderStopLoss() - (Point * 10) || OrderStopLoss() == 0)
                  {
                     bool res = OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, Red);
                     if(!res) Print("Error modifying Sell order trailing stop: ", 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;
}
Post Reply