# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview quant-trading: a quantitative backtesting framework and live forward-testing trader for equity strategies across US (S&P 500) and China A-shares (CSI 300), plus a web UI to browse backtests and live books. Uses Yahoo Finance data with persistent local CSV storage. The repository has two halves that share one data directory and one `.env`: - **Python engine** (repo root, `uv`): strategies, backtests, `trader.py`, research scripts. - **Web UI and API** (`web/`, Node + React + Vite): the API spawns `uv run python bridge.py {list,backtest,live}` at the repo root and reads `data/precomputed/backtest_results.json`, written by `precompute_backtest.py`. `bridge.py`'s JSON output and `web/src/shared/strategyTypes.ts` are one contract: change both in the same commit. ## Commands ```bash # Backtesting uv run python main.py # Run US backtest (default) uv run python main.py --market cn # Run China A-share backtest uv run python main.py --capital 50000 # Custom starting capital uv run python main.py --top-n 20 # Override stock selection count uv run python main.py --years 5 # Backtest last N years only uv run python main.py --no-plot # Skip matplotlib charts uv run python main.py --fixed-fee 2.0 # Add $2 per-trade fixed fee uv run python main.py --execution open-close # Signal on open, execute at close # Daily trading simulator uv run python trader.py auto --market us --strategy recovery_mom_top10 # Single daily run (for cron) uv run python trader.py morning --market us --strategy recovery_mom_top10 # Morning: generate orders uv run python trader.py evening --market us --strategy recovery_mom_top10 # Evening: record execution uv run python trader.py monitor # Monitor ALL markets & strategies (for tmux) uv run python trader.py monitor --market us # Monitor US only uv run python trader.py status --market us --strategy recovery_mom_top10 # Portfolio status uv run python trader.py simulate --market us --strategy recovery_mom_top10 --start 2026-01-01 --end 2026-04-01 # Historical replay uv run python trader.py log --market us --strategy sim_recovery_mom_top10 --start 2026-03-01 # View daily log uv run python trader.py simulate --integer-shares --fixed-fee 2.0 ... # Integer shares mode # Precompute the strategy page's backtests (writes data/precomputed/) uv run python precompute_backtest.py # Setup uv sync # Install/sync dependencies cp .env.example .env # Then fill IPADS_API_KEY and QUANT_MARKET_PROXY (cd web && npm ci) # Tests uv run python -m unittest discover tests (cd web && npm test && npm run build) # Web UI in development (API :8787, Vite :5173) (cd web && npm run dev) ``` ## Architecture **Universe provider** (`universe.py`): Dynamically fetches index constituents (S&P 500 from Wikipedia, CSI 300 from Wikipedia) and converts to Yahoo Finance ticker format. Constituent lists are cached daily in `data/universe_*.json`. New markets are added by registering in `UNIVERSES` dict. **Data manager** (`data_manager.py`): Persistent price storage in `data/{market}.csv` (close) and `data/{market}_open.csv` (open). First run downloads 10 years of history; subsequent runs append only new trading days (fast bulk fetch for gaps ≤7 days). New tickers from index rebalances are backfilled automatically. Tickers with >50% missing data are dropped. Pass `with_open=True` to also maintain open price files. **Backtest engine** (`main.py`): Orchestrates data loading, strategy execution, and visualization. The `backtest()` function is vectorized — it takes a strategy and price DataFrame, applies transaction costs (proportional + optional fixed per-trade fee) via turnover, and returns an equity curve. Supports two execution modes: `close` (classic) and `open-close` (signal on open prices, execute at close). **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). Available strategies: `recovery_mom_top10`, `recovery_mom_top20`, `momentum`, `momentum_quality`, `dual_momentum`, `inverse_vol`, `trend_following`, `buy_and_hold`, plus 32 factor-combo strategies (`fc_{signal}_{freq}` — see `strategies/factor_combo.py`). **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. **Strategies**: - `buy_and_hold.py` — Equal-weight static allocation - `momentum.py` — Cross-sectional momentum (12-1 month factor), selects top_n winners - `inverse_vol.py` — Inverse-volatility (risk parity) weighting - `multi_factor.py` — Combines momentum + value factors with benchmark MA timing filter - `mean_reversion.py` — Short-term mean reversion - `trend_following.py` — MA crossover + momentum trend filter - `dual_momentum.py` — Absolute + relative momentum - `momentum_quality.py` — Momentum + return consistency + low drawdown - `adaptive_momentum.py` — Momentum weighted by inverse volatility - `recovery_momentum.py` — Recovery (price/63d low) + 12-1mo momentum composite. Best US performer. - `factor_combo.py` — Configurable factor-combination strategies with daily/weekly/biweekly/monthly rebalancing. US champions: `rec_mfilt+deep_upvol` (50.7% CAGR monthly), `ma200+mom7m+rec126`, `rec_mfilt+ma200`, `mom7m+rec126`. CN champions: `up_cap+quality_mom` (26.1% CAGR monthly), `down_resil+qual_mom`, `rec63+mom_gap`, `up_cap+mom_gap`. All registered in trader.py as `fc_{signal}_{freq}` (e.g., `fc_rec_mfilt_deep_upvol_monthly`). 32 new strategies total. **Metrics** (`metrics.py`): Standalone functions for portfolio analytics (Sharpe, Sortino, Calmar, max drawdown, etc.). `summary()` prints a formatted report and returns a dict. ## Key Conventions - Strategies output **weights**, not buy/sell signals. Weights are normalized so each row sums to 1 (or 0 during warm-up). - Warm-up periods: each strategy zeros out its first N rows where indicators are undefined. - `data/` contains persistent price CSVs, universe JSON caches, and trader state files, plus `data/precomputed/` (precomputed backtests) and `data/web/` (watchlist, per-stock cache, backtest result cache). Not checked into git (only `data/.gitkeep` and `data/sp500_history.json` are tracked). - Python 3.12+, managed with `uv`. - Do not show matplotlib figures when running backtests; use `--no-plot`. ## Server Deployment Three `systemd --user` services, defined in `deploy/systemd/`, run from `/home/gahow/projects/quant-trading`: | Service | Script | Role | |---|---|---| | `quant-trading-monitor` | `deploy/start-monitor.sh` | `trader.py monitor`: morning/evening phases for US + CN, all live strategies | | `quant-trading-api` | `deploy/start-web-api.sh` | Web API on `127.0.0.1:8787` | | `quant-trading-vite` | `deploy/start-web-vite.sh` | Vite on `127.0.0.1:5174`, behind nginx on `:5443` | ```bash cp deploy/systemd/*.service ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now quant-trading-monitor quant-trading-api quant-trading-vite journalctl --user -u quant-trading-monitor -f ``` The monitor catches up on startup, so restarting it between phases is safe. If it starts mid-day (after open, before close), it falls back to `auto` mode for the evening phase. Compare live books after a while: ```bash uv run python trader.py compare # US strategies uv run python trader.py compare --market cn # CN strategies ``` ### Alternative: cron Run daily after market close. The `auto` command is idempotent — safe to re-run: ```bash # US market: 5pm ET weekdays 0 17 * * 1-5 cd /home/gahow/projects/quant-trading && uv run python trader.py auto --market us --strategy recovery_mom_top10 >> data/cron.log 2>&1 # CN market: 4pm CST weekdays 0 16 * * 1-5 cd /home/gahow/projects/quant-trading && uv run python trader.py auto --market cn --strategy inverse_vol >> data/cron.log 2>&1 ```