Files
easy-tdx/CHANGELOG.md
T

546 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 更新日志
本文件记录 easy-tdx 的版本变更。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/)。
## [1.15.4] — 2026-06-29
### 修复
- **ETF / 指数 / 基金 / 可转债 / 国债实时行情价格被放大 10 倍**(`commands/security_quotes.py`[Issue #8](https://github.com/handsomejustin/easy_tdx/issues/8))— `get_security_quotes` 返回的 `price_raw` 及五档差分字段统一以「厘」(0.001 元) 为基本单位编码,但**报价精度按品种而异**:股票 2 位(分),ETF / 指数 / 基金 / 可转债 / 国债 / 国债逆回购 3 位(厘)。此前一律按 `/ 100.0`2 位)解析,导致 ETF 等本应 `/ 1000.0`(3 位)的品种价格被放大 10 倍(如现价 6.123 元的 ETF 错误显示成 61.23)。
- 新增 `_price_decimal_digits(market, code)`,凭 `market + code` 代码段推断有效小数位:沪市 `5`ETF/基金)、`000`(指数)、`8`(行业指数)按 3 位;深市 `1`ETF/LOF/可转债/国债)按 3 位;其余股票按 2 位。
- 同一代码不同市场含义不同,必须结合市场判断:`SZ 000001` = 平安银行(股票,2 位),`SH 000001` = 上证指数(3 位),二者不可混淆。
- 价格字段(现价 / 昨收 / 今开 / 最高 / 最低 / 五档买卖价)除法从硬编码 `/100.0` 改为按 `divisor = 10 ** 位数` 动态除法;`rise_speed` 等非价格字段保持 `/100.0` 不变。
- `SecurityQuote` 新增 `decimal_point` 字段(默认 2,向后兼容),标注该条行情实际采用的小数位数,便于核对。
- `decimal_point` 不在行情响应包内,仅能凭代码段推断(pytdx 把这一步留给用户,本项目做自包含解析)。新增 4 个单元测试覆盖 ETF/股票/指数精度与品种分类,全量 680 单测通过,既有 `600000` fixture 断言不变(股票行为无回归)。
## [1.15.3] — 2026-06-27
### 变更
- **`company-info` 传板块名时自动读完整正文** — 此前传板块名仍需用户关心 `--offset`/`--length`,体验笨拙。现在传板块名时自动按目录里的 `length` 分块循环读取整个板块(单次上限 30720 字节,大板块如「公司大事」77 万字节也能一次读全),`--offset`/`--length` 仅在传文件名时生效。
- 用户只需:`easy-tdx company-info SH 601088 "公司概况"` 即可读到该板块完整内容,无需任何 offset/length。
- 修复分块 offset 推进 bug:原按解码后字符串 GBK 重编码计字节数,遇到 GBK 无法解码的字符(U+FFFD)会抛 `UnicodeEncodeError`;改为按请求字节数推进(服务器按字节偏移工作)。
### 修复
- **多服务器 F10 目录版本不一致**(`cmd_company.py`)— 通达信不同服务器返回的 F10 目录板块名版本不一致(新版含「公司大事/研究报告/...」,旧版含「机构持股/分红融资/...」)。传板块名时若当前服务器未命中,现自动重试多个服务器(新建连接,最多 4 次)直至命中,避免「列目录能看到、读正文却找不到」的割裂。
## [1.15.2] — 2026-06-27
### 变更
- **`company-info` 命令合并** — 把 `company-info`(列目录)与 `company-info-content`(读正文)合并为一个命令,消除「列目录」和「读正文」两个相似命令名的混淆:
- 无板块名参数 → 列 F10 板块目录(原 `company-info`
- 有板块名参数 → 读板块正文(原 `company-info-content`
- `company-info-content` 保留为**隐藏别名**`hidden=True`),向后兼容 v1.15.1 脚本,不出现在 `--help`
- 示例:`easy-tdx company-info SH 600519 "公司概况"` 现在直接读正文(无需记忆用哪个命令)。
### 新增
- **examples/06_finance 文档完善** — 补全财务快照与 F10 公司信息的三种调用方式 demo:
- 新增 `README.md`:命令关系图、16 个 F10 板块完整列表、字段说明、三方式快速开始。
- 新增 `company_cli.sh`CLI 命令 demofinance-info / company-info 全用法、输出格式切换、错误处理)。
- 新增 `company_web_api.py`Web API 调用 demo`/finance` `/company/category` `/company/content`)。
- 更新 `company_info.py` 板块名列表为实测的 16 板块(分红扩股/高层治理/龙虎榜单等)。
## [1.15.1] — 2026-06-27
### 新增
- **通达信原生 F10 与财务快照 CLI 命令** — 把 `TdxClient` 上已封装但未暴露给 CLI 的三个方法做成命令,数据源与 Web 层 `/finance` `/company/*` 端点同源,覆盖 `f10`(新浪三表)之外的 F10 全文板块。
- 新增 `easy-tdx finance-info` — 最新财务快照(37 字段:股本结构、资产负债、利润、现金流、每股指标),与 `f10`(多期三表)互补。
- 新增 `easy-tdx company-info` — F10 板块目录,列出最新提示/公司概况/财务分析/股东研究/股本结构/资本运作/业内点评/行业分析/公司大事/研究报告/经营分析/主力追踪/分红扩股/高层治理/龙虎榜单/关联个股等板块及其文件偏移。
- 新增 `easy-tdx company-info-content` — 读取 F10 板块正文,`name_or_filename` 既可传板块名(自动定位到该板块起点读取),也可直接传文件名;`--offset` 语义随入参而定(板块名=板块内相对偏移,文件名=文件绝对偏移),`--length` 控制读取范围。
- 新增 `get_tdx_client()` 上下文管理器(`cli/conn.py`),仿 `get_mac_client()` 包装 `TdxClient.from_best_host()`
## [1.15.0] — 2026-06-25
### 新增
- **强势股排名(strength** — 全市场按 5/20/60 日涨幅加权合成强势分,选出"最近最强"的股票。
- 新增核心引擎 `easy_tdx.screen.strength.StrengthRanker`,纯离线读取本地 `.day` 文件,复用 `SignalScanner` 的并发/进度回调架构。
- 新增 CLI 子命令 `easy-tdx screen strength`,支持表格 / JSON 输出。
- 新增 Web API 端点 `GET /api/v1/market/strength`,通过线程池执行避免阻塞事件循环。
- **三种预设模式**
- `steady`(默认):中长期稳健,60 日权重主导 + 波动率惩罚,选出"稳着涨"的票。
- `breakout`:近期妖股爆发,5 日权重主导,纯加权涨幅(不除波动率),选出短期最猛的票。
- `balanced`:三周期均衡 + 波动率调整。
- 支持自定义权重(自动归一化)、成交额过滤、上市天数过滤、并发扫描。
- 输出含 `data_date` / `last_date` 字段,标注数据截止日,便于判断时效。
- 示例代码见 `examples/23_screen_strength/`
### 修复
- **`_detect_security_type` 代码段判定不全**`offline/daily_bar.py`)—— 上交所科创板 ETF588/589)、LOF560-563)、货币 ETF551)、普通 ETF(520-530)等代码段,以及深交所封闭式基金/LOF(17/18 开头)、国债逆回购(204 开头)被默认返回值误判为深市 A 股,导致 `screen strength` / `screen scan` 把基金和 ETF 混入股票排名。修复后补全所有已知代码段,默认返回 `UNKNOWN`(不再误判成 A 股)。
- **`screen strength` / `screen rank` 名称补齐分批 bug**`screen/cli.py``screen/ranker.py`)—— `MacClient.get_stock_quotes` 单次最多 80 只,传入超过 80 只时末尾名称被服务器静默丢弃。修复后改为 80 只/批分页查询。
### 变更
- `easy_tdx.screen.__init__` 导出 `StrengthRanker``StrengthResult``STRENGTH_PRESETS`
- README 增加「强势股排名(strength)」章节及 Web API 调用示例。
## [1.14.5] (2026-06-17)
**缠论可视化日期自适应时分** — 响应网友反馈,分钟级别(1/5/15/30/60min)的缠论结果日期字段现在输出完整时分 `YYYY-MM-DD HH:MM`,日/周/月/年级别仍只输出日期 `YYYY-MM-DD`(无多余 `00:00`)。
新增 `ChanlunResult._fmt_dt()``frequency` 自适应格式化,统一作用于 `bis` / `zss` / `mmds` / `bcs` / `xds` 所有日期字段。兼容 CLI 原始值(`5MIN`/`30MIN`)与 Web 映射值(`5min`/`30min`)的大小写。三层接入同步生效。
## [1.14.4] (2026-06-16)
**CI 修复** — 修复 v1.14.3 中 `cmd_chanlun.py` 两处 `click.echo(...)` 未按 `ruff format` 行宽规则合并导致的 CI 格式检查失败(纯格式调整,无功能变化)。
## [1.14.3] (2026-06-16)
**缠论 CLI table 模式补日期** — 延续 v1.14.2 的可视化增强,在 `easy-tdx chanlun --table` 表格输出中也为中枢 / 买卖点 / 背驰带上对应日期,与 `笔` / `线段` 的风格对齐。日期缺失时显示 `—`
- **中枢**`[idx] <start_date> → <end_date> zg=... zd=...`
- **买卖点**`<type> (<date>): <msg>`
- **背驰**`[✓/✗] <type> (<prev_date> → <curr_date>): <msg>`
## [1.14.2] (2026-06-16)
**缠论结果可视化字段增强** — 响应 [Discussion #2](https://github.com/handsomejustin/easy-tdx/discussions/2),为缠论分析 JSON 输出(`ChanlunResult.to_dict()`)中的中枢 / 买卖点 / 背驰补上对应 K 线日期,方便前端/可视化工具直接用来标点画图。纯增量、向后兼容,不破坏任何已有 JSON 字段。
新增字段:
- **中枢 `zss`**:输出起始笔与结束笔的日期 `start_date` / `end_date`(第一笔起点 → 最后一笔终点)。
- **买卖点 `mmds`**:输出触发该买卖点的笔确认日期 `date`(买卖点确立时刻的 K 线日期)。
- **背驰 `bcs`**:输出背驰对照两笔的日期 `curr_date`(当前背驰笔)/ `prev_date`(对照基准笔)。
日期统一采用 `YYYY-MM-DD` 格式(与已有 `bis` / `xds` 输出一致),全部字段对 `None` 做了兜底。三层接入(Python API / CLI `easy-tdx chanlun` / Web `/chanlun/analyze`)同步生效,Web 接口直接返回新字段无需改动。
## [1.14.1] (2026-06-15)
**高级回测 ExecutionModel 路径 3 个真实数据兼容 Bug 修复** — 实测 `601088` 高级回测(方根滑点 + TWAP)暴露:权益曲线恒定、收益归零。根因为 ExecutionModel 路径与真实行情数据的格式/列名/类型脱节。
Bug 修复:
- **datetime 类型分歧(致命)**`ExecutionModel``Trade.datetime` 转成 `int(YYYYMMDD)`,而 `PortfolioTracker` 用 df 原始 `Timestamp` 作为 `trade_map` 字典 key,导致 TWAP/VWAP/Limit 路径的交易**全部静默丢失**、权益曲线恒定、收益恒为 0%。修复:`Trade.datetime` 改用 df 原始值,与 `OrderSimulator` 一致。
- **volume 列名分歧**`execution.py`/`orders.py` 仅认 `"volume"` 列,但真实行情(`get_security_bars`)列为 `"vol"`,导致滑点模型 volume 恒为 0、`SquareRootSlippage` 退化百分比模式、VWAP 退化为等权。修复:兼容 `vol`/`volume` 列名。
- **date/datetime 列名分歧**:日线 `get_security_bars` 返回 `date` 列,但 `BacktestEngine` 硬性要求 `datetime` 列,按文档直接跑日线回测会 `ValueError`。修复:`BacktestEngine.run` 入口缺 `datetime` 时由 `date` 派生,下游无感兼容。
为何此前未发现:`test_engine_with_twap` 仅断言「生成了交易」,未断言「交易实际影响了组合」;execution 单测用 int datetime 掩盖了类型分歧。本次新增 3 个回归测试编码「权益曲线随交易变化」「vol 列可读」「date 列可跑」契约,均经红灯验证(修复前精确失败)。
验证:全部 650 单测通过,backtest 模块 ruff + mypy strict 清洁,`examples/22_backtest_advanced/backtest_601088_advanced.py` 实测权益曲线不再恒定、高级档收益从假的 0% 修正为真实的 -3.57%。
## [1.14.0] (2026-06-15)
**新增新浪财报三表** — 三层接入(编程 API / CLI / Web API),独立数据源,无需连接 TDX 行情服务器。
- 新模块 `easy_tdx.sina``SinaClient().get_financial_report(code, report_type=, num=)` 返回 `DataFrame`(每行一期,列为科目名 + `{科目}_同比`
- 三表:`lrb`(利润表)/ `fzb`(资产负债表)/ `llb`(现金流量表),report_type 支持中英文别名
- CLI`easy-tdx f10 600519 [--type lrb|fzb|llb] [--num N]`(接管原 f10 占位符)
- Web`GET /api/v1/sina/financial-report?code=&type=&num=`
- 标准库 urllib 实现,零新依赖
- 修复参考脚本 bug`item_value` 字符串转 float(原 object 列无法数值计算)
- 大类标题行(如「流动资产」)保留为 None,完整反映报表结构
- `SinaError` 继承 `TdxError`,保证全局 `except TdxError` 覆盖
测试:`tests/unit/test_sina.py` 27 个离线用例(mock HTTP,零网络),覆盖三表解析、数值转换、报告期格式化、同比键、paperCode 推导、错误转换。
## [1.13.1] (2026-06-15)
**cninfo 公告检索 Bug 修复 + PDF 下载**(实测 `easy-tdx announcement 601088` 暴露的 3 个 Bug + 新增 PDF 下载功能)。
Bug 修复:
- `url` 404:原仅拼 `announcementId` 一个参数,补全 4 参数 `stockCode`/`announcementId`/`orgId`/`announcementTime`(少任一参数 404
- `type` 列全 null:cninfo 对很多公告不填 `announcementTypeName`,回退到 `adjunctType`(如 "PDF"
- 表格输出 `url` 被截断成 `https://www.cninfo.com.cn/new/``output._render_table` 对 object 列硬切 30 字符;新增 `_render_table_full``announcement --table` 专用不截断
新增功能 — PDF 下载:
- `CninfoClient.download_pdf(announcement, dest_dir=, filename=)`:接受 `Announcement` 或 DataFrame 一行,自动建目录,默认文件名 `{YYYYMMDD}_{announcement_id}.PDF`
- CLI`--download N --download-dir DIR` 批量下载最新 N 条 PDF
- `Announcement` dataclass 扩展字段:`code`/`org_id`/`announcement_id`/`announcement_time`/`pdf_url``pdf_url``static.cninfo.com.cn` 直链)
测试:`tests/unit/test_cninfo.py` 24 → 35 个用例,新增 URL 4 参数、type 回退、pdf_url 构建、`download_pdf`(成功/无附件/建目录/Series 兼容/网络失败/自定义文件名)共 11 个场景。全部 621 单测通过,mypy strict + ruff 清洁。
## [1.13.0] (2026-06-14)
**新增巨潮公告检索** — 三层接入(编程 API / CLI / Web API),独立数据源,无需连接 TDX 行情服务器。
- 新模块 `easy_tdx.cninfo``CninfoClient().get_announcements(code, count=, page=)` 返回 `DataFrame[title, type, date, url]`
- CLI`easy-tdx announcement 688017 [--count N --page N --table]`
- Web`GET /api/v1/announcements?code=&count=&page=`
- 标准库 urllib 实现,零新依赖
- 沿用 #19 修复的 orgId 动态映射 + 三段硬编码 fallback(保证 601xxx 段可查)
## [1.12.0] (2026-06-14)
**新增 4 个技术指标(30 → 34)** — 按"语义空白"补齐三类现有指标库缺失的维度:止损位、机构成本价、趋势启动时机。均为纯 numpy 实现,零新依赖。
**新增指标**
- **SAR 抛物线转向**`high, low``SAR`):基于 Wilder 加速因子的动态止损位,填补 32 个指标里"止损位"语义的空白。可直接喂给 `BacktestEngine` 做动态 `stop_loss`。实现含反转检测、AF 加速/封顶、SAR 不穿越前两根 K 线极值的限制。
- **VWAP 成交量加权均价**`close, high, low, vol``VWAP`):N 日滚动机构基准成本价,填补"机构成本"维度空白。用典型价格 `(H+L+C)/3` 加权,含除零保护(零成交量返回 nan)。
- **AROON 阿隆指标**`high, low``AROON_UP, AROON_DOWN, AROON_OSC`):用"N 周期内新高/新低距今多少根"识别趋势启动时机,与现有 DMI(判断趋势强度但滞后)互补而非冗余。
- **FK 趋势指标**`close``FK`):清理孤儿函数——`MyTT.FK` 此前已实现但未在 `indicator.py` 注册,用户通过 CLI/API 无法调用。现正式注册暴露。语义为 EMA(2) 是否突破斜率外推 EMA(42),本质是动量偏离检测。
**架构**:所有新指标沿用现有 `IndicatorSpec` 注册模式,`compute_indicators()` / `get_stock_kline_with_indicators()` / CLI `easy-tdx indicator` 自动可用,无需改动调度层。
**除零与边界保护**
- SAR:一字板/停牌(高低价相同)不崩溃、不产生 inf;空输入返回空数组
- VWAP:零成交量返回 nan(不产生 inf);前 N-1 根为 nanrolling 窗口)
- AROON:输出严格落在 [0, 100] 区间
**类型存根**`MyTT.pyi` 同步补充 SAR/VWAP/AROON/FK 四个函数签名,mypy strict 零错误。
**测试**:新增 `tests/unit/test_mytt.py`,22 个用例覆盖三个新指标 + FK 的数值正确性、单边行情行为、除零/空输入边界。注册层端到端覆盖复用 `test_indicator.py::test_all_registered_indicators_run`
## [1.11.6] (2026-06-13)
**CI 类型与格式修复** — 修复 CI 流水线 mypy strict13 errors)和 ruff format8 files)失败,全部为类型标注与存根问题,无运行时行为变更。
**mypy strict 修复(13 errors → 0**
- `portfolio/optimizer.py``register_optimizer` 装饰器返回类型从 `type[WeightOptimizer]` 改为 `Callable[[type[WeightOptimizer]], type[WeightOptimizer]]`,消除 4 个子类 "Too many arguments" 误报
- `factor/engine.py``_datetime_to_int``isinstance` 收窄替代 `object → int` 强转,消除 call-overload + no-any-return
- `backtest/orders.py` / `execution.py`:年化波动率 `np.sqrt()` 表达式用 `float()` 包裹,消除 no-any-return
- `factor/builtin/technical.py``MyTT.pyi``MACD` 存根删除错误的 `LOW/HIGH` 参数,与 `MyTT.py` 实际签名 `MACD(CLOSE, SHORT, LONG, M)` 对齐
- `pyproject.toml`:新增 scipy mypy override`ignore_missing_imports`),统一处理可选依赖的 stubs 缺失,移除冗余 inline `type: ignore`
**ruff format**8 个 test 文件统一格式化。
**测试**564 passed, 0 failedmypy 192 文件零错误;ruff check/format 全绿。
## [1.11.5] (2026-06-13)
**稳定性与代码质量修复** — 全项目代码审计 + 一个潜伏的 ping 崩溃 bug 修复。
**Bug 修复**
- 修复 `easy-tdx ping` 在非交易时间(服务器握手阶段关闭连接)整个命令崩溃的问题。根因:`ping_host` 仅捕获 `OSError`,但握手期 `_recv_exact_sock` 抛出的 `TdxConnectionError`(继承自 `TdxError(Exception)` 而非 `OSError`)逃出捕获,经 `ping_all``fut.result()` 重新抛出,导致单台服务器不可用就拖垮整条测速命令。修复后符合 docstring 承诺"不可达服务器不包含在结果中",并加防御层让 `ping_all` 对异常 future 容错跳过。
- 修复回测 `OrderSimulator._find_bar_index` 把 DataFrame 的 index label 当位置索引用的隐患。当传入 df 的 index 非默认 RangeIndex 时,`idxmax()` 返回的 label 与 `iloc[]` 期望的位置不一致,可能导致撮合取错 K 线。改用 `to_numpy().argmax()` 取真实位置。
**依赖与工程化**
- scipy 隐式硬依赖声明:`factor/analysis.py` 的 Rank ICspearman)通过 pandas lazy import scipy,干净环境必报 `ModuleNotFoundError`。新增 `science` 可选依赖组(`pip install easy-tdx[science]`),并在 spearman 分支加 try-import 友好报错(复用 `optimizer.py` 现有模式)。
- `mac/client.py` 板块 N 日涨跌幅排行中静默吞异常的 `except Exception: continue` 补上 `logger.debug` 日志,便于排查。
- `.gitignore` 补全 `.coverage``signals.json`
**文档**
- `CLAUDE.md` 架构章节更新:补全 `mac/``ex/``unified.py``portfolio/``factor/``offline/``screen/` 等子包,说明四套 clientWindows/macOS/扩展/macOS扩展)的 sync+async 镜像关系。
**测试**564 passed, 0 failed+8 新增:2 ping 容错回归、2 非连续 index 回归、4 既有覆盖增强)
## [1.11.1] (2026-06-12)
**量化因子引擎 + 组合管理 + 高级回测增强** — 三大新模块,补齐从因子研究到组合执行的完整量化链路。
**因子引擎(factor/**
- `Factor` ABC + 注册表模式(`@register_factor` 装饰器),19 个内置因子
- `FactorEngine`:单股多因子 / 截面批量 / 远期收益计算
- 因子类别:动量、波动率、质量、成交量、技术(桥接 MyTT)、缠论(桥接 ChanlunAnalyser)、价值(占位)
- 因子预处理管道:去极值(MAD)、标准化、排名归一化、填充缺失、正交化
- `FactorAnalyzer`IC(Spearman)、分层收益(5 组)、换手率、衰减分析、完整报告
**组合管理(portfolio/**
- 4 种权重优化器:等权、因子加权、风险平价(逆波动率)、均值方差(scipy 可选)
- 风险模型:Ledoit-Wolf 收缩协方差、组合风险分解
- `RebalanceEngine`:多期调仓回测(周/月/季),100 股整手、佣金+印花税
**高级回测增强(backtest/**
- 4 种滑点模型:Fixed、Percent、SquareRootAlmgren-Chriss)、Volume
- 4 种执行仿真:Immediate、TWAP、VWAP、Limit(限价单 + TTL
- `AttributionAnalyzer`:成本归因、Brinson 归因(配置/选股/交叉)、因子归因
- 完全向后兼容(`BacktestEngine` 新增 `slippage_model` / `execution_model` 可选参数)
**CLI**
- `easy-tdx factor list` / `factor analyze` — 因子列表和分析
- `easy-tdx pfactor backtest` — 组合因子选股回测
**测试**556 passed, 0 failed+176 新增)
## [1.10.5] (2026-06-12)
**Web API 全面补齐 + 稳定性修复** — 新增 18 个 REST 端点,Web API 与 CLI 接口覆盖对齐,修复多个生产环境问题。
- **板块分析(6 端点)**:板块列表、成分股、所属板块、板块摘要、涨幅排名、N日涨幅排行
- **资金/信息(3 端点)**:个股资金流向、个股信息快照、服务器交易时段
- **排行/竞价/异动(3 端点)**:分类排序行情列表、集合竞价、市场异动
- **扩展市场(4 端点)**:港股/美股/期货的 K 线、报价、分时、逐笔成交
- **技术指标(2 端点)**:指标列表、指标计算(POST)
- 新增 `AsyncMacClient` 依赖注入(`get_mac_client`),Web 层同时管理 TDX + MAC 双客户端连接
- 新增 `AsyncExTdxClient` 依赖注入(`get_ex_client`),可选启用扩展市场端点
- 新增 6 个 MAC 枚举转换器(BoardType/SortType/SortOrder/Category/ExMarket/FilterType
- 新增 `DictResponse``ComputeIndicatorsRequest` schemas
- Web API 端点总数从 22 增至 40
- 修复 MAC 客户端连接失败时 12 个端点返回 `AttributeError`500),现正确返回 503
- 修复扩展市场 dataclass 序列化时 `_raw: bytes` 字段导致 JSON 编码 500 错误
- 修复 `/redoc` 页面 404CDN `redoc@next` 已失效),手动注册端点并锁定 `redoc@2.2.0` 稳定版
## [1.10.0] (2026-06-12)
**Web API 层** — 新增 FastAPI REST + WebSocket 服务,一键将 easy-tdx 暴露为 HTTP API。
- 新增 `src/easy_tdx/web/` 模块:app factory、6 个路由(market/bars/finance/block/chanlun/realtime)、Pydantic schemas、异常处理
- 新增 `easy-tdx serve` CLI 命令,支持 `--host``--port``--tdx-host``--reload` 参数
- REST 端点覆盖全部 `AsyncTdxClient` 方法(K线/报价/资金流向/板块/财务/缠论分析等)
- WebSocket 端点 `/ws/realtime/{symbol}` 支持实时行情订阅和多标的动态切换
- 自动生成 Swagger UI (`/docs`) 和 ReDoc (`/redoc`) 文档
- 可选依赖 `pip install easy-tdx[web]`,核心安装不受影响
- 20 个离线单元测试覆盖 schemas、路由注册、OpenAPI schema 生成、输入验证
- 修复 `deps.py``AsyncTdxClient``TYPE_CHECKING` 下导致运行时 `NameError`500 → 正常启动)
- 修复 market/category 参数不支持小写(`sz`/`sh`)和非法值(`ZZZ`)导致 500 的问题,统一返回 400 Bad Request
## [1.9.10] (2026-06-11)
**板块 N 日涨跌幅排行** — 新增 `board-change-ranking` 命令,支持按行业/概念/风格板块计算指定日期前 N 个交易日的涨跌幅并排行。
- 新增 `MacClient.get_board_change_ranking()` / `AsyncMacClient` 同名异步方法
- 新增 CLI 命令 `easy-tdx board-change-ranking`,支持 `--type``--date``--days``--top``--asc` 参数
- 利用板块指数 K 线直接计算,无需逐个聚合成分股,效率远高于现有 `board-ranking`
- 支持指定截止日期(`--date YYYYMMDD`),周末/节假日自动回退到前一交易日
- 默认列出全部板块,`--top N` 截断前 N 个
- 12 个单元测试覆盖计算正确性、边界条件、排序方向
## [1.9.9] (2026-06-11)
**Bug 修复** — 修复并发扫描(`--workers`)在动态加载策略时静默返回空结果的问题。
- **根因**`ProcessPoolExecutor` 将动态 `importlib` 加载的策略类 pickle 序列化后发送到子进程,子进程无法反序列化(模块未注册到 `sys.modules`),异常被 `except` 静默吞掉
- **修复**`_scan_parallel` 改为传递策略文件路径(字符串),子进程内通过 `_load_strategy_class` 自行加载策略类
- 新增 `_get_strategy_file` 辅助函数:从类方法 `co_filename` 反查策略文件路径
- 新增回归测试 `TestParallelPickleFix`
## [1.9.8] (2026-06-11)
**CI 修复** — 修复 CI 流水线 ruff 和 pytest 配置问题。
- 修复 `MyTT.pyi` 类型存根文件行过长导致 ruff check 失败(`.pyi` 文件排除 ruff 检查)
- 添加 `pytest-asyncio` 依赖,修复 `test_realtime.py` 异步测试报错
- 修复 `test_backtest_engine.py` 中未使用变量 `result` 的 lint 警告
- 380 个测试全部通过,CI 全绿
## [1.9.7] (2026-06-11)
**CLI 全量集成** — v1.9.6 新增的 6 项功能全部暴露到 CLI,修复缠论多级别联立的 client 生命周期 bug。
- **`screen scan` 并发扫描**:新增 `--workers N` 参数,ProcessPoolExecutor 并行处理,推荐 4-8 进程,扫描速度提升 4-8 倍
- **`screen scan` 增量缓存**:新增 `--cache PATH` 参数,mtime 检测未修改的 `.day` 文件自动跳过
- **`backtest` 缠论桥接**:新增 `--chanlun-level LEVEL` 参数,引擎自动计算缠论分析并注入策略 `self.chanlun`
- **`portfolio` 组合回测**:新增 `easy-tdx portfolio` 命令,多标的共享资金池、均等分配、汇总绩效
- **`chanlun` 多级别联立**:新增 `--multi-level PERIOD` 参数,分析高级别最后一笔在低级别中的趋势方向、笔重叠、背驰条件
- **Bug 修复**`cmd_chanlun.py``_run_multi_level``with` 块外使用 `client`,导致已关闭连接报错
## [1.9.6] (2026-06-11)
**工程质量全面升级** — 基于 Devin AI 代码审查的 12 项改进建议全部落地,覆盖 CI、回测引擎、缠论模块、扫描引擎和架构层面。
- **CI 覆盖率强制执行**:pytest 命令加入 `--cov-fail-under=50`CI 不再空转
- **真实平均持仓天数**`avg_holding_days` 从硬编码 5.0 改为 FIFO 配对计算,区分 int/Timestamp 两种日期格式
- **向量化 datetime 转换**`_datetime_to_int``pd.to_datetime` 向量化替代 Python for 循环,大数组性能提升 100x+
- **止损/止盈实际执行**`BacktestEngine` 新增 `_StopCondition` 跟踪,`OrderSimulator` 在每根 bar 检查 SL/TP 并触发平仓信号
- **缠论信号自动桥接**`BacktestEngine` 新增 `chanlun_level` 参数,自动调用 `ChanlunAnalyser` 并注入策略,两模块正式打通
- **多标的组合回测**:新增 `PortfolioBacktestEngine`,支持多股票共享资金池、均等/自定义分配、资金加权绩效汇总
- **并发扫描**`SignalScanner` 新增 `workers` 参数,`ProcessPoolExecutor` 并行处理,扫描速度提升 4-8 倍
- **增量扫描缓存**:新增 mtime 检测 + JSON 缓存文件,未修改的 `.day` 文件自动跳过
- **缠论增量更新**`ChanlunAnalyser` 新增 `append_klines()` 方法,追加新 K 线后去重重新计算,支持实时场景
- **多级别联立增强**`query_low_level_qs` 新增趋势方向、笔重叠、背驰条件判断字段
- **MyTT 类型存根**:新增 `MyTT.pyi`,50+ 指标函数的类型标注,mypy strict 零错误
- **实时推送框架**:新增 `realtime/` 模块,`EventBus` 发布/订阅 + `RealtimeStrategy` 基类,asyncio 事件驱动架构(API 骨架)
- 380 个测试通过,57.56% 覆盖率,mypy strict 150 文件零错误
## [1.9.5] (2026-06-10)
**OBV 能量潮趋势策略** — 新增 `obv_trend.py` 策略,基于 OBV 与其 30 日均线 MAOBV 的关系判断多空方向。
- 新增 `strategies/obv_trend.py`OBV 能量潮趋势策略
- 入场条件:OBV 超过 MAOBV 达 2% 缓冲带 且 MAOBV 趋势向上(20 根确认)
- 出场条件:OBV 跌破 MAOBV,资金流向转空即离场
- MAOBV 趋势仅作入场过滤(确认趋势存在),出场只看 OBV/MAOBV 交叉信号
- 可调参数:`maobv_period`30)、`maobv_lookback`20)、`obv_buffer`0.02
## [1.9.4] (2026-06-10)
**Bug 修复** — 修复 `easy-tdx version` 命令硬编码版本号的问题,改为从 `pyproject.toml` 动态读取。
- 修复 `cmd_admin.py``version` 命令硬编码 `1.1.0` 的问题
- 版本号现在通过 `importlib.metadata``pyproject.toml` 动态获取,不再需要手动同步
## [1.9.3] (2026-06-10)
**新增 `run-all` CLI 命令** — 一行命令批量运行 strategies/ 目录下所有策略并排名,与 `run_all_strategies.py` 脚本功能完全一致。
- 新增 `easy-tdx run-all` CLI 命令,支持 `--count``--cash``--commission``--adjust``--period``--combo``--combo-mode``--show``--strategies-dir` 参数
- 绩效排名 + 综合评分 + 最佳策略交易明细,输出与脚本完全一致
- 支持多因子组合回测(`--combo 2 --combo 3`)和资金曲线图表展示(`--show`
- 支持自定义策略目录(`--strategies-dir`
- `run_all_strategies.py` 保持不变,两种方式并存
## [1.9.2] (2026-06-10)
**策略选股扫描器** — 新增 `screen` 命令组,用策略扫描全市场找出触发买入信号的股票,再做历史回测排名。纯离线数据,零网络 IO。
- 新增 `screen scan` CLI 命令:纯离线扫描本地 `.day` 文件,提取策略信号,输出 JSON
- 新增 `screen rank` CLI 命令:读取扫描结果,批量回测并按夏普/回撤等指标排名
- 新增 `src/easy_tdx/screen/` 模块:`SignalScanner`(扫描引擎)、`SignalRanker`(排名引擎)
- 两步走工作流:scan 几秒扫完全市场 → rank 对信号股做历史评估
- 支持 `--universe` 指定范围(all/sh/sz/自定义文件)、`--sort` 排序、`--names` 在线补名称
- 支持管道模式:`easy-tdx screen scan ... | easy-tdx screen rank --from - --table`
- 新增 20 个单元测试(离线,无需网络)
## [1.9.0] (2026-06-10)
**多因子组合回测** — 新增组合回测引擎,支持 2-3 个因子信号叠加,自动遍历所有组合寻找最优搭配。
- 新增 `backtest/combo.py` 模块:`CombinationRunner``extract_factor_signals``combine_masks``FactorSignals``ComboResult`
- 信号合并模式:AND(全部同意)、OR(任一同意)、MAJORITY(过半同意)
- CLI 新增 `--combo-strategies``--combo-mode` 参数,支持指定策略文件组合回测
- `run_all_strategies.py` 新增 `--combo``--combo-mode` 选项,自动遍历 C(N,2)/C(N,3) 所有组合并排名
- 核心思路:预提取 N 个因子信号(只跑一次)→ 遍历组合合并遮罩(纯 numpy)→ 批量回测排名
- 新增 14 个单元测试(离线,无需网络)
- 修复 MyTT `MFI()` / `CR()` 指标分母为零时的 RuntimeWarning
## [1.8.2] (2026-06-09)
**策略扩充 + 可视化** — 新增 6 个策略(共 15 个)、`--show` 资金曲线图、茅台 demo 截图。
- 新增 `run_all_strategies.py --show` 参数:自动弹出最佳策略资金曲线 vs 股价归一化对比图(matplotlib 双轴图 + 买卖点标记)
- 新增 `zhuoyao_momentum` 策略:ZHUOYAO 多周期共振(SHORT/TREND/MID 三重过滤)
- 新增 `dmi_trend` 策略:DMI/ADX 趋势强度跟踪
- 新增 `cci_breakout` 策略:CCI ±100 区间突破
- 新增 `mfi_volume` 策略:MFI 量价反转(带成交量权重的 RSI)
- 新增 `trix_cross` 策略:TRIX 三重平滑趋势交叉
- 新增 `mtm_momentum` 策略:MTM 动量零线穿越
- 新增 SH600519 贵州茅台 demo 截图
## [1.8.1] (2026-06-09)
**回测增强** — 批量策略对比脚本新增最佳策略完整交易明细输出;版本号统一为单一来源(`pyproject.toml`)。
- `run_all_strategies.py` 排名结束后自动输出最佳策略的绩效概要 + 最近 10 笔交易记录
- 修复 `turtle_breakout` 策略 `TAQ()` 返回 3 值但只解包 2 个的 bug
- 版本号统一:`pyproject.toml` 为唯一来源,`__init__.py` / `cli/__init__.py` / `docs/conf.py` 均动态读取
## [1.8.0] (2026-06-09)
**回测引擎** — 内置向量回测引擎,支持自定义策略回测和全策略批量对比。
- 新增 `backtest` 子包:Strategy 基类、BacktestEngine、OrderSimulator、PortfolioTracker、PerformanceAnalyzer
- 新增 `easy-tdx backtest` CLI 命令,支持 `--strategy-file``--cash``--commission``--adjust` 等参数
- 绩效报告包含 19 项指标:总收益率、年化收益、最大回撤、夏普比率、索提诺、卡玛、胜率、盈亏比等
- 新增 `strategies/` 目录,包含 9 个开箱即用的策略示例(MA/EMA/MACD/BOLL/RSI/KDJ/BIAS/海龟/量价)
- 新增 `run_all_strategies.py` 批量对比脚本,一键跑完全部策略并按收益率和综合评分排名
- 自带策略在 SZ 300308 上 3 年回测:收益率最高 1413%expma_cross),综合最优 turtle_breakout
- 30+ 离线单元测试覆盖,零网络依赖
## [1.7.1] (2026-06-08)
**Bug 修复** — 修复缠论笔计算在持续下跌/上涨走势中因"分型陷阱"导致近期笔丢失的问题。
- 修复 `find_bis()` 贪心算法在密集交替分型场景下提前终止的 bug
- 根因:当异类型分型 gap=0 时,算法仍用更极端的同类型分型替换 start_fx,导致 right_kline_index 不断前推,后续所有异类型分型 gap 永远为 0
- 新增 `pending_opposite` 保护机制:存在未配对异类型分型时冻结替换,保留 start_fx 较前位置
- 影响范围:持续下跌/上涨中的高价股(如贵州茅台)或分型密度高的股票
- 新增回归测试 `test_fractal_trap_regression`
## [1.7.0] (2026-06-07)
**缠论技术分析模块** — 新增完整的缠论(ChanLun)计算引擎,通过 CLI 和 Python API 提供个股缠论分析。
- 新增 `chanlun` 子包:K线合并、分型识别、笔/线段/中枢/买卖点/背驰计算
- 新增 `easy-tdx chanlun` CLI 命令,支持 JSON/表格输出
- 新增 MACD 指标计算(纯 numpy,无额外依赖)
- 新增多级别联立分析(MultiLevelAnalyser
- 计算管道:`DataFrame → K线合并 → 分型 → 笔 → 中枢 → 线段 → 买卖点 → 背驰`
- 49 个离线单元测试覆盖,零网络依赖
## [1.6.1] (2026-06-07)
**Bug 修复** — 修复 sync-all/sync-daily 对指数文件误用股票解析器导致垃圾日期的问题。
- 修复 `_fetch_all_daily_bars` 对指数文件(sh00/sh88/sh99, sz39)错误调用 `get_security_bars()` 的问题
- 指数文件现在正确使用 `get_index_bars()`(服务端响应每条记录多 4 字节上涨/下跌家数)
- 新增 `_is_index_code()` 辅助函数,根据市场和代码前缀判断证券类型
## [1.6.0] (2026-06-07)
**离线数据写入同步** — 从服务端获取最新日线数据并写入本地通达信 .day 文件,替代通达信内置下载功能。
- 新增 `offline sync-daily` CLI 命令:同步单只股票日线,自动增量/全量判断,支持分页获取完整历史
- 新增 `offline sync-all` CLI 命令:一键扫描沪深全市场 .day 文件并同步
- 新增 `write_daily.py` 模块:日线编解码(`encode_daily_bar`)、追加写入(`append_daily_bars`)、末尾日期检测
- 新增 `write_ex_daily.py` 模块:扩展市场日线写入(期货/港股,价格 float32)
- 新增 `write_min_bar.py` 模块:分钟线写入(.5/.lc1/.lc5 格式)
- 写入自动跳过重复日期,空文件自动全量下载,已有数据只做增量追加
- 50 个新增单元测试覆盖编解码 round-trip、追加去重、边界条件
## [1.5.0] (2026-06-02)
**离线数据 CLI 命令** — 新增 `offline` 命令组,无需网络即可通过 CLI 读取本地通达信数据文件。
- 新增 `offline home`:检测通达信安装目录
- 新增 `offline daily`A 股日线数据(.day 文件)
- 新增 `offline min`:分钟线数据(.5/.lc1/.lc5 文件,`--type` 指定格式)
- 新增 `offline ex-files`:列出扩展市场可用日线文件
- 新增 `offline ex-daily`:扩展市场日线数据(期货/港股/外盘)
- 新增 `offline gbbq`:股本变迁数据
- 新增 `offline financial`:历史财务数据
- 新增 `offline blocks`:自定义板块数据
## [1.4.3] (2026-05-28)
**30日乖离率信号指标** — 新增 BIAS_SIGNAL 指标,在标准乖离率基础上叠加短/长信号线,通过三者位置关系判断趋势方向和转折点。源自通达信经典指标。
- 新增 `BIAS_SIGNAL` 指标:输出 BS_X/BS_SMA/BS_LMA 三条线
- CLI: `easy-tdx indicator BIAS_SIGNAL -m SH -c 600519 --table`
- Python API: `indicators=["BIAS_SIGNAL"]`
- 详见 [30日乖离率信号指标详解](docs/indicator-bias-signal.md)
## [1.4.2] (2026-05-28)
修复 1.4.1 发布遗漏:MyTT.py 中 ZHUOYAO 函数定义未包含在 1.4.1 的 PyPI 包中。
## [1.4.1] (2026-05-28)
**捉妖大师指标** — 新增 ZHUOYAO 多周期涨幅共振指标,通过 20/60/120 日涨幅及指数平滑判断短中长线趋势是否同向,用于筛选趋势刚启动的强势股。
- 新增 `ZHUOYAO` 指标:输出 ZY_LONG/ZY_MID/ZY_SHORT/ZY_TREND 四条线
- CLI: `easy-tdx indicator ZHUOYAO -m SH -c 600519 --table`
- Python API: `indicators=["ZHUOYAO"]`
- 详见 [捉妖大师指标详解](docs/indicator-zhuoyao.md)
## [1.4.0] (2026-05-28)
**技术指标计算** — 集成 [MyTT](https://github.com/mpquant/MyTT) 麦语言指标库,支持 30 个常用技术指标,一步获取 K 线 + 指标值。
- 新增 `indicator.py` 核心模块:注册表驱动的指标调度,`compute_indicators()` 纯计算无 IO
- 新增 `MacClient.get_stock_kline_with_indicators()` / `AsyncMacClient` 同名方法
- 新增 `UnifiedTdxClient.get_stock_kline_with_indicators()` / `AsyncUnifiedTdxClient` 同名方法
- 新增 CLI 命令 `easy-tdx indicator``easy-tdx indicator-list`
- 自动获取 200+ 条历史数据预热 EMA,用户只需指定返回条数
- 支持的指标:MACD, KDJ, RSI, BOLL, DMI, ATR, WR, CCI, BIAS, OBV, VR, EMV, MFI, BRAR, ASI, TRIX, DPO, MTM, ROC, EXPMA, BBI, PSY, DFMA, CR, KTN, XSII, MASS, TAQ
## [1.3.1] (2025-05-15)
- 新增 `board-summary``board-ranking` CLI 命令
- 新增 `get_board_summary()` 板块汇总(成交额、主力净流入、涨跌家数)
- 新增 `get_board_ranking()` 板块涨跌幅排行榜
## [1.3.0] (2025-05-12)
- 新增 MAC 协议客户端 `MacClient` / `AsyncMacClient`(端口 7709
- 新增扩展市场客户端 `MacExClient` / `AsyncMacExClient`(端口 7727
- 新增统一客户端 `UnifiedTdxClient` 自动路由 A 股 / 扩展市场
- 新增板块、资金流向、集合竞价、异动、个股特征等数据接口
- 新增 `easy-tdx` CLI 工具,默认 JSON 输出
## [1.2.1] (2025-04-20)
- 离线数据读取模块(日线、分钟线、板块、财务)
- 除权除息、股本变迁读取
## [1.0.0] (2025-03-01)
- 首个正式版本
- TdxClient / AsyncTdxClient 标准协议客户端
- K 线、实时报价、分时、逐笔成交、财务数据