Commit Graph

25 Commits

Author SHA1 Message Date
92a2a585e1 docs: fix CLAUDE.md lines misplaced by partial staging
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>
2026-10-09 22:07:58 -07:00
6b24bedcbd research: daytime reversal of the overnight gap on S&P 500 (STOP)
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>
2026-10-09 22:07:26 -07:00
4899bb9702 research: overnight-only momentum in the sleeve book (CONTINUE), CTA sleeve (KEEP)
- 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>
2026-10-09 22:03:18 -07:00
c34367161d research: ORB (STOP), overnight-only momentum (STOP), Alpaca paper forward test
- 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>
2026-10-09 20:06:34 -07:00
65b8db7a12 research: 50%-target search — conservative book, daily quick checks, Alpaca intraday
- managed_futures_book: three sleeves + managed futures (DBMF, tsmom24 proxy
  before 2019-05) cuts MaxDD -37% -> -27% but CAGR 16-19%, Sharpe unchanged
  (REJECT).
- small_cap_reversal / turn_of_month / short_vol: preregistered quick checks,
  all STOP (net of spread costs, post-publication decay, post-2013 VRP 0.37).
- fetch_alpaca: resume-safe Alpaca SIP intraday bars 2016+ (1-min ETFs,
  5-min liquid S&P 1500), keys from .env and never logged.
- intraday_momentum: the SPY noise-area strategy replicates (yearly corr
  1.00 with the paper) but SPY Sharpe 0.99, ~0 after publication, and only
  QQQ of five other ETFs works (STOP).
- orb_stocks_in_play: preregistered 5-min ORB replication (not yet run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:58:47 -07:00
f1c1210724 research: beta-hedged momentum (STOP) and 24-market futures TSMOM quick checks
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>
2026-10-08 22:45:21 -07:00
8845f31b3b research: risk-budgeted book of five return streams (REJECT)
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>
2026-10-08 21:17:12 -07:00
0f9554e77f research: S&P 600 replication of mid-cap quality sleeves (all REJECT)
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>
2026-10-08 18:46:45 -07:00
92af4e5ac0 feat(research): Tiingo backfill of delisted names; honest PIT panels
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.
2026-10-08 09:48:05 -07:00
2f754998a3 research: S&P 500 ∪ S&P 400 universe for overnight_recovery_top10 (FAIL)
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>
2026-10-08 08:43:50 -07:00
722cade974 fix: unify backtest execution and add forward validation candidates
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.
2026-10-01 02:24:01 -07:00
761725d2c8 feat: agent-reviewed overnight_recovery_agent_top10; guard monitor hot-reload
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>
2026-09-30 20:25:20 +08:00
db1ce69702 chore: untrack data/csi300_history.json
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>
2026-09-29 15:15:31 +08:00
5e0ab6eb3b chore: untrack generated data; add momentum + fundamentals experiment
- 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>
2026-09-29 14:42:49 +08:00
ad569f1cea feat: us_momentum_qqq_trend; alpha-vs-QQQ research across new data sources
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>
2026-09-29 13:40:15 +08:00
2c19e5efe5 feat: US 3-sleeve portfolio and lowrisk_top20; US portfolio research harness
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>
2026-09-29 01:03:50 +08:00
38a55e7882 feat(books): drop trend_rider_v3_vt24 and v4 from selected_2026_09
v3_vt24 held the same position as v7_vt24. 29 strategies remain.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 22:26:42 +08:00
465189ba9a feat(books): selected_2026_09 adds trend_rider, $2/¥10 per order, CN ¥100k
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>
2026-09-25 22:13:49 +08:00
5dbabc3e08 feat: named live books; start selected_2026_09 (26 strategies)
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>
2026-09-25 20:46:09 +08:00
cc1366b2dc feat: robust-momentum strategies live; fix live universe, lots and UI backtests
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>
2026-09-25 19:12:02 +08:00
83495bcd23 chore(deploy): keep start scripts and systemd units in deploy/
The three services become quant-trading-monitor, quant-trading-api and
quant-trading-vite, run from /home/gahow/projects/quant-trading. Their
units were previously untracked files in ~/.config/systemd/user.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 11:42:40 +08:00
ae25f2f6b5 Add 32 factor-combo strategies with configurable rebalancing frequency
New FactorComboStrategy class (strategies/factor_combo.py) implements
8 champion factor signals (4 US, 4 CN) discovered through iterative
factor research, each at 4 rebalancing frequencies (daily/weekly/
biweekly/monthly). Registered in trader.py as fc_{signal}_{freq}.

Existing strategies and state files are untouched — safe to git pull
and restart monitor on server.

Also includes factor research scripts (factor_loop.py, factor_research.py,
etc.) used to discover and validate these factors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 10:41:34 +08:00
14ec64c1da Single-process monitor for US + CN markets
- `trader.py monitor` now handles all markets in one process
  (US 9:45/16:35 ET, CN 9:45/15:35 CST) with unified UTC event loop
- Events from different markets/timezones are merged; sleeps until
  the globally next event across all markets
- Overlapping events (e.g. US evening + CN morning) fire together
- `trader.py compare` defaults to US, use --market cn for A-shares
- One tmux session handles everything: just `uv run python trader.py monitor`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:16:46 +08:00
942164a38f Two-phase monitor, integer shares, and daily log
- Monitor now runs morning (9:45 → signals) and evening (4:35 → execute)
  instead of single daily run; falls back to auto if morning missed
- Add --integer-shares flag for whole-share-only trading (no fractional)
- Add daily_log to state: each day records holdings, cash, and operations
- Add 'log' subcommand to view daily snapshots with date range filter
- record_daily_snapshot() called from both simulate and auto commands

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 23:57:03 +08:00
42218741d4 Initial commit: quant backtesting framework with daily trading simulator
Backtesting engine supporting 11 strategies across US (S&P 500) and CN (CSI 300)
markets with open-to-close execution, proportional + fixed per-trade fees.

Daily trader (trader.py) with auto/morning/evening/simulate/status commands
and cron-friendly `auto` mode for unattended daily runs on a server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 00:41:19 +08:00