Commit Graph
244 Commits
Author SHA1 Message Date
Justin Gu a3d6d93122 feat: strategy screener - scan all stocks by signal, rank by backtest performance (v1.9.2)
- Add 'screen' CLI command group with 'scan' and 'rank' subcommands
- scan: offline signal scanning from local .day files, zero network IO
- rank: backtest ranking of scanned signals by sharpe/drawdown/etc
- Two-step workflow: scan outputs JSON, rank reads JSON and evaluates
- Support --universe (all/sh/sz/custom file), --sort, --names
- Support pipe mode: scan ... | rank --from - --table
- New module: src/easy_tdx/screen/{scanner,ranker,cli}.py
- 20 unit tests (offline, no network required)
2026-06-10 03:03:03 +08:00
Justin Gu cb0a8ef6c5 chore: bump version to 1.9.1 2026-06-10 02:14:53 +08:00
Justin Gu 5691bb8432 refactor: screen() reuses run_combination(), single runner across combo sizes
- screen() now calls run_combination() internally, eliminating duplicated
  signal extraction/combination logic
- _run_combo_screen creates one CombinationRunner before the size loop,
  so signal cache is reused across 2-factor and 3-factor screens
- Add MAJORITY(2)=AND note to screen() docstring
2026-06-10 02:13:28 +08:00
Justin Gu 1e99feb7c2 feat: multi-factor combo backtest engine (v1.9.0)
- Add backtest/combo.py: CombinationRunner, extract_factor_signals, combine_masks
- Signal merge modes: AND / OR / MAJORITY (majority default)
- CLI: --combo-strategies and --combo-mode for easy-tdx backtest
- run_all_strategies.py: --combo 2 --combo 3 auto-screen best combos
- Fix MyTT MFI/CR divide-by-zero RuntimeWarning
- 14 new unit tests, 328 total passing
2026-06-10 01:37:28 +08:00
GitHubandClaude Opus 4.8 7f1bc645c2 release: v1.8.2 - 5 new strategies, --show chart, 15 total
- New strategies: dmi_trend, cci_breakout, mfi_volume, trix_cross, mtm_momentum
- run_all_strategies.py --show: dual-axis equity curve vs stock price chart
- zhuoyao_momentum strategy (from earlier commit)
- README: updated strategy table (9→15), changelog, demo screenshots
- Bump version to 1.8.2

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:17:04 +08:00
GitHubandClaude Opus 4.8 8fcedeb47a feat(strategies): add zhuoyao_momentum strategy + Maotai demo screenshot
- New ZHUOYAO multi-timeframe momentum strategy (strategies/zhuoyao_momentum.py)
- Entry: SHORT>0 + TREND>0 + SHORT>MID (triple resonance)
- Exit: SHORT<0 or TREND<0 (conservative, any triggers sell)
- Add SH600519 Maotai demo screenshot (strategies/demo/4.png)
- Update README with 4th demo screenshot

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:59:19 +08:00
GitHub b57d8f4669 feat(backtest): add --show flag for best strategy equity curve chart
- Add --show/--show-chart flag to run_all_strategies.py
- Display dual-axis chart: normalized stock price vs strategy equity curve
- Mark buy/sell points with green/orange triangles
- Auto-detect Chinese fonts (SimHei/YaHei on Windows, PingFang on macOS)
- Fetch stock name via get_stock_quotes for chart title
- Add 3 demo screenshots to README with disclaimer
- Update README with --show usage and visual examples
2026-06-09 22:41:14 +08:00
GitHubandClaude Opus 4.8 b44636207b release: v1.8.1 - single-source version, batch backtest detail output
- Consolidate version to pyproject.toml as single source of truth
- __init__.py, cli/__init__.py, docs/conf.py all read dynamically
- run_all_strategies.py now shows best strategy full trade details
- Update README changelog for 1.8.1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:12:27 +08:00
GitHubandClaude Opus 4.8 b5b5d0dc5b release: v1.8.0 - backtest engine with batch strategy comparison
- Add backtest section to README with CLI usage and run_all_strategies.py demo
- Update all version numbers to 1.8.0 (pyproject.toml, __init__.py, cli/__init__.py, docs/conf.py)
- Fix turtle_breakout strategy: TAQ returns 3 values (UP, MID, DOWN)
- Add run_all_strategies.py batch comparison script
- Update README intro to highlight backtest feature
- Add backtest to CLI command table and architecture tree

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:35:38 +08:00
GitHubandClaude Opus 4.8 70c69c8a66 fix(backtest): cli _print_table used wrong key 'sharpe_ratio' instead of 'sharpe'
Performance dict outputs 'sharpe' but _print_table looked up 'sharpe_ratio',
so perf.get('sharpe_ratio', 0) always returned the default 0 regardless of
actual Sharpe value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:02:20 +08:00
GitHubandClaude Opus 4.8 46298e68d7 fix(backtest): max drawdown now correctly measures peak-to-trough percentage
Previous formula was: max(absolute_drawdown) / initial_capital, which
exceeds 100% when the portfolio grows then drops (e.g. from 600k to 300k
on a 100k initial = 300% drawdown, which is nonsensical).

Fixed to use drawdown_pct (drawdown / peak) which is always in [0, 1].
This correctly measures the maximum percentage drop from the highest
equity peak, matching the standard financial definition.

Also added regression test: test_max_drawdown_never_exceeds_100_pct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 19:00:11 +08:00
GitHubandClaude Opus 4.8 5550702620 fix(strategies): unpack BIAS triple return value in bias_reversal
MyTT.BIAS returns (BIAS6, BIAS12, BIAS24) but the strategy was assigning
all three to a single variable, causing 'array with more than one element'
ValueError when comparing to a scalar threshold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:56:07 +08:00
GitHubandClaude Opus 4.8 6a6d75f5d5 fix(backtest): strategy position not tracked during signal generation
Root cause: _generate_signals() iterated all bars calling strategy.next()
but never updated _position_size or _cash on the strategy. Strategies
that check self.position['size'] before buy/sell always saw 0, producing
only BUY signals with no SELL — exhausting cash and producing drawdowns
exceeding 100%.

Fix: add _update_strategy_position() that estimates position changes
after each bar's signals using close price. This gives the strategy an
accurate view of its holdings so it can correctly alternate buy/sell.

Regression tests added:
- test_position_aware_buy_sell_alternation: verifies BUY/SELL alternation
- test_position_aware_no_duplicate_buys: no suspicious tiny duplicate buys

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:50:13 +08:00
GitHubandClaude Opus 4.8 f7e1abd873 feat: add 9 demo strategy files for backtest engine
Strategies included:
- ma_cross: MA5/MA20 dual moving average crossover
- expma_cross: EMA12/EMA50 crossover (more responsive)
- macd_cross: MACD golden/death cross
- bollinger_breakout: Bollinger band breakout
- rsi_reversal: RSI overbought/oversold reversal
- kdj_golden: KDJ low golden cross / high death cross
- turtle_breakout: Turtle trading (Donchian channel)
- bias_reversal: BIAS mean reversion
- volume_price: Volume-price confirmation

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:45:01 +08:00
GitHubandClaude Opus 4.8 00b7d75caa docs: add backtest engine usage manual
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:37:58 +08:00
GitHubandClaude Opus 4.8 04c2be1d7f fix(backtest): resolve mypy and ruff lint issues
- dsl.py: use NDArray type annotations, fix None narrowing
- cli.py: add type annotations, fix import sorting
- strategy.py: fix UP038 isinstance, add noqa for I() method name
- tests: fix E712 bool comparison assertions

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:21:25 +08:00
GitHubandClaude Opus 4.8 fc0777533e feat(backtest): add CLI command with auto data fetch and table output
- Created src/easy_tdx/backtest/cli.py with backtest command
- Supports --strategy-file to load Python strategy classes
- Supports --indicators to precompute technical indicators
- Supports --cash, --commission, --execution, --period, --adjust, --count options
- Supports json/table/csv output formats
- Auto-loads K-line data via get_mac_client()
- Registered backtest command in src/easy_tdx/cli/__init__.py
- Added tests/unit/test_backtest_cli.py with basic CLI tests

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:15:37 +08:00
GitHubandClaude Opus 4.8 706f22ba5e feat(backtest): add DSL strategy skeleton and update __init__.py exports
- Add dsl_strategy decorator in dsl.py (P1 skeleton implementation)
- Update __init__.py to export BacktestEngine, Strategy, and related types
- All 106 backtest unit tests pass

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:12:38 +08:00
GitHubandClaude Opus 4.8 371915a5f9 feat(backtest): add BacktestEngine with vectorized execution pipeline
- Implement BacktestEngine orchestrator with 4-step pipeline:
  1. Signal generation (Strategy)
  2. Order simulation (OrderSimulator)
  3. Portfolio tracking (PortfolioTracker)
  4. Performance analysis (PerformanceAnalyzer)
- Support both strategy class and instance initialization
- Add PnL calculation for sell trades
- Add JSON serialization with numpy/timestamp support
- Include comprehensive test coverage (12 tests, all passing)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:11:20 +08:00
GitHubandClaude Opus 4.8 94fabccef8 feat(backtest): add PerformanceAnalyzer with 19 metrics
- Implement PerformanceAnalyzer class with compute() method
- Calculate 19 performance metrics: total_return, annual_return, max_drawdown,
  max_dd_duration, sharpe, sortino, calmar, trade statistics, and volatility
- Handle edge cases: empty data, no negative returns (sortino=999), no drawdown (calmar=999)
- Add 20 comprehensive unit tests covering all metrics
- Type annotations use NDArray pattern for mypy strict compliance
- All tests pass, mypy and ruff checks clean

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:05:33 +08:00
GitHubandClaude Opus 4.8 a2aa319803 feat(backtest): add PortfolioTracker with equity curve and drawdown
- Pre-allocate numpy arrays for performance (cash, position, avg_price)
- apply_trades() processes buys/sells with commission and slippage
- equity_curve returns DataFrame with drawdown calculation
- positions returns DataFrame with market value and unrealized PnL
- 12 unit tests covering all scenarios

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:55:24 +08:00
GitHubandClaude Opus 4.8 16dc2e7da9 feat(backtest): add OrderSimulator with 5 execution modes and reject policy
- Implement OrderSimulator class for order matching simulation
- Support 5 execution modes: next_open, next_close, this_close, worst, best
- Support 3 position modes: full, fixed, percent
- Support 2 reject policies: reduce (partial fill), skip (reject)
- Implement fee model: commission (min 5 CNY), stamp tax (0.1% sell only), slippage
- Add future_leak_warning flag for this_close mode
- Handle both int and datetime column types in DataFrame
- Add comprehensive test suite with 24 test cases covering all modes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:52:31 +08:00
GitHubandClaude Opus 4.8 687851fc67 feat(backtest): add Strategy base class with DataProxy and crossover
- Add _SeriesAccessor for relative indexed data access ([0] current, [-1] previous)
- Add StrategyDataProxy for efficient DataFrame column access via numpy arrays
- Add crossover() function for golden cross detection (fast line crosses above slow line)
- Add Strategy abstract base class with:
  - init() for indicator registration via self.I()
  - next() for signal generation via buy()/sell()
  - Internal engine hooks (_bind_data, _call_init, _set_bar_index, etc.)
- All code is mypy strict compliant with full type annotations
- 25 unit tests covering all components

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:53:57 +08:00
GitHubandClaude Opus 4.8 f37b75ea42 feat(backtest): add core data types (Signal/Trade/Position/BacktestResult)
- Add Signal dataclass for trading signals with optional price/stop_loss/take_profit
- Add Trade dataclass for executed trades with commission/slippage/pnl/rejected
- Add Position dataclass for position snapshots (long/short/flat)
- Add BacktestResult dataclass with to_dict()/to_json()/summary() methods
- Add comprehensive unit tests (13 test cases, 100% pass)
- All code passes mypy strict, ruff lint+format checks

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:43:44 +08:00
GitHubandClaude Opus 4.8 5f14c44791 docs: add backtest engine implementation plan
10 tasks, TDD approach, covering:
- Core data types (Signal/Trade/Position/BacktestResult)
- Strategy base class with DataProxy and crossover
- OrderSimulator (5 execution modes + reject policy)
- PortfolioTracker (equity curve + drawdown)
- PerformanceAnalyzer (18 metrics)
- BacktestEngine (vectorized execution pipeline)
- DSL skeleton (P1)
- CLI integration with auto data fetch

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:25:11 +08:00
GitHubandClaude Opus 4.8 28925063d4 docs: finalize backtest spec with minor clarifications (rev 2.1)
- DSL identifier rules: letters/digits/underscores
- reduce mode: min(requested, max_affordable) formula
- Chanlun time alignment: nearest K-line <= timestamp
- GridResult/run_many return types documented

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:17:02 +08:00
GitHubandClaude Opus 4.8 480e635dcb docs: revise backtest spec per feasibility review (rev 2)
- DSL requires explicit column references (close/open/high/low)
- Add order_reject_policy: reduce | skip
- Add future_leak_warning for this_close execution
- Add benchmark datetime alignment rules
- Support pre-computed indicator columns via StrategyDataProxy
- Add chanlun_result injection (P0 interface, v2 auto-integration)
- Adjust priorities: DSL→P1, run_many/run_grid→P1, chanlun→P1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:14:05 +08:00
GitHubandClaude Opus 4.8 8d68e9c094 docs: add backtest engine design spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:05:17 +08:00
Justin Gu 626d0aae44 docs: remove unused badges (readthedocs, black, isort) 2026-06-08 03:44:46 +08:00
Justin Gu 9d906c340c docs: add Sphinx + Read the Docs infrastructure
- Add .readthedocs.yaml build config (Ubuntu 22.04, Python 3.11)
- Add docs/conf.py with myst-parser for Markdown support
- Add docs/index.md toctree including README and existing docs
- Add docs/readme.md to include root README via myst directive
- Add docs/requirements.txt for Sphinx build dependencies
- Add docs/_build/ to .gitignore
2026-06-08 03:36:40 +08:00
Justin Gu 6f7f5bac16 docs: update README 2026-06-08 03:28:58 +08:00
Justin Gu 79670b7777 docs: rewrite README intro to reflect project mission and values 2026-06-08 03:26:47 +08:00
Justin Gu 112ba7849f fix: chanlun bi algorithm stuck in fractal trap during sustained trends
Fix find_bis() greedy algorithm terminating early when dense alternating
fractals cause gap=0 for every opposite-type fractal. The root cause was
blindly replacing start_fx with more extreme same-type fractals, pushing
right_kline_index forward and making subsequent gaps permanently 0.

Solution: add pending_opposite guard — when an opposite-type fractal fails
the gap check, freeze start_fx replacement until a valid bi is formed.

- Affects: sustained up/down trends with dense fractals (e.g. high-price stocks)
- 600519: 114 bi (ending 04-28) -> 142 bi (ending 05-27)
- 601088: 131 bi -> 147 bi (end date unchanged)
- New regression test: test_fractal_trap_regression
- Bump version to 1.7.1
2026-06-08 03:08:12 +08:00
Justin Gu 0175acec43 docs: rewrite README intro to reflect project mission and values 2026-06-07 23:41:21 +08:00
Justin Gu fd4a1233b4 feat: add chanlun (ChanLun) technical analysis module, bump to v1.7.0
- New chanlun/ subpackage: K-line merge, fractal, bi/xianduan/zhongshu/mmd/beichi
- New 'easy-tdx chanlun' CLI command with JSON/table output
- MACD calculation (pure numpy, no extra dependencies)
- Multi-level analysis (MultiLevelAnalyser)
- Pipeline: DataFrame -> merge -> fractal -> bi -> zhongshu -> xd -> mmd -> beichi
- 49 offline unit tests covering all calculation steps
- Detailed README docs with output explanation
- Bump version: pyproject.toml 1.6.1 -> 1.7.0, cli 1.5.0 -> 1.7.0
2026-06-07 23:29:52 +08:00
Justin Gu 4cab9aa325 fix: route index files to get_index_bars() in sync-daily/sync-all
Root cause: _fetch_all_daily_bars used get_security_bars() for all files,
but index server responses have 4 extra bytes per record. Wrong parser
produced garbage dates like '12897-50-77' for sh000001, sh000300, etc.

Fix: add _is_index_code() to detect index codes by prefix (sh: 00/88/99,
sz: 39) and route to get_index_bars() accordingly.

Bumps version to 1.6.1.
2026-06-07 21:55:26 +08:00
Justin Gu d01b11fa74 feat: add offline data write-back and sync commands, bump to v1.6.0
- Add write_daily.py: encode/append daily bars to .day files
- Add write_ex_daily.py: encode/append extended market daily bars
- Add write_min_bar.py: encode/append minute bars (.5/.lc1/.lc5)
- Add sync-daily CLI: sync single stock with pagination support
- Add sync-all CLI: one-command sync for all SH/SZ .day files
- Update README with sync commands and Python write API docs
- 50 new unit tests covering encode round-trip, append dedup, edge cases
- Bump version 1.5.0 -> 1.6.0
2026-06-07 21:13:49 +08:00
Justin Gu b17e98468b feat: add offline CLI commands and bump version to v1.5.0
- New 'offline' command group with 8 subcommands: home, daily, min,
  ex-files, ex-daily, gbbq, financial, blocks
- No network required, reads local TDX data files directly
- Updated CLI examples and README with offline documentation
- Added v1.5.0 changelog entry
2026-06-02 12:30:24 +08:00
Justin Gu 07c1eca5e8 docs: add V4.0 version note for ZHUOYAO/BIAS_SIGNAL in MyTT.py 2026-06-02 12:06:55 +08:00
Justin Gu 903898512a Merge branch 'main' of https://github.com/handsomejustin/easy_tdx 2026-06-02 12:01:00 +08:00
GitHubandClaude Opus 4.7 2eabbb219a chore: bump version to 1.4.3
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 22:31:31 +08:00
GitHubandClaude Opus 4.7 4c5817f7b0 feat: add BIAS_SIGNAL indicator (30-day bias with signal lines)
Add BIAS_SIGNAL indicator derived from TongDaXin's 30-day bias formula.
Outputs BS_X (raw bias), BS_SMA (short signal line), BS_LMA (long signal
line) for trend direction and reversal detection via asymmetric bull/bear
logic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 22:31:17 +08:00
GitHubandClaude Opus 4.7 7572b16614 chore: bump version to 1.4.2
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 18:07:48 +08:00
GitHubandClaude Opus 4.7 3410b922ad fix: include ZHUOYAO function in MyTT.py (missing from 1.4.1 release)
The 1.4.1 commit added the indicator registry entry in indicator.py but
forgot to include the actual ZHUOYAO() function definition in MyTT.py.
Also includes lint cleanups (trailing semicolons, import formatting).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 18:07:31 +08:00
GitHubandClaude Opus 4.7 6b06f9eb40 feat: add ZHUOYAO indicator (multi-period momentum resonance), bump to 1.4.1
Add 捉妖大师 (ZHUOYAO) indicator to the indicator registry. Outputs
ZY_LONG/ZY_MID/ZY_SHORT/ZY_TREND four lines based on 20/60/120-day
ROC with EMA smoothing for trend resonance detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:49:30 +08:00
GitHubandClaude Opus 4.7 bcddf5a052 feat: add technical indicator calculation (30 indicators via MyTT), bump to 1.4.0
Integrate MyTT library to provide 30 technical indicators (MACD, KDJ, RSI,
BOLL, DMI, ATR, etc.) accessible via API and CLI with automatic EMA warm-up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:05:40 +08:00
Justin Gu 95e225d6d7 Merge branch 'main' of https://github.com/handsomejustin/easy_tdx 2026-05-27 00:39:19 +08:00
GitHubandClaude Opus 4.7 280af9ecf5 feat: add board-summary and board-ranking CLI commands, bump to 1.3.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 23:28:41 +08:00
Justin Gu 6959e66e14 Merge branch 'main' of https://github.com/handsomejustin/easy_tdx 2026-05-26 22:58:28 +08:00
GitHubandClaude Opus 4.7 c825515ee6 ci: disable sigstore attestations to fix 502 from rekor
Sigstore's rekor server returning intermittent 502 Bad Gateway,
blocking all publishes. Attestations are optional; disable until
the service stabilizes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 22:50:28 +08:00