Commit Graph
52 Commits
Author SHA1 Message Date
Justin Gu 54dd65ed85 feat(web): add Web API docs to README, bump version to 1.10.0 2026-06-12 03:10:01 +08:00
Justin Gu eb8a7a5675 feat(web): add FastAPI app factory, all routers, CLI serve command, and tests
- App factory with lifespan management and CORS middleware
- Market router: security list, quotes, market stat, fund-flow
- Bars router: kline, index kline, minute, transaction
- Finance router: xdxr, finance, company info, financial records
- Block router: block file parsing
- Chanlun router: POST /chanlun/analyze
- Realtime router: WebSocket /ws/realtime/{symbol}
- CLI: easy-tdx serve command
- 16 unit tests, all passing offline (no network)
2026-06-12 03:08:12 +08:00
Justin Gu 9dc70566a5 feat(web): add Pydantic schemas and error handling 2026-06-12 03:02:04 +08:00
Justin Gu 7f44ba1d06 feat(web): scaffold web API module with [web] optional dependency 2026-06-12 03:00:49 +08:00
Justin Gu 786c7e3619 fix: remove unused type: ignore comments for mypy strict 2026-06-11 04:30:39 +08:00
Justin Gu c25570eb86 fix: mypy strict — type annotate co_filename in _get_strategy_file 2026-06-11 04:27:54 +08:00
Justin Gu c9ed57e66d fix: parallel scan pickle bug — pass strategy file path instead of class to child processes 2026-06-11 04:24:09 +08:00
Justin Gu ddcb9d4425 release: v1.9.8 — CI fixes (ruff .pyi exclude + pytest-asyncio + lint) 2026-06-11 04:11:01 +08:00
Justin Gu bd373b9c3c fix: exclude .pyi from ruff + fix unused variable in test 2026-06-11 04:06:52 +08:00
Justin Gu 193d1b0d82 fix: add pytest-asyncio dependency for async realtime tests 2026-06-11 04:03:00 +08:00
Justin Gu 15cc7680c4 release: v1.9.7 — CLI全量集成(workers/cache/chanlun-level/portfolio/multi-level)+ bugfix 2026-06-11 03:57:48 +08:00
Justin Gu d2f4cb126e release: v1.9.6 — Devin AI 12项改进全量落地 2026-06-11 02:40:31 +08:00
Justin Gu 92edc189bb feat: realtime event-driven market data push framework
- Add EventBus for async publish/subscribe market events
- Add MarketEvent dataclass with tick/bar/signal/error types
- Add RealtimeStrategy base class with on_tick/on_bar callbacks
- Add emit_signal() for strategy-to-engine signal publishing
- Support per-symbol and global subscriptions
- API skeleton: transport-level subscription TBD
- Add 10 tests covering events, bus, and strategy
2026-06-11 02:34:00 +08:00
Justin Gu 9c39ad054d feat: multi-stock portfolio backtest engine
- Add PortfolioBacktestEngine for shared-capital multi-stock backtesting
- Support equal allocation mode (total_cash / N per stock)
- Individual BacktestEngine per stock with allocated capital
- Aggregate performance via capital-weighted returns
- Add StockData, PortfolioResult data classes
- Add 4 tests: basic run, equal allocation, empty stocks, serialization
2026-06-11 02:31:43 +08:00
Justin Gu fa5bd2d44d feat: add MyTT.pyi type stubs, enable strict mypy
- Create type stub file for 50+ MyTT indicator functions
- Covers all 31 functions used in the project + common utilities
- Remove mypy disallow_untyped_defs/calls override for MyTT
- MyTT now covered by strict mypy via .pyi stubs
2026-06-11 02:29:47 +08:00
Justin Gu f4dc28c5d2 feat: add append_klines for incremental chanlun analysis
- Store previous DataFrame in ChanlunAnalyser after process_klines
- Add append_klines(df_new) to concatenate and recompute
- Handles datetime deduplication automatically
- Raises RuntimeError if called before initial process_klines
- Add 2 tests: append + recompute, error without init
2026-06-11 02:25:42 +08:00
Justin Gu 6d74c2e5eb feat: enhance multi-level chanlun analysis with trend/overlap/divergence
- Add trend_direction detection (up/down/None) via consecutive bi analysis
- Add bi_overlap detection for consolidation identification
- Add divergence_possible check (2+ ZS + diminishing amplitude)
- Return type changed from dict[str, int] to dict[str, Any]
- Backward compatible: all original fields preserved
- Extract 3 helper functions for clean separation of concerns
2026-06-11 02:22:31 +08:00
Justin Gu ec8d21b7e2 feat: incremental scanning with mtime-based cache
- Add cache_file param to SignalScanner for persistent scan cache
- Cache stores {filepath: {mtime, result}} as JSON
- On rescan, skip files with unchanged mtime (reuse cached results)
- Files with changed mtime are rescanned and cache updated
- Add 3 tests: cache reuse, no-cache full scan, cache invalidation
2026-06-11 02:17:52 +08:00
Justin Gu b7e0f17842 feat: concurrent scanning with ProcessPoolExecutor
- Add workers param to SignalScanner.scan() (default=0 for serial)
- workers=2+ uses ProcessPoolExecutor for parallel .day file processing
- Extract _scan_one_file as top-level function for pickle compatibility
- Results identical between serial and parallel modes
- Add 4 tests with synthetic .day file fixtures
2026-06-11 02:09:10 +08:00
Justin Gu af005d9fe4 feat: auto-bridge chanlun analysis into backtest strategies
- Add chanlun_level param to BacktestEngine constructor
- When set, auto-create ChanlunAnalyser and compute ChanlunResult
- Manual chanlun_result in run() takes priority over auto-compute
- Update Strategy.chanlun type to Any (accepts ChanlunResult or dict)
- Add 2 tests: auto-bridge and manual override priority
2026-06-11 01:56:59 +08:00
Justin Gu 815b3ddf7c feat: implement stop-loss/take-profit execution in backtest engine
- Track SL/TP conditions from BUY signals in _generate_signals loop
- Check active conditions against each bar's high/low price range
- Auto-generate SELL signal at trigger price when condition is met
- Modify OrderSimulator to respect signal.price for direct execution
  (previously signal.price was stored but never used in execution)
- SL/TP activates on bar AFTER BUY signal (consistent with next_open)
- Stop-loss checked before take-profit (conservative for holder)
- Add 4 tests: SL trigger, TP trigger, no-trigger, priority over manual sell
2026-06-11 01:53:11 +08:00
Justin Gu 06b2617ebc fix: CI coverage enforcement, real avg_holding_days, vectorize _datetime_to_int
- Add --cov and --cov-fail-under=50 to CI pytest command
- Replace hardcoded avg_holding_days=5.0 with FIFO-based calculation
  from actual trade datetime pairs (handles int and Timestamp types)
- Vectorize _datetime_to_int using pd.to_datetime().strftime()
  instead of Python for-loop (~100-200x faster on large arrays)
- Add 3 new test cases: weighted holding days, no datetime fallback,
  only-buys edge case
2026-06-11 01:44:39 +08:00
Justin Gu 5aac7d3a39 chore: add risk disclaimer, CI pipeline, pytest coverage config
- Add risk warning after backtest demo output (survivorship bias, overfitting)
- Add disclaimer section at README end
- Add slippage comment to backtest demo command
- Add CI workflow (test + lint + mypy) for PR/push to main
- Add pytest config with coverage threshold (fail_under=50, current=56%)
2026-06-10 12:43:02 +08:00
Justin Gu 21f71d3701 chore: ignore .omc, .claude, .playwright-mcp directories and remove from tracking 2026-06-10 11:54:08 +08:00
Justin Gu c867297d45 fix: remove hardcoded version in 'version' command (v1.9.4) 2026-06-10 03:40:28 +08:00
Justin Gu 531d0c05bc fix: remove hardcoded version in 'version' command, read from importlib.metadata 2026-06-10 03:39:09 +08:00
Justin Gu 862f713483 feat: add 'run-all' CLI command for batch strategy backtesting (v1.9.3) 2026-06-10 03:24:31 +08:00
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
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
Justin Gu 95e225d6d7 Merge branch 'main' of https://github.com/handsomejustin/easy_tdx 2026-05-27 00:39:19 +08:00
Justin Gu 6959e66e14 Merge branch 'main' of https://github.com/handsomejustin/easy_tdx 2026-05-26 22:58:28 +08:00
Justin Gu 462779b47d Merge branch 'main' of https://github.com/handsomejustin/easy_tdx
# Conflicts:
#	README.md
#	examples/01_connection/async_connect.py
#	examples/02_market_info/market_stat.py
#	examples/02_market_info/security_list.py
#	examples/02_market_info/security_list_all.py
#	examples/02_market_info/security_quotes.py
#	examples/03_kline/index_bars.py
#	examples/03_kline/security_bars.py
#	examples/04_minute/history_minute_data.py
#	examples/04_minute/minute_time_data.py
#	examples/05_transaction/history_transaction.py
#	examples/05_transaction/transaction_data.py
#	examples/06_finance/company_info.py
#	examples/06_finance/finance_info.py
#	examples/06_finance/price_limits.py
#	examples/06_finance/xdxr_info.py
#	examples/07_block/block_info.py
#	examples/08_fund_flow/fund_flow.py
#	examples/08_fund_flow/history_fund_flow.py
#	examples/09_file_download/report_file.py
#	pyproject.toml
#	src/easy_tdx/client.py
2026-05-23 00:30:56 +08:00
Justin Gu d7547f7c4c docs: update README to reflect merged datetime fields in DataFrame output 2026-05-22 04:22:27 +08:00
Justin Gu f693cbe218 docs: update README to reflect merged datetime fields in DataFrame output 2026-05-22 04:22:27 +08:00
Justin Gu 02701952ca feat: merge datetime fields in DataFrame output, hide MinuteBar internal fields
- K-line: daily+ periods output 'date' only, minute periods output 'datetime'
- Transactions (tick-by-tick): combine date param + hour/minute into 'datetime'
- XdxrRecord, HistoricalFundFlow: year/month/day merged to 'date'
- MinuteBar: rename unknown_1 to _unknown_1 (hidden from DataFrame)
- MinuteBar: add datetime column computed from bar index (A-share 240-bar pattern)
- get_minute_time_data: use history endpoint only (current-day endpoint broken in pytdx too)
- Update all examples to reflect new DataFrame column names
2026-05-22 04:19:07 +08:00
Justin Gu 00825eb24a feat: merge datetime fields in DataFrame output, hide MinuteBar internal fields
- K-line: daily+ periods output 'date' only, minute periods output 'datetime'
- Transactions (tick-by-tick): combine date param + hour/minute into 'datetime'
- XdxrRecord, HistoricalFundFlow: year/month/day merged to 'date'
- MinuteBar: rename unknown_1 to _unknown_1 (hidden from DataFrame)
- MinuteBar: add datetime column computed from bar index (A-share 240-bar pattern)
- get_minute_time_data: use history endpoint only (current-day endpoint broken in pytdx too)
- Update all examples to reflect new DataFrame column names
2026-05-22 04:19:07 +08:00
Justin Gu ace1099ab0 chore: add CLAUDE.md and .claude config 2026-05-21 13:02:27 +08:00
Justin Gu 604f7cdf57 feat: expand KNOWN_HOSTS with 42 servers from TDX connect.cfg 2026-05-21 13:00:00 +08:00