The Commission Offset (BreakevenExtraPips): Moving a stop exactly to position.EntryPrice guarantees a net loss when hit, because you still pay the broker's spread on the exit and commissions on both the entry and exit. Adding a customizable 0.5 to 1.0 pip buffer ensures a true "scratch trade" where you exit flat on your remaining equity.
The isForwardMove Check: Because your OnBar method is independently trailing the stop behind Heikin Ashi wicks, there is a rare edge case where a massive news candle triggers your HA trailing stop to jump past your scale-out target before the tick data registers the RR hit. If you simply fired ModifyPosition(position, position.EntryPrice), the bot would aggressively drag your stop loss backward, exposing you to unnecessary risk.
Shared Object Scope: When ClosePosition executes a partial close, cTrader updates the underlying position object natively. You do not need to hunt for a new Position ID; you simply pass the exact same position reference into ModifyPosition() on the very next line.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Testing partial close and breakeven logic in cTrader’s Visual Backtester requires specific engine configurations. Because the scale-out and retry mechanisms execute inside OnTick while the trailing stop executes inside OnBar, using standard bar-level backtesting will mask bugs, suppress your cooldown loops, and produce false fills.
Follow this setup to stress-test the logic under realistic, volatile market conditions.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
1. Configure the Backtesting Engine for Tick Precision
Open the Automate tab in cTrader, select your cBot, and click on Backtesting. Set up the testing environment with these parameters:
Data Feed: Set Data strictly to "Tick data from Server (accurate)".
Why: If set to "m1 bars (interpolated)" or "Open prices only", cTrader simulates only 4 ticks per minute or 1 tick per bar. In that mode, your OnTick cooldown logic (RetryCooldownMs = 500) and intrabar touch of the target will not evaluate correctly.
Execution Latency: Click the gear icon (Settings) next to the backtest controls and set Latency to 50 ms – 150 ms.
Why: Live brokers never fill instantly. Introducing artificial latency ensures that price movement between the order dispatch and the broker's response doesn't create invalid order modifications.
Commission & Spread: Under settings, verify that your account type includes standard broker commissions (e.g., $30 per million / $3.00 per lot per side). This verifies whether your BreakevenExtraPips accurately covers the commission deduction on the remaining volume.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
In the previous step, state persistence was wired to save files directly into AppData/Roaming. If you run a backtest with that code active, two problems occur:
The backtest will read and overwrite the state file used by your live or demo bots.
If you restart a backtest mid-run, it will load remnants of previous simulated trades from your physical drive.
Add a guard in your file initialization using cTrader's RunningMode property to isolate backtest storage:
When running the Visual Backtester at 10x–50x speed, inspecting log lines in real time is impractical. Inject visual chart lines so you can observe the exact moment the target is crossed and the stop moves to breakeven:
To verify that the code does not lock up, crash on rounding, or throw API exceptions during liquidity gaps, test across these specific market conditions:
High-Impact News Spike:
Check whether a 40-pip candle in 2 seconds triggers the 50% scale-out without throwing a TechnicalError or volume sizing exception.
Liquidity Gap / Rollover:
Spreads expand 5x–10x. Ensure your MaxSpreadPips filter halts new entries while allowing open trades to exit smoothly.
Aggressive Trend Deceleration
Ensure that when price tags the RR target and immediately retraces violently, the breakeven stop halts the trade at net zero instead of negative equity.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
After the Visual Backtest finishes, inspect the bottom tabs in cTrader to confirm mechanical execution:
Positions & History Tab:
1.) Filter by your BotLabel.
2.) Find a completed trade that reached the target. You should see two separate Closing Deals under the same trade sequence:
Deal 1: Volume equal to 50% of the original units, marked with a realized profit.
Deal 2: The remaining 50% of the units, closed either by the HA Trailing Stop in deep profit or at your breakeven price.
Events / Journal Tab:
Look for the sequence:
a.) [Attempting Scale-Out] Requesting X units...
b.) [Scale-Out Success] 50% partial executed.
c.) [Risk Free] Stop Loss moved to breakeven at...
Verify there are no unhandled Requote, NoMoney, or BadVolume exceptions.
Verify that if the Heikin Ashi trailing stop had already passed the entry level before the RR target hit, the journal prints [Filter] Breakeven skipped. HA Trailing Stop is already beyond... and preserves your existing stop loss.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Because cTrader’s backtesting engine rigidly fills orders at the exact historical tick price upon receiving an API command, you cannot pass a "fake" worse price to the ClosePosition method.
To simulate worst-case execution, professional quants use two parallel methods: The Latency Queue (which forces the bot to experience real broker network lag) and The Shadow Ledger (which mathematically calculates a worst-case equity curve).
Here is how to build both into your institutional framework.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.