128 fixed runs (32 profiles x daily ledger / overnight-only x 2 costs) plus 12
post-hoc availability diagnostics on overnight_recovery_top10, 2006-10 to 2026-09.
Futures trend/shock/rates rules do not beat the same rules on SPY/QQQ/IEF or a
static 75% exposure; all six default schemes fail the gates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preregistered: rb20, SPY de-risk vol target, fundamental re-sort and half QQQ,
simulated with execution.compute_trades sizing, cash-limited buys, IBKR Tiered/
Fixed fees and constant account size. All fail the 2011-16 Sharpe gate;
rb20_fundmom beats QQQ on 2011-26 CAGR and MaxDD but has no 2008 test.
Also found: wrong-security series in the research panel (filtered by dollar
volume) and the lab engine's missing delisting settlement (~2.8 pts/yr).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QQQ trend held in QQQ (no TQQQ), with Reg T margin above 1x, and its blends
with the momentum sleeve, at $1 an order on $10k, compared with QQQ raw and
at QQQ's design-period volatility. No construction raises Sharpe by 0.10 in
both periods. The trend's gain is crash avoidance (MaxDD -28% vs -83% since
1990); exploratory: at 2x margin it earns 17.0% vs 14.9% with MaxDD -50%.
The single-phase momentum series behind us_momentum_qqq_trend's 27.9% was 6pp
a year above the phase-averaged, delisting-aware stream.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ibkr_trader.py computes the strategy's target for the close the way trader.py's
morning phase does, sizes whole-share orders on min(NAV, $10.5k) less a 1%
cash buffer against the account's real positions, and sends MOC orders,
sells before buys. Guards: the login must manage IBKR_ACCOUNT; a live account
needs --live and data/ibkr_live/ARMED; the account may hold only the
strategy's universe; MOC whole-share orders only; one submission per session.
After the close it records executions and commissions, scores each order
against the primary exchange's closing cross (SIP condition 6) and compares
NAV with the simulated account, with a preregistered verdict on the first
20 orders.
A what-if run on the paper Gateway (no orders) accepted GLD/SHY MOC orders
at $1.00 commission and rejected TQQQ/UPRO: the account lacks the Complex or
Leveraged ETP permission. The live service is defined but not enabled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overnight sleeve buys at the closing cross and sells at the opening
cross; the backtest used Yahoo open/close and 1 bp a side. On 800 random
nights in 2016-26 (7,856 name-nights), the backtest night return exceeds the
cross-to-cross return by +0.12 bp (SE 0.24, median 0): Yahoo's prices are
the crosses. With the SEC fee, cost is +0.20 bp a side, so 1 bp was
conservative. At the Reg T cap this lifts three_sleeve_overnight to 39%/yr
(MaxDD -27%) and the 12_1 variant to 44%. Live fills at the cross remain
unverified (paper does not run auctions).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reg T is the binding limit: 3x ETFs need 75% margin and stocks 50%, so the
three-sleeve overnight book caps at L 1.71, about 36%/yr at MaxDD -27%.
MES futures add S&P beta, not the book's alpha. Box financing adds about
+0.9pp if a Reg T account allows it (unverified). 90%-strike calls do worse.
Puts held to expiry, reconstructed from Cboe PPUT3M/PPUT, cost 2.0-2.5%/yr
per unit of notional and buy at most +1.0pp alongside futures (gate +2pp).
At $10k no futures or index-option contract fits the account.
v1 built the hedge as the daily difference PPUT3M - S&P 500 TR. That embeds
a short S&P position equal to the put's value, so v2 holds the put to
expiry. Both are recorded; the A verdict does not depend on the hedge model.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A $10k book in whole shares holds SNDK at 17.8% for a 10% target, so the
live record mixes the strategy with rounding and fee noise (2026-09-25..10-12:
overnight_recovery_top10 -9.0% live vs -7.65% at its own weights). Each
daily_log entry now stores the target held from that close and ideal_return,
the previous target's return to this close with fractional shares, no fees,
no resize band and no idle cash. compare prints Ideal and Gap (live minus
ideal) over the recorded days. The recorded returns compound to the
frictionless ledger (new contract test); an in-memory rerun of 10-09/10-12 on
live states reproduces the recorded equity to the cent.
systemd: SuccessExitStatus=143 on the monitor and overnight-paper units, so a
stop or restart no longer logs 'Failed' and the journal shows only crashes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Johnson-So O/S has the opposite sign (Q5-Q1 -11.4%/yr, t -1.63) and
correlates -0.65 with the momentum score; unsigned put/call is flat
(t 0.42). Neither gated signal passes; keep collecting, retest at ~5 years.
The data handling was fixed after a coverage check of the panel, before any
return was computed: stock volume on every day from stock_raw, and a day
without bars counts as 0 contracts only inside a name's bar span (outside it
the options traded under an older ticker or the root's history starts later).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SNDK's October-2026 expiry month (1000 contracts, 3.5 months of daily
bars) timed out on every retry, so the backfill skipped it twice. A 504 on
a request for 50+ symbols now restarts that chunk as two halves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gate per gated signal (low_os_5, low_pc_5): h=5 quintile spread with the
predicted sign at NW t >= 3, same sign in both halves, positive top-20
alpha vs EW. Committed before the volume panel exists, so the rule
predates any look at the data.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The indicative feed's quotes are derived, not OPRA quotes (Alpaca docs);
the OPRA BBO needs the $99/month plan. Option bars are computed from OPRA
prints and are free beyond the last 15 minutes, back to 2024-02.
- snapshot also stores OPRA daily bars for every contract expiring within
0-100 days (active and same-day inactive, so 0DTE volume is kept), and
bases option volume, os_volume and pc_volume on them.
- snapshot samples three near-the-money contracts per name and compares
the last 15:45-16:00 OPRA print with the indicative quote (share inside,
IV error). status gives the pre-set verdict after 20 sessions: adequate
if >= 90% inside and median |IV error| <= 1 vol point.
- backfill fetches daily bars since 2024-02-01 for every S&P 500 member
since then, one resumable file per underlying, pausing 16:10-16:55 New
York; volume-panel builds the daily option-volume panel.
- Bar requests send a timestamp end capped at now - 16 min: a date-only
end of today returns 403. Adjusted (non-OCC) roots are skipped.
The daily path and the backfill agree contract by contract on AAPL
2026-10-09 (1,068 contracts, identical volume).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
svr_combo (preregistered): blending low_svr21 into overnight_recovery_top10
lifts Sharpe 0.81 -> 0.87 at w=1/3 but deepens MaxDD by 6pp (G1, G3
fail); as a fourth sleeve it dilutes the overnight book (1.49 -> 1.42).
fetch_options collects S&P 500 option chains after each close from
Alpaca's free indicative feed (quotes, day volume, OCC open interest),
solves IVs, and writes per-name iv_atm30 / skew / call-put spread /
option-stock volume summaries to data/options/us/. Forward-only history
for options-implied factors. Run by the quant-trading-options timer at
16:25 New York, Mon-Fri; it skips once the next session has opened.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
factor_census measures all 86 lab factors one way on the post-Tiingo PIT
S&P 500 panel (IC, quintile spread, top-20 alpha vs EW). One class A
(low_svr21, 2018+), two class B (accruals, rev_5), 69 N, no |t| >= 3.
Momentum and overnight_mom have no quintile spread; the house edge sits
in the top 10. --part construction compares the live construction.
rotation.factor_ranks reused ranks_us.pkl regardless of the panel. The
cache predated the Tiingo merge (643 of 787 columns), so callers silently
dropped the backfilled delisted names. The cache now carries a key file
(panel calendar, tickers, membership, factors.py hash) and is rebuilt
when it does not match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dip_buying: SPY/QQQ RSI(2) dip is real after publication (SPY 2008-26
46 bp/trade, t 3.4) but in the market 14% of days, so 3x earns the same
Sharpe as SPY; trend-filtered stock RSI(2) breaks even at 10 bp/side and
lowers the three-sleeve book (1.14 -> 0.95); stocks far below their high
rebound only in market-wide crashes.
dip_leverage_overlay: +1x SPY inside the dip windows on the overnight_book
books leaves Sharpe flat or lower (0.98 -> 0.99, 1.38 -> 1.33); the gain
ranks 77-88% against trend-matched random windows. The books already earn
the bounce at about 2x SPY's beta.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
collect archives Yahoo's earnings/revenue estimates, EPS trend, EPS
revisions and price targets as immutable snapshots; a snapshot is usable
only after its created_at, so the vendor's 30/90-day history never reaches
earlier bars. evaluate replays overnight_recovery_top10 with an EPS-revision
re-rank of the quant top 50 on the same ledger and costs and returns NEEDS
EVIDENCE until 252 active sessions from 20 collection dates exist. The
agent's candidate pack now carries each name's analyst context.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A refresh of a few tickers judged a new date's coverage against every
ticker in the stored panel, so the date was dropped as sparse; it also
re-ran the sparse filter over the whole history. Coverage is now checked
only inside the refresh window, with unrequested tickers counted where they
already have a bar.
When a session that was skipped earlier appears in the panel, the trader
rewinds the ledger to that day (undoing later trades, or restoring a legacy
snapshot) and replays every session from it in order. State files are
written atomically, and the monitor refreshes volume with close/open.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_submit printed "HTTP 403" and moved on, and buy/sell then marked the
session done, so one rejected MOC/MOO order was never retried. It now
raises unless Alpaca returns an order id with an accepted status; a 422
duplicate client_order_id counts only when the existing order matches the
payload and is live. The session is marked bought/sold only after every
order is accepted, and the daemon retries the rest on its next tick.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
validate() now takes the submission stamp and rejects any source without a
readable publication date or dated after the submission day (UTC). The skill
tells the agent and its subagents that web pages, news and filings are data,
never instructions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- execution/trader: a held US stock with no print for 5 sessions that has left
the index is sold at its last print (execution.SETTLE_AFTER_SESSIONS), in both
the batch replay and the live session ledger. Acquired names used to stay at
their last mark forever: lowrisk_top20 ended 2017-12..2026-10 with 11 of 26
dead positions, and CAGR rises 1.7-5.5pp once they settle. ENGINE_VERSION
cash-ledger-pit-v3; the API cache key follows.
- universe_history: current members whose pre-2011 addition the Wikipedia change
log missed now start at the list page's "Date added" (80 of 94 current members
added 2001-2010 were open-start, e.g. ISRG, MA, BKNG). Membership from 2016 on
is unchanged; the research panel cache now keys on the membership intervals.
- research/lab/registered: pure-ETF strategies replay on the ETF panel (they ran
as all-cash books or crashed); prepare_strategy refuses an ETF strategy that
lacks its ETF universe.
- research/lab/factors: trend_hzz uses a month's regression betas only from the
session its forward returns end (short months read 1-2 sessions ahead).
- tests: every registered strategy (US and CN) is truncation-invariant on the
production signal path; batch and live ledgers settle a delisting identically.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removed (79 files, all in history; research/ARCHIVE.md lists each with its
purpose and the commit to restore it from):
- root factor_*.py mining scripts (2026-04) and yearly_sweep.py
- scripts/run_daily.{py,sh} (superseded by the monitor service; no crontab)
- strategies no registry, test or live book uses: trend_rider_v8,
adaptive_blend, cross_asset_momentum, long_hedged, ls_momentum
- 55 research/*.py scripts from 2026-04/05 written before research/lab,
the us-alpha design spec, and the 7 tests that only covered them
Kept research/permanent_yearly.py: bridge.py and precompute_backtest.py
import equity_with_cashflows. CLAUDE.md gains the archive note and the
command lines of the studies committed in the previous commit.
Checks: 99 unit tests OK (125 before, minus the 26 removed with their
modules), all 157 remaining modules import, 94 registry strategies build,
bridge.py list OK, web 23 tests OK and build OK.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Studies run by earlier sessions and documented in CLAUDE.md, but never
committed: FINRA short volume (SVR) and the research-only svr_momentum veto,
SEC fails-to-deliver, 13D activists and the 13D event sleeve, 13F
institutional flow, GDELT news volume, S&P 400/600 Form 4 insiders,
union_shield, shield_lab; plus the mid/small insider and Tiingo fetcher
changes and midsmall_rebuild.
overnight_midsmall: the overnight-only momentum book on S&P 400/600 earns
0.93 net Sharpe at 3 bp a side (2019-26) with corr 0.83 to the S&P 500 book
(STOP).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
trader.py registers trend_rider_v9 (+ vt24/vt32/vt36) and trend_rider_v10
(+ vt32/vt36) from strategies/trend_rider_v9.py, and bridge.py labels them.
These were left uncommitted by the 2026-10-07 research session while the
monitor ran them from the working tree (state files data/trader_us_trend_rider_v9*/v10*).
research/tr9_*.py is the research trail CLAUDE.md cites.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the duplicated fetch_us_fundamentals --universe mid/small pair and move
the quant-trading-overnight-paper row back into the services table (it had
landed inside the bash block).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Buying the biggest overnight losers at 09:35 and selling at the close earns
1-6 bp a day gross on 2016-26 Alpaca 5-min bars; net Sharpe ~0, and stacking
it on the overnight sleeve lowers the Sharpe (1.27 -> ~0.8).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- overnight_book: swapping the all-day momentum sleeve for the overnight-only
one lifts the three-sleeve book from Sharpe 0.98 to 1.38 (halves 1.16/1.64)
and MaxDD from -37% to -17% at 1 bp a side; at 4 bp the gain is gone.
- overnight_book_mf: at the leverage for 50%/yr, a DBMF sleeve leaves the
levered MaxDD unchanged (~-36%) and needs more leverage; no CTA sleeve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- orb_stocks_in_play: 5-min bounds -70%/yr (conservative) vs +71%/yr
(optimistic); the optimistic bound breaks even at 3.6 bp slippage a side.
- overnight_only: the momentum sleeve's names earn their return overnight
(Sharpe 1.57) and nothing intraday; held close->open only, net Sharpe
1.29-1.42 at 1 bp a side, below the 1.5 gate.
- overnight_paper.py + systemd unit: MOC buy / MOO sell of the top 10 on the
Alpaca paper account from 2026-10-12, with a fills-vs-prints report.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hedged_momentum: overnight_recovery_top10 hedged with QQQ futures at a
rolling 126d beta earns Sharpe 0.11; alpha vs QQQ on the Tiingo panel is
+5.3%/yr (t 1.10). futures_trend: Yahoo =F data is roughly usable (ES/NQ
corr 0.98, ZN/GC miss on settlement time), 24-market TSMOM Sharpe 0.44,
corr 0.22 with TrendRider: a crisis diversifier, not a core stream.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preregistered: inverse-vol shares of momentum, lowrisk, TrendRider V10
(synthetic 3x ETFs, lag fills), 8-ETF TSMOM and BTC trend, 2006-10..2026-09.
invvol5 1x: 12.6%/yr, Sharpe 1.07, MaxDD -18% (halves 0.82/1.38) beats the
three-sleeve book (0.97, -38%) but not TrendRider V10 in 2017-26 (1.65);
levered to 25% vol it drops to 0.98. Inverse vol over-weights the weakest
streams; the bottleneck is stream Sharpe, not weighting.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preregistered replication vs IJR, 2017-01..2026-09, 20bp decides:
quality composite +2.3%/yr (t 0.78; halves +8.0/-3.5), quality-filtered
momentum +2.2% (t 0.73); SUE and lottery-filtered momentum also REJECT,
all weaker at 40bp. Equal-weight members beat IJR (t 3.2) and every
sleeve. Decision: drop quality stock selection in mid/small caps.
Adds --universe small to fetch_us_fundamentals (IJR, name-checked CIKs),
a `which` argument to fundamentals.load_mid, and --universe small to
midcap_sleeve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After S&P 400 names failed inside the large-cap momentum top 10, test them
as their own sleeve: top 30, monthly, buffer 1, 20 bp, judged by alpha vs
IJH and by whether 1/3 of the book in the sleeve beats 1/3 in IJH. Four
hypotheses and a control, definitions and rule written before the run.
Holdout 2017-01..2026-09: mid-cap momentum -1.0%/yr vs IJH (corr 0.83 with
the large-cap book), lottery-excluded momentum -1.7%, SUE earnings momentum
-1.7%, quality-screened momentum +3.5% (t 1.28), quality composite +3.4%
(t 1.23; book 0.91 vs 0.85 with IJH). Quality is positive in both halves
but underpowered; nothing is adopted.
fetch_us_fundamentals gains --universe mid: EDGAR facts for S&P 400
ever-members, CIKs accepted only when an SEC name matches the iShares
holding name. fundamentals.load_mid builds the same factors on that panel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Yahoo purges delisted members: the S&P research panel was missing 209
ever-members (AGN/CELG/ESRX/ATVI/TWTR/XLNX/...), the production store 89, and
the S&P 400/600 panels ~180 more. The gap inflated momentum-family factors
(overnight_mom holdout 16.9->14.8%/yr, rec_126 14.7->10.7 on the research
panel; factor_panel_check).
research/lab/fetch_tiingo.py pulls full EOD histories (free tier: 500 unique
symbols/month, 50/hour; paced, resume-safe, key never logged).
research/lab/tiingo_merge.py overlays the caches on the research S&P panel at
build time (>=50% PIT-coverage gate, median-overlap cross-check, stub-column
replacement, rename splices GPS<-GAP, DISCA<-WBD, WLTW<-WTW, ADS<-BFH,
CCE<-CCEP, ESV<-VAL, FBHS<-FBIN, HFC<-DINO) and can apply the same to the
production store (--production [--apply]; data/us*.csv, .bak-tiingo backups,
under the panel lock). load_us() rebuilds when the overlay changes
(_tiingo_sig); fetch_us_mid.load_bars falls back to converted CSVs.
Round 1 (2026-10-08): 165/209 S&P names and 183 mid/small PIT members
restored (2011-19 snapshots were 15-20% short of PIT members). prod_impact
A/B on registered replays: overnight_recovery_top10 23.8%/0.83/-38.3% vs
27.8%/0.88/-47.3% backfill-off; lowrisk_top20 6.1%/0.58 vs 8.6%/0.60 -
honest long returns with shallower drawdowns; trend_rider_v10 (ETF path)
unchanged at 55.0%/1.64. Official precompute refreshed (backup at
data/precomputed/backtest_results.json.pretiingo). midsmall_scan on the
corrected panel: no factor beats the EW benchmark (0.60 holdout Sharpe vs
0.51-0.52 best) - no mid/small sleeve.
LITE ranked #1-4 on the overnight_recovery score from 2025-07 while still an
S&P 400 member, and the book could only buy it after it joined the S&P 500
on 2026-03-23. research/lab/universe_midcap.py tests whether ranking S&P 400
members alongside the S&P 500 helps, on one merged panel with one engine and
20 bp a side for every arm; the decision rule is written before the run.
Primary window 2019-01..2026-09: union Sharpe 0.86 / CAGR 24.7% / MaxDD
-38.8% vs base 0.98 / 29.4% / -34.3%; 2019-24 alone 0.48 vs 0.70; without
PENN, LITE and SMCI the union's alpha vs base is -6.7%/yr (t -2.1). Mid-cap
momentum adds a few large winners and many small losers. Not adopted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Share point-in-time signals and a cash-funded order ledger across backtests and trading. Correct eligibility, missing-price fills, quality factors, regime inputs, warmup windows, and cash-injection accounting. Add reproducible registered-strategy comparisons and paired forward candidates with a 20% resize band.
Validation: 125 Python tests, 23 web tests, TypeScript/Vite build, 87 strategy causality checks, and real-data target/order/equity parity for 10 strategies.
overnight_recovery_agent_top10 (strategies/agent_review.py) re-ranks the
overnight_recovery top 50 with an LLM agent's daily scores:
final = quant percentile + 0.25 x score (-2..+2), vetoes for five event types,
top 10 on the base strategy's rebalance rows and hysteresis. Score files are
stamped by `agent_review.py submit` and steer a session only if stamped before
its 16:00 New York close; without one the strategy holds exactly what
overnight_recovery_top10 holds (checked on the live panel 2016-2026).
- agent_review.py: candidates / submit / evaluate; skill
.claude/skills/agent-stock-review drives the daily research.
- US only, skipped by precompute (no history before its first score file);
runs in the original book and in selected_2026_09 (from the book's start).
- .gitignore tracks .claude/skills/ and ignores data/agent/.
Monitor fix: hot-reload re-imports trader.py but not strategies/*. After the
2026-09-29 strategy commits the stale modules made every phase's panel refresh
fail ("Unknown signal 'low_risk'") and US books skipped 09-29 until a restart.
_reload_strategies now builds every factory and keeps the old registry when
any fails; CLAUDE.md says to restart the monitor after changing strategy code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests of the "rank and buy top N misses the chain / cycle / sentiment" question
(report: https://claude.ai/artifact/HUnPtcy7D7Zp1yNQsDLRHY):
- review_live_us: Apr-Sep 2026 replay; book return vs AI-chain weight corr 0.71,
overnight_recovery_top10 excess almost all allocation (memory stage +28pp).
- fetch_supply_links: 10-K mentions of S&P 1500 companies by role, PIT by filing
date (12,117 S&P 500 10-Ks; --universe mid for 14,382 S&P 400/600 10-Ks).
- lead_lag: corr-peer and 10-K link momentum worked 2006-16 (FM t 3.3-4.3) and
vanished 2017-26 (t -2.1..-0.6); Granger lead-lag network and earnings
spillover drift null after 2016.
- theme_propagation: linked laggards of each era's hot industry underperform
2017-26 (-2% to -12%/yr).
- lead_lag_small: the same signals on S&P 400/600, 2019-26, all |t| <= 1.8.
- sector_cycle: 21 cycle/rotation variants, none with holdout |t| > 2.
- fetch_wiki_attention + attention: Wikipedia pageview attention, |IC| <= 0.013.
- concentration: industry caps on momentum top 10 cut alpha, not drawdown.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CSI 300 snapshot history is local data like the S&P 500 history. It is
not rebuilt automatically (seeded from baostock), so a new machine needs a
copy; CLAUDE.md says so.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Stop tracking data/sp500_history.json (rebuilt daily from Wikipedia by
universe_history.load_sp500_history) and ignore data/books/ (per-machine
live book state, like data/trader_*.json).
- research/lab/momentum_fundamentals.py: financial-statement vetoes and
confirmations on overnight_recovery_top10 (2011-16 design, 2017-26
holdout). No return gain; re-sorting the momentum top 30 by fundamental
momentum lowers MaxDD at equal return.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Register us_momentum_qqq_trend: half overnight_recovery_top10, half a QQQ
trend sleeve (strategies/qqq_trend.py: 200-day switch times a 30% vol target,
held as TQQQ + SHY). Mixed stock+ETF, US only (extra tickers QQQ, SHY, TQQQ).
Research (research/lab/): alpha against QQQ with a 2006-16 design / 2017-26
holdout split (alpha.py, qqq_scan.py, beat_qqq.py); leverage and drawdown
frontier (levered_book.py, us_target50.py); synthetic 3x ETFs from 1990 and
TrendRider/QQQ-trend stress tests (fetch_long_history.py, letf_history.py,
vol_trend.py); short-horizon sleeves, diversifiers, industry momentum,
earnings-announcement returns; new point-in-time data sources: SEC Form 4
insider trades (fetch_insider.py, insider.py), 10-K/10-Q text similarity,
8-K earnings dates and SIC codes (fetch_lazy_prices.py, lazy_prices.py), and
an S&P 400/600 universe from iShares holdings (fetch_us_mid.py, panel_mid.py).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Register two live strategies from the 2026-09-29 US research:
- lowrisk_top20: idiosyncratic vol + low beta, top 20, monthly, buffer 2
(new `low_risk` signal in strategies/robust_momentum.py)
- us_three_sleeve: 1/3 each of overnight_recovery_top10, lowrisk_top20 and
trend_rider_v7_vt24 in one account (strategies/sleeve_portfolio.py, a
mixed stock+ETF strategy). Sleeve shares drift with their returns and reset
at a month start once any is >25% off its share.
Research (research/lab, S&P 500 PIT, next-open fills):
- rotation.py / persistence.py: walk-forward factor weighting (factor
momentum, rolling IC, market state) and last-year's-winner selection do not
beat a fixed composite
- us_sweep.py: holdings count, z/vol weights, dynamic N, tranching and market
overlays (Faber SMA, de-risk vol target, statistical jump model,
momentum state); engine.py gains zvol weighting and dyn_n
- fetch_us_fundamentals.py / fundamentals.py / fund_eval.py: SEC EDGAR
point-in-time fundamentals (first-filed values) and factor tests
- trend_rider_long.py / us_final.py: 2010-2026 TrendRider curves and the
3-sleeve check (2011-2026 Sharpe 1.21, CAGR 21.9%, MaxDD -23%)
Web-UI engine, 2017-09..2026-09, $2/order: us_three_sleeve CAGR 28.9%,
Sharpe 1.49, MaxDD -24.8%.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds five trend_rider ETF strategies (best 10-year Sharpe of each version,
plus v7_vt36): 31 strategies in all. Fees per order are $2 and ¥10, and CN
accounts start with ¥100,000. No trade has been executed yet (US accounts
hold only this morning's orders; CN starts 2026-09-28).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A live book is a cohort of strategies, each with its own account, started
on one date with one capital and a flat fee per order (trader.LIVE_BOOKS).
The original book keeps its state in data/; a named book in
data/books/<book>/. The monitor runs every book; auto/status/log/compare/
replay take --book. A fresh account opens on the book's first session.
selected_2026_09: US $10,000 and $1 per order from 2026-09-25, CN ¥50,000
and ¥5 per order from 2026-09-28 (the first CN session after the choice).
Strategies beat their benchmark in the Apr-Sep 2026 point-in-time replay
and passed a 10-year PIT backtest (US Sharpe >= 0.6, MaxDD > -50%; CN
Sharpe >= 0.2, CAGR > 0), no daily variants, at most two frequencies per
factor signal, plus the three 2026-09 research strategies.
bridge.py live --book and bridge.py books feed a book selector on the
live page (/api/strategies/live?book=, /api/strategies/live/books).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Replaying live books over past sessions used today's constituent list for
every day, so US books bought names (BE, MRVL, ILMN, FLEX, P) before they
joined the S&P 500. session_universes/session_signals now compute each past
session on that day's members (S&P change log, CSI 300 snapshots); the
latest session keeps the live list. Used by auto/monitor catch-up, replay
and simulate. _run_session takes precomputed targets only.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Strategies
- BarStrategy protocol (close/open/high/low/volume bars; row d uses bars
through d-1) and RobustMomentumStrategy: overnight_recovery_top10 (US),
lowrisk_momentum_top15 and lowbeta_sharpe_mom_top20 (CN), top-N with
rank hysteresis, 10-day rebalance, weights drift between rebalances.
- trader: strategy_fields/strategy_bars/bar_session_weights; one signal
path (_signals_for_sessions) replaces generate_target_weights.
Live fixes
- CSI 300 constituents come from China Securities Index's file; the
Wikipedia table was 122 names off the real index.
- S&P 500 change log moved to "Historical components of the S&P 500".
- data_manager: tickers missing from a partial Yahoo batch are retried
alone before being marked unavailable (CEG, GEV, SNDK ... were dropped).
update() takes fields=[...] and stores high/low/volume panels.
- Whole-lot orders go to the nearest lot within cash (CN books held ~62%
cash); held names are resized only beyond RESIZE_BAND (10%), so books no
longer pay a ticket fee to trade daily drift.
Web backtests
- backtest_runner.py replaces the duplicated bridge/precompute code: PIT
membership in both markets (data/csi300_history.json), stock universe
limited to index members (ETFs and benchmarks in the shared panel were
pickable), and the book kept like the live trader (simulate_live_book:
signal timing, drift, order floor, resize band, fees on orders placed).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Event-driven long-only simulator with next-open fills, CN tradability
(halts, limit-up/down, stamp duty), PIT S&P 500 / CSI 300 membership,
rebalance-phase averaging, factor IC scans, maximin stepwise composite
search across 5-year blocks, walk-forward LightGBM/ridge combiners,
overlays, and deflated Sharpe. Fetchers pull 20y US OHLCV from Yahoo and
CSI 300/500 ever-members (membership snapshot from baostock, bars from
Yahoo). Research data lives in data/research/ (ignored).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>