Files
tick-stock-panel/backend
shy3130 2d629197c1 fix(backtest,services,frontend): 回测成交口径/任务注册表并发/查询键一批正确性修复
回测成交口径:
- close_t 按收盘价成交的建仓日: 当日 high 发生在建仓之前, 不得进入移动止损
  峰值 (峰值虚高会把风控线上移、退出提前) — 矩阵独立/矩阵组合/legacy 三条
  路径同口径; 新增回归测试锁定 open_t+1 对照组不被误伤
- 矩阵路径补收盘封死跌停拦截 (含一字), 经 pending_exit 递延到下一可卖日,
  与独立/legacy 路径同口径 (此前尾盘封板股按跌停价"卖出"低估亏损)
- #388 当日指标纪律同口径: 盘中成交不可知当日收盘, 代数剔除当日 enriched
- 分钟回放: 入场价用前复权口径 (与日线出场同尺度); 除权日涨停参考价按
  ex_factor 还原 (直接用 raw_prev 会把涨停价算高, 除权日封板拒买漏检)
- 指标管线: 涨停参考价除权口径修正 + 夏普用样本标准差 (ddof=1, 与 engine 一致)
- 回测任务: _acquire_or_evict_job 收口同 key 复用/强制重建 (参数不同先取消
  旧任务, 避免旧任务占着重任务槽跑完)

服务与并发:
- task_registry 读-改-写加锁: 两个前端 fire-and-forget 并发上报时后写者
  覆盖先写者 (丢终态翻转或整条记录); 文件写入本身原子, 锁只护 RMW 段
- quote_service 生命周期锁串行化 start/stop/enable 的 check-then-act (双标签页
  并发开关会起两条轮询线程 → 双倍拉取配额 + 重复 SSE 广播)
- 系统通知投递移入专用单线程池: notify_adapter 底层 subprocess 逐条最长 5s,
  在 _poll_loop 同步执行会让告警风暴阻塞一轮监控评估, 拖慢行情拉取与推送
- sector_monitor / minute_refresh / wecom_bot: 同类单实例与停止时序加固
- ai_provider: 401 识别加词边界 (避免模型正文含 401 数字串误判鉴权失败并
  附出不相关指引); 自定义可执行路径校验可执行位
- api/data: 清空数据期间暂停全量分钟增量线程 (否则"清完又被写回部分今日
  数据"); 状态接口偏好/能力探测异常降级而不是 500
- api/kline: 失效内存 enriched 快照 (非空缓存不校验 generation, 只刷 DuckDB
  视图会让重建结果对自选/筛选/监控不可见直到进程重启)
- api/position_policies: 非法 ID 纵深防御按不存在处理

前端:
- assistant store: 生成终态 (中断提示/流式收敛) 钉在发起会话, 切换或删除会话
  不再把"已中断"写进无关新会话
- backtestTask: 键上挂着旧任务且新参数不同 (不同 job_key) 时先取消旧任务,
  避免其占着重任务槽跑到自然结束; 同参重跑跳过取消 (后端按同 key 复用 /
  force 重建已完成任务)
- 查询键集中与正确性: QK.instrumentNames (排序去重, 同一集合不同来源顺序
  复用缓存)、QK.kline 滚动窗口空串边界 (useQuoteStream 焦点股增量合并可
  修补)、regimeHistory 用实际请求三元组 + 裸前缀失效全部变体
- Data 页 / Regime / SectorRotationCard / RuleEditor / monitor / lots /
  stock-analysis 接入集中键, useQuoteStream 对齐

验证: 后端全量 3546 passed (含 close_t 峰值/分钟回测/跌停递延/并发上报等
新增用例); 前端 49 文件 348 用例 + pnpm build 通过; ruff 改动文件零新增
(141 vs 基线 142)。

Signed-off-by: shy3130 <shy3130@qq.com>
2026-10-30 00:20:52 +08:00
..