diff --git a/app/db/paper_trading.py b/app/db/paper_trading.py index 3f23e91..9f1f8d7 100644 --- a/app/db/paper_trading.py +++ b/app/db/paper_trading.py @@ -1044,7 +1044,20 @@ def _fill_paper_order(conn, order: dict, rec: dict, current_price: float, event_ if not global_ok: # Market/account risk is a temporary execution gate, not proof that the # original limit order is invalid. Keep the order pending so it can fill - # later if risk improves, instead of instantly wiping every touched order. + # later if risk improves. But if price has already run far past the target + # in the adverse direction, the pullback premise is void → cancel so we + # don't later fill at a stale, distorted target price. + side = str(order.get("side") or "long").lower() + target = _safe_float(order.get("target_price")) + threshold = max(0.0, _safe_float(cfg.get("order_cancel_far_from_entry_pct"), 12.0)) + too_far = False + if target > 0 and current_price > 0 and threshold > 0: + if side == "short": + too_far = current_price > target * (1 + threshold / 100) + else: + too_far = current_price < target * (1 - threshold / 100) + if too_far: + return _cancel_paper_order(conn, order, "risk_paused_far_from_entry", event_time) conn.execute("UPDATE paper_orders SET updated_at=%s WHERE id=%s", (event_time, order["id"])) return { "skipped": True,