8 Commits

Author SHA1 Message Date
35d750f0a5 Accept paper MOC orders IBKR holds as PendingSubmit; stop retrying after the order window
On 2026-10-13 the 09:53 ET run placed six MOC orders and failed: the paper
account reports MOC orders as PendingSubmit until the closing auction and sent
no acknowledgement within 30 s, so confirm_orders treated them as rejected.
IBKR listed all six with permanent ids and filled them at the close, as it did
the 14 PendingSubmit orders of 2026-09-29. Every retry then stopped at "6 open
orders already exist", and after 15:45 ET at the order window, and the start
limit's 6-hour window reset at 15:50 ET, so the job restarted every 10 minutes
into the evening (42 restarts by 17:28 ET).

- confirm_orders accepts a PendingSubmit order once IBKR lists it with a
  permanent id, re-reading this client's open orders every 5 s for up to 60 s.
- rebalance --submit succeeds without sending anything when every open order
  comes from today's runs and IBKR still holds every order those runs sent;
  a missing one still fails.
- The trade unit skips starts after 15:45 ET (ExecCondition), which systemd
  does not restart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:30:41 -07:00
e55c4ffbdb Restart the Gateway when its historical data farm stops serving
On 2026-10-12 the Gateway answered account requests but every bar request
timed out from 09:50 to 10:24 ET: make gateway reported OK, so the Gateway was
never restarted, and six retries 5 minutes apart gave up after 35 minutes. The
data came back only with the Gateway's daily restart.

ibkr-quant gateway --history also requires SPY daily bars within 30 s; the
trade job's ExecStartPre passes it, so ensure-gateway.sh restarts a Gateway
whose data farm is down. The trade job now retries every 10 minutes until
about 15:30 ET (34 starts in 6 h) instead of giving up after 35 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:27:16 -07:00
8238651af6 Let the strategy own the whole account; drop the unmanaged list
Every position is the strategy's: names it does not select, including ones
outside the index such as AAOI, are sold at the next rebalance, and sizing
uses the full NAV less the cash buffer. A position that is not a USD stock
cannot be traded as a SMART/USD order, so rebalance refuses to run while
one exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:28:49 -07:00
e2b06f1b1c Manage every USD stock position except an explicit unmanaged list
rebalance treated only today's S&P 500 members as the strategy's, so a held
name that left the index (or was renamed on Wikipedia) was never sold and
its value shrank the investable amount, unlike quant-trading's engine, which
sells non-members at the next rebalance. Now every USD stock/ETF position
is managed except execution.unmanaged (AAOI); a holding without bars is
priced from the account for its exit. On the paper account the managed set
is unchanged (the 10 current members).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:26:06 -07:00
a87a0c3b54 Confirm MOC orders were accepted before reporting success
rebalance used to sleep 3 s and record whatever status TWS had sent; on
2026-09-29 every order was still PendingSubmit with permId 0. Now it waits
up to 30 s for PreSubmitted/Submitted/Filled, records the final statuses in
orders.csv either way, and exits non-zero naming any rejected or
unacknowledged order so the systemd unit's failure is visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:15:53 -07:00
365f0c7181 fix 2026-10-01 11:11:53 -07:00
d945624601 Switch to overnight_recovery_top10, rebalanced every 10 sessions
Under quant-trading's PIT research engine (S&P 500 members 2006-2026,
10 bp), overnight_recovery_top10 filled at the next close beat the
daily UpCap+MomGap by 10.5%/yr (paired Newey-West t 2.44) at 3x instead
of 29x yearly turnover. UpCap+MomGap was a CN champion there, and its
daily variant was never picked for the US book.

- strategy: overnight-return momentum (12m skip 1m) + distance from the
  126-day low, ported from strategies/robust_momentum.py; top 10 equal
  weight, a held name stays while ranked within 30. Scores and picks
  match RobustMomentumStrategy on the IB bars (25 rebalances, 0 diffs).
- rebalance: every 10 sessions from strategy.anchor (2026-09-29), on
  completed sessions through yesterday's close, MOC at today's close;
  other sessions do nothing and weights drift.
- backtest trades only on rebalance sessions, like the live loop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 18:06:14 +08:00
dc94f63839 Daily UpCap+MomGap trading on an IBKR paper account
Connects to IB Gateway through ib_async and trades the S&P 500 with the
UpCap+MomGap factor combo ported from quant-trading's
fc_up_cap_mom_gap_daily: signal on opens through today's open, equal
weight top 10, MOC orders filled at today's close, 10% resize band.

- make universe/bars/check/plan/submit/fills for the daily loop; refuses
  non-paper accounts unless allow_live, open orders, stale bars, and
  orders outside 09:31-15:45 ET
- make backtest replays the live loop day by day with plan_orders and
  IBKR Fixed commissions; selection uses each day's index members
- make bars fails fast when the Gateway's historical farm is down

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:53:31 +08:00