Page 2 of 2
Re: Silver squeeze days: why my size goes to minimum
Posted: Tue Sep 15, 2026 8:13 am
by FTtrader
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).
Re: Silver squeeze days: why my size goes to minimum
Posted: Tue Sep 15, 2026 8:13 am
by FTtrader
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
Posted: Tue Sep 15, 2026 8:14 am
by FTtrader
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.
Re: Silver squeeze days: why my size goes to minimum
Posted: Tue Sep 15, 2026 9:23 am
by LondonScalper
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.
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.
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?