GitHub
|
ef9b34b88d
|
release: v1.32.3 — 策略库保存名称带股票名 + 参数寻优买入持有基准对比
|
2026-09-04 22:45:04 +08:00 |
|
GitHub
|
75a741e03c
|
release: v1.32.2 — baostock 自动兜底数据源(TDX 全败时最后一级回退 + warehouse 多源 + EXE 内置)
|
2026-09-04 19:58:09 +08:00 |
|
GitHub
|
01e8fc0cc1
|
feat: /bars 自动兜底数据源 baostock — TDX 全部路径失败时最后一级回退(仅日线及以上),响应带 source 字段标注数据来源
|
2026-09-04 19:24:05 +08:00 |
|
GitHub
|
41db6b0ca7
|
release: v1.32.1 — 行业/概念总览上线:WebUI 板块全景双栏目(热力图/表格+统计条+三榜/翻红翻绿+板块弹窗复用)
|
2026-09-04 16:00:04 +08:00 |
|
Justin Gu
|
d0b72e1bd1
|
release: v1.31.3 — 紧急修复盘中分时数据错乱(实时命令解析错位,全程改走历史分时)
|
2026-09-04 12:42:44 +08:00 |
|
Justin Gu
|
9d2b0397bd
|
release: v1.31.2 — 修复分时接口盘前/休市/指数返回空(最近交易日锚定+指数K线适配)
|
2026-09-04 04:40:50 +08:00 |
|
GitHub
|
f0122e74e0
|
release: v1.31.1 — 策略库「重跑到今天」补齐组合分析(多策略组合级WF+一条龙+AI解读)
|
2026-09-04 00:14:18 +08:00 |
|
GitHub
|
81fceb626a
|
release: v1.31.0 — 组合回测分析体系对齐单标的(组合级WF+一条龙+完整绩效+AI解读)
|
2026-09-03 23:22:54 +08:00 |
|
Justin Gu
|
9f260dfb09
|
release: v1.30.3 — 修复一键寻优所有策略漏掉新策略(STRATEGY_PRESETS 19→54 同步 + 一致性回归测试)
|
2026-09-03 03:31:51 +08:00 |
|
Justin Gu
|
62e80d892e
|
release: v1.30.2 — 无未来函数指标扩容16个(注册指标50个)+ 内置策略补齐54个:WebUI回测全覆盖,新增前缀一致性无未来函数回归测试
|
2026-09-03 03:07:57 +08:00 |
|
Justin Gu
|
1433f4eed0
|
release: v1.30.1 — 移除 ZIG 未来函数指标与 zig_breakout 策略:回测数字可信优先
|
2026-09-03 02:02:19 +08:00 |
|
Justin Gu
|
1e95bab476
|
release: v1.29.2 — 可编辑安装失效友好报错(#58):入口守卫 _editable_guard 经 force-include 存活于失效态
|
2026-09-03 00:46:28 +08:00 |
|
GitHub
|
3a982ba6b2
|
release: v1.29.1 — 中金所成交持仓排名采集(ccpm):CLI/API/WebUI 三端 + 新手科普
- 新增 easy_tdx.ccpm 模块(独立数据源,官网 XML,标准库 urllib 零依赖)
- 8 品种:IF/IH/IC/IM 股指期货 + TS/TF/T/TL 国债期货;
latest_rank 自动回溯最近交易日,按日缓存(发布后不可变,历史零网络)
- CLI easy-tdx ccpm / API /ccpm/* / WebUI「期货持仓排名」页
(品种下拉+日期+一键采集,主力页签,多空净持仓概览,三组排名表格)
- 三段新手科普:数据口径 / 品种一览 / 多空加减仓解读
(空单多 ≠ 看空市场——排名看不出套保还是投机)
- 测试 20 例(mock HTTP);CI 8/8 绿(含 Playwright E2E)
|
2026-09-02 21:01:43 +08:00 |
|
GitHub
|
4bd5b5d833
|
release: v1.29.0 — 借鉴社区 Fork 六项特性:ZIG 策略 + 交易时段感知刷新 + 120M K 线 + 逐 bar 衍生字段 + 159 龙头池 + 多 Provider LLM 直连
- ZIG 右侧突破回补策略:MyTT 新增 ZIG 之字转向(未来函数,含前视偏差警示);
波谷启动建仓挂硬止损(OCO)→ 见顶清仓记前高 → 右侧突破回补;路径依赖不实现
entry_exit_masks(向量化守护测试白名单);含寻优预设网格与 --strategy-file 独立文件
- 交易时段感知刷新:realtime/session.py(09:15~11:30:30 / 13:00~15:05)+
GET /market/session;看板 30/60/120s 轮询休市自动暂停(三态状态栏 + 开关持久化
+ 手动刷新不受限);SSE/WS 既有会话语义不动
- 120 分钟 K 线:/bars?category=MIN_120(MAC 原生 Period.MINS×120 优先,
2×60M 相邻聚合兜底,标准客户端上限 400 根);前端周期选择器同步
- 逐 bar 衍生字段:/bars 与 /bars/index 附带 pre_close/change/change_pct/
amplitude_pct(pre_close≤0.01 兜底防除零)
- 159 只核心龙头池:数据资产取自 Fork(东财全行业龙头名单,四组分层);
universe=core 接入 screen scan / SignalScanner / StrengthRanker / market strength;
GET /market/core-leaders + WebUI「龙头池」页(搜索/个股详情)
- 多 Provider LLM 直连:easy_tdx.ai + /llm/*(DeepSeek/通义/智谱/Kimi/MiniMax/
OpenAI/Claude/Ollama/自定义,openai 兼容 + anthropic 原生双协议);
配置落盘 ~/.easy_tdx/llm.json(WebUI「AI 设置」页 ⇆ 手工编辑双向兼容,
文件>环境变量>预设;key 脱敏回显/CLEAR 清除);「AI 解读」后台任务化
(复用 task_runner,提交+轮询,不占 HTTP 连接);思考型模型空白正文防御
(reasoning_content 耗尽 max_tokens → 可操作报错;默认 16000);
AI 解读历史页(自动归档 Prompt/正文/策略上下文 + 去回测带参引导)
- WebUI 加固:SPA fallback 对未知 /api/* 返回 JSON 404(不再 200 HTML 伪装解析错);
index.html 一律 Cache-Control: no-store(防缓存旧资源引用);路由兜底重定向;
全局风险提示常驻底栏 + 龙头池/AI 解读针对性免责声明
- 测试:新增 9 个单测文件共 59 例;黄金基线仅新增 zig_breakout 条目(其余零漂移);
全量 1448 例通过
|
2026-09-02 20:19:17 +08:00 |
|
GitHub
|
eeed45b171
|
fix(bars): 指数/个股 K 线 vol 字段协议语义修正(#64)
通达信服务端 K 线记录第一个 4 字节字段的语义随周期/品种变化,此前原样
透传错误数据(逐字节拆包 + 新浪实时行情/东方财富三方交叉验证锁定):
- 指数分钟线(MIN_1/3/5/15/30/60,含 880xxx 板块指数):f1 实为
成交额(百元),与 amount 恒差 100 倍,真实分钟成交量不在报文中
(15:00 上证 5min 真值 13,954,814 手 vs 返回 208,748,512≈amount/100)
→ vol 置 NaN,不拿成交额冒充成交量;
- 指数与个股周/月/季/年线(cat 5/6/10/11):f1 = 真实成交量/100
(上证本周三日日线 vol 合计 1,666,668,288 手 vs 周线 16,666,683)
→ ×100 还原,与日线单位对齐(指数=手、个股=股);
- 日线(cat 4)与 cat 9(日线变体,枚举名误标 YEAR,真年线是 cat 11)
不受影响,cat 9 明确不套 ×100 并由测试锁定。
配套:DataFrameResponse NaN→null(Starlette allow_nan=False 透传会 500);
client/路由 docstring 写明各单位;回归测试 7 例(实抓原始字节构造报文);
验收脚本 scripts/verify_issue64.py 连真实服务器复测。附带发现仅记录:
指数分时 vol=成交额(万元)、/bars?category=YEAR 实际返回日线(cat 9)。
|
2026-09-02 17:12:00 +08:00 |
|
GitHub
|
8a5ed52a1f
|
release: v1.28.1 — WebUI 名词解释折叠帮助 + AI 解读 Prompt 导出 + WF 窗口序列化修复(to_json_native 有限 float 落入 str 兜底,逐窗指标变字符串)
|
2026-09-02 15:49:41 +08:00 |
|
Justin Gu
|
0a00ca3f70
|
release: v1.28.0 — 深度风险报告+移动止损+黄金测试(借鉴 akquant):25 项绩效 / α·β·IR·TE 基准对比 / trail_stop OCO
|
2026-09-02 11:53:53 +08:00 |
|
Justin Gu
|
90f2595d3d
|
release: v1.27.2 — 市场异动类型解析补齐(#62):盘中强弱/竞价尾盘/急速拉跌/竞价试盘方向
|
2026-09-02 10:44:20 +08:00 |
|
GitHub
|
1aacce9b7d
|
release: v1.27.1 — 回测页附加分析布局修复 + WebSocket 实时推送收录
|
2026-09-01 23:30:02 +08:00 |
|
GitHub
|
917295edaf
|
release: v1.27.0 — 通达信公式解析器三通道 + 轮动组合引擎 + 回测页WF/评估开关 + Docker 部署
升级计划 P3 + P4(部分)。全量 1252 单测、ruff/mypy strict、前端 vue-tsc+vite build 全绿。
- 通达信公式解析器(formula.py):自建 tokenizer + 递归下降 AST + 30+ 函数白名单求值
(不走 Python eval);命名布尔输出=信号列、数值输出=排名列;除零→NaN、预热期不出信号
- 公式三通道:CLI easy-tdx formula compute|screen|backtest;REST /formula/validate|compute|
backtest|screen(run/async);Python API run_formula_backtest(买/卖列自动挑选)
- 轮动组合引擎(rotation.py):排名定期换仓(打分只用截至当日数据)、槽位等额、
跌出排名自动补位、日/周/月刷新、槽内止盈止损;momentum_score/formula_score 打分;
REST /backtest/rotation/run/async
- 回测页附加分析开关(Web UI):勾选后随回测并行跑 WF(逐窗红涨绿跌柱状图+汇总卡,
窗口数 2~12)与一条龙评估(评分分项条/高适配徽标/买入持有对比/8 项适配检查);
新增 WalkForwardPanel/EvaluatePanel 组件与 store runWalkforward/runEvaluate;
WF 端点 ?n_windows= 透传;修复报告 numpy 标量 REST 400(源头清洗)
- Docker 部署(Dockerfile + docker-compose.yml,/data 卷 + 健康检查)与
scripts/verify_ci.sh 一键门禁
- 升级计划文档 docs/upgrade-plan-2026H2.md(四阶段全部完成 + 诚实实测数据)
- 未做(独立排期):Playwright E2E、WebSocket 实时联动、引擎逐 bar 向量化
|
2026-09-01 22:17:57 +08:00 |
|
GitHub
|
9569b2653c
|
release: v1.26.0 — DuckDB K线仓库 + provisional 状态机 + 增量同步 + 健康自检
升级计划 P2(P2-2 评级后端化已随 1.25.0 提前交付):把碎片化缓存升级为统一数据底座,
对齐 indicator-lab 自建 DuckDB 层的定位。
- warehouse/ 包:DuckDB 单文件(~/.easy_tdx/warehouse.duckdb,随 EASY_TDX_CONFIG_DIR),
列存 + 主键 upsert 去重;duckdb 为可选依赖(pip install easy-tdx[warehouse])惰性导入
- provisional/completed 状态机:15:05 前当日 bar 逐行标记临时,查询/回测默认忽略,
promote_provisional 过期转正,include_provisional 显式可见
- 增量同步器:首同步全量(默认 8000 根)此后只补尾部 15 根,批次进度回调、单标失败不中断
- 健康自检:疑似缺口/异常跳变(复用 QFQ 对拍跳空检测)/最新度/provisional 统计
- CLI easy-tdx warehouse sync|query|stats|check(sync 支持 @文件标的列表)
|
2026-09-01 22:17:28 +08:00 |
|
GitHub
|
b2509a8d0e
|
release: v1.25.0 — Walk-Forward/适配性/一条龙评估防过拟合链 + 评分评级后端化 + 寻优加速
升级计划 P1:补上两个下游项目都在自研的样本外验证空白。
- Walk-Forward 引擎(walkforward.py):7 窗样本外、每窗独立开仓(backtest-system v1.2.1 踩坑语义)、
上下文预热不污染;CLI --wf、REST /backtest/wf/run/async
- 适配性评估(fitness.py):train/valid/test 三段 + 8 项可解释检查 + 高适配标记;
evaluate_prefix 滚动过滤原语(无未来泄漏)
- 一条龙评估(benchmark.py evaluate_strategy):回测+WF+适配性+评分+评级+买入持有基准对比;
CLI --evaluate、REST /backtest/evaluate/run/async
- 综合评分(scoring.py,收益50/夏普15/回撤10/Sortino5/WF20)+ 评级后端化(grading.py,
前端 TS 忠实移植,REST 响应新增 grade/score 字段)
- 多 seed 验证 + 四项晋级门槛(validation.py);REST /backtest/multiseed/run/async
- 寻优两段式加速:IndicatorCache(36 点网格命中率 41.7%)+ workers 进程并行(实测约 2x);
诚实注:指标缓存墙钟 ~1.01x,瓶颈在逐 bar 循环,后续向量化
- strategy.I() 指标缓存钩子 + 数据代理零拷贝(astype copy=False);
types.to_json_native 统一 numpy 清洗
|
2026-09-01 22:17:08 +08:00 |
|
GitHub
|
1fc1d00c90
|
release: v1.24.0 — QFQ 对拍验证体系 + 回测任务持久化 + 品种感知费率
升级计划 P0(docs/upgrade-plan-2026H2.md)。源自 backtest-system / indicator-lab 两个下游项目的逆向调研。
- QFQ 对拍验证:公式法(NONE+XDXR)与跳空检测法(板块感知涨跌停阈值)双证据链互检,
检出负价/残留跳空/方向反演/XDXR 缺记录四类问题,接入 MAC 同步/异步客户端(mac/qfq_check.py);
含茅台式多重分红、浦发式送转方向合成案例回归(13 用例)
- 回测任务 SQLite 持久化:~/.easy_tdx/tasks.db 双写内存 LRU + 磁盘(保留 500 条),serve 重启不丢;
重启恢复中断任务标记;GET /backtest/tasks/{id}/export?format=json|csv 导出端点
- 品种感知费率:ETF/可转债免印花税等法定差异(backtest/fees.py),CLI --auto-fees、
REST auto_fees 字段、组合引擎逐标的解析(34 用例)
- 修正 avg_holding_days 过时注释(实现早已是 FIFO 真实口径)
- tests/conftest.py 默认 EASY_TDX_NO_TASK_DB=1 防止单测污染用户任务库
- 注:engine/cli/routers/schemas 为跨版本累积态,后续版本提交继续演进
|
2026-09-01 22:16:44 +08:00 |
|
GitHub
|
6412880dbe
|
release: v1.23.3 — serve --no-ui 纯 API 模式 + 概念冷榜修复 + 文档截图
|
2026-09-01 18:37:00 +08:00 |
|
GitHub
|
6bfe5a2cee
|
release: v1.23.2 — 1.23.1 质量门禁补丁(mypy strict + ruff 全绿)
|
2026-09-01 18:02:40 +08:00 |
|
GitHub
|
a79861af76
|
release: v1.23.1 — 行情终端 WebUI 重大升级
|
2026-09-01 17:45:12 +08:00 |
|
 毛利哥andGitHub
|
12d308e1a4
|
fix!: 扩展日线槽位语义——第6槽为 float32 成交额,移除误导字段 hk_stock_amount(#57) (#61)
read_ex_daily_bars 原把第7槽(成交量)同时赋给 amount 与 vol(amount=vol),
真实成交额藏在第6槽 float32 重解释值里、以 hk_stock_amount 之名暴露。
实测对照:47#IF300 2023-09-11 第6槽 float32=186871758848(元)、第7槽
uint32=105358016(手),与标准市场 sh000300.day 同日 amount/vol 完全一致。
- _EX_DAILY_FMT: <IffffIIf → <IfffffIf,第6槽正名为 float32 成交额
- ExDailyBar.amount: int → float;移除语义错误的 hk_stock_amount 字段
- encode 端沿新 fmt 自动正确:大成交额按 float32 编码,不再溢出 uint32
- CLI offline ex-daily 输出新增 amount 列
- 新增真实样本回归测试(47#IF300 原始记录)+ 补齐缺失的 amount 往返断言
Co-authored-by: GitHub <action@github.com>
|
2026-08-31 20:43:35 +08:00 |
|
GitHub
|
6c30b72e29
|
release: v1.20.13 — sync-daily 成交量单位修复(#60):股→手换算,修复大盘股 uint32 溢出
|
2026-08-31 20:28:32 +08:00 |
|
GitHub
|
a7b14d3388
|
release: v1.20.12 — ex tick --date 修复(#56):接受 YYYYMMDD 整数,对齐 A 股日期语义
|
2026-08-28 22:41:24 +08:00 |
|
GitHub
|
05db452cc0
|
release: v1.20.11 — 资金流口径标注(#55):聚合逐笔成交额分档,实质为主动买卖总失衡
|
2026-08-28 20:14:41 +08:00 |
|
GitHub
|
fd53ec4c90
|
fix(mac): 板块列表涨速恒 0——值槽实为排序键列值,暴露 sort_column(issue #53)
抓包+对值锚定确认:0x1231 响应中 price 与 pre_close 之间的 float 是
"当前排序列的值"(板块与领涨股各一份),并非固定涨速;此前硬编码
sort_column=0(涨跌幅,仅排序键、值槽恒 0),故该列永远全 0。
排序列映射(实测):0=涨跌幅(值槽恒0) 1=涨速 2=3日 3=20日 4=60日
5=年初至今 6=5日 7=10日。
- 新增 BoardSortColumn 枚举并公开导出;get_board_list(sync/async)
新增 sort_column 参数,取涨速传 SPEED,默认涨跌幅排序行为不变
- BoardInfo 字段更名 rise_speed→sort_value、symbol_rise_speed→
symbol_sort_value(旧名语义错误且恒 0,属破坏性更名)
- Web /board-mac/list 新增 sort_column 参数;CLI board-list 新增 --sort
- 新增 9 个测试;README 示例更新
|
2026-08-26 15:21:35 +08:00 |
|
GitHub
|
8c35a864e8
|
release: v1.20.9 — 历史资金流修复(#52):当日主力净额盘中可取 + main_net_inflow 列
|
2026-08-26 15:01:50 +08:00 |
|
GitHub
|
7c9e19de93
|
release: v1.20.8 — 信号雷达:一键扫描全部已保存策略买卖信号
|
2026-08-21 16:57:16 +08:00 |
|
GitHub
|
67a5e1d08a
|
release: v1.20.7 — /bars MIN_1 时间修复(#49)+ 寻优参数语义约束(#39)+ 依赖安全升级
|
2026-08-19 19:06:59 +08:00 |
|
GitHub
|
5a3ad15477
|
feat(web): /bars 迁移到 MacClient + 支持复权(issue #43)
Web 获取 K 线此前用 AsyncTdxClient.get_security_bars(标准协议不支持复权),
导致 REST API 无法取前复权/后复权数据。将 /bars(个股 K 线)迁移到
AsyncMacClient.get_stock_kline(MAC 协议,支持 NONE/QFQ/HFQ + QFQ 负价兜底),
保持旧输出契约不变(日线 date 列、分钟线 datetime 列、OHLC 顺序、无 float_shares),
新增 adjust 参数(默认 QFQ),MAC 主机不可用时自动回退标准 TdxClient。
⚠️ 半破坏性变更:/bars 默认复权从"不复权"改为 QFQ(前复权)。老调用方若需
不复权请显式传 ?adjust=NONE。输出 DataFrame 列名/顺序/字段与旧版完全一致
(_normalize_mac_df 规整),仅价格数值因复权变化。
改动:
- bars.py:/bars 改走 mac_client.get_stock_kline(adjust=...),MAC 不可用回退
get_security_bars(无复权 + warning);新增 _normalize_mac_df 规整输出契约;
新增 adjust 查询参数(默认 QFQ)。
- convert.py:period_times_from_category(KlineCategory→Period 映射,显式处理
YEAR 9→YEARLY 11、SEASON→QUARTERLY)+ adjust_from_str。
- deps.py:get_mac_client_optional(未连接返回 None,供回退判断)。
- schemas.py:AdjustEnum(OpenAPI 文档用)。
测试:新增 7 个(period_times 映射全表 + 不可映射值、adjust 转换、_normalize_mac_df
日线/分钟线/空 df)。全套 996 passed;ruff format/check + mypy 改动文件零错误。
不在本次范围:/bars/index(指数 K 线,MAC 另一套接口)、/minute、/transaction*
(MacClient tick_chart 语义不同,暂不迁移)。
|
2026-08-05 16:37:10 +08:00 |
|
GitHub
|
0490f67a16
|
fix(client): get_history_fund_flow 加空数据故障转移(issue #41)
用户反馈 get_history_fund_flow(SH, "600519") 返回空 DataFrame,日志显示
"K线响应为空(声称 800 条但首条即解析失败...)"。排查定位:当前 host 对
常见标的也返回 ret_count 撒谎的空 body,但资金流兼容回退路径(直连空 →
拉 K 线 + 历史逐笔重算)未接入 v1.20.4 的空数据故障转移,"服务器回包正常
但内容是假的空" 既非 TdxConnectionError 也不触发换台,用户卡在坏服务器上。
修复:get_history_fund_flow(sync+async)当前 host 直连与 K 线回退均空时,
按延迟顺序逐台实测找首台返回有效数据的服务器(与 get_security_bars/
get_index_bars 同源逻辑)。因资金流获取涉及多命令,无法用单 cmd 复用泛化版
_find_host_returning_data,故内联 _fund_flow_failover:每台候选上跑完整
_fetch_fund_flow_records(原直连+K线回退逻辑抽出成独立方法),返回首台非空
结果。全空返回空 DataFrame(不 raise,区分"真无历史数据"与"服务器缺数据")。
测试:新增 6 个(4 sync + 2 async)。全套 989 passed;ruff/mypy 改动文件零错误。
|
2026-08-05 15:53:49 +08:00 |
|
Justin Gu
|
3b7ce97f2a
|
chore(release): v1.20.4 服务器健康分引擎 + K线空数据故障转移
版本包含(PR #37):
- 新增 _health.py 服务器健康分引擎(降权/冷却/恢复)
- get_index_bars/get_security_bars 空数据自动逐台换台
- 8 个 client _execute 统一健康分联动
- select_best_host_*/find_working_host_* 应用 rank_by_health
- security_bars 截断日志区分空响应与末尾截断
- 26 个新增测试,CI 8/8 通过
|
2026-07-13 16:36:11 +08:00 |
|
GitHub
|
d84a08b7f2
|
fix(backtest): v1.20.3 修复回测绩效统计两个 bug(issues #30 #31)
#31: RebalanceEngine 缺失价格导致净值假崩塌
已持仓标的当日缺 K 线(停牌/日历错位)时 prices.get(code,0)=0,
持仓市值记 0 → 净值单日暴跌(159915 在 20210208 缺一天,持仓 ~93%,
净值 1.1M→91,845,全期最大回撤 -92%)。
修复:last_known_price forward-fill,缺失日沿用最近已知收盘价。
附带:_compute_performance 最大回撤改正值口径(与 BacktestEngine 一致)。
验证:真实 ETF 数据 max_drawdown 24.01%(backtrader 基准 27%),
total_return 220.56% 不变。
#30: PortfolioTracker 交易静默漏单
apply_trades 用 trade.datetime 作 dict key、df["datetime"].to_numpy()[i]
查找;两端类型不一致(int vs datetime64)时永不命中,交易被静默丢弃,
净值恒定(total_return=0 但 trades 表有 PnL)。
修复:改为按"位置索引"匹配(归一化 datetime 后查位置),类型无关。
验证:int-trade+datetime64-df 修复前净值=100000(恒定),修复后=100289。
测试:新增 4 回归测试(未修复代码上均失败,修复后通过);
全套 936 passed;mypy 改动文件零错误;ruff 全绿。
|
2026-07-10 15:12:47 +08:00 |
|
GitHub
|
a67e5588d0
|
fix(types): v1.20.2 修复 v1.20.1 引入的 CI mypy 失败
v1.20.1 把 BacktestResult.performance 扩大为 dict[str, float | str]
(为塞 diagnostic_warning 字符串),破坏 6 处下游消费方类型契约,
CI mypy job 转红。重构为更干净的设计:
- 诊断信息走独立的 BacktestResult.diagnostic 字段(performance.py
PerformanceAnalyzer.diagnostic 属性 → engine 透出 → to_dict 含该字段
→ CLI 显示),performance 字典回归 dict[str, float](保留别名键)。
- optimizer.py 补 npt.NDArray 标注,消除 3 个既有 ndarray type-arg 错误。
测试:932 passed;mypy backtest/+portfolio/ 零错误;ruff 全绿。
|
2026-07-09 20:34:23 +08:00 |
|
GitHub
|
00b8c6374a
|
fix(backtest): v1.20.1 修复回测引擎 3 个 bug(issues #22 #23 #25)
排查发现用户反馈的"回测统计数据缺失/异常"并非服务器连接问题,
而是回测引擎与组合优化器自身的代码缺陷:
#23: 首根 bar 访问 close[-1] 崩溃
_SeriesAccessor 负向越界改返回 NaN(不抛 IndexError);
BacktestEngine 新增 warmup_bars 参数跳过指标预热期。
#25-A: FactorWeightedOptimizer 权重坍缩
n_stocks=2 且得分接近时,减最小值把低分标的权重压到 ~6e-8,
等于单股满仓、n_stocks 被无视,进而出现持仓1只/-99.98%回撤。
新增 _apply_weight_floor 权重下限保证入选标的都有实质权重。
#25-B: RebalanceEngine total_trades 统计错误
total_trades = len(equity_curve)(天数)改为 len(trades_df)(真实笔数)。
#22: 绩效别名键 + 数据异常诊断
performance dict 新增 sharpe_ratio/start_cash/end_value 别名键;
资金曲线异常时返回 diagnostic_warning 而非静默全 0,CLI 显示提示。
文档:README 加入回测手册导航;backtest_usage.md 补充 warmup 说明。
测试:新增 6 个回归测试,更新 3 个;932 passed。
|
2026-07-09 20:16:12 +08:00 |
|
GitHub
|
d0d65d64b8
|
feat: v1.20.0 服务器失败自动 ping 切换(无需手动 easy-tdx ping)
服务器连不上或返回空数据时,自动测速切到延迟最低的可用服务器再试,
Python API / CLI / Web API 三入口全部自动生效。
核心改动:
- _reconnect.py 新增 select_best_host_sync/async(连接失败 failover)
和 find_working_host_sync/async(空数据逐台实测)
- 8 个 client 的 _execute 注入跨主机故障转移(复用 auto_reconnect 开关)
- get_market_stat 空数据时按延迟顺序逐台实测找返回数据的服务器
- 新增 _reconnect/_areconnect helper 收敛重建连接副本
- MacClient failover 用 save_best_mac_host(延续 v1.19.4 不污染 best_host)
- 顺手修复 test_commands_offline 未使用 import(main CI failure 根因)
测试:925 passed(新增 18 个 failover 测试),ruff/mypy 零新增错误。
|
2026-07-08 18:07:37 +08:00 |
|
Justin Gu
|
14debdb446
|
feat(web-ui): v1.19.7 服务器设置页面(测速+切换通达信服务器)
新增 web UI 第六个页面「服务器设置」,让用户在浏览器上:
1. 列出全部 50+ 候选服务器
2. 一键并发测速(显示延迟和可达性)
3. 点选切换到最快或可用的服务器(热重连,无需重启)
解决不同地区/运营商对通达信各服务器连通性不同的问题。
新增:
- AsyncTdxClient.reconnect_to(host) 热切换方法(持锁,关旧建新)
- GET/POST /api/v1/server/hosts|test|switch 三个端点
- ServerSettingsView.vue 页面(列表+测速+切换)
- 导航栏第六个入口
设计: 先reconnect成功再save_best_host(避免污染config),
host校验只允许候选列表内IP,不自动测速避免首屏卡顿。
|
2026-07-07 23:08:32 +08:00 |
|
Justin Gu
|
c2c3e7ffb4
|
fix(release): v1.19.6 release.yml 先构建前端再 pip install(修复EXE丢依赖)
v1.19.5 EXE 只有 11MB,双击报 ModuleNotFoundError: No module named 'pandas'。
根因:release.yml 先 pip install -e '.[web,packaging]' 再 Build frontend,
但 force-include 要求 web-ui/dist 在 pip install 时就存在——install 阶段
dist 不存在导致 editable install 静默降级,PyInstaller 收集不到第三方包。
修复:调换步骤顺序,Build frontend 在 Install Python deps 之前。
ci.yml 上一 commit 已同样修复。
|
2026-07-07 22:23:30 +08:00 |
|
Justin Gu
|
e8b088bca1
|
fix(ci): ci.yml test/mypy job 先构建前端再 pip install
pyproject.toml 的 force-include 要求 web-ui/dist 存在,否则 pip install -e .
报 FileNotFoundError。ci.yml 的 test 和 mypy job 此前没有构建前端步骤,
导致全部 CI 失败。
修复:test(6 矩阵)和 mypy job 在 pip install 前加 setup-node + npm ci +
npm run build。frontend job 本来就有,不变。
同时清理 pyproject.toml:恢复 force-include(之前误改成 build-hook 但
hatchling 自定义 hook 需要插件注册,过于复杂)。
|
2026-07-07 22:14:03 +08:00 |
|
Justin Gu
|
9ab093a3c7
|
fix(build): hatchling artifacts 让 sdist 也含 web-ui/dist
python -m build 先构建 sdist 再从 sdist 构建 wheel。sdist 默认尊重 .gitignore
不含 web-ui/dist(构建产物),导致 wheel 阶段 force-include 找不到源报
FileNotFoundError。用 [tool.hatch.build] artifacts 强制 sdist 和 wheel
都包含 web-ui/dist。
本地验证:sdist 含 4 个 dist 文件,wheel 含 4 个 web/dist 文件。
|
2026-07-07 20:50:48 +08:00 |
|
Justin Gu
|
d5309454bc
|
fix(packaging): v1.19.5 PyPI wheel 含前端 dist(pip install 后不再 404)
根因:PyPI wheel 只有 Python 包,不含前端 dist。_resolve_web_dist_dir
三级探测(env/_MEIPASS/仓库根)在 PyPI 安装环境下全失败返回 None,
StaticFiles 不挂载,GET / 返回 404。
修复:
- pyproject.toml hatchling force-include 把 web-ui/dist 映射到包内
easy_tdx/web/dist
- publish.yml 在 python -m build 前先 npm ci && npm run build
- _resolve_web_dist_dir 新增第 4 级探测:包内 easy_tdx/web/dist
验证:本地构建 wheel 含 4 个前端文件,模拟 PyPI 安装后第 4 级探测
成功找到 dist。907 测试全过。
|
2026-07-07 20:46:26 +08:00 |
|
Justin Gu
|
3bc15e620c
|
fix(config): v1.19.4 MAC客户端不再污染标准best_host(取不到数据根因)
根因:mac/client.py 的 MacClient.from_best_host 和 AsyncMacClient.from_best_host
调用 save_best_host(best),把选中的 MAC 协议服务器(如 121.36.248.138)
写进了全局 best_host 字段——但这个字段是标准 TDX 协议用的。之后标准
AsyncTdxClient 用 get_best_host 读到这个 MAC host,用标准协议请求 MAC
服务器,返回空 body(偏移 2 剩余 0)。web app lifespan 启动 MAC 客户端
时触发污染。
修复:
- config.py 新增独立的 best_mac_host 字段 + get_best_mac_host / save_best_mac_host
- mac/client.py 4 处改用新字段(不再碰 save_best_host / get_best_host)
- get_best_host 加交叉污染校验:缓存 host 不在标准列表里自动重置
(自动修复已被污染的 config.json,用户无需手动操作)
测试:新增 5 个回归测试(污染检测 + MAC host 隔离),907 全过。
|
2026-07-07 20:36:44 +08:00 |
|
Justin Gu
|
032f5a40c0
|
fix(web): v1.19.3 K线空body不再500 + SPA路由刷新404
两个独立问题(日志证据):
1. K线空body 500:SH600519 等正常股票偶发请求时,通达信返回
ret_count>0 但 body 完全为空(偏移2 剩余0)。v1.18.3 的容错有
'if bars:' 条件,bars 为空时 raise → 500。移除该条件,始终 return
(空列表让前端分页重试比 500 友好)。GetIndexBarsCmd 同改。
2. SPA fallback 缺失:/optimize /portfolio 等前端路由刷新时 404。
子类化 StaticFiles 为 SPAStaticFiles,404 时返回 index.html。
API 路径不受影响。
测试:更新 test_security_bars_truncated_first_record(原断言 raise,
现断言返回空列表)+ 新增空 body 回归测试。902 全过。
|
2026-07-07 20:13:39 +08:00 |
|
Justin Gu
|
ecd6e298f5
|
fix(packaging): v1.19.2 修复干净 Windows 上 EXE 页面纯黑(MIME 类型)
根因:干净 Windows(无开发环境)注册表里没有 .js 的 Content Type 映射,
mimetypes.guess_type('.js') 返回 None,StaticFiles 回退到 text/plain。
浏览器 <script type="module"> 启用严格 MIME 检查,拒绝执行 text/plain
的 JS → Vue 不挂载 → 页面纯黑(/docs 不受影响因为它是 API 路由)。
修复:mount 前用 mimetypes.add_type 强制注册 .js/.mjs/.css/.svg 的正确
MIME,无论机器装没装开发工具都生效。
同时改 easy_tdx.spec:datas 用 pathlib.rglob 逐文件展开,更可靠。
|
2026-07-07 15:18:53 +08:00 |
|
Justin Gu
|
0b4ed9af62
|
feat(packaging): v1.19.1 支持 Windows 单 EXE 打包 + 系统托盘 + 自动发版
面向零基础老年用户,easy-tdx 可打包成单一 Windows EXE,双击即用。
新增:
- 后端同源托管前端 dist(app.py 三级探测:env → _MEIPASS → web-ui/dist)
- easy-tdx serve 默认 --open-browser,启动后自动开浏览器
- PyInstaller 打包入口(__main__.py)+ spec 配置(easy_tdx.spec)
- 系统托盘(tray.py):右下角图标,右键"打开浏览器/退出"
解决老人不会用任务管理器关闭的问题
- GitHub Actions release.yml:打 v* tag 自动构建并发布 EXE 到 Releases
- docs/packaging.md 打包使用文档
修复:
- K 线残缺尾记录导致 500(security_bars.py):通达信服务器偶发
ret_count 与 body 长度不匹配,改为 try/except 优雅降级丢弃残缺尾,
返回已解析的完整记录。GetIndexBarsCmd 同改。加 4 个回归测试。
- PyInstaller frozen 模式三个坑:
1. console=False 下 stdout/stderr 为 None → 重定向到日志文件
2. multiprocessing spawn 子进程重新 import __main__ → freeze_support + 子进程检测
3. 系统托盘需主线程消息泵 → uvicorn 挪到后台线程
文档:
- README/手册改为三档分流:EXE(零基础)/ Python(一条命令)/ 源码(打包)
- 删除 npm run dev / 5173 / 两个终端的过时说明
- 手册补虚拟环境配置 + EXE 打包附录 + EXE 排错 FAQ
|
2026-07-07 01:48:07 +08:00 |
|