2 Commits
Author SHA1 Message Date
momentum devandClaude Opus 4.8 9ab12bb3d6 Fix: open catch-up flatten wrongly flattened partially-filled fresh positions
Root cause of SSPC getting flattened on a mid-session restart (2026-06-24):
flatten_overnight_carries built its today's-buy set from orders with
status=="filled" only. But a marketable buy that PARTIALLY fills (SSPC: 84 of
88) cancels its unfilled remainder, so the order reads status=="canceled" even
though it opened 84 real shares. The carry-detector saw "no filled buy today"
for SSPC, tagged it an overnight carry, and market-closed a position opened ~6
min earlier. (Harmless this time — closed +$20 — but it could cut a runner or
realize a loss.) Marketable orders partial-fill far more than resting limits, so
flipping to marketable exposed this latent bug.

Fix: extract buy_fills_from_orders() (runtime/flatten.py) that counts a buy as a
real today-entry by filled_qty>0 + filled_at, NOT status=="filled" (scans legs
too). flatten_overnight_carries uses it. Pure + unit-tested: partial-fill counts,
full fill counts, zero-fill backout does not, and the partial-fill position is
no longer flagged a carry.

Note: only manifests on a mid-session restart (a clean session's EOD flatten
leaves the book flat, so the open finds no carries). Deploys on next restart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 11:05:05 -04:00
momentum devandClaude Opus 4.8 1be2dfd042 Open catch-up flatten: close stale overnight carries at the open
The backstop behind the EOD-flatten fix: even with the EOD flatten working, a
carry can survive (loop down at EOD, or the held-qty 403 before it was fixed) and
bleed for days — ATPC sat 4 days over the Juneteenth gap, -$651. This closes any
position carried from a PRIOR session, at the open, before it bleeds.

- runtime/flatten.find_overnight_carries (pure, tested): open positions with no
  BUY filled today (ET) = carried overnight. Today's fresh names have a buy
  today, so they're never touched.
- ExecutionService.flatten_overnight_carries: detects carries from the broker
  (positions + filled buys) and closes them via the robust cancel-legs-then-close
  path — WITHOUT halting the session (unlike close_session), so today's trading
  continues. Emits an open_catchup_flatten risk event.
- run_live_paper step_open_catchup_flatten: once per session, during RTH, gated by
  TRADING_OPEN_CATCHUP_FLATTEN_ENABLED (def 1). Loud log when it flattens a carry.

Dry-run against the live book: correctly targets ONLY ATPC (6/18 carry), leaves
today's DAMD/ECX. 38 runtime/safety tests pass. Needs a loop restart to activate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:08:09 -04:00