Page 1 of 2

XAGUSD relative strength vs gold as a scalp filter

Posted: Mon Sep 14, 2026 10:14 pm
by LondonScalper
XAGUSD relative strength versus gold as a scalp filter.

Silver can lead or lag gold in messy ways. I sometimes glance at relative strength (or simple side-by-side) as a veto / confidence filter, not as a standalone signal. If I want a gold long and silver is already collapsing relative to gold, I think twice about size.

Limits
Silver spreads and slips harder. Using XAG as confirmation then trading XAG is how you pay twice. Usually I trade the metal with the cleaner book and only use the other as context. On squeeze days relative strength goes vertical and filters break -- size goes to minimum regardless.

This stays optional. If the comparison adds hesitation without improving the journal, I drop it for a month and check.

Do you use silver/gold relative behaviour live, or only in hindsight review?

When spreads on silver are already offensive, I do not even open the relative strength pane -- context is useless if I cannot transact cleanly. Filter hierarchy: tradable book first, cross-metal story second. Pretty correlations do not rebate commission.

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:16 am
by FTtrader
LondonScalper wrote: Mon Sep 14, 2026 10:14 pm XAGUSD relative strength versus gold as a scalp filter.

Silver can lead or lag gold in messy ways. I sometimes glance at relative strength (or simple side-by-side) as a veto / confidence filter, not as a standalone signal. If I want a gold long and silver is already collapsing relative to gold, I think twice about size.

Limits
Silver spreads and slips harder. Using XAG as confirmation then trading XAG is how you pay twice. Usually I trade the metal with the cleaner book and only use the other as context. On squeeze days relative strength goes vertical and filters break -- size goes to minimum regardless.

This stays optional. If the comparison adds hesitation without improving the journal, I drop it for a month and check.

Do you use silver/gold relative behaviour live, or only in hindsight review?

When spreads on silver are already offensive, I do not even open the relative strength pane -- context is useless if I cannot transact cleanly. Filter hierarchy: tradable book first, cross-metal story second. Pretty correlations do not rebate commission.
Hi LondonScalper,

Here is a draft for your forum reply, followed by a custom Pine Script you can include in the post to add technical value to the discussion.

Forum Post Draft
Great post. You hit the nail on the head regarding the "tradable book first" hierarchy. Silver’s microstructure can be brutal—the spread and slippage during volatile sessions will absolutely eat a 1-minute or 5-minute scalp alive if you aren't careful. Paying twice on execution costs is a fast track to a blown journal.

To answer your question: I use it live, but strictly as a contextual divergence filter.

I look at the relative behavior primarily on the 15m chart to gauge the broader intraday context before zooming into the 1m for execution. I am looking specifically for liquidity sweeps where the metals disagree. For example, if Gold sweeps a structural low and rejects cleanly, but Silver fails to make that lower low, that divergence is a massive confidence booster for a Gold long.

But exactly as you mentioned, on squeeze days or when spreads widen out, the correlation breaks down. Raw price action and order book liquidity will always take precedence over a derived correlation. If the spread is offensive, the relative strength pane doesn't even matter.

To make glancing at this relationship easier without cluttering the raw price action on the main chart, I coded a lightweight Pine Script. Instead of looking at a raw ratio line (which can be hard to contextualize quickly), it calculates a rolling Z-Score of the XAU/XAG ratio. This normalizes the spread, giving you a clean histogram that flags sudden intraday deviations instantly.

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:16 am
by FTtrader
Pine Script (v5)

Code: Select all

//@version=5
indicator("XAU/XAG Relative Strength Z-Score [Scalp Filter]", shorttitle="Metals RS", overlay=false)

// --- Inputs ---
symGold = input.symbol("OANDA:XAUUSD", title="Gold Ticker")
symSilver = input.symbol("OANDA:XAGUSD", title="Silver Ticker")
length = input.int(20, title="Lookback Period", tooltip="Period for the rolling average and standard deviation.")
threshold = input.float(2.0, title="Deviation Threshold", tooltip="Z-score level to flag significant divergence.")

// --- Fetch Data ---
// Using timeframe.period ensures it scales with whatever chart you are scalping on
goldClose = request.security(symGold, timeframe.period, close)
silverClose = request.security(symSilver, timeframe.period, close)

// --- Core Logic ---
// Calculate the raw Gold/Silver Ratio
ratio = goldClose / silverClose

// Calculate the Z-Score to normalize the ratio for quick visual scanning
ratioSma = ta.sma(ratio, length)
ratioDev = ta.stdev(ratio, length)
zScore = ratioDev == 0 ? 0 : (ratio - ratioSma) / ratioDev

// --- Plotting ---
// Baselines and Thresholds
hline(0, "Baseline", color=color.new(color.gray, 50), linestyle=hline.style_dotted)
hline(threshold, "Gold Outperforming", color=color.new(color.teal, 50), linestyle=hline.style_dashed)
hline(-threshold, "Silver Outperforming", color=color.new(color.maroon, 50), linestyle=hline.style_dashed)

// Histogram Colors: Highlights only when the ratio deviates significantly
plotColor = zScore > threshold ? color.teal : zScore < -threshold ? color.maroon : color.new(color.gray, 70)

plot(zScore, title="RS Z-Score Histogram", color=plotColor, linewidth=3, style=plot.style_histogram)
plot(zScore, title="RS Z-Score Line", color=color.new(color.white, 80), linewidth=1)

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:17 am
by FTtrader
How to use it as a veto filter:

Gray bars: Metals are moving in tandem. Trade your normal price action setups.

Teal spikes (Z-Score > 2): Gold is rapidly gaining relative to Silver. If you are looking to short Gold based on a 1m setup, this is your veto/size-down signal.

Maroon spikes (Z-Score < -2): Silver is rapidly gaining on Gold. If you are looking to long Gold, you might want to pause and wait for better structure.

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:18 am
by FTtrader
However, as you noted, during squeeze events or when the spread becomes offensive, correlation models fail. Microstructure and raw price action take absolute precedence. If the XAG spread is un-tradable, the relative strength context is discarded.

To quantify this without cluttering the main chart with raw ratio lines, I use a normalized Z-Score of the XAU/XAG ratio. This strips out absolute price and isolates standard deviations in the spread, instantly flagging statistical extremes where divergence is most actionable.

Here is the Pine Script. It uses strict barmerge settings to prevent repainting.

Pine Script (v5)

Code: Select all

//@version=5
indicator("XAU/XAG Relative Z-Score [Scalp Filter]", shorttitle="Metals Z-Score", overlay=false, timeframe="")

// --- Inputs ---
var grp_sym = "Symbol Configuration"
symGold = input.symbol("OANDA:XAUUSD", title="Primary (Gold)", group=grp_sym)
symSilver = input.symbol("OANDA:XAGUSD", title="Secondary (Silver)", group=grp_sym)

var grp_stat = "Statistical Parameters"
length = input.int(20, title="Rolling Period", minval=2, group=grp_stat, tooltip="Lookback for mean and standard deviation calculation.")
threshold = input.float(2.0, title="Z-Score Threshold", step=0.5, group=grp_stat, tooltip="Sigma level denoting statistical divergence.")

// --- Data Fetching (Strict No-Repaint) ---
// Fetching close data strictly without lookahead to prevent repainting in live environments.
goldClose = request.security(symGold, timeframe.period, close, barmerge.gaps_off, barmerge.lookahead_off)
silverClose = request.security(symSilver, timeframe.period, close, barmerge.gaps_off, barmerge.lookahead_off)

// --- Core Math ---
// XAU/XAG Ratio
ratio = goldClose / silverClose

// Rolling Mean and Standard Deviation
ratioMean = ta.sma(ratio, length)
ratioStd = ta.stdev(ratio, length)

// Z-Score Calculation (Handle potential div by zero)
zScore = ratioStd == 0 ? 0 : (ratio - ratioMean) / ratioStd

// --- Visualization ---
// Baseline & Thresholds
hline(0, "Mean", color=color.new(color.gray, 50), linestyle=hline.style_dotted)
hline(threshold, "+ Sigma (XAU Premium)", color=color.new(color.teal, 60), linestyle=hline.style_dashed)
hline(-threshold, "- Sigma (XAG Premium)", color=color.new(color.maroon, 60), linestyle=hline.style_dashed)

// Histogram Color Logic
histColor = zScore >= threshold ? color.new(color.teal, 20) : zScore <= -threshold ? color.new(color.maroon, 20) : color.new(color.gray, 80)

plot(zScore, title="Z-Score Histogram", color=histColor, style=plot.style_histogram, linewidth=3)
plot(zScore, title="Z-Score Line", color=color.new(color.silver, 30), linewidth=1)

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:19 am
by FTtrader
Execution Rules:

Neutral Zone (Gray): Metals are moving in tandem. Trade standard price action setups.

+ Sigma Break (Teal > 2.0): Gold is rapidly outperforming Silver. If your 1m model generates a Gold short here, this is your veto/size-down signal due to underlying relative strength.

- Sigma Break (Maroon < -2.0): Silver is rapidly outperforming Gold. If you are looking to long Gold, wait for better structure or XAG confirmation.

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:20 am
by FTtrader
The biggest pitfall when moving cross-asset logic from Pine Script to MetaTrader is handling time-series synchronization. MT4 and MT5 do not automatically align arrays when one symbol has a missing tick or a data gap, which will instantly corrupt a rolling standard deviation.

These scripts use explicit time-matching (iBarShift in MT4, CopyClose by time in MT5) and manual array indexing to ensure the synthetic ratio calculation stays strictly aligned with the primary chart's timeframe, preventing repainting in live execution.

MetaTrader 5 (MQL5)

Code: Select all

//+------------------------------------------------------------------+
//|                                              Metals_Z_Score.mq5  |
//|                                      Strict Cross-Asset Filter   |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1

#property indicator_label1  "RS Z-Score"
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrTeal, clrMaroon, clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- Inputs
input string   InpSecondarySymbol = "XAGUSD"; // Secondary Symbol (Silver)
input int      InpPeriod          = 20;       // Rolling Period
input double   InpThreshold       = 2.0;      // Z-Score Threshold

//--- Buffers
double         ZScoreBuffer[];
double         ColorBuffer[];
double         RatioBuffer[]; // Internal buffer for rolling math

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, ZScoreBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, ColorBuffer, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, RatioBuffer, INDICATOR_CALCULATIONS);
   
   IndicatorSetInteger(INDICATOR_DIGITS, 2);
   IndicatorSetDouble(INDICATOR_MAXIMUM, 4.0);
   IndicatorSetDouble(INDICATOR_MINIMUM, -4.0);
   
   // Add baseline and threshold levels
   IndicatorSetInteger(INDICATOR_LEVELS, 3);
   IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, 0.0);
   IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, InpThreshold);
   IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, -InpThreshold);
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   // Enforce strict reverse indexing to match MT4 logic and simplify rolling loops
   ArraySetAsSeries(time, true);
   ArraySetAsSeries(close, true);
   ArraySetAsSeries(ZScoreBuffer, true);
   ArraySetAsSeries(ColorBuffer, true);
   ArraySetAsSeries(RatioBuffer, true);

   int limit = rates_total - prev_calculated;
   if(prev_calculated == 0) limit = rates_total - InpPeriod - 1;

   for(int i = limit; i >= 0 && !IsStopped(); i--)
     {
      double closeSec[1];
      // Fetch secondary symbol close exactly matching the primary chart's bar time
      if(CopyClose(InpSecondarySymbol, PERIOD_CURRENT, time[i], 1, closeSec) <= 0)
        {
         ZScoreBuffer[i] = 0;
         ColorBuffer[i] = 2; // Gray
         continue;
        }

      double closePri = close[i];
      if(closeSec[0] == 0) continue;
      
      RatioBuffer[i] = closePri / closeSec[0];

      // Calculate rolling mean
      double sum = 0;
      for(int j = 0; j < InpPeriod; j++) sum += RatioBuffer[i + j];
      double mean = sum / InpPeriod;

      // Calculate rolling standard deviation
      double sqSum = 0;
      for(int j = 0; j < InpPeriod; j++) sqSum += MathPow(RatioBuffer[i + j] - mean, 2);
      double stdDev = MathSqrt(sqSum / InpPeriod);

      // Z-Score computation
      if(stdDev == 0) ZScoreBuffer[i] = 0;
      else ZScoreBuffer[i] = (RatioBuffer[i] - mean) / stdDev;

      // Histogram color mapping
      if(ZScoreBuffer[i] >= InpThreshold)       ColorBuffer[i] = 0; // Teal (XAU Premium)
      else if(ZScoreBuffer[i] <= -InpThreshold) ColorBuffer[i] = 1; // Maroon (XAG Premium)
      else                                      ColorBuffer[i] = 2; // Gray (Neutral)
     }

   return(rates_total);
  }

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:20 am
by FTtrader
MetaTrader 4 (MQL4)

Code: Select all

//+------------------------------------------------------------------+
//|                                              Metals_Z_Score.mq4  |
//|                                      Strict Cross-Asset Filter   |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1  clrGray // Base color, overridden dynamically

//--- Inputs
input string   InpSecondarySymbol = "XAGUSD"; // Secondary Symbol (Silver)
input int      InpPeriod          = 20;       // Rolling Period
input double   InpThreshold       = 2.0;      // Z-Score Threshold

//--- Buffers
double         ZScoreBuffer[];
double         RatioBuffer[]; // Hidden buffer for math

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, ZScoreBuffer);
   SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 3);
   SetIndexLabel(0, "RS Z-Score");

   SetIndexBuffer(1, RatioBuffer);
   
   IndicatorDigits(2);
   SetLevelValue(0, 0.0);
   SetLevelValue(1, InpThreshold);
   SetLevelValue(2, -InpThreshold);
   SetLevelStyle(STYLE_DASH, 1, clrDimGray);
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int limit = rates_total - prev_calculated;
   if(prev_calculated == 0) limit = rates_total - InpPeriod - 1;

   for(int i = limit; i >= 0 && !IsStopped(); i--)
     {
      // Synchronize secondary symbol time to handle gaps
      int shiftSec = iBarShift(InpSecondarySymbol, Period(), time[i], false);
      double closeSec = iClose(InpSecondarySymbol, Period(), shiftSec);
      double closePri = close[i];

      if(closeSec == 0) continue;
      
      RatioBuffer[i] = closePri / closeSec;

      // Calculate rolling mean
      double sum = 0;
      for(int j = 0; j < InpPeriod; j++) sum += RatioBuffer[i + j];
      double mean = sum / InpPeriod;

      // Calculate rolling standard deviation
      double sqSum = 0;
      for(int j = 0; j < InpPeriod; j++) sqSum += MathPow(RatioBuffer[i + j] - mean, 2);
      double stdDev = MathSqrt(sqSum / InpPeriod);

      // Z-Score computation
      if(stdDev == 0) ZScoreBuffer[i] = 0;
      else ZScoreBuffer[i] = (RatioBuffer[i] - mean) / stdDev;
     }

   // Optional: MQL4 lacks a native DRAW_COLOR_HISTOGRAM with more than 
   // one color per plot efficiently. To simulate the Pine color breaks, 
   // we manually reset the buffer colors in the loop if drawn via Objects, 
   // or just rely on the baseline breaks visually.
   
   return(rates_total);
  }

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:21 am
by FTtrader
Notes for Deployment:

Ensure the InpSecondarySymbol exactly matches your broker's Silver ticker string in the Market Watch (e.g., XAGUSD, SILVER, XAGUSD.pro).

Because MT4 lacks native multi-colored histogram buffers without building out 3-4 separate array indices, the MQL4 version relies on the hardcoded levels (+2.0 and -2.0) for visual identification. The MQL5 version includes the full conditional color logic identical to the Pine Script.

Re: XAGUSD relative strength vs gold as a scalp filter

Posted: Tue Sep 15, 2026 8:23 am
by FTtrader
On the technical side, relying on MQL for cross-asset synchronization can be clunky. Since you are handling complex logic, I have added a cTrader (cAlgo) C# implementation.

This leverages an object-oriented architecture, handles cross-asset time-series synchronization much more cleanly than MetaTrader, and utilizes built-in algorithmic data series for the rolling math rather than manual for loops.

I monitor the relative behavior top-down on the 15m to establish the macro structure, before zooming into the 1m or tick charts for execution. I am specifically hunting for asynchronous liquidity sweeps. If XAU sweeps a structural low and absorbs the resting liquidity cleanly, but XAG fails to confirm the lower low, that microstructure divergence provides high-probability context for a long setup. I then route the execution entirely through the XAU book where the liquidity is thicker and slippage is manageable.

However, during squeeze events or when the spread becomes offensive, correlation models fail. Microstructure and raw price action take absolute precedence. If the XAG order book thins out, the relative strength context is immediately discarded.

To quantify this without cluttering the main chart, I use a normalized Z-Score of the XAU/XAG ratio. This strips out nominal price and isolates standard deviations in the spread itself, flagging statistical extremes where the divergence is actually actionable.