The dynamic stop-loss part is pretty interesting. How does the engine behave during sudden high volatility moves.
cTrader cBot Risk Engine: High-Precision C# Dynamic Stop-Loss Architecture
2 Comments
@[Md Siddikur Rahaman]
Great question. During sudden high-volatility moves (e.g., news releases, market opens, or liquidity flash-drains), the engine behaves across two distinct states: pre-trade sizing and in-flight open positions.
1. Pre-Trade: Inverse Compression & The Minimum Clamp Trap
When volatility spikes right before an entry, $ATR(14)$ expands. Because position volume is derived as:
\[\text{RawUnits} = \frac{\text{RiskBudget}}{\text{StopDistancePrice} \times \text{TickValuePerUnit}}\]
The engine automatically compresses position size so that monetary risk remains identical (e.g., exactly $100).
However, during violent shocks, the formula might call for a size below the broker minimum (e.g., 500 units when VolumeInUnitsMin is 1,000 units / 0.01 lot). That’s where the clampedToMin flag comes in:
if (floored < volumeMin) {
floored = volumeMin;
clampedToMin = true;
}
effectiveRisk = finalVolume * (stopDistancePrice / pipSize * tickValuePerUnit);
Rather than silently reporting a $100 risk while holding an exposure that actually risks $220 due to the wider stop, it reports effectiveRisk. In production, you should add an entry veto:
if (clamped && effectiveRisk > MaxTolerableRisk) return;
2. In-Flight Positions: Monotonic Ratchet Invariant
If volatility spikes after you are already in the market, a common flaw in naive dynamic stops is that they recalculate a wider stop and move it backward, taking on more dollar risk.
In our TrailAtr method:
double newStop = Symbol.Bid - 1.0 * atrDistancePrice;
if (newStop > position.StopLoss + Symbol.PipSize)
ModifyPosition(position, newStop, position.TakeProfit);
When volatility surges, the wider $ATR$ pushes newStop further away from the current Bid. Because newStop is now lower than the existing position.StopLoss, the condition fails completely. The stop never widens into deeper risk—it is strictly monotonic.
3. Execution Reality: Gapping & Noise Filtering
Two microstructure caveats to keep in mind:
- Bar-Close Evaluation: Running the check on
OnBar()rather thanOnTick()prevents the trailing stop from whipsawing due to transient 1-second spread blowouts. - Slippage on Trigger: In cTrader, a Stop Loss triggers as a Market order. If price gaps across an empty order book during high volatility, negative slippage will occur regardless of the calculated ATR. That is why high-volatility events are best managed with an upstream economic calendar filter rather than relying solely on post-event stop orders.
Please log in to add a comment.
Please log in to comment on this post.
More Posts
- © 2026 Coder Legion
- Feedback / Bug
- Privacy
- About Us
- Contacts
- You Tube
- Tiktok
- Premium Subscription
- Terms of Service
- Early Builders
I design open-source... Show moreFounder & Lead Quantitative Engineer at Gueta Quant (https://guetaquant.com).
I design open-source risk engines, statistical falsification frameworks, and algorithmic execution architectures across MetaTrader 5 (MQL5), cTrader (C#), TradingView (Pine Script v6), and Python.
Creator of 44 open-source quantitative tools (AGPLv3) registered on CERN Zenodo (DOI: 10.5281/zenodo.22012203). Show less
More From Guetaquant
Related Jobs
- Dynamics 365 CRM Developer- Tech SpecialistInsight · Full time · Philippines
- Software Engineering Intern - Spring 2027Mercury · Part time · Canada
- Senior iOS Platform EngineerMagnet Forensics · Full time · Canada
Commenters (This Week)
Contribute meaningful comments to climb the leaderboard and earn badges!