diff --git a/CLAUDE.md b/CLAUDE.md index 150d10b..c093732 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,7 @@ uv run python -m unittest discover tests **Daily trader** (`trader.py`): Live/forward-testing system with persistent portfolio state in `data/trader_{market}_{strategy}.json`. The `auto` subcommand runs both signal generation and execution in a single invocation — designed for cron. The `simulate` subcommand replays a date range day-by-day with realistic portfolio tracking (fractional shares, cash, commissions). Orders: whole A-share lots are allocated nearest-lot within cash (`_allocate_lots`); a held name is resized only when ≥ `RESIZE_BAND` (10%) off target. Available strategies: `recovery_mom_top10`, `recovery_mom_top20`, `momentum`, `momentum_quality`, `dual_momentum`, `inverse_vol`, `trend_following`, `buy_and_hold`, 32 factor-combo strategies (`fc_{signal}_{freq}` — see `strategies/factor_combo.py`), and the robust-momentum bar strategies `overnight_recovery_top10`, `lowrisk_momentum_top15`, `lowbeta_sharpe_mom_top20`. -**Live books** (`trader.LIVE_BOOKS`): a book is a cohort of strategies, each with its own account, started on one date with one capital and a flat fee per order. The original book (every live strategy, `MONITOR_CAPITAL`, `MARKET_FEES`) keeps state in `data/trader_*.json`; a named book keeps it in `data/books//`. The monitor runs every book; `auto`/`status`/`log`/`compare`/`replay` and `bridge.py live` take `--book`, and `bridge.py books` lists them for the UI's book selector. `selected_2026_09` (26 strategies, US $10,000 / CN ¥50,000, $1 / ¥5 per order) starts on 2026-09-25 (US) and 2026-09-28 (CN). +**Live books** (`trader.LIVE_BOOKS`): a book is a cohort of strategies, each with its own account, started on one date with one capital and a flat fee per order. The original book (every live strategy, `MONITOR_CAPITAL`, `MARKET_FEES`) keeps state in `data/trader_*.json`; a named book keeps it in `data/books//`. The monitor runs every book; `auto`/`status`/`log`/`compare`/`replay` and `bridge.py live` take `--book`, and `bridge.py books` lists them for the UI's book selector. `selected_2026_09` (31 strategies, US $10,000 / CN ¥100,000, $2 / ¥10 per order) starts on 2026-09-25 (US) and 2026-09-28 (CN). **Strategy protocol** (`strategies/base.py`): All strategies inherit from `Strategy` ABC and implement `generate_signals(data) → DataFrame` where the returned DataFrame contains portfolio weights (rows = dates, columns = assets, values sum to ~1.0 per row). Each strategy is responsible for applying its own 1-day lag via `.shift(1)` to avoid lookahead bias — the backtest engine does not shift. A `BarStrategy` declares `fields` (close/open/high/low/volume) and receives `{field: DataFrame}`; live it uses completed bars only (row d from bars through d-1, traded at the close of d), while close-price strategies read the session's open as their latest price. diff --git a/trader.py b/trader.py index 972dc56..d159c94 100644 --- a/trader.py +++ b/trader.py @@ -118,13 +118,15 @@ LIVE_BOOKS: dict[str, dict] = { # CN starts with the first session after the strategies were chosen # (the choice was made after the CN close of 2026-09-25). "start": {"us": "2026-09-25", "cn": "2026-09-28"}, - "capital": {"us": 10_000.0, "cn": 50_000.0}, - "fee_per_order": {"us": 1.0, "cn": 5.0}, + "capital": {"us": 10_000.0, "cn": 100_000.0}, + "fee_per_order": {"us": 2.0, "cn": 10.0}, # Chosen on 2026-09-25: beat the benchmark in the Apr-Sep 2026 replay # (point-in-time members) 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 - # strategies from the 2026-09 PIT research. + # strategies from the 2026-09 PIT research, and the trend_rider ETF + # strategies (lost 7-12% in Apr-Sep, 10-year Sharpe 0.8-1.4): the best + # 10-year Sharpe of each version, and v7_vt36 (the V7+VT36 champion). "strategies": { "us": [ "fc_up_cap_quality_mom_biweekly", "fc_up_cap_quality_mom_weekly", @@ -137,6 +139,8 @@ LIVE_BOOKS: dict[str, dict] = { "fc_rec_mfilt_ma200_monthly", "fc_rec_mfilt_ma200_biweekly", "hybrid_alpha_top10", "recovery_mom_top10", "overnight_recovery_top10", + "trend_rider_v7_vt24", "trend_rider_v7_vt36", "trend_rider_v3_vt24", + "trend_rider_v5_vt30", "trend_rider_v4", ], "cn": [ "fc_up_cap_mom_gap_monthly", "fc_up_cap_mom_gap_biweekly",