shy3130
|
ecec9f5e54
|
test(factors): 修 materialize_cache 测试的注册表残留污染
uf_* 因子注册进进程级 _REGISTRY 后未注销, 累积运行时泄入
test_factor_registry 快照与 test_factor_store 断言 (6 条必挂,
HEAD 全量复现)。夹具收尾注销本文件注册的 id。
全量: 3372 过 / 0 factor 污染; 余 4 条 assistant_actions 挂
经纯净 worktree 验证为 ext_pull 会话未提交 WIP 引入, 非本分支存量
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 15:35:55 +08:00 |
|
shy3130
|
a3fcf99c7f
|
fix(strategy): 特征依赖常量流推断 — 跨文件/属性调用点/关键字实参
- 列名经辅助函数形参传递 (_ema(col, alpha) 形态) 时, 家族全部调用点
(含 _dep.helper 跨模块属性调用) 实参为常量即并入收集, 不再整体回退
- 修复三处缺陷: 闭包 uninferable 缺 nonlocal、关键字实参被默认值遮蔽、
分类返回值被调用点丢弃 (fail-closed 破坏)
- 动态形参注册表与调用点解析改为跨文件合并 — 常量流跨 _*.py 生效
- full_fallback 兜底补载 instruments 股本列 (float_shares/total_shares)
- 回归: custom_v1_kanban_strict 精确推出 7 列含 float_shares,
实盘回测 error=None (20 标的, 2.1s)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 15:26:27 +08:00 |
|
shy3130
|
f3c30b728b
|
feat(definitions): P4 统一定义目录 + 导入即冒烟 — 导入到可回测全链 <2s, P0-P4 收官
「一切皆扩展」的消费面与验收闭环:
- GET /api/definitions: 跨 kind (signal/factor) 统一目录视图 (label/lang/
依赖/warmup/状态) — 统一选择器的数据半边; 单个坏定义不阻断目录 (隔离)。
- POST /api/definitions/smoke: 导入冒烟 (静态层) — validate → 编译 → 依赖
可解析性 (enriched/指标/注册表因子/扩展字段的并集判据, 拼错列名 W001
当场报出)。信号编译告警经日志捕获转为 issue, 不静默。
- 备份导入内置冒烟: apply_archive 对每个导入的信号/因子落盘后立刻冒烟,
结果随响应返回 (smoke 字段); 冒烟自身异常不阻断导入 (fail-open)。
- 验收 (docs/ext-architecture-plan.md P4 ≤2 分钟): 自动化全链测试 —
构建含新信号+新因子的备份 ZIP → apply (冒烟 ok) → 立即用引用该信号的
策略跑回测成功, 全程 <2s。
- 前端选择器组件/参数表单自动渲染属前端后续工作, 数据与 API 契约已就绪。
- 回归: config_backup/definitions/factor 67 测试全过; ruff 新增文件全清
(main.py/config_backup 存量告警与 HEAD 逐条一致)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:59:52 +08:00 |
|
shy3130
|
0f12836401
|
feat(factors): P3 T2 表达式级 Python — SKDJ 类口径零 DSL 可表达
自定义因子新增第二档编写语言 (lang=python): 受限 Python 表达式块,
只返回单个 Polars 表达式。三档编译层就此齐备: T1 DSL < T2 表达式级
Python < T3 自由 Python 策略。
- app/factors/py_expr.py: AST 白名单文法 (仅赋值/表达式语句; 名字限
ctx/pl 与已赋值局部量; 禁 import/def/lambda/循环/推导式/下划线属性/
map_*/apply/IO 类调用) + {ctx, pl} + 空 builtins 求值; ctx.col 构造期
登记依赖 (无需推导); warmup 从窗口常量保守求和 (显式声明只能增大,
少算失真是错误方向)。
- 贯通链路: FactorSpec.lang (默认 dsl, 存量零影响) → to_spec 编译分支 →
materialize 按 lang 分发 (T2 结果同样进 P2b 内容寻址缓存, 依赖即缓存键
输入) → API /validate 与 /trial 支持 lang=python。
- 验收 (docs/ext-architecture-plan.md P3): 看板口径 SKDJ — 9日RSV
(分母 0 时取 50) → EMA(α=0.5) 两级 — 的 T2 单表达式与策略文件的分阶段
列实现逐元素一致; 19 个契约测试 (含依赖登记/warmup 下限/11 种文法拒绝
形态/物化与缓存贯通), 相关回归 568 全过, ruff 新增文件全清。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:46:42 +08:00 |
|
shy3130
|
6d51bb52de
|
feat(factors): P2b 内容寻址因子列缓存 — +10 因子热路径增量 0.1ms, P2 两项验收达成
自定义 (DSL) 因子此前每次求值都全量重算 frame_transform (132 万行帧上
每因子 ~36ms, 随因子数线性增长 — 回测/守护复验/实验室批量的共同热路径)。
- app/factors/materialize_cache.py: 键 = sha256(定义 + 依赖列内容指纹 +
行数) — 内容指纹即失效传播 (公式变/输入任何值变 → 键变), 无需数据版本
号。两层: 进程内 LRU (字节上限) + 磁盘 parquet (跨进程, 文件数上限,
目录可整删)。fail-open: 任何故障回退现算。列指纹按帧记忆化 (weakref
finalize 回收), 同帧 K 个因子每列只哈希一次 (~8ms/百万行)。
- materialize_scoring_columns 两段式: 命中列一次批量附着 (成本与因子数
无关); 未命中逐个现算 (依赖顺序)。DSL 分阶段临时列不再泄漏进下游帧
(与命中路径列集合完全一致)。
- 顺带修复存量 bug: winsorize(x) 省略 k 时 DSL 编译器直接 IndexError
(该写法此前完全不可用), 补回归测试。
- 基准 (132 万行, K3→K13): 热路径 0.0ms→0.1ms (+10 因子绝对增量 0.1ms,
基线 +400ms 线性); 冷启动 480.7ms vs 无缓存 478ms (开销 ~0.5%)。
端到端优化器复测 trials 4.23×/含 prepare 3.16×, stats 完全一致。
- 回归: 552 个相关测试全过 (含 6 个缓存契约测试: 命中等价/输入与定义
变更失效/损坏回退/小帧旁路/临时列不泄漏); ruff 新增文件全清。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:36:58 +08:00 |
|
shy3130
|
583462a704
|
feat(backtest): P2a-2 共享矩阵编码 — 参数无关半边一次编码, 调参循环 3.14×
build_market_matrix 内部的参数无关成本 (build_market_data_matrix 行情
矩阵 + _encode_axes 轴 + _signal_code_matrix 信号码, 占剩余每组成本
~55%) 拆出复用:
- matrix.py 新增 PanelMatrixEncoding / encode_panel_matrix /
build_market_matrix_from_encoding; build_market_matrix 改为两者的组合
(单一实现, 无平行路径)。score 场随参数变化 (universe 置空), 不进共享
编码 — 逐组散布进信号矩阵, 非有限值→nan 语义与 _float_matrix 一致。
- PreparedPanelBacktest.sim_encoding: prepare 期构建 sim 窗口编码 (失败
回退逐组建矩阵, 只损失性能); run 侧列序 (忽略 score 列) 与行数比对
通过才走共享编码, 否则整建 — 回退是优化放弃, 不是正确性闸门。
- 基准 (同进程交错 A/B, 15 组): 试算 4.24×, 含 prepare 3.14× (P2a 单
面板共享为 1.8×); stats 剔除计时字段后完全一致。对应 P2 验收 ≥2×。
- 回归: tests/backtest 410 全过 (含新增矩阵级逐元素等价测试); ruff
零新增 (与 HEAD 逐条相同)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:27:37 +08:00 |
|
shy3130
|
660ce71fca
|
feat(backtest): P2a 面板路径 prepare-once — 参数网格共享特征面板, 调参循环 1.6-1.9×
默认后端 (polars_expr/python_history_legacy) 的优化器此前每组参数都完整
重跑 载盘/指标计算/信号注入/扩展表 join (profile: 占每组成本 ~35-60%);
只有 matrix_native 有 prepare-once。本提交补齐面板路径:
- PreparedPanelBacktest: 逐组解析依赖计划取并集 (参数驱动的列差异由并集
覆盖), 一次加载全组复用; run 逐组做 签名校验 + 所需列子集校验, 缺列
显式报错不静默回退 (fail-closed, 掩盖计划漂移比失败更危险)。
- _merge_resolved_feature_plans 放宽为单一后端即可 (composite 的全
matrix_native 语义不变); _panel_backend 谓词与 run 面板分支同口径。
- 优化器: polars_expr 分支 prepare 一次 + 全部试算与最优复跑复用同一面板;
进度新增 optimizer_prepare 事件 (shared_panel_bytes)。
- 基准 scripts/bench_optimizer_prepare.py 同进程交错 A/B (消除页缓存
顺序偏置): 15 组实测 trials 1.72×, 含 prepare 1.62× (6 组 1.92×/1.64×);
stats 剔除计时字段后与逐组独立加载完全一致, 交易逐笔一致。
- 回归: tests/backtest 408 全过; ruff 零新增 (optimizer/strategy 告警
与 HEAD 逐条相同)。
下一步 (P2a-2): build_market_matrix 的面板编码 (build_market_data_matrix
+_encode_axes, 参数无关, 占剩余每组成本 ~55%) 提到 prepare 复用, 预期
含 prepare 越过 2×; 其后 P2b L2 内容寻址物化。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:21:50 +08:00 |
|
shy3130
|
e382232243
|
feat(definitions): 统一定义契约 P1b — Store 基类收口四处持久化 + kind 注册分发
- app/definitions.py 新增 JsonDefinitionStore: 原子写 + 损坏跳过告警 +
目录 mtime 签名, glob/日志名/逐条归一化参数化; 自定义信号/自定义因子/
监控规则/批次四处同型实现收口为委托, 公开签名零变化。
- DefinitionKind 注册表 + validate_definition / definition_dependencies
统一分发入口; 内置 kind (signal/factor) 惰性导入, 消费方无需预导入领域
模块。signal 依赖提取复用编译表达式 root_names (与回测/管线同源),
factor 复用 to_spec DSL 编译 — 不引入第二套提取逻辑。
- 验收: 新增第三种 kind = 注册一个描述器即走同一存取/校验/依赖管线
(test_new_kind_reuses_same_pipeline), 对应路线图 P1b 验收标准。
- 契约视图归一化渲染留给 P4 消费方; 失效广播/文件锁随 P2 叠加。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 14:02:54 +08:00 |
|
shy3130
|
a5e9d8fd28
|
feat(strategy): 依赖推导扩为模块家族 — 补辅助函数/_*.py 硬编码列漏推导
P1a 首版只解析 filter_history 函数体, 列引用在模块级辅助函数或 import _dep
依赖文件里硬编码时会漏推导 → 回测帧缺列 ColumnNotFoundError (响亮报错而非
静默错算, 但相对永远全量兜底仍是行为回归)。
推导范围改为整个策略文件 + 同目录 _*.py 依赖文件 (引擎加载本就把策略目录
插入 sys.path, import _dep 是受支持形态): 家族内任一文件出现动态列名/
pl.all/cs.* 即整体返回 None 保持全量兜底 — 范围放宽只会多载列, 不会漏。
新增 infer_features_from_sources 承载家族推导, 单函数版保留为薄包装。
实测基准宽度不变 (short_term_top10 动态循环仍正确走全量兜底)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 13:51:44 +08:00 |
|
shy3130
|
9d554a519f
|
fix(ext): 内置预设只播种一次 — 删除后重启不再复活
用户删除 ext_gn_ths/ext_hy_ths 后, 每次重启 ensure_builtin_presets 都会重建
配置 (uvicorn --reload 也触发), 与用户自有源并存叠加每日 710 次成分股拉取。
引入 ext_data/.builtin_presets_seeded 播种标记: 预设创建仅发生在标记缺失时
(全新数据目录 / 老库首次升级); 已播种后缺失 = 用户删除过, 不复活。标记独立
于表目录, 删单表不误清。配方迁移 (_RETIRED_FACTORY_PULLS) 不受标记限制,
存活表的出厂配方升级继续送达; 中途失败下次启动幂等重试。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 13:51:29 +08:00 |
|
shy3130
|
8cedb67c36
|
feat(strategy): filter_history 列依赖 AST 推导 — 消灭回测全量兜底 (P1a)
- feature_deps: 追踪 pl.col/cols 常量引用推导输入列; 动态列名/pl.all/cs.*
等不可证明形态一律返回 None, 保持全量兜底 (fail-closed, 宁慢不错列)
- engine: REQUIRED_FEATURES 缺失且存在动态过滤时加载期自动推导
- bench_feature_resolution: legacy(空依赖) vs 推导 的解析宽度对比基准
- 实测: 看板策略等 4 个无声明策略 37→3~5 指标列 (宽度比 7~12x);
short_term_top10 动态列名循环正确保持兜底
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 13:39:39 +08:00 |
|
shy3130
|
e9b938a3ac
|
docs(arch): 一切皆扩展架构优化路线 (P0-P4) — 分层物化/统一契约/依赖推导
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 13:39:39 +08:00 |
|
shy3130
|
2892c644f1
|
feat(backup): 配置备份与迁移 — 18 类别 ZIP 导出导入, 彻底解决多设备配置丢失
- 后端 config_backup service + /api/config-backup 三端点: 按类别导出/预览/导入
- 覆盖策略/监控/信号/因子/偏好/自选/持仓/模拟盘/挖掘候选/数据源/菜单/扩展页面/扩展数据集/语音包/历史记录
- 密钥与访问凭证默认脱敏不导出, 显式勾选才打包; 偏好/密钥 merge 写入
- ZIP 白名单路径 + 防炸弹 + 策略 AST 安全校验, 冲突默认跳过可选覆盖
- 监控徽标/导航形态/回测列表高度/设置页收起接入 uiPrefs 跨端同步
- 设置页新增「配置备份」标签页, 导出/导入向导式 UI; 16 个专项测试
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 12:13:19 +08:00 |
|
shy3130
|
b1a4dc6e38
|
chore: v0.3.17
Signed-off-by: shy3130 <shy3130@qq.com>
v0.3.17
|
2026-10-26 09:59:09 +08:00 |
|
shy3130
|
7fadaa907d
|
fix(tdxquant): 分钟K整批0行 — Time数值形态归一 + Value包装解包 + 零行诊断
issue #509: 分钟同步进度正常、积分已扣, 但 0 行落库且全程无告警。三类叠加缺陷:
- Time 列归一: 原生返回混出 int/float 裸值(93100)与缺前导零 5 位串,
旧 _minute_dt 的 6 位数字串强校验把这类返回整批静默丢弃(全天 240 根
整型时间 → 0 行)。归一规则对齐 SDK get_market_data 的 "%06d" 拼法,
4 位及以下按 HHMM 补零(分钟K 9:30-15:00 时段内唯一有效读法)。
- Value 包装解包: 部分环境原生返回把数据整体包在 "Value" 键里, SDK
有同款防御而插件没有 → 0 行。client.his_dats 统一解包, provider
解析层(_kline_rows/_minute_rows)双保险。
- 分钟请求 end 传完整时刻: 截到 00:00:00 会把当日分钟全部排除在窗口外。
- 零行诊断: 返回非空但解析 0 行(复验剔除窗口过滤的正常情形)时打出
带字段样本的 WARNING, 进程内限 3 个标的防刷屏 — 格式漂移不再静默。
测试: +8 项形态矩阵(全天整型时间复现/Value包装/HHMM/end保时刻/
诊断含样本/限流), 组内 48 绿; 后端全量 3271 绿(ruff 零新增)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 09:58:55 +08:00 |
|
shy3130
|
b573ca43eb
|
feat(mining): 挖掘锁撞锁降级启动 + 持有者诊断 + 一键强制释放
复现的原始问题: 旧实例挂死在 shutdown (热重载撞上挖掘运行) 或 worker
成为孤儿后, `.mining_process.lock` 被无限期占用, 后续所有后端实例
在 lifespan 抢锁时直接启动失败, 用户只能对着笼统报错手动找进程。
- 锁文件记录持有者 {pid, started_at, role, host} (flock 仍是唯一
事实, 内容只是诊断线索; 旧格式 "0" 兼容, 视为持有者未知);
新增非阻塞探测, 无需抢锁即可判断是否被持有。
- 撞锁降级启动: lifespan 抢锁失败不再上抛, 面板照常可用; 挖掘
启动入口 (手动/自动/周度调度) 返回 409 并指引到挖掘页; 桌面版
预检从「秒退失败页」改为留日志继续启动; 守护复验不受影响。
- 挖掘页锁占用横幅: 显示持有者 pid/角色/挖掘存储静默时长; 满足
陈旧判定时可一键「强制停止并接管」(SIGTERM→SIGKILL→当前后端
获取锁, 挖掘入口立即恢复)。
- 陈旧判定全部 fail-closed: 持有者信息可读、进程存活且 pid 未被
复用 (POSIX 比对进程实际启动时间)、无进行中的挖掘运行、挖掘
存储 10 分钟内无写入 — 任一不满足即拒绝并给出原因。不做启动
时自动清理, 终止进程必须人工确认。
测试: 新增 test_mining_lock_admin (含真实外部持锁进程的强停回路与
五类拒绝路径), 重写 lifespan 降级契约与桌面预检继续启动契约;
后端全量 3239 通过, 前端 308 通过, ruff 零新增; 沙盒 E2E 完整
复刻「持锁→降级→强停→接管→恢复」事故场景通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 00:01:20 +08:00 |
|
shy3130
|
e01fe96241
|
chore: v0.3.16
本次发布包含自动策略实验室 (feat(lab): 守护复验 + 稳健选冠/权重
精调 + 组合建议 + 闭环编排), 让挖掘发布的策略在真实新数据上被
持续验证 (健康/观察/退役), 冠军按稳健分选出并做权重精调, 健康
冠军间低相关可一键生成组合策略, 实验室战报聚合守护/挖掘/名额。
版本号同源: VERSION / frontend/package.json / backend/pyproject.toml /
backend/app/__init__.py 的 _FALLBACK_VERSION / release.yml 的 inputs
默认值; uv.lock 仅改项目自身条目。
Signed-off-by: shy3130 <shy3130@qq.com>
v0.3.16
|
2026-10-25 23:43:45 +08:00 |
|
shy3130
|
21279ecfa2
|
feat(lab): 自动策略实验室 — 守护复验 + 稳健选冠/权重精调 + 组合建议 + 闭环编排
在既有挖掘链路之上补齐「发布后持续验证与持续组合」闭环
(设计: docs/auto-strategy-lab-plan.md):
- P1 策略守护: 挖掘发布自动落 mining_gate 基线 (天然 OOS); 每日收盘
数据更新后在新数据上切 K 段真实回测复验, 按稳健分对比基线判定
健康/观察/退役三态 (段回测失败只降级观察不退役; 新数据 <30 交易日
跳过本轮; retired 不再自动复验)。任意策略可手动入护 (尾随参考基线,
判定只针对入护后新数据)。回测页稳健性验证新增「策略守护」子页。
- P2a 稳健选冠: 冠军排序分从外层折 Sharpe 均值改为 0.6×中位+0.4×最差
(复用 robust_score); artifact 新增可选列 oos_worst_sharpe (v2 旧档
兼容读取); strict 档发布额外要求最差折 Sharpe>0; 算法版本升
mining-v3 并进数据指纹, 防止升级后 claim 幂等复用旧口径结果。
- P2b 权重精调: 冠军组合在 {0.5,1.0,1.5,2.0} 比率网格 (首因子固定
1.0, 截面分位打分天然尺度不变) 两段式精调 — 外层测试窗选优 + 全窗
复验退化>20% 放弃; 消耗 run 剩余预算 (不足自动跳过); 产物为独立
签名候选行, run summary 带 refinement 摘要。
- P2d 组合建议: 守护运行时扫描健康冠军间近 126 个交易日日收益 Pearson
相关性 (≥30 共同交易日, ≤0.7 入选); 前端人工确认后生成等权
composite 策略 (fail-closed 建议对校验 + blake2b 幂等) 并自动以
尾随参考基线入护。
- P3 闭环编排: lab_mined_slot_limit 偏好 (默认 10, 0=不限) 在发布
门槛通过后校验, 名额满则新冠军停在 pending 等位;
/api/backtest/lab/report 聚合守护/挖掘/名额战报 (前端总览卡);
lab_schedule 单入口编排周度挖掘 + 日度守护 (失败互不阻断)。
测试: 新增 guardian 判定/运行时/存储/调度/API/组合与挖掘 v3 选冠/
精调用例; 后端全量 3224 通过, 前端 308 通过; 真实数据沙盒 E2E
(挖掘 v3 全链路 / 发布门槛 / 名额边界 / 复验语义 / 组合扫描 /
战报核对 / 性能延迟) 通过。P2c (overlay 候选) 按设计稿按需启动,
默认不做。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 23:43:34 +08:00 |
|
shy3130
|
797f0c5f70
|
chore(frontend): 清理 klineBatchLimits 测试未用导入
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
5e2c1f76eb
|
feat(frontend): 回测页策略选择区支持拖拽调高
策略列表底部新增拖拽手柄 (指针捕获, 80-480px, 键盘上下方向键微调),
高度记忆到 localStorage, 刷新自动恢复。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
df9d178060
|
feat(assistant): 中断提示可点击重试 + 历史会话显示时间
- 生成中断后的"已中断, 可点击重试"提示此前是纯文本, 现在是可点击按钮,
点击即携带原上下文重发
- 历史会话列表每项增加时间行 (今天/昨天 HH:MM, 更早 MM-DD / YYYY-MM-DD)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
fff52f93cc
|
feat(settings): 自定义提示音语音包上传
设置页可上传/试听/删除自定义提示音 (mp3/wav/ogg 等 8 类, ≤4MB),
存储 data/sound_packs/, 键名 custom:<文件名> 复用现有 alert_sound
偏好通道, 零新配置项; 删除当前正在用的语音包时自动回退默认提示音。
后端 6 项测试 + 前端 3 项测试。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
62c8a8bd56
|
fix(backtest): 矩阵回测接入扩展时序数据
扩展数值列按设计不落 enriched parquet (只存 14 列), 此前矩阵回测引用
ext_* 字段直接报 fields unavailable — 叠加条件/评分引用扩展数据的策略
无法回测, 扩展数据失去回测意义。
修复: 引擎在矩阵加载后按矩阵自身 (日期×标的) 骨架现场注入时序模式数值
扩展字段 (attach_matrix_ext_fields, 与策略页帧路径同一台 PIT 安全 join,
缺失补空值=条件不命中), 与财务因子 attach 同构; parquet 矩阵缓存不受
影响。快照模式与字符串扩展字段仍拒绝 (快照回看历史=未来函数), 引用时
前置校验给出明确报错。
实测: 隔夜溢价精选·迭代优化 + 人气排名 20~100 叠加条件, 回测 1.1s 跑通,
交易数 29→22 证明过滤真实生效; 新增 7 个单测 (对齐/NaN/拦截/叠加联动/
端到端正反例), 全量回归 3131 通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
da9dbca422
|
feat(backtest): 稳健参数筛选与滚动样本外检验重构 (P1-P4)
参数排名从单窗样本内得分改为 K 段折外稳健分 R = 0.6×中位 + 0.4×最差
(设计: docs/robust-optimizer-plan.md), 四阶段全部落地:
- guards 共享护栏: 主目标白名单 + 最小交易数门槛 (fail-closed, 缺交易数
按不达标处理), 两模式一处实现
- robust_optimizer: 等分切窗 (2-6 段, 每段≥14天) / 稳健分 / 冠军收敛诊断
(unanimous/majority/scattered) / Top-20 全窗 IS 细化与退化率 /
高原判据 (邻域得分衰减, 零额外回测); worker 接线 robust_optimize 任务
- 滚动样本外检验补强: 每折 OOS 最小交易数门槛 (无效折透明跳过),
前端折预览 / 参数漂移轨迹 / 采用最新折参数
- 前端: 冠军卡 (收敛/高原徽章/乐观偏差) + K 段排名表 + 验证窗预览 +
应用参数闭环 (POST /strategies/config, 可逆); SSE 重连与跨设备接回
- P4 摒弃旧路径: 删 /optimize/stream 与 /optimize/cancel 端点及 worker
optimize 任务类型; 白名单全面生效 (optimizer.VALID_OBJECTIVES 收敛到
guards; walkforward 端点校验退化目标 400)
- 附带修复: 叠加条件×矩阵路径 SignalMatrix 只读违规 (np.where 产物
可写), optimizer_trial 轻量统计恒保留 n_trades
实测: 126 组合全市场网格 1.71× 旧版耗时 (视图复用优化自 2.01×; 差额
为引擎层每 run 固定开销, 详见方案文档第九节); 全量回归 3131 通过。
api.ts 同时带入稳健优化折预览客户端与声效语音包 API 客户端
(语音包功能随后续提交落地界面)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:10 +08:00 |
|
shy3130
|
c0daaa8302
|
docs(readme): 同步测试数与助手动作工具数
- 测试数 2400+ → 3000+ (后端 3096 + 前端 55 个测试文件)
- 动作工具 4 → 5: 补创建 AI 策略草稿; 补免确认开关说明 (默认关,
轮次检查点安全阀不受影响)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:40:19 +08:00 |
|
shy3130
|
7f6cad0f8f
|
feat(factors): 因子生命周期状态下发 + 发现页三视图重构 (批量/单因子/挖掘)
- 因子注册表按 id 合并下发完整生命周期 status (draft/active/watch/retired),
registry 的 stability 降为其二元投影; asset_type 过滤适用资产
- FactorDiscovery 重构为 批量/单因子/挖掘 三视图 (MiningWorkbench),
标的列表解析兼容中英文逗号/分号/顿号/空白分隔
- FactorLibrary/FactorEditor/回测页配套调整
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:16 +08:00 |
|
shy3130
|
6c8805204e
|
feat(assistant): 动作免确认开关 + create_strategy 工具 + 毛玻璃遮罩
- 动作工具免确认开关 (助手界面, 默认关): 只影响动作确认, 轮次检查点
安全阀不受影响; 偏好读取失败一律按关闭处理
- 新增 create_strategy 动作工具: 写入 ai_ 策略草稿, 发布后才生效
- 助手打开时页面毛玻璃遮罩, 点击遮罩关闭助手 (可开关)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:11 +08:00 |
|
shy3130
|
ddaab1fbf1
|
fix(minute): 全量分钟服务落盘持仓库写锁 + 原子写临时名唯一化 + 基准状态暴露
- minute_refresh 落盘改持 repo._write_lock: 与 minute-batch 补拉/盘后同步
同一纪律。此前服务是唯一不持锁的写者, 并发替换同一分区时后写者以过期
基底覆盖丢整批行, 且共用固定名 tmp 会交错损坏且无自愈。实测增量轮落盘
~10ms, 锁占用可忽略
- _atomic_write_parquet 临时名加 uuid 后缀: 消除两写者共用同一 tmp 的
交错损坏窗口; 崩溃孤儿 tmp 不匹配 *.parquet glob
- 服务每轮记录本地库 raw 基准状态 (status 新增 minute_basis_raw 字段),
未迁移库一次性警告不刷屏; 插件契约文档补"full_minute 必须返回原始价"条款
- 修正头注释 clamp 漂移 ([3,300]→[3,120])
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:05 +08:00 |
|
shy3130
|
d43a3021da
|
feat(kline): 批量上限可配置(前后端同源) + 响应懒净化与 Polars 直出
- 日K/分时批量单请求上限改为系统设置可配 (默认 400), 后端守卫与前端分块
读同一偏好值, 不再发出必然被拒的请求; 两档独立 (分时成本约为日K 20 倍)
- _gzip_payload 懒净化: 无 NaN/inf 常态跳过 _json_safe 整树深拷贝,
峰值 -65% (40→14MB/块), CPU -25%
- minute-batch/daily-batch 全程持有 Polars 帧直出 JSON (write_json 行式),
不再构建 Python dict: 96k 根序列化 1222ms→26ms, 峰值 69→18MB;
字节级等价由 tests/test_kline_batch_frames_json.py 锁定 (含 inf/NaN/None)
- 白盒测试改为解析 Response body (HTTP 真实契约)
- 随 kline.py 同文件: minute-batch 门控在全量分钟服务健康时放行本地读,
补拉限速改走 resolve_limit (×0.8, 与盘后同步同 rpm 桶)
实测: 300 只分时(7.2万根)整请求 191ms; 20 并发尖峰 +728MB→+60MB
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:01 +08:00 |
|
shy3130
|
5f70eb9ef2
|
chore: v0.3.15
本次发布包含三组修复:
- fix(ext-data): 资金流等当日快照接口不再被日期一致性校验误拒写;
schema 端点恢复返回真实列类型 (DuckDB 1.5 的 DESCRIBE 列名变更);
拉取配置的分页参数不再保存后静默丢失。
- fix(settings): 系统设置的通知弹窗/声效/语音播报/外链模板/界面缩放
改后端持久化, 修复桌面版换端口 (origin 变化) 后配置丢失。
- fix(minute): 残缺分钟分区不再被当作无数据丢弃; 新增分钟缺口体检
面板, 让「同步完成≠数据完整」可见。
同时引入 DCO 贡献来源声明与再许可授权条款, PR 须逐提交带
Signed-off-by (CI 由 .github/workflows/dco.yml 检查)。
版本号同源 5 处: VERSION / frontend/package.json / backend/pyproject.toml /
backend/app/__init__.py 的 _FALLBACK_VERSION / release.yml 的 inputs 默认值;
uv.lock 仅改项目自身条目 (上次升版误改 pytesseract 的问题不再复现)。
Signed-off-by: shy3130 <shy3130@qq.com>
v0.3.15
|
2026-10-24 22:56:37 +08:00 |
|
shy3130
|
864ad2a95c
|
chore(contributing): 引入 DCO 贡献来源声明 + 再许可授权条款
为未来的协议切换 (MIT → AGPL-3.0) 与商业双授权做准备:
- CONTRIBUTING.md 新增第 14 节: 每次提交须带 Signed-off-by 尾注
(git commit -s), 并授予维护者永久、不可撤销、全球范围、非独占、
免版税的再许可权; 明确本节仅对生效日之后的提交生效, 历史贡献永久
保持 MIT; 列出需签署正式 CLA 的情形 (职务作品/专利/大额贡献)。
- .github/workflows/dco.yml: PR 事件逐提交检查 Signed-off-by 尾注,
跳过 merge commit; 仅检查 PR, 不阻塞 main 上的直接提交。
- README.md 贡献入口补充 DCO 提醒。
仅有 DCO 尾注不足以支撑协议切换 —— 缺少明确的再许可授权时, 维护者
只能在现有协议下分发第三方贡献, 无法完成 AGPL 化与商业双授权。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:49 +08:00 |
|
shy3130
|
cce38f2ce7
|
fix(settings): 系统设置改后端持久化, 修复换端口后配置丢失
用户反馈系统设置里部分配置保存后重新打开又变回之前的状态。
根因不是保存逻辑坏了, 而是存储位置错。系统设置页有 9 项只写浏览器
localStorage: 通知弹窗开关/最大弹窗个数/声效开关/声效选择/语音播报
开关/音色/语速/个股外链模板/界面缩放。而浏览器按 origin (协议+主机+
端口) 隔离 localStorage, 桌面版启动时用 _find_free_port(3018) 从 3018
起取第一个空闲端口再以 http://127.0.0.1:{port} 打开窗口 —— 端口一变,
对这个应用就是另一个站点, 此前存的设置全部读不到。走 preferences.json
的那些设置一直正常, 所以现象是「有些配置会丢」。
修复: 后端权威副本 + localStorage 本地缓存的双写方案。
- preferences.py 新增 ui_prefs: 9 个键的白名单、只接受 JSON 标量、
null 表示删除、16KB 上限;
- 新增 PUT /api/settings/preferences/ui-prefs, GET /preferences 带上
ui_prefs;
- 新增 lib/uiPrefs.ts: setUiPref 写本地后 300ms 合并上推后端,
hydrateUiPrefs 启动时从后端回填;
- 系统设置页 7 处 localStorage 直写、外链模板、界面缩放改走 setUiPref;
- main.tsx 启动触发回填并重放一次缩放。
保留 localStorage 而非全部搬到后端, 是因为通知/语音/缩放等模块在非
React 路径 (SSE 回调、index.html 首帧脚本) 同步取值, 不能等网络。
回填规则为本地优先: 本地已有值上推后端, 不被启动时的旧副本覆盖; 只有
本地缺失的键才用后端值补 —— 升级用户首次启动即完成迁移。
验证: 端到端模拟「清空 localStorage 换端口」后重载, 三项设置在 ~330ms
内全部恢复且稳定, UI 正确反映 (弹窗数 5 / 语音开启 / 缩放 110%);
后端 test_ui_prefs 8 passed (stash 实现后 8 个全失败, 确认用例有效);
tsc --noEmit 与 pnpm build 通过; ruff 告警数与基线持平。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:41 +08:00 |
|
shy3130
|
a40c0780d7
|
fix(ext-data): 快照接口误拒写 + schema 类型丢失 + 分页配置静默丢弃
用户反馈资金流扩展表点「手动拉取」报错、板块轮动的资金流下拉为空。
排查出三个独立缺陷:
1. 日期一致性校验用错判据 (ext_pull.py)
报错: 「接口返回的日期与请求日期不一致, 已拒绝写入该分区」。
_assert_rows_date 无条件校验响应 date 必须等于请求日期, 但该契约的
目的只是防「接口忽略 ?date= 却把当日值写进历史分区」, 仅对按日查询
接口有意义。资金流/人气等当日快照接口只有最新一个交易日的数据,
周末/节假日/数据源 T+1 时响应日期本就落后于请求日期, 被误判成
「接口忽略日期参数」而整表拒写。
修复: 新增 _assert_rows_date_if_dated, 仅在 pull.date_param 已配置
时校验; 历史回补的 fail-closed 防污染契约不变。
2. schema 端点一直抛异常走兜底 (api/ext_data.py)
「SELECT column_name, data_type FROM (DESCRIBE ...)」在 DuckDB 1.5
抛 BinderException —— 该版本输出列名是 column_type (1.4 及以前才是
data_type)。异常被吞后回退到配置字段, 那些对象只有 dtype 没有 type,
前端按 type 判断数值列的资金流下拉因此永远为空。
修复: 按实际输出列名取值, 两个版本都可用; 兜底分支键名统一为 type。
同时关掉 hive 分区推断 —— date=YYYY-MM-DD 目录会让 DuckDB 凭空多出
一个 date 列, 污染列选择器。
前端 NUMERIC_TYPES 由写死的 5 个简写改为类型族匹配, 覆盖 DOUBLE /
BIGINT / DECIMAL 等 Parquet 真实类型名。
3. 分页配置保存后被静默丢弃 (api/ext_data.py)
PullConfigReq 缺少 page_param / page_size_param / page_size /
page_start / max_pages, 前端「拉取设置」提交这些值后 Pydantic 直接
忽略, 保存后再打开退回默认的单次请求, 且不报错。
修复: 补齐请求模型字段并透传到 PullConfig。
验证: 三处均先写复现用例 (未修复代码上 7 个用例失败), 修复后全绿;
扩展相关后端测试 202 passed; 前端 SectorRotationCard 7 passed;
pnpm build 通过; 真实接口验证 —— 修复前 400「日期不一致」, 修复后
200 写入 5580 行, schema-all 返回 DOUBLE/BIGINT/VARCHAR 真实类型。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:40 +08:00 |
|
shy3130
|
7812c02ec4
|
fix(minute): 残缺分钟分区不再丢弃 + 新增缺口体检面板
用户反馈自选/策略列表分时列「今天能看、昨天不能看、前天又能看」。
根因有两处:
1. /api/kline/minute 把「不完整」等同于「无数据」直接丢弃, 转而请求
分钟源; 而分钟源通常只提供最近 N 天历史, 补拉历史残缺日期恒为空,
前端白屏 —— 用户看到「同步完成却显示不出来」。
修复: 历史日期本地有行时优先返回已有行 (source=local_partial), 不再
为补不回来的缺口丢弃可用数据; 分时图顶部提示「不完整 x/240 根」并
提供「尝试补齐」。当日盘中保持原行为: 本地落后于实时源是常态, 仍走
补拉 (见 test_minute_lunch_break_still_pulls_when_morning_incomplete)。
2. 「同步完成」不等于「数据完整」, 缺口只能靠用户撞见白屏才被发现。
新增 GET /api/kline/minute-gaps 体检: 扫描本地 kline_minute 分区,
列出不完整的 (symbol, 交易日), 判定口径与 /api/kline/minute 的
is_complete 一致 (>= expected*0.9 视为完整; 当日按已开盘分钟折算,
不误报盘中进度)。只做发现不做批量补齐 —— 超出上游窗口的缺口补不
回来, 盲目重试只是白等, 面板如实标注可补/超窗。
前端: 数据页分钟K卡片新增「数据体检」区块 (MinuteGapPanel), 按交易日
汇总缺口并支持按需补拉单只。
验证: 后端 65 passed (含新增缺口扫描/当日折算/窗口外标注用例);
前端 pnpm build 通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:36 +08:00 |
|
shy3130
|
aa29522484
|
fix(intraday): 竞价图不再整幅铺满 + 手动刷新无分钟数据
- AuctionOnly: 无分钟K时竞价限左侧窄栏 (按宽度档, 默认 30%), 右侧留「暂无分时」占位,
不再整幅渲染竞价曲线让人误以为就是分时
- 增量 since 逐 symbol 计算并按 since 分组发请求: 块内混有未缓存 symbol 时不再被裁到 1 根
- 残序列自愈: 缓存不足 2 根时视为未缓存全量重取, 修复「1 根卡死 → 刷新永远只回 1 根」
- 测试: 逐 symbol since 拆分/残序列自愈回归 + 竞价窄栏布局断言
|
2026-10-24 17:50:53 +08:00 |
|
shy3130
|
ceb1b70a4b
|
perf(watchlist): 大列表内存优化 — 批量K线视口化+分块+缓存收敛
- 后端: minute-batch/daily-batch 单次 symbols 上限 400, 挡千只自选整表直发的服务端 dict 峰值 (test_kline_batch_symbol_cap 4 例)
- 分时批量视口化: 表格视图接入视口上报 (StockDataTable onVisibleRowsChange), 分钟数据只拉视口集合, 缓存 LRU 淘汰封顶 500 只; 列表 ≤300 只行为不变
- 请求分块: 自选/选股/中签页批量日K统一 300/块串行拉取合并 (klineBatchChunked)
- queryKey 收敛: minute-batch/kline-batch 去掉全量 symbols 拼串 (增删自选不再整批重拉/双份共存); Layout 与自选页 enriched 缓存合一
- SSE watchlist-enriched invalidate 5s 节流 (leading+trailing), 消除每秒整表重拉
- 单测 16 例新增: 分块/since 增量/LRU 淘汰/节流器
|
2026-10-24 11:28:26 +08:00 |
|
shy3130
|
13ac689427
|
feat(pages): 扩展页面新增「新建 URL 页」快捷入口 — 一键以 URL 嵌入模板打开表单
|
2026-10-23 22:27:39 +08:00 |
|
shy3130
|
5d6ac5c736
|
fix(logs): 日志归拢 data/logs/ 并为桌面版 desktop.log 增加大小切割
- 新增 app/logfile.py attach_rotating_log: 统一 data/logs/ 子目录 + RotatingFileHandler + 旧位置日志一次性迁移 (目标已存在/被占用则跳过, 失败仅 warning 不阻断启动)
- desktop.py: desktop.log 由无限追加 FileHandler 改为 10MB×5 切割 (长期挂机不再无限增长); 失败页与错误提示的用户可见路径同步 data\logs\desktop.log
- main.py: backend.log 改用共享函数, 参数不变 (10MB×3), 目录随迁
- README/dev.ps1 排障路径同步; 新增 test_logging_setup.py 4 例 (迁移/冷启动/不覆盖/不可写容错)
|
2026-10-23 22:00:51 +08:00 |
|
shy3130
|
14391914e3
|
feat(analysis): 轮动卡可读性优化 — 领涨易主标注/末端板块名/热力图领涨轨迹/图例条与头部分层
- 走势线: 新王接管时点圆点+板块名标注 (computeLeaderReigns, 按在位时长截断), 线末端常显板块名 (shiftY 防叠)
- 热力图: 配色两端饱和+可见中性色, 领涨轨迹亮琥珀描边+辉光, 未封口列白描边, 格间细缝
- 三图段落说明改为真实色块图例条; 头部拆分 标题/状态 行与数据塑形工具行, 显示模式改胶囊分段
- x 轴刻度 hideOverlap+间隔放宽, 修复末尾刻度与强制最大刻度叠字
- 新增 SectorRotationCard.test.tsx (纯函数+渲染断言 6 例)
|
2026-10-23 15:03:10 +08:00 |
|
shy3130
|
c286af7040
|
fix(desktop): 失败页排查链路收尾 — 预检窗口兜底, 启动失败真因落盘 desktop.log
PR #497 复审建议落地:
- main() 预检冲突路径在 try/finally 之外, _open_static_window 自身失败
(如缺 webview 依赖) 会裸穿 main(): console=False 闪退无反馈且
.desktop.lock 跳过释放 → 补兜底, 锁必释放、退出码 1
- uvicorn log_config=None: uvicorn.* 默认独立 console handler 且
propagate=False, windowed 模式 stderr 已被守护替换, lifespan 启动失败
到不了 desktop.log (失败页承诺的排查入口) → 走 root FileHandler 落盘
- lifespan 抢挖掘锁失败先 logger.error(含 traceback) 再 raise, 不依赖
uvicorn 版本的日志行为
测试: uv run --extra dev pytest tests/test_desktop_startup.py
tests/test_main_mining_lifespan.py -q → 13 passed; 全量 tests -q →
2995 passed, 7 skipped, 1 xfailed; ruff 改动前后均 19 条历史遗留, 零新增
|
2026-10-23 14:13:44 +08:00 |
|
 wshyandGitHub
|
1fa7e84f45
|
Merge pull request #497 from yanbaobao010913/pr/desktop-failure-page
feat(desktop): 启动失败页带定位原因 — 预检挖掘锁, 不再笼统报超时
|
2026-10-23 14:02:45 +08:00 |
|
shy3130
|
3632f60baf
|
fix: 修正 uv.lock 版本升版位置 (误改 pytesseract 条目导致解析失败)
v0.3.14 升版时 uv.lock 的项目条目行号已漂移, grep 首个命中误改了恰好
同为 0.3.13 的 pytesseract 依赖版本, CI uv 解析锁文件失败 (desktop/docker
双流水线红)。现回滚 pytesseract 至 0.3.13, 项目条目 tickflow-stock-panel-
backend 升至 0.3.14 — 与 v0.3.13 同款最小编辑模式。
v0.3.14
|
2026-10-23 11:44:22 +08:00 |
|
shy3130
|
a747d1f615
|
chore: v0.3.14
|
2026-10-23 11:37:41 +08:00 |
|
shy3130
|
60081d1e5f
|
fix(kline): minute-batch 补拉落空时回退本地行, 分时图不再整只消失
上游断网窗口 (2026-10-23 实测 40 分钟) 中, 全量分钟服务停写致所有标的
尾部落后, 实时补拉同时失败 → 未修复代码把这些标的整只从结果丢弃, 前端
分时列全部退化为只剩竞价栏。该行为自端点设计之初即存在 (非近期 PR 引入)。
修复: 结果合并步骤对「本地已有部分K但本轮补拉失败/为空」的标的回退返回
本地已落盘的行 (图冻结在最后落盘时刻), 响应新增 truncated 字段标记残缺
symbol 供前端提示; 严格只回本地行不外推。新鲜路径与 prefer_local 抑制
路径零变化; truncated 与 data 键一致, since 过滤后无行的标的不标记。
|
2026-10-23 11:37:21 +08:00 |
|
shy3130
|
b0022a088b
|
chore: v0.3.13
v0.3.13
|
2026-10-22 22:24:11 +08:00 |
|
shy3130
|
74e3934495
|
wip(list-columns): 列配置底座 + 默认方案快照 + series-identity (自 stash 恢复)
自已删除的 feat/list-column-config 分支 WIP 暂存恢复 (stash 曾是唯一副本):
列自定义面板底座扩展、默认列方案快照、series-identity 稳定键。
验证: vitest 278 passed (另 2 个失败文件为存量空占位), tsc -b 通过。
|
2026-10-22 22:13:33 +08:00 |
|
shy3130
|
20a36681e9
|
Merge PR #493: 减少日K同步临时读写
|
2026-10-22 21:52:59 +08:00 |
|
shy3130
|
5866dab938
|
Merge PR #496: fix(kline): 自定义分钟源按块流式落盘, 中断不再全量丢失
# Conflicts:
# backend/app/services/kline_sync.py
|
2026-10-22 21:52:51 +08:00 |
|
shy3130
|
f5c291c287
|
Merge PR #498: fix(pipeline): 分钟同步门控与 api/kline 对齐, 自定义源按 dataset 放行
|
2026-10-22 21:51:22 +08:00 |
|
shy3130
|
19961810a7
|
Merge PR #494: 修复自定义分钟源失败后误用 TickFlow
|
2026-10-22 21:51:13 +08:00 |
|