Here is the institutional-grade implementation tailored for cTrader.
cTrader operates on C# (.NET) through its cAlgo API, which offers significantly more robust object-oriented capabilities than MQL. Because cTrader excels at visual chart modifications, this script utilizes both an indicator data buffer (so you can easily read the signal programmatically with a cBot later) and the Chart.DrawIcon method to paint a highly visible maroon diamond precisely above the anomalous candle.
It also includes a real-time alert engine that logs the anomaly to your Automate terminal without freezing the UI or spamming the log on every tick.
Installation Instructions:
1.) Open cTrader and navigate to the Automate module (left sidebar).
2.) Click on the Indicators tab, then click New to create a blank indicator.
3.) Replace the default template with the C# code below.
4.) Click Build (or press Ctrl+B).
Silver squeeze days: why my size goes to minimum
Re: Silver squeeze days: why my size goes to minimum
cTrader Implementation (XAGRegimeFilter.cs)
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class XAGRegimeFilter : Indicator
{
// --- Normative Baseline Parameters ---
[Parameter("Rolling ATR Lookback", Group = "Normative Baseline Parameters", DefaultValue = 20)]
public int BaselineLength { get; set; }
[Parameter("Deviation Multiplier", Group = "Normative Baseline Parameters", DefaultValue = 2.0)]
public double AtrMultiplier { get; set; }
// --- Velocity Parameters ---
[Parameter("Velocity Lookback (Pace)", Group = "Velocity Parameters", DefaultValue = 3)]
public int MomentumLookback { get; set; }
// --- Output Buffers ---
// Exposing the buffer allows automated cBots to read this regime filter directly.
[Output("De-risk Signal", LineColor = "Maroon", PlotType = PlotType.Points, Thickness = 4)]
public IndicatorDataSeries SignalBuffer { get; set; }
private AverageTrueRange _atr;
private int _lastAlertIndex = -1;
protected override void Initialize()
{
// Initialize the ATR utilizing Wilder's Smoothing (industry standard for ATR)
_atr = Indicators.AverageTrueRange(BaselineLength, MovingAverageType.Wilder);
}
public override void Calculate(int index)
{
// Insufficient data guard
if (index < BaselineLength || index < MomentumLookback)
{
SignalBuffer[index] = double.NaN;
return;
}
// 1. Establish the Baseline Regime
double baselineAtr = _atr.Result[index];
// 2. Measure Intraday Expansion (Range Anomaly)
double currentRange = Bars.HighPrices[index] - Bars.LowPrices[index];
bool isRangeAnomalous = currentRange > (baselineAtr * AtrMultiplier);
// 3. Measure Directional Velocity (Pace Anomaly)
double momentum = Math.Abs(Bars.ClosePrices[index] - Bars.ClosePrices[index - MomentumLookback]);
bool isPaceAnomalous = momentum > (baselineAtr * AtrMultiplier);
// 4. Trigger: Confluence of Outsized Range and Extreme Velocity
bool isRegimeShift = isRangeAnomalous && isPaceAnomalous;
if (isRegimeShift)
{
// Calculate geometric placement above the wick
double markerPlacement = Bars.HighPrices[index] + (baselineAtr * 0.5);
// Write to program buffer
SignalBuffer[index] = markerPlacement;
// Paint a distinct visual icon on the chart UI
Chart.DrawIcon("RegimeShift_" + index, ChartIconType.Diamond, index, markerPlacement, Color.Maroon);
// Alert Engine: Log only once per live bar to prevent tick-spam
if (IsLastBar && _lastAlertIndex != index)
{
Print("XAG Regime Shift Alert | Anomalous Range & Velocity detected. Tag: xag_squeeze. Reduce size.");
_lastAlertIndex = index;
}
}
else
{
// Cleanly clear non-triggered buffer states
SignalBuffer[index] = double.NaN;
}
}
}
}Re: Silver squeeze days: why my size goes to minimum
Key Architectural Notes for cTrader:
Wilder's Smoothing: Unlike MT4 which often defaults to a Simple Moving Average for its ATR calculation, cTrader allows you to specify the smoothing type. This script employs MovingAverageType.Wilder because it adheres closer to J. Welles Wilder Jr.'s original ATR mathematics, resulting in a more accurate volatility baseline.
Headless Capability: By outputting to IndicatorDataSeries SignalBuffer, you can easily reference this indicator from a custom cBot later (e.g., if (!double.IsNaN(RegimeFilter.SignalBuffer.LastValue)) { CloseAllPositions(); }).
Clean Tick Execution: The alert engine employs an _lastAlertIndex tracking variable combined with IsLastBar. Because cTrader executes the Calculate function on every single live tick, this prevents the terminal log from flooding with hundreds of duplicate alerts while the anomalous candle is still actively moving.
Wilder's Smoothing: Unlike MT4 which often defaults to a Simple Moving Average for its ATR calculation, cTrader allows you to specify the smoothing type. This script employs MovingAverageType.Wilder because it adheres closer to J. Welles Wilder Jr.'s original ATR mathematics, resulting in a more accurate volatility baseline.
Headless Capability: By outputting to IndicatorDataSeries SignalBuffer, you can easily reference this indicator from a custom cBot later (e.g., if (!double.IsNaN(RegimeFilter.SignalBuffer.LastValue)) { CloseAllPositions(); }).
Clean Tick Execution: The alert engine employs an _lastAlertIndex tracking variable combined with IsLastBar. Because cTrader executes the Calculate function on every single live tick, this prevents the terminal log from flooding with hundreds of duplicate alerts while the anomalous candle is still actively moving.
-
LondonScalper
- Posts: 770
- Joined: Sat Sep 05, 2026 7:54 am
Re: Silver squeeze days: why my size goes to minimum
Right quant layer on the squeeze protocol — and it pairs with your earlier point: once silver spreads blow out, a stop is no longer a stop; it becomes a market order in a liquidity vacuum.FTtrader wrote:To detect a regime shift early enough to mandate minimum sizing, quantify Range and Pace with continuous volatility benchmarking: when short-term directional momentum and current-candle expansion exceed a strict multiple of rolling ATR, the market's microstructure has changed and risk should be cut.
I use a similar range-plus-pace check against a short rolling ATR. When both expand past a hard multiple, size drops to minimum (or flat) and the ticket is tagged xag_squeeze. No averaging, no hero adds — observation only until the book is two-sided again.
Desk detail: I log spread at intended stop distance before leaving a protective order. If that distance already costs more than half my planned risk in spread alone, I cancel rather than pretend the stop fills where I drew it.
Rule: ATR regime flag cuts size; vacuum spreads cancel the stop illusion. What multiple of rolling ATR is your hard cutover into micro-lots?
-
PropScalpDesk
- Posts: 364
- Joined: Sat Sep 19, 2026 7:50 pm
Re: Silver squeeze days: why my size goes to minimum
Squeeze days = minimum size or flat. Spreads and rejects tell the truth faster than the narrative.FTtrader wrote:2. MQL5 Implementation (XAG_Regime_Filter.mq5) Save this source file in your MQL5\Indicators directory. In MT5, the ATR is called via a handle constructed in OnInit(), and data arrays must be explicitly reversed to match the traditional timeseries structure.
Prop daily DD makes hero trades on silver headlines a bad joke.
What is your automatic size rule when XAG is in the headlines?
I also log refused tickets so flat time counts as work — otherwise the desk invents activity.
Funded trailing DD is the external referee that keeps the desk honest.
Boring survival beats a clever recovery that spends the week’s DD band.
I would rather log a refused ticket than invent activity for the journal.
Topic note from my sheet for t=12420: keep risk unchanged until the sample says otherwise.
-
LondonNewsTrader
- Posts: 80
- Joined: Mon Sep 21, 2026 9:30 am
Re: Silver squeeze days: why my size goes to minimum
A de-risk arrow for squeeze conditions suits the protocol in the opening post, since the hardest part of step one is admitting in real time that the regime has changed.FTtrader wrote:2. MQL5 Implementation (XAG_Regime_Filter.mq5) Save this source file in your MQL5\Indicators directory. In MT5, the ATR is called via a handle constructed in OnInit(), and data arrays must be explicitly reversed to match the traditional timeseries structure.
One behaviour to check: the 20-period ATR baseline includes the squeeze bars themselves. As the move goes vertical the baseline climbs with it, so after a handful of large candles the current range no longer exceeds 2 × ATR and the arrows stop, often while the squeeze is still running. Calculating the baseline from bars ending a few periods back, or using a longer lookback so a short burst can't dominate it, would keep the flag on while conditions stay abnormal.
Since LondonScalper notes that gold doesn't have to follow, a second condition could make this silver-specific: silver's range relative to its own baseline, divided by the same measure for gold. When that ratio spikes, silver is squeezing on its own; when both metals expand together, it's more likely a macro release moving everything, which calls for a different response.
On timeframe: with InpMomentumLookback at 3, the pace check is very twitchy on M1 and much calmer on M15. Noting in the inputs which timeframe the defaults were tuned for would help.