@@ -419,12 +419,21 @@ void BacktestEngine::compact_filled_pending_orders(
419419 exit_closed_was_long ? PositionSide::LONG : PositionSide::SHORT ;
420420 size_t write = 0 ;
421421 for (size_t read = 0 ; read < pending_orders_.size (); ++read) {
422+ // Mirror classify_order_eligibility's carve-out: a resting pure-limit
423+ // entry (a GTC limit order from a prior bar, no stop/trail) survives a
424+ // full close — see the rationale there (3commas DCA safety orders).
425+ bool resting_limit_entry_carry =
426+ pending_orders_[read].type == OrderType::ENTRY
427+ && pending_orders_[read].created_bar < bar_index_
428+ && !std::isnan (pending_orders_[read].limit_price )
429+ && std::isnan (pending_orders_[read].stop_price );
422430 bool stale_same_direction_entry_after_exit =
423431 exit_closed_from_bar >= 0
424432 && (pending_orders_[read].type == OrderType::ENTRY
425433 || pending_orders_[read].type == OrderType::MARKET )
426434 && pending_orders_[read].is_long == exit_closed_was_long
427- && pending_orders_[read].created_position_side == closed_side;
435+ && pending_orders_[read].created_position_side == closed_side
436+ && !resting_limit_entry_carry;
428437 if (!is_filled (read)
429438 && !stale_same_direction_entry_after_exit) {
430439 if (write != read) pending_orders_[write] = std::move (pending_orders_[read]);
@@ -1026,8 +1035,24 @@ BacktestEngine::OrderEligibility BacktestEngine::classify_order_eligibility(
10261035 bool pre_armed_opposite_sibling =
10271036 order.created_position_side != PositionSide::FLAT
10281037 && order.created_position_side != requested;
1038+ // A RESTING pure-limit entry carried from a PRIOR bar (a GTC limit
1039+ // sitting in the book, not one freshly (re-)armed this bar) fills on
1040+ // its own touch even when another priced entry already filled this
1041+ // bar: TradingView sweeps the whole bar path against every resting
1042+ // limit order, filling each at its own limit price. The per-bar
1043+ // throttle models TV's treatment of freshly (re-)placed priced orders,
1044+ // not resting book orders — a 3commas DCA bot fills a deal's own SO1
1045+ // and a prior deal's carried-over deep SO limit on the SAME bar when
1046+ // the drop sweeps through both (pullback-sniper deal #15: SO1 @2495.21
1047+ // and the carried SO4 @2471.04 both fill on one bar). Restricted to
1048+ // pure limits (no stop/trail) created on an earlier bar so the
1049+ // same-bar stop-entry throttle (probes 80/92) is untouched.
1050+ bool resting_limit_entry =
1051+ order.created_bar < bar_index_
1052+ && !std::isnan (order.limit_price )
1053+ && std::isnan (order.stop_price );
10291054 if (!flat_armed_opposite_close && !flat_armed_same_dir_pyramid
1030- && !pre_armed_opposite_sibling) {
1055+ && !pre_armed_opposite_sibling && !resting_limit_entry ) {
10311056 return OrderEligibility::Skip;
10321057 }
10331058 }
@@ -1039,10 +1064,26 @@ BacktestEngine::OrderEligibility BacktestEngine::classify_order_eligibility(
10391064 // position (created_position_side matches the closed direction).
10401065 PositionSide closed_side =
10411066 exit_closed_was_long ? PositionSide::LONG : PositionSide::SHORT ;
1067+ // Carve-out: a RESTING pure-limit entry (a GTC limit order sitting in the
1068+ // book since a PRIOR bar, no stop/trail leg) is NOT cancelled by a full
1069+ // close. TradingView leaves pending strategy.entry() orders in the book
1070+ // across strategy.close_all() until they fill or are explicitly cancelled
1071+ // (strategy.cancel); such an order fills in a later deal when its limit is
1072+ // next touched. The same-direction cancel below targets MARKET adds and
1073+ // freshly (re-)armed priced entries tied to the just-closed position
1074+ // (deferred-flip carries — probes 72/80/93), NOT resting limit book
1075+ // orders such as a 3commas DCA bot's unfilled deep safety orders
1076+ // (pullback-sniper: an SO limit placed one deal fills the next).
1077+ bool resting_limit_entry_carry =
1078+ order.type == OrderType::ENTRY
1079+ && order.created_bar < bar_index_
1080+ && !std::isnan (order.limit_price )
1081+ && std::isnan (order.stop_price );
10421082 if (exit_closed_from_bar >= 0
10431083 && (order.type == OrderType::MARKET || order.type == OrderType::ENTRY )
10441084 && order.is_long == exit_closed_was_long
1045- && order.created_position_side == closed_side) {
1085+ && order.created_position_side == closed_side
1086+ && !resting_limit_entry_carry) {
10461087 return OrderEligibility::Remove;
10471088 }
10481089
0 commit comments