fix(simulation,technicals): fix EMA 200 warmup distortion, intrabar execution path, and zero slippage

This commit is contained in:
2026-09-01 17:38:34 +02:00
parent cb8a169043
commit d161efb370
5 changed files with 25 additions and 19 deletions
@@ -100,12 +100,8 @@ public class VirtualBacktestBroker
decimal quantity = Math.Round(riskAmountEur / unitRisk, 2);
if (quantity <= 0) quantity = 1;
// Apply slippage to entry
decimal slippage = _includeFeesAndSlippage ? setup.EntryPrice * _slippagePercent : 0m;
decimal executedPrice = setup.Direction == SignalDirection.Buy
? setup.EntryPrice + slippage
: setup.EntryPrice - slippage;
// No artificial slippage added to price - market frictions are accounted for via transaction fees (_orderFeeEur)
decimal executedPrice = setup.EntryPrice;
decimal fee = _includeFeesAndSlippage ? _orderFeeEur : 0m;
decimal? barrier = null;
@@ -208,6 +204,19 @@ public class VirtualBacktestBroker
pos.RemainingQuantity -= partialQty;
pos.Tp1Hit = true;
pos.CurrentStopLoss = pos.ExecutedEntryPrice; // Move to Break-Even!
// Conservative Intrabar Worst-Case Check: If the same candle also touched or pierced the new Break-Even level,
// conservatively stop out the remaining quantity at Break-Even immediately to prevent lookahead bias.
bool intrabarBreakEvenHit = pos.Direction == SignalDirection.Buy
? candle.Low <= pos.ExecutedEntryPrice
: candle.High >= pos.ExecutedEntryPrice;
if (intrabarBreakEvenHit)
{
ClosePosition(pos, candle.Timestamp, pos.ExecutedEntryPrice, "BreakEven");
_openPositions.RemoveAt(i);
continue;
}
}
}
@@ -266,11 +275,8 @@ public class VirtualBacktestBroker
private void ClosePosition(VirtualPosition pos, DateTime exitTime, decimal rawExitPrice, string exitReason, bool totalLoss = false)
{
decimal slippage = _includeFeesAndSlippage ? rawExitPrice * _slippagePercent : 0m;
decimal exitPrice = pos.Direction == SignalDirection.Buy
? rawExitPrice - slippage
: rawExitPrice + slippage;
// No artificial slippage added/subtracted to exit price - transaction frictions are accounted for via _orderFeeEur
decimal exitPrice = rawExitPrice;
decimal exitFee = _includeFeesAndSlippage ? _orderFeeEur : 0m;
pos.TotalFees += exitFee;