Commit Graph
100 Commits
Author SHA1 Message Date
shy3130 9a4bdcd07d feat(backtest): 环境数据缺口一键补算并自动重跑
- 回测报错横幅识别环境数据缺失文案(提取缺失首日), 显示「补算环境数据并重跑」按钮
- 点击后调用已有 /api/regime/recompute 补算缺口区间, 完成后自动重跑本次回测
- 补算请求超时放宽到 5 分钟(需扫全市场 enriched 数据)
- 预热区间不足的报错变体不显示按钮(补算无法解决, 文案自说明)
2026-09-08 22:16:21 +08:00
shy3130 85c903704a feat(screener): 叠加策略创建与配置体验优化
- 新建默认交集合并模式, 选项顺序对调; 可选策略列表加高
- 策略名称默认子策略名用 + 连接, 手动编辑后停止跟随
- 子策略权重改为滑块 (0-100 百分比), 保存时自动按比例归一, 移除手动归一按钮
- 子策略名可点击弹出其配置编辑 (创建对话框与配置对话框均支持)
- 策略池: 叠加策略并入自定义分组并标记「叠加」徽标, 修复误显示为内置
- 创建策略/修改策略池后自动扫描新增日线策略, 免手动刷新
2026-09-08 21:45:38 +08:00
shy3130 908b385501 feat(ext-data): 拉取接口支持 API Key 鉴权 + 扩展数据弹窗加宽可滚动
后端:
- PullConfig 新增 auth (none/bearer/header/query, 与自定义行情源
  AuthConfig 同口径); 拉取/测试/回补共用 _request_json, 鉴权注入
  只有一套口径, 用户自定义 Headers 仍优先于 UA 标识头
- Key 本体存 secrets_store (data/user_data/secrets.json, 0600),
  不落 config.json; EXT_{ID}_API_KEY 环境变量兜底; 配置了鉴权但
  未设 Key 时 fail-closed 拒绝请求
- 新增 GET/PUT /api/ext-data/{id}/api-key (GET 只返回脱敏值);
  删除配置时清理残留 Key; 历史 config.json 无 auth 字段读为 None
  行为不变; PUT /pull 不带 auth 时沿用现有鉴权

前端:
- 拉取面板新增"接口鉴权"区块: 方式下拉 + 请求头名/参数名 + Key
  密码框 (输入新 Key 覆盖, 清空保存删除), 随保存/测试/开关一起生效
- SettingsModal 加 width prop, 扩展数据设置弹窗与 EditExtDialog
  加宽至 max-w-2xl; SettingsModal 加 max-h-[88vh] + 内容区独立
  滚动, 矮视口下不再被截断
2026-09-07 22:54:05 +08:00
shy3130 f8a23b7ce5 fix(api): quote_service 缺失时 quote-interval 兜底返回默认档位 (#261)
PUT /preferences/quote-interval 的 if not qs 分支错误调用
qs.get_min_interval(),此时 qs 必为 None,触发 AttributeError → 500。
改为返回硬编码默认值 6.0,与 GET 接口兜底写法及
QuoteService.DEFAULT_INTERVAL 保持一致,并新增复现测试。
2026-09-07 22:01:12 +08:00
shy3130 cd1cff0089 style(screener): 策略设置对话框加宽 980px → 1200px 2026-09-07 15:26:00 +08:00
shy3130 f03bc38a16 feat(screener): run_all 渐进式返回, 快策略先出、慢策略后台补算
策略页全量 run_all 需 ~2 分钟, 期间卡片全空。现在按历史耗时升序执行,
首返时限 (strategy_run_all_first_return_s, 默认 15s) 内算完的策略随
响应返回, 慢策略转后台继续算并逐个写入策略缓存, 前端轮询
cached-summary 逐个点亮卡片数字 (未出的显示脉冲占位)。

后端:
- services/strategy_run_queue: 单飞 daemon 工作线程 + handle 状态。
  相同 key (资产/周期/日期/策略集) 且未完成的请求搭车现有执行不重算;
  已完成的重跑即新执行。后端全局同时只跑一个 run_all, 补上前端
  防重入之外的第二道 Numba 并发防线
- run_all 渐进分支 (仅日线 + summary_only): 逐策略增量写缓存 (同日
  按 sid 合并), 收尾整体重写保持旧口径; 结果带 computed_at 时间戳;
  分钟周期与明细请求保持整段阻塞不变
- 历史耗时落盘 user_data/strategy_run_timings.json, 次日起快策略自动
  排前; cached-summary 透传 computed_at

前端:
- 请求通用 30s 超时 + 慢接口豁免清单 (run_all/run/backtest/factor 等
  300s), 避免一个挂起请求占满 HTTP/1.1 连接拖死全站
- Screener: 收到 pending 后 summaryQuery 每 2s 轮询, 以
  computed_at >= started_at 判新 (防同日旧缓存冒充), 8 分钟兜底;
  StrategyCard 三种尺寸新增 computing 脉冲占位

验证: 新增 13 测试 (排序/落盘/搭车/串行化/端点行为/旧路径兼容),
全量套件 1762 passed; pnpm build 通过。
2026-09-07 15:25:54 +08:00
shy3130 a1ef095334 perf(strategy): run_all 逐策略计时日志与可选并行执行
- 每策略计时: ≥1s 用 INFO、否则 DEBUG, 热点策略 (macd_below_zero_revival
  ~155s / platform_consolidation_breakout ~131s / bullish_alignment ~82s)
  可直接从日志定位; 矩阵构建单独计时
- parallel 参数 + strategy_run_all_workers 配置 (默认 1=串行): 实测
  2026-09-07 外层 4 worker 并发 41 策略 299.6s 慢于串行 ~112s (polars
  eager 内部已多线程, 外层并发属超订), 故默认串行、保留开关供调优
- 叠加策略递归 run_all 固定 parallel=False, 防嵌套线程数爆炸
- 单测: 并行与串行结果/失败语义一致
2026-09-07 15:25:48 +08:00
shy3130 5618b4ef1d perf(polars): 并发闸+写锁收缩+看门狗三层防死锁, 升级 polars 1.44
线上曾出现并发 LazyFrame.collect 触发 polars streaming 执行器死锁,
叠加 _write_lock 区间内做重活, 放大为全站请求冻结。本次按触发缩小、
爆炸半径收缩、自动恢复三层布防:

- polars_guard: BoundedSemaphore 并发闸 (总闸 4 + 后台车道 2, 后台
  先拿子闸再拿总闸防死锁); repository 18 处 collect 按交互/后台分级接入
- repository 写锁区间收缩: 分区合并移出锁外, 锁内 (mtime_ns,size)
  指纹校验 + 3 次乐观重试, 失败回退锁内合并; 5 处 _write_lock 重构
- watchdog: 周期探测 collect 闸与全局写锁, 连续 2 次失败退出交由
  supervisor 拉起 (可配置, 默认开)
- polars >=1.44,<1.45 (1.44.1); 附并发压测脚本
  scripts/stress_polars_concurrency.py 供复现验证

另: config 新增 polars_collect_permits / watchdog_* /
strategy_run_all_workers / strategy_run_all_first_return_s 旋钮
(后两者供后续 run_all 优化提交使用, 默认保持旧行为基准)。
2026-09-07 15:25:41 +08:00
shy3130 58b161b16d fix(enriched): 自愈孤儿 publishing 标记, 步进优化不再误报 publishing
清库半删除等异常会留下 owner 已死但状态仍为 publishing 的 generation
标记, 后续读取直接抛 EnrichedGenerationUnavailableError, 步进优化连锁失败。

- 读取侧仅在「owner 是其他进程且该进程已死」时判孤儿并在独占锁内
  自愈 (换新 uuid 重建 ready 标记); 同 pid 无活跃对象时保守不判,
  避免暴露清库半删除的数据 (fail-closed)
- 回测引擎改为 data_generation_await 轮询等待 (300s 上限), 遇短暂
  publishing 自动重试而非直接失败; worker 错误文案同步为可重试提示
2026-09-07 15:25:27 +08:00
shy3130 4a27dc45d5 fix(docker): 修复容器启动卡死 — uv 锁过期触发运行时重装 + 运行时无镜像源
47 服务器部署实测暴露两个连环问题:
1. main 上的 uv.lock 停留在 0.2.2 (pyproject 已 0.2.3), 容器 CMD 是
   'uv run uvicorn', 启动时 uv 校验锁不一致 → 在容器内重新锁+重装依赖;
2. uv 国内源 (UV_DEFAULT_INDEX) 只在构建期 RUN 内 export, 未持久化为
   ENV —— 运行时重装走默认 pypi.org, 国内网络直连极慢, 容器表现为
   零日志不监听。

修复: 重新生成 uv.lock (仅项目版本 0.2.2→0.2.3, 依赖版本不变, 源 URL
改用阿里云镜像); Dockerfile 将 UV_DEFAULT_INDEX/UV_EXTRA_INDEX_URL
持久化为运行时 ENV, 与构建期同源。

验证: 本地 uv run --locked 通过 (锁与 pyproject 一致, 0.2.3)。
2026-09-07 00:34:34 +08:00
shy3130 6ee8e44ce4 fix(docker): USE_CN_MIRROR=1 时 apt 也换阿里云镜像
python:3.11-slim 的 sources 指向 deb.debian.org, 部分国内网络(实测
阿里云 ECS)下 apt-get 单阶段耗时 8 分钟以上, 此前仅 npm/pypi 有换源
开关、apt 遗漏(旧注释误以为 debian 镜像已配好源)。补齐 sed 换源,
兼容 bookworm deb822 (debian.sources) 与旧 sources.list 两种格式。

服务器实测: 换源后该阶段恢复秒级。
2026-09-07 00:29:16 +08:00
shy3130 8131cfe853 feat(pipeline): 定时复盘默认 15:40 — 等盘后管道跑完再复盘
默认 15:10 的"即时复盘"走实时快照缓存, 不含盘后管道产出的最终口径
(含盘后量校正的日K/enriched)。默认改为 15:40: 盘后管道默认 15:35
启动后留 5 分钟缓冲, 复盘直接使用管道数据。

强制下限仍为 15:00, 偏好即时复盘的用户可自行调早; 存量已保存的
review_schedule 不受影响 (读取不迁移)。

验证: 无本地存储时默认生效 {'hour': 15, 'minute': 40}; prefer/pipeline/
review 相关测试 67 通过; ruff 与 HEAD 一致无新增。
2026-09-06 23:38:55 +08:00
shy3130 ddb265b0f8 feat(ext-data): 出站请求默认携带 tsp 标识头
扩展数据的三个出站点 (定时/手动拉取与历史回补、内置预设拉取、URL 探测
测试) 统一经 outbound_headers() 注入 User-Agent: tsp/<版本> 与
X-TSP-Client: tick-stock-panel, 服务端 (如 tickflow-hub) 可据此识别
本项目的请求来源。

用户在拉取配置里显式设置的同名请求头优先 (大小写不敏感匹配, 不重复
发送), 需要特定 UA 的数据源不受影响。

验证: pytest 22/22 (含 3 个新用例: 默认标识头/用户头优先/实际请求携带);
逐文件 ruff 与 HEAD 对比零新增。
2026-09-06 23:16:27 +08:00
shy3130 d949d9618c docs(readme): 数据扩展条目补充时序表历史回补 2026-09-06 23:11:36 +08:00
shy3130 af97df1349 fix(frontend): 分时轮询停表 — 历史日/收盘定版后不再无效轮询
自选个股详情弹窗打开即按 6s 轮询分时接口 (StockPreviewDialog), 但两类
场景下数据不可变, 轮询纯属浪费: 周末/翻看历史日期 (后端回退出的历史日
本地分钟K不变), 以及当日收盘定版后。

新增共享停表工厂 minuteRefetchInterval (kline.ts 单一权威):
- source=none / 响应日期 < 北京今天 → 停
- 当日: 收盘根 (≥15:00 的K) 已出现 且 已过 15:30 → 停。
  完整性只认收盘根不按根数 —— 实测全天 241 根 (含 09:30 竞价根与
  15:00 收盘根), 按根数阈值会在第 240 根 (14:59) 到位时误停, 错过
  收盘根; 15:00 后盘后固定价成交可持续到 15:30, 其间量/额仍可能变,
  与后端 quote 定版窗口终点 (15:30) 同口径
- 其余 (当日盘中) 照常轮询, 实时性不受影响

StockMultiDayIntradayChart 的最新日查询此前无条件轮询 (无 source=none
停表), 一并接入。判定扫全行取时间标签, 不依赖后端排序契约。

验证: pnpm build 通过。
2026-09-06 22:35:30 +08:00
shy3130 ecbb45b8ef feat(pipeline): 盘后管道默认 15:35, 与盘后固定价终点 (15:30) 拉开缓冲
实测 2026-09-04 数据: 836 只可比标的中 24 只日K量大于分钟K合计 (最大
5.4%), 差额产生于 15:00 收盘后的盘后时段 (盘后固定价/大宗类成交计入
日成交量但不产生分钟K) —— 盘中实时落盘的日K注定缺失该尾巴, 只有
15:30 之后的官方日线才完整。

- 默认调度 15:30 → 15:35: 避开供应商日线未定稿窗口, 也与 quote 定版
  重试窗口终点 (15:30) 不再精确重合
- set_pipeline_schedule 保存下限从 15:00 收紧到 15:35 (存量已存配置
  不迁移, 读取不钳制, 仅下次显式保存时生效)
- 定时复盘默认 15:10 (即时复盘走实时快照缓存, 不依赖管道) 刻意不动

验证: set 钳制冒烟 (15:30→15:35, 15:35/15:36 原样); ruff 与 HEAD 基线
一致无新增; pytest prefer/pipeline/daily 相关 128 通过。
2026-09-06 22:35:24 +08:00
shy3130 cd9e20610f feat(ext-data): 时序表历史回补 — date_param 按日拉取 + tickflow-hub 404 契约
人气排行等 timeseries 扩展表此前只能从开启拉取之日起逐日累积。拉取配置
新增日期参数名 (date_param), 接口支持按日查询时即可历史回补: 按本地交易日
逐日请求 ?{date_param}=YYYY-MM-DD 写入对应分区, 幂等 (已有分区跳过),
单次上限 120 天, 429 限流退避重试 + 连续限流中止可续补。

适配 tickflow-hub PR#19 (/exports、/fuyao-rank 按日历史截面):
- 该日无快照返回 404 → 计入 empty 跳过, 不进失败清单 (主循环与 429
  退避重试两条路径均覆盖)
- 防污染契约: 响应行 date 与请求日期不一致 (接口忽略日期参数) 时
  fail-closed 拒写该分区, 避免当日值污染整个历史时序
- 修复调度器 next_run 计算的 UTC 未导入 NameError

前端拉取面板新增日期参数名配置与回补入口; 回补落盘的历史数据立即进入
信号/因子/回测按日对齐通道 (PIT)。

验证: pytest tests/test_ext_backfill.py 16 通过 (含 404/429/幂等/防污染),
ext 全套 144 通过; pnpm build 通过。
2026-09-06 22:35:08 +08:00
shy3130 537728a870 docs(plugin-dev): 修正 volume 单位契约为「手」(#195)
契约表与 get_realtime 字段表原标注 volume 单位为「股」,与项目实际口径不符
(日K/实时快照均为手,股票/ETF/指数一致,与上游 TickFlow 一致)。

复核方法: 对 135 根日K 做 VWAP 区间检验(amount÷volume÷100 均落在当日
[low,high] 内,「股」假设 0/135 通过),确认 issue #195 所述 ETF 与 A股
单位不一致不存在,已按非缺陷关闭。契约表补充单位自验方法与 provider
显式换算要求(上游给股时 /100,参考 fuyao)。
2026-09-06 21:56:11 +08:00
shy3130 e3a2fbce13 feat(ext-data): 扩展表字段接入信号与因子(数值因子/评分 + string 归属筛选)
数值字段(int/float) → 信号+因子双通道:
- ext_factors: 帧组装时 join 扩展列并注册 kind=base 因子(分组「扩展数据」),
  时序模式按 (symbol,交易日) 精确对齐无未来函数, 快照模式仅当日单日帧
  注入(历史帧跳过防未来函数)
- registry.all_factors 惰性同步(配置目录签名幂等, 以注册表为权威增删);
  custom_signals.allowed_fields 自动并入 → 信号下拉/因子库/AI提示词/检验
  同一份清单; factor 补算入口按需注入
- 失效链: 上传/拉取/配置变更自动清扩展帧缓存+策略缓存, API层补
  repo.clear_cache; 写入后下一次计算立即生效
- 列名保留中文(预设表字段名), 非ASCII数值字段只进信号不注册因子
  (DSL标识符ASCII-only)

string 字段(概念/行业归属) → 仅信号条件通道:
- 运算符 包含(contains,字面量匹配非正则)/等于/不等于, 右值为字符串字面量,
  可与数值条件混合(强势板块归属 AND 热度阈值)
- 前端信号编辑器按字段类型切换运算符与右值输入; /options 暴露
  stringFields; AI 提示词含字符串字段清单与 contains 用法
- string 不注册为因子(数值口径), 空值不误报

测试: test_ext_factors 18个(PIT对齐/跨日不泄露/快照门控/写入失效/
contains字面量/中文列名端到端等); 存量因子计数测试补 data/ 运行时隔离
夹具(黄金断言不依赖本机扩展表); 受影响回归148个全过; pnpm build 通过;
ruff 对齐 main 基线
2026-09-06 18:27:33 +08:00
shy3130 716897f41a feat(signals): 信号库新增盘中信号(分钟K特征)
- intraday_features: 会话对齐特征帧构造器(vwap/涨跌幅/1·3·5分钟放量比/
  日内与开盘30分钟高低点距离, 滚动窗口不跨午休, 只用已收盘bar防未来函数)
- custom_signals: timeframe=daily|intraday 双 schema, 盘中条件支持
  cross_up/cross_down 穿越算子; 输出为当日条件上升沿(首bar不触发,
  null特征判false绝不误报)
- 旧4个分时穿越信号列名零迁移(评估器回映射历史列名, 存量监控规则不动)
- 引擎单点注入 csgi_ 列: 监控/分钟策略/分钟回测共用同一构造器;
  日线策略引用盘中信号显式报错
- 回放验证 API /api/custom-signals/intraday/replay(本地历史分钟K重放,
  区间≤60天标的≤200, 先验证再配置监控)
- 能力门槛: 分钟K能力(订阅池)或全量分钟能力(本地分区); 回放仅需本地历史

验证: 新增16个测试(特征数值/边界/旧4信号黄金等价/引擎注入/回放端点),
受影响回归109个全过, ruff对齐基线, docs/features.md 同步
2026-09-06 18:26:29 +08:00
shy3130 91d2268532 docs(strategy): 新增 AI 策略迭代指南
- 新增 docs/strategy-iteration.md:两阶段闭环(粗调/精调)与分层验证、迭代台账与版本快照、证据包格式、判定门槛/留出集终审/停止规则、五张提示词卡片、现有功能映射表、UI 工作台规划(显式标注未实现)
- docs/strategy.md 方式二末尾加互链
- README 完整文档表加入口行
2026-09-06 11:13:14 +08:00
shy3130 ae30b0cb85 docs(deploy): 快速开始按推荐度重排,新增 GHCR 镜像与 AI 代部署方式
- 核心功能表改 HTML 表格并给模块/详见列加 nowrap,修复 GitHub 渲染换行
- 快速开始新增方式 C(本机 AI 代部署)与 GHCR 现成镜像,重排为 A=GHCR / B=Compose / C=AI / D=Dev
- 修正过时表述:Docker/GHCR 镜像默认不含 stock-sdk(与 Dockerfile/CI 实际一致)
- docs/deployment.md 四方式同步重排,补镜像直跑用户的更新流程
- 操作说明书新增 2.5 GHCR 镜像启动,25.1 补镜像更新命令
2026-09-06 09:54:24 +08:00
shy3130 e9359c4fa7 feat(screener): 新建策略模板统一 basic_filter 默认值
- 普通与矩阵两个模板统一为: 价格 5~200、流通市值 30~1500 亿 (float_cap)、
  换手率下限 1%、排除 ST、次新 30 天、板块默认不含北交所
- 成交额与总市值下限显式置 None: 引擎合并规则下省略键会继承
  DEFAULT_BASIC_FILTER (成交额 0.2 亿 / 总市值 10 亿), 显式 None 才表达"不设"
- 矩阵模板原无 basic_filter (落库后走引擎兜底), 一并补齐消除两模板不一致

验证: pnpm build 通过; 字段语义核对 (_basic_filter_expr 对 None 跳过,
float_cap=close*float_shares, turnover_rate 为百分数口径, boards 白名单制)。
2026-09-05 20:48:45 +08:00
shy3130 c289ac5767 fix(backtest): 步进优化支持 python_history_legacy/polars_expr 策略
问题: WalkForwardService._prepare_shared_matrix 对非 matrix_native 策略直接抛
"步进优化暂仅支持矩阵策略", filter_history 类自定义策略 (如 everbloom 系列)
无法做步进优化。

根因: 闸门把非矩阵后端一刀切, 但 run() 内部本就存在 shared_market_data=None
的通用路径 (每折独立优化 + 独立 OOS 回测), 只是永远不会被走到。

方案: 闸门改分流 —— matrix_native 仍走共享矩阵加速路径; python_history_legacy
与 polars_expr 返回 None 走通用每折回测路径 (正确但无矩阵加速); composite /
minute_filter 维持 fail-closed 拒绝, 错误文案同步更新。

兼容: matrix_native 行为不变; 结果字段 shared_market_data=false 标识通用路径。
性能: 非矩阵策略每组合×每折一次完整回测, 大网格耗时线性放大 (UI 已有耗时提示)。

验证: uv run --frozen pytest tests/backtest/test_walkforward.py -q (23 passed,
含新增 3 例: legacy 走通用路径/polars_expr 放行/minute_filter 拒绝);
tests/backtest 全套 282 passed; ruff 无新增告警;
真实 API 端到端: everbloom_tupengpan 2x2 网格 120/30 步进 8/8 折全部完成。
2026-09-05 20:33:31 +08:00
shy3130 b3e492d890 feat(factor-editor): 算子/字段面板与模板库 UX 迭代
- 算子区去重: 移除裸 chips 行, 速查表升级为唯一算子面板(默认展开, 挂载时置 open 避免与折叠态打架)
- 速查表重设计: 时序(13)/截面(3)/工具(9)三张分组卡片, 每行=完整签名+中文说明+参数约束, 点击整行插入公式光标处; 与 chips 共用 OPERATOR_GROUPS 单一数据源
- 折叠标题突出: 白色前景色+medium 字重+accent 箭头(展开旋转), 悬停变色
- 可用字段: 展开高度 160→256px; 分组名提亮加粗; 字段英文 id 蓝色(与算子签名同色), 中文保持灰色
- 模板库 5→12: 新增 低波动/量比回落/RSI超卖/低振幅/隔夜反转/距高点回落/换手稳定, 全部经 /api/factors/validate 预校验
- 校验/试算按钮居右(ml-auto)
- factor-platform-plan.md §5.2 模板计数同步
2026-09-05 18:19:34 +08:00
shy3130 2ff909cd36 fix(notifications): #244 维护者补丁 — 移除预埋类型并修正全角标点
- 移除 api.ts 中与通知无关的 MainCostEstimate/StockLevels.main_cost 类型(对应后端字段在本仓库不存在, 属跨 PR 预埋, 全仓库零引用)
- settings.py 5 处 PR 新增字符串的全角逗号改半角, RUF001 恢复到 main 基线(28 ≤ 29)
- 验证: 通知测试 48 passed, 前端 build 通过
2026-09-05 17:16:58 +08:00
shy3130 e40bf15a50 docs(manual): 操作说明书适配 v0.2.3 — 新增因子与信号库章节, 28 章重排
- 新增第 10 章「因子」: 检验/因子库/编辑器/组合/挖掘五 tab 与因子↔策略四条桥, 原 9.1 因子回测内容迁入并扩充
- 新增第 11 章「信号库与持仓提醒」: 信号库独立页(原设置 19.6 迁出)与持仓提醒页
- 第 9 章重构: 回测页改为「策略|验证」两视图口径, 小节重排为 9.1 策略回测/9.2 参数优化/9.3 步进优化
- 原 10-26 章顺移为 12-28(含目录锚点与交叉引用); 1 章概览、5.1 菜单、4 章流程、21 章设置清单同步更新
- 校验: 目录 28 条与正文 H2 完全一致, 章节号连续, 无坏锚点与过时引用
2026-09-05 16:52:40 +08:00
shy3130 e0cd625ef4 feat(platform): 因子平台与因子↔策略双向联动 v0.2.3
- 因子平台: /factors 一级页(检验/因子库/编辑器/组合/挖掘), DSL 公式因子(25 算子点选、双语字段、我的因子模板、脏公式守卫), 版本与生命周期, 自动挖掘 L1 统计筛选
- 因子↔策略四条桥: 触发器 Zap 快建因子条件信号、因子一键生成排名策略、自定义信号 AI 提示词接入因子分组、策略回测因子归因(胜/败单入场信号日因子均值, 独立 tab, 双语因子名)
- 回测: 统计卡新增盈亏比(≥1 红/<1 绿), 蒙卡回撤合并为中位/95% 双值卡(自适应字号), 高级设置基础过滤与策略编辑器参数对齐(5 组区间)
- 信号库独立页 /signals(原设置 tab 迁出), 持仓提醒入导航; 挖掘并入因子页第 5 tab, /mining 旧链接重定向
- 研究线配套: 因子目录 61→77(评分/矩阵双内核), stats_v2(Newey-West/BH-FDR/DSR), enriched 管道与异动/报价服务配套调整
- 文档: README 导航与特性表、features.md 因子平台章节、操作说明书 9.2、factor-platform-plan 执行状态与 §5、二开文档桥接说明; 交流与支持节改版
- 版本 0.2.2 → 0.2.3; 后端全量 1625 passed(1 例环境性跳过), 前端 build 通过
2026-09-05 15:41:15 +08:00
shy3130 bab609b2d4 fix(ai): DeepSeek thinking 禁用参数被 400 拒绝时去参重试 (#240 跟进)
_openai_kwargs 对 DeepSeek V4 官方域名注入的 thinking 禁用参数
(extra_body) 属外部 API 契约, 模型/接口版本差异可能报 400。照
temperature / reasoning_effort 既有模式补第三条定向回退: 400 且
错误信息指向 thinking 时移除 extra_body 重建请求 (回退默认思考
模式; 若正文因此被推理挤占, 由 _iter_openai_text 显式报错指引)。

与 thinking 无关的 400 不触发回退, 直接抛出。
2026-09-04 12:50:50 +08:00
shy3130 a9af2bce1c fix(pipeline): enriched 全量重建流式化, 峰值内存与历史长度解耦 (#208/#174)
小内存机器 (2C2G) 延长历史后全量重建必然 OOM 的两个根因:
  1. 全量模式把所有批次结果累积在内存 date_buffers 直到统一写盘,
     5 年 x 5500 只 (~800 万行) 全表驻留 0.5-1GB;
  2. 批次大小按「每只 ~244 行」的年代设定, 历史延长后单批宽表
     (指标全列) 瞬时 ~600MB。

修复 (双核模拟实测: 275 万行峰值 RSS 958MB -> 415MB, 耗时 +37%):
  - 流式暂存发布: 每批结果立即写暂存文件 (enriched 树外隐藏目录,
    不被 **/*.parquet 业务 glob 扫到; polars/duckdb 的 ** 均匹配
    点目录), 最后按日期分块流式合并、逐分区原子替换; 日期覆盖
    校验与 EnrichedPublication 崩溃语义保持不变, finally 保证
    暂存清理, 历史残留按 mtime (24h) 启动清扫;
  - 自适应批次: 检测内存 <8GB 时按单批目标行数 15 万收缩,
    >=8GB 保持用户设置 (大机器行为不变, 20 核实测耗时持平);
  - 刷新路径同修: 启动/盘后的 300 天窗口计算 (repository) 改走
    compute_enriched_history_window 分批执行, 与整帧顺序等价
    (各步骤均 over(symbol) 分组), 峰值与标的总量解耦。

验证: 新增 5 项回归测试 (流式输出与整帧直算逐列相等/暂存清理/
残留清扫/自适应批次/窗口分批等价), 全套 backend 1498 项通过,
ruff 基线零新增。
2026-09-04 12:40:04 +08:00
shy3130 8c28132361 fix(analysis): 概念/行业映射缓存命中返回类型与签名不一致 (#186)
_load_concept_map_df 正常路径返回 (map_df, count) 元组, 但缓存只存了
裸 map_df —— 600s TTL 内二次访问命中缓存返回 DataFrame, 调用方按元组
解包把两列拆成两个 Series, 概念/行业分析二次打开必报错 (issue #186
报告者定位)。

- 缓存与返回值同构: 存 (map_df, count) 元组, 类型注解同步
- 移除 market_mainline / rps_rotation 两处针对旧 bug 的防御性兼容层
- 删除失效的 bare-DataFrame 兼容测试, 新增缓存契约回归测试 (3 次连跑通过)
2026-09-04 11:59:00 +08:00
shy3130 2ce8b4b17d fix(ext-data): 内置概念/行业 preset 不再启动即自动联网拉取 (#199) 2026-09-04 11:53:15 +08:00
shy3130 7ea741e4dc fix(backtest): 回测交易/选股行支持键盘打开K线弹窗 (#239 维护者补丁) 2026-09-04 11:41:54 +08:00
shy3130 4cb30e48aa fix: screener JIT 透传 turnover_rate (#187) + PullScheduler 线程安全 (#203)
- #187: _compute_enriched_full/_load_enriched_history 的 warmup 读取
  白名单补上存储列 turnover_rate —— instruments 不可用无从重算时,
  自定义 SQL 用该列做条件会 Binder Error 被吞成静默空结果
- #203: refresh 的 _tasks 增删 diff 从调用方线程移进主循环闭包,
  消除 TOCTOU 窗口; 行为测试覆盖增删/幂等

#187 测试已在修复前代码上验证会失败 (instruments 为空时列丢失)。
2026-09-03 13:45:12 +08:00
shy3130 91fef6d793 test: 加强 #201/#224 回归测试至可复现级别
- #201 warmup 测试改为与全历史计算基准对比数值 (ewm 指标从首值播种,
  仅断言非 NaN 无法区分新旧代码)
- #224 注入测试改用合法同构 parquet 做目标 (读 /etc/passwd 在未加固
  连接下同样报错, 区分不了攻击面是否真实闭合)

两个测试均已在修复前代码 (41205b1/e89ea9b) 上验证会失败。
2026-09-03 13:26:42 +08:00
shy3130 ef59df4a67 fix: 修复 6 个 issue (#225/#226/#201/#188/#200/#196)
后端:
- #225 自定义源分钟K字符串 datetime 不再被 cast 成 null:
  _normalize_minute 对 Utf8 列按常见格式链式解析 (参照 kline_sync 口径)
- #226 自定义源日K/除权因子单批失败只隔离该批 (重试 1 次 + 跳过 +
  warning 汇总), 不再丢弃已成功批次的全部进度
- #201 旧信号回测 _load_panel 加指标 warmup 窗口 (120 交易日保守日历日),
  计算后裁回 [start,end]; 数据不足时自然退化

前端:
- #188 因子回测单标的不再整面板空白: 外层条件改 !error, IC 卡片
  单独守卫并给出需 >=2 只的提示
- #200 因子回测支持调仓频率 (日/周/月) 与滑点 (bp) 配置
- #196 自选页板块筛选新增 ETF 分类, 旧偏好加载时补 ETF 键保持默认可见
2026-09-03 13:20:59 +08:00
shy3130 e89ea9becf fix: 修复 4 个 P1 issue (#224/#232/#223/#215)
- #224 screener 自定义 SQL 的内存连接关闭 enable_external_access,
  注入的 read_parquet/COPY 文件读写直接报错 (安全)
- #232 指数展示缓存百分数口径在消费边界显式 /100:
  pipeline._bench_rt_pct_of 与 abnormal_moves._bench_rt_pct 两处,
  修复 3/10/30 日偏离值被放大两个数量级
- #223 盘后管道按同日 daily/enriched 行数比较检测实时合并提前
  创建的部分分区, 删除后由增量重算全市场补齐
- #215 _basic_filter_for_asset 扩展中和股票专属键 (price_min/max/boards),
  并应用到回测/挖掘/策略扫描三个运行期入口, 修复 ETF 静默零信号
2026-09-03 13:01:43 +08:00
shy3130 41205b197c chore: follow-ups for PR #231/#233 reviews
- monitor_rules: raise from None in remind_date validation (B904)
- lots: log warning on asset-type fallback to stock (fail-open traceability)
- matrix: demote turnover NaN-column notice to debug
2026-09-03 12:45:24 +08:00
shy3130 de5d5a9769 chore: update assets 2026-09-02 16:27:38 +08:00
shy3130 7ac0456c53 feat(mining): 实时行情与挖掘的冲突确认弹窗
盘中实时开启时 enriched 每轮落盘推进数据世代, 排队中的挖掘任务
开跑会因首轮世代校验失败而报错 (mining data generation changed
after the run was queued, 用户反馈)。两个方向加确认弹窗:

- 挖掘页: 实时开启时点「开始挖掘」→ 三按钮确认 (取消 / 仍要开始 /
  关闭实时并开始 — 后者一键关实时并提交任务)
- 侧边栏实时开关: 存在 queued 挖掘任务时开启 → 确认弹窗;
  运行中任务自动跟随新世代, 不拦截

验证: tsc 零错误 + build 通过 + 浏览器验收 7/7 (弹窗出现/取消
无副作用/关实时并启动任务链路/无排队任务不拦截/环境恢复)。
2026-09-02 15:20:48 +08:00
shy3130 bd84d4c0ae feat(ui): 侧边栏桌面三态 + 移动端抽屉 (落地 #166 设计)
桌面 (≥768px): 展开 14rem → 图标条 3.5rem → 隐藏 0 + 左缘悬浮按钮
(hover 1s 以 overlay 预览不挤压主区, 点击固定展开 push); 三态持久化
localStorage tf-nav-state, 自动迁移旧 tf-nav-collapsed 两态键。

移动端 (<768px): aside 换壳为 fixed 抽屉 (80vw / max 320px + 半透明
遮罩), 左上角汉堡唤出, ESC/路由跳转/点导航/点遮罩关闭; 原移动端
强制收起为图标条的旧逻辑移除, 抽屉内恒为完整形态。

数据挂起门控对齐: 图标条/隐藏/抽屉关闭态均不为侧栏隐藏 UI 发请求。

交互设计取自 PR #166 (intfoo), 贴现有 navCollapsed 体系实现而非
合并其平行 sidebar 组件树 (其桌面两态与 main 现有能力重复)。

验证: tsc 零错误 + build 通过 + 浏览器验收 8 项 PASS (桌面三态
两轮循环含隐藏恢复、移动抽屉开合/遮罩/ESC); 修复验收发现的
overlayPreview 残留导致的"恢复后侧栏 fixed 覆盖主区"bug。
2026-09-02 12:40:56 +08:00
shy3130 22add7179c merge: PR #167 监控自定义信号全显 + 信息条弹窗性能优化
冲突解法: SignalPicker 采用 options 形态 (PR 重构) + 保留 main 的
intradayDisabledSignals/intradayDisabledHint 变量 (含自选分组作用域
禁用分时穿越的增强语义, 自动合并会被 PR 旧内联表达式悄悄丢掉)
+ filterCustomByKind: false (监控场景显示全部自定义信号)。
验证: tsc 零错误, pnpm build 通过。
2026-09-02 10:56:49 +08:00
shy3130 576850d0fa feat(data): 数据页同步任务支持手动停止 (二次确认)
- 同步运行中顶栏出现「停止」按钮, 点击先弹二次确认: 注明协作式停止
  (当前分块完成后中断, 不损坏已写入数据) + 停止后再次拉取需重新走
  完整管道 (拉取→指标计算→监控规则), 无法从停止处续跑
- api.ts 新增 pipelineJobCancel, 调用既有 POST /api/pipeline/jobs/{id}/cancel
  (取消标志 + 分块回调检查 + JobCancelledError 协作式退出, 后端零改动)
- 补 cancel 端点契约测试: running/pending 可停、终态 400、未知 404、
  停止后可立即新建任务
2026-09-01 22:42:59 +08:00
shy3130 84725cd362 fix(pipeline): 解锁设置页 A 股拉取开关 (#216 维护者补丁)
后端 getter/白名单已随 pr-218 修复, 前端 PipelineScopeConfig 的
locked 特判 (v0.1.60 为配合后端硬编码所加) 未解锁 — 不删则 issue
的用户路径 (设置界面取消勾选 A 股) 依然走不通。删除特判, 恢复与
ETF/指数开关对称的行为。
2026-09-01 22:41:33 +08:00
shy3130 67b271285c Merge branch 'pr-218' into merge/pr-218 2026-09-01 22:40:50 +08:00
shy3130 bfe76e8273 Merge branch 'pr-206' into merge/pr-206 2026-09-01 22:38:50 +08:00
shy3130 d266131f90 Merge branch 'pr-213' into merge/pr-213 2026-09-01 22:33:28 +08:00
shy3130 e8c870af73 Merge branch 'pr-219' into merge/pr-221-220-219 2026-09-01 22:20:01 +08:00
shy3130 d0595eb4d7 Merge branch 'pr-220' into merge/pr-221-220-219 2026-09-01 22:20:01 +08:00
shy3130 a9c00fd567 Merge branch 'pr-221' into merge/pr-221-220-219 2026-09-01 22:20:01 +08:00
shy3130 c7a921cc60 merge: feat/full-minute-dataset (全量分钟数据集开放) 合入 main
分支已含 main 全部提交, 合并前验证: 涉改 106 用例 + 前端 tsc 零错误
+ 全量 1340 passed (test_mining_manager 偶发为存量, 合并前 main 可复现)。
2026-09-01 13:13:49 +08:00
shy3130 95cd99ab8c merge: 同步 main (辐射本地读 + 传输压缩/网络设置) 到全量分钟分支
冲突两处均为 minute-refresh status 字段两侧各自新增, 两者全保留
(healthy + provider/provider_effective/repair_only)。
2026-09-01 13:05:21 +08:00
shy3130 bc9461da9a feat(net): 分时/日K批量响应可选 gzip 压缩与网络设置
- _gzip_payload: 偏好开启 + Accept-Encoding 协商 + 超 1KB 才压
  (level 6); datetime 序列化与非压缩路径一致, 保证 since 增量
  字符串字典序合并不受影响
- minute-batch / daily-batch 端点各自独立偏好键, 逐请求即时生效;
  实测分时 9.1MB→1.28MB (86%), 日K 736KB→156KB (79%)
- 超时设置 tab 更名网络设置, 卡内新增压缩区: 大开关 OR 联动
  (任一子开即亮, 全关才灭, 点击全开/全关) + 分时/日K两个子开关
- preferences.save() 加线程锁: 修复并行 PUT read-modify-write
  互相覆盖 (总开关批量关不齐的根因), 存量偏好写入一并受益
- 测试: 双端点压缩/关闭直通/无协商头直通/偏好默认 + 并行 save 竞态
2026-09-01 13:04:00 +08:00
shy3130 f84cb671ef feat(data): 全量分钟健康时策略页与监控注入切读本地分时
- 策略页: healthy 时解除分时列 100 只截断并 prefer_local 读本地分区
- 监控信号注入: 股票 healthy 时直接读本地当日分区, 免每分钟 bucket
  一次的全量 API 拉取; ETF 不在服务 universe, 不健康/读失败回落原路径
- minute-refresh status 增加 healthy 读侧新鲜度字段 (前端共享判断)
- 测试: 注入本地读 3 用例 (健康读本地/不健康回落/ETF 恒走 API)
2026-09-01 13:03:54 +08:00
shy3130 010c484289 feat(data): 全量分钟 (full_minute) 数据集开放插件/自定义源接入
像其他能力一样可路由: 声明 full_minute 数据集并在设置页路由, 即接入
盘中全市场分钟落盘服务 (与 TickFlow Expert 同一能力键 intraday.universe)。

- policy: _DATASET_CAP_MAP 增补 full_minute → INTRADAY_UNIVERSE, 自定义源
  声明且被路由时自动补授能力, 服务门控对两类源统一口径
- capabilities 注册表: full_minute 从不可路由 (field=None) 改为
  full_minute_data_provider 偏好路由; preferences/settings API 收发新字段
- 插件契约: get_intraday_batch (修复轮, 未实现回退 get_minute 当日窗口) +
  get_intraday_latest (稳态增量, 可选; 未实现降级仅修复轮, 节奏下限 60s)
- YAML 声明式源: full_minute 数据集与 minute 同形, loader 白名单放行,
  源编辑器 UI 可配置; 仅修复轮语义
- kline_sync 边界: fetch_intraday_custom_batch / _fetch_intraday_custom_latest,
  帧过北京墙钟守卫, 与 TickFlow 边界函数同纪律
- minute_refresh: 删「自定义分钟源让位」逻辑, 改按路由取数;
  status 增 provider / provider_effective / repair_only
- 前端: 监控页卡片按能力驱动, 数据源页路由矩阵, api.ts 类型
- 测试: 门控/路由/降级/增广新增用例, 后端 1332 全过
- 文档: plugin-development / custom-data-source / configuration / features /
  CONTRIBUTING 契约细化 (AI 可照文档接入)
2026-08-31 22:53:24 +08:00
shy3130 dab8a2c676 test(screener): 矩阵策略计数 18→25 — 补 58f8d7b 新增 7 策略漏改 2026-08-31 22:53:12 +08:00
shy3130 5757950e45 docs(data): 补全量分钟 (full_minute) 能力接入说明
- 定位为独立能力: 当前接入方式为 TickFlow Expert, 而非档位封闭功能
- configuration.md: 档位表 Expert 行补全量分钟 + 新增接入小节 (配 Key→检测→
  开实时行情→自动落盘, 修复轮/增量轮/时段/幂等行为, ETF 不在标的池)
- features.md / plugin-development.md: 增对应条目与插件现状说明
  (数据集暂未纳入 loader 白名单; 自定义分钟源在位时内置服务让位)
2026-08-31 22:36:19 +08:00
shy3130 bdad0fefb5 feat(screener): 策略列标签折叠 — 表头全表开关 + 行级展开
- 默认收起: 每行显示前 N 个策略 + 计数 (跟随列设置"显示前N个", 未配置默认 3)
- 表头图标切换全表展开/收起, 收起时清除行级展开状态, 状态持久化
- 排列方向始终跟随列设置 tagLayout (展开不再强制横向)
2026-08-31 22:30:45 +08:00
shy3130 2fc7d3f439 feat(screener): 策略池支持一键清空与本组全加 2026-08-31 22:30:44 +08:00
shy3130 58f8d7b883 feat(strategy): 新增 7 个矩阵原生内置策略, 公开计数 18→25
- 趋势/形态: 均线粘合突破 · 平台整理突破 · 放量创60日新高
- 量价/涨停: 涨停基因活跃股 (max_change_pct 参数过滤当日已大涨)
- 反转/波动: MACD 零下回升 · 长下影反击 (close_position>=0.5 兼容假阴线) · RSI 中轴回踩
- 阈值统一小数制口径 (change_pct/momentum 除以 100), 一致性测试计数 26
2026-08-31 22:30:44 +08:00
shy3130 be799abfa0 fix(intraday): since 增量时区崩溃 — 客户端直传原始时间串, 服务端归一 aware 输入
客户端 toISOString 生成带 Z 的 UTC, Python 3.12 解析为 aware datetime,
与行内 naive 北京时间比较 TypeError (第二轮轮询 500), 且换算差 8 小时。
- 客户端: since 直接回传最旧最后一根的原始 datetime 字符串 (同格式同时区,
  字典序即时间序), 消灭一切换算
- 服务端: fromisoformat 后 aware 输入先转北京墙钟再去 tzinfo, 防御旧客户端
2026-08-31 22:01:46 +08:00
shy3130 ed2f81c312 feat(realtime): 首用门禁 — 本地无数据时禁止开启实时行情
日K/enriched 均空 (与看板首用弹窗同口径) 时开启实时行情返回 409 并给
同步指引, 不落偏好。展示/监控/梯队全部依赖本地数据底座, 空数据下轮询
只是空转耗配额且缺 instruments 维表。只拦开启不影响关闭, 已开后清库
下次重开自然被拦。
2026-08-31 21:45:07 +08:00
shy3130 320969497a perf(intraday): 分时链路增量传输 + SSE 续画 + 视口感知
- minute-batch 支持 since 增量响应: 只回 >= since 的K (含动态最后一根),
  客户端按 (symbol, datetime) upsert 合并, 轮询流量从全天序列降到每轮一两根
- 自选分时 SSE 续画: enriched tick 前端续写分钟序列最后一根/滚动追加新K
  (纯视图叠加不写缓存, 服务端定版值始终权威); tick 新鲜时轮询降为 30s 兜底
- 视口感知: 从虚拟器直读渲染中 symbol 集合 (可见+overscan), 数据层只拉视口内;
  since 只按本轮请求集合取最旧尾部, 视口外落后不放大窗口; 集合变化 300ms
  防抖补拉; 剔除指数保持端点契约
- since 过滤专项测试: 含 since 当根 / 早于全部K / 无 since 三态
2026-08-31 21:45:06 +08:00
shy3130 869c49bb0b fix(kline): 分钟增量起点改为最后一根本身 — 形成中的动态K需重拉覆盖 2026-08-31 20:54:56 +08:00
shy3130 b78ba9940d perf(kline): 分钟批量补拉取到即落盘 + 尾部增量窗口
- 补拉结果经 _write_minute_partition upsert 落盘 (持仓库写锁, 与全量分钟
  服务/盘后同步同一纪律), 下一轮命中本地, 大自选从每轮全天重拉降为增量
- 完整性判定由 0.9 根数比例改为 期望-2 根: 比例阈值会让持久化数据在 90%
  处冻结尾巴
- 分类三态: fresh 直读本地零请求 / 尾部落后从最后一根+1min 增量拉 /
  中间有洞 (间距非 1min/午休 91min) 退回全天重拉回填, 防增量窗口漏数据
- 落盘失败降级为仅返回本轮数据 (持久化是优化而非正确性前提)
2026-08-31 20:53:23 +08:00
shy3130 bfe01e06d9 feat(data): 无除权因子能力时同步前置二次确认
除权因子不可用时同步静默降级 (日K不复权入库、enriched 直接用 raw 价),
此前无任何提示。现于两个同步入口 (数据页同步按钮、首用欢迎弹窗开始获取)
检测能力矩阵 usable 标志, 不可用先弹确认: 告知不复权口径与除权事件后
需重新校准, 支持不再提示 (localStorage)。矩阵未加载完成时 fail-open 不拦截。
2026-08-31 20:34:27 +08:00
shy3130 bfc2eede3e style(monitor): 设置监控页右列「全量分钟」移至「连板梯队降级修正」上方 2026-08-31 20:04:14 +08:00
shy3130 bfcad563d3 feat(frontend): 自选分时请求带 prefer_local, 策略页行为不变
- klineMinuteBatch 加 preferLocal 参数, 响应类型补 full_minute_local
- 仅 Watchlist 分时轮询传 true (全量分钟健康时股票不走批量补拉);
  Screener 不传, 严格限定本轮只辐射自选场景
2026-08-31 17:10:09 +08:00
shy3130 df5cae143e feat(minute): 自选分时接入全量分钟本地供给 (prefer_local + freshness 判定)
- MinuteRefreshService.is_healthy(): 偏好开 + 线程活 + 最近一轮距今
  ≤ max(2×间隔, 30s)。last_round_at 只在取数+落盘成功后更新, 连续失败
  自动超时判不健康, 冷启动修复轮期间天然不健康
- /api/kline/minute-batch 加 prefer_local 标志: 服务健康时股票 incomplete
  不再批量补拉, 本地有多少给多少 (服务下一轮落盘补全; 停牌票补拉也是空,
  无损); ETF 不在全量分钟 universe 内维持补拉; 不健康回落现状兜底。
  响应加 full_minute_local 标记
- 大自选 (数百上千只) 不再每 6s 轮询持续打批量分钟接口
- 4 个新用例: 健康跳过股票补拉/ETF 仍补, 不健康回落, 无标志不受影响,
  is_healthy 三条件边界
2026-08-31 17:10:02 +08:00
shy3130 6d72efc624 docs: 指数固定清单契约 + 自定义源指数补充协议
- CONTRIBUTING 能力路由矩阵小节: 实时指数为产品级固定契约不走路由矩阵
  (index_const 单一权威, 指数页固定四只, 指数偏好已删, 监控标的不受限);
  自定义源 get_realtime_indices 可选协议与 fuyao 连坐语义注记
- plugin-development: get_realtime_indices 方法契约与软失败语义
2026-08-31 16:50:38 +08:00
shy3130 58b86a962b feat(frontend): 指数页固定核心四只, 删除全指数搜索与侧栏指数配置
- /indices 指数页保留: 左侧固定核心四只(核心指数卡片), 删除搜索框与
  全量指数列表; 右侧日K/分时详情与同步指数日K按钮不变
- 侧栏指数条固定四只常驻显示, 点击跳指数详情
- 监控设置"左侧菜单指数"配置卡删除(四选多选+固定显示开关)
- api.ts: 删 indexList/indexSearch, Preferences 移除 5 个指数偏好字段;
  queryKeys 同步清理
2026-08-31 16:50:28 +08:00
shy3130 3c6ed99922 feat(index): 指数收敛为固定核心四只 + fuyao 指数快照接入
- 新建 app/services/index_const.py 单一权威: 展示层固定四只核心指数
  (上证/深证成指/创业板/科创综指), quote_service/overview/
  market_overview_builder/sector_monitor 四处重复定义全部收敛
- fuyao 插件接入指数快照端点 (/api/a-share-index/prices/snapshot):
  client 增加 index_snapshot (批量上限 627 码), provider 实现可选协议
  get_realtime_indices — .BJ 后缀先行过滤 (未知代码整批 1002 连坐),
  volume 不做股转手; 修复 fuyao 路由下指数冻结在日K兜底的 bug
- quote_service 自定义源分支鸭子类型调用 get_realtime_indices 补拉指数,
  请求清单 = 核心四只 + 启用指数监控规则标的; 未实现的源走日K兜底
- TickFlow 分支指数固定按码显式拉取, 移除 CN_Index 全量 universe 与
  mode core/all 分支; 指数落盘固定 merge 不截断
- 指数偏好全套下线: realtime_index_symbols / sidebar_index_symbols /
  indices_nav_pinned / realtime_pull_index / realtime_index_mode
- /api/index/list 与 /search (全指数浏览搜索) 删除; daily/minute 保留
  供指数详情页, sync_instruments/sync_daily 保留供数据页
- sector_monitor 指数标的恒可监控, catalog 签名不再依赖指数偏好
- 新增 7 个用例: 指数快照映射/.BJ 过滤/软失败 + 自定义源指数补充链路
  (含监控规则并入/无协议源静默/指数失败软降级)
2026-08-31 16:50:21 +08:00
shy3130 e287a55e82 fix(capabilities): redetect 同步刷新 app.state 快照并升级 tickflow SDK 0.1.25
- /api/capabilities/redetect 重新探测后同步写回 app.state.capabilities,
  minute_refresh 等门控服务即时读到新档位, 不再需要重启
- tickflow 0.1.24 缺 intraday_universe 方法导致 Expert 档全量分钟探测失败,
  升级到 0.1.25
- 全量分钟轮次异常与模式补充 warning 日志, 便于线上诊断
2026-08-31 16:50:12 +08:00
shy3130 4d27f3139e Merge branch 'feat/capability-routing': TickFlow 列式直转提速与除权因子时区修复, 分钟增量间隔上限 120s 2026-08-30 22:29:57 +08:00
shy3130 d29f9c0ea8 perf(data): TickFlow 取数切换 as_dataframe=False 列式直转; 修复除权因子日期 UTC 偏移一天
- 全部 K 线取数点改走 CompactKlineData 列式直转 polars (无 pandas 中转,
  全市场单轮本地转换 ~1.1s → ~0.1s), 时区口径统一 _timestamp_to_beijing_datetime
- 除权因子 trade_date 原取 UTC 日期, 北京零点事件整体早一天 → 转北京墙钟后取日期
- 盘中分钟增量间隔上限 300s → 120s (universe 仅回最新 3 根, 超限必留缺口)
2026-08-30 22:29:33 +08:00
shy3130 0417216439 Merge branch 'feat/capability-routing' (v0.2.2): 能力路由矩阵、fuyao 插件、分钟策略回测、盘中/复盘增强、首用引导改版 2026-08-30 19:47:19 +08:00
shy3130 1a7e6ad32c Merge remote-tracking branch 'origin/main' into feat/capability-routing
# Conflicts:
#	README.md
#	backend/app/backtest/worker.py
2026-08-30 19:47:11 +08:00
shy3130 80ecb6e409 chore(release): 版本号统一升级至 v0.2.2 2026-08-30 19:43:52 +08:00
shy3130 a8a6c81fff Merge remote-tracking branch 'origin/feat/volume-delta-alert' into feat/capability-routing
# Conflicts:
#	backend/app/services/quote_service.py
2026-08-30 19:42:43 +08:00
shy3130 bbe44af63b docs(readme): 声明/联系/交流群/打赏文案润色 2026-08-30 19:40:15 +08:00
shy3130 10f01ea091 style(onboarding): 不可用能力提示改为「该能力目前不可用」 2026-08-30 19:20:51 +08:00
shy3130 9a4621c8de feat(onboarding): 能力路由步骤进入时按 tickflow-fuyao-stocksdk 优先级自动设置路由 2026-08-30 19:19:08 +08:00
shy3130 dbd0e7f316 style(onboarding): 注册链接独占一行显示 2026-08-30 19:14:28 +08:00
shy3130 7ed2660d63 feat(onboarding): Key 表单附注册链接, TickFlow 链接带邀请码 2026-08-30 19:09:53 +08:00
shy3130 299790d38f docs(readme): 修改readme相关内容 2026-08-30 19:05:49 +08:00
shy3130 560a2d7735 feat(onboarding): API Key 表单常驻展开, 不再折叠收起 2026-08-30 19:05:48 +08:00
shy3130 2cd0ea987b feat(onboarding): 数据源步骤改为只读展示, 仅保留 API Key 配置 2026-08-30 19:05:48 +08:00
shy3130 0bcb0849dc feat(onboarding): 数据源步骤双 Key 入口与 fuyao 增强路由 2026-08-30 19:05:47 +08:00
shy3130 6b49231d67 feat(onboarding): 第3步由「能力探测」改为「能力路由检测」
- 以能力路由矩阵呈现(7 数据集逐行: 生效源+可用性+候选提示),
  替代以 TickFlow 档位为中心的旧视图, 多源下矩阵即真相
- 不可用行针对性提示: 有候选给「可切换候选: X」; TickFlow 未配 Key
  给「配置 Key 后可解锁」; 底部汇总 N/M 可用与 None 档说明
- 步骤名/注释同步改为能力路由; 移除不再使用的 TickFlow 档位视图代码
- 浏览器实测: 7 行矩阵渲染正确, 可用性/候选/汇总与当前环境一致
2026-08-30 19:05:46 +08:00
shy3130 3225713826 feat(onboarding): 引导页支持填写 TickFlow API Key
- 数据源卡片网格下新增入口「为 TickFlow 填写 API Key(可选)」,
  复用内联 Key 表单(TICKFLOW_API_KEY, 密码框自动聚焦)
- 文案区分: 留空=免费 None 模式可直接用, 填 Key 按档位解锁更多数据集;
  TickFlow 不自动切换数据源(与插件不同, Key 与选源正交)
- 走 /tickflow-key 先探后存: 浏览器实测假 Key 返回「Key 无效或已过期」
  且 secrets.json 未落盘
2026-08-30 19:05:45 +08:00
shy3130 a499da95c4 fix(onboarding): 引导页支持内联配置缺 Key 型插件(如 fuyao)
此前 fuyao 因未配 Key 被自检判为不可用, 向导数据源步骤按「缺依赖」
一律禁用, 文案误导(需安装依赖)且无处可配。

- 区分两类不可用: 缺依赖(真禁用) vs 缺 Key(api_key_env 声明型,
  卡片可点, 显示「需配置 API Key,点击填写」)
- 点击展开内联 Key 表单: 官网申请链接 + 先探后存(POST /plugin-key,
  无效不落盘), 验证成功自动选用该数据源
- 浏览器实测: fuyao 卡片可点、表单呈现/自动聚焦/空值禁用正确,
  无效 Key 返回实探错误且不落盘, 取消正常关闭
2026-08-30 19:05:44 +08:00
shy3130 25c2802d6f feat(onboarding): 首用引导更新为多源口径并增加后续步骤
- 获取数据说明保持数据源中立(TickFlow 免费服务器/当前源), 本地分析
  提示不再 TickFlow 专属
- FetchDataCard 增加 fuyao(同花顺 REST) Key 解锁提示(财务/龙虎榜/
  盘前风向标/竞价异动), 附设置页直达链接
- WelcomeFetchModal 新增「获取完成后的推荐步骤」: 配 fuyao Key →
  分钟落盘(可选, 分钟回测/板块分时) → 自选/策略/回测研究闭环
- tsc 通过, 看板页 HMR 后渲染正常
2026-08-30 19:05:43 +08:00
shy3130 893cf960e3 fix(chart): 关闭 lightweight-charts TradingView 归属角标
- layout.attributionLogo=false: 板块分时图与个股日K两处一致
- licence 链接要求改由 README 技术栈 Lightweight Charts 外链承担
- 实测: 个股分析页图表渲染正常, DOM 无 tv-attr-logo 残留

# Conflicts:
#	README.md
2026-08-30 19:05:35 +08:00
shy3130 3f27d412d1 docs(readme): 架构图重排为数据向上流的精简分层, 数据集口径改为多数据集
- flowchart BT: 数据源自下而上流向前端, 修正箭头方向歧义
- 节点标签精简为专业短词, 细节保留在关键机制表
- 能力路由不再写死数量(现 6 个数据集, 注册表持续扩展):
  图内改「多数据集 · 按能力独立路由」, 正文/核心功能表/features.md 同步
- 浏览器实测: 779×1045, 六层序 呈现→应用→研究→计算→存储→数据源

# Conflicts:
#	README.md
2026-08-30 19:05:34 +08:00
shy3130 b4f2605b81 docs(readme): README 按分支能力重写并新增技术架构章节, features.md 补齐
- 新增 🏗️ 技术架构: 六层 mermaid 分层图(数据源插件化/能力路由/Polars
  计算/研究执行/FastAPI 服务/React 前端) + 六条关键机制 + 技术栈表,
  数字均对照代码核验(15 列存储/68 列现算/62 因子/18 策略)
- 核心功能表/页面详情/路线图补 v0.3: 能力路由矩阵、fuyao 源、分钟体系、
  交易日探针、龙虎榜+风向标、全时段异动、导出与载入复测、成分股弹窗
- features.md 补: 分钟策略回测与结果沉淀、异动监控三tab(偏离值阈值
  按板块分档精确化)、复盘龙虎榜/风向标注入、指标现算口径
2026-08-30 19:05:33 +08:00
shy3130 75c2ab29f7 feat(frontend): 异动中心三tab、回测导出与载入复测、看板成分股弹窗与板块分时
- 异动监控重构为按交易时间线三tab: 竞价异动(风向标+当日/次日对照+追高标记,
  fuyao 未配置统一引导态)/盘中异动(信号筛选+连板/量比/振幅/换手表)/偏移异动
- 复盘页移除风向标卡片(AI 注入保留在后端)
- 回测结果导出 CSV(BOM, 概要/净值/交易明细/分标的统计四段)
- 候选方案「载入复测」: 弹窗→策略页传递, 23 项配置回填复跑
- 看板概念/行业排名行点击弹出成分股(dimensionKindForSourceField 判型),
  领涨股带涨跌幅与板块徽章
- 成分股弹窗新增板块等权分时: 双线(板块/全市场)+0%基线, 伪时间戳轴
  HH:MM 标签, 分钟未落盘引导态, 60s 轮询续期
2026-08-30 19:05:32 +08:00
shy3130 fb7785ceb9 feat(abnormal,dashboard): 盘中异动聚合、维度 source_field 与板块分时端点
- abnormal_moves 新增 build_intraday: enriched 七类当日信号聚合,
  优先级(涨停>炸板>翘板>跌停>新高>新低>放量)+涨跌幅排序, GET /api/abnormal/intraday
- 维度排名项携带 group_source 与 source_field(configId.field),
  前端可精确判定概念/行业而非字符串包含
- ext_data 新增 dimension-intraday: 成分股×当日分钟分区等权聚合,
  prev_close 优先/首根退化基准、成分网格化 ffill、全市场对照线,
  小数制涨跌幅契约、60s 进程内缓存、点击触发不预计算
- 板块分时 7 测 + 盘中异动 4 测
2026-08-30 19:05:32 +08:00
shy3130 3d627aba5e feat(recap): 盘前风向标服务与 AI 复盘注入
- fuyao 客户端新增 short-term-benchmark 端点透传
- auction_benchmark 服务: 历史按日 JSON 缓存(当日不缓存)、交易日回退、
  四态降级(ok/fallback_prev/source_unavailable/no_data)
- 读取时从相邻日K分区现算当日/次日收益对照, 不落缓存
- 复盘 user prompt 注入「盘前风向标(竞价)」上下文
- 11 个测试覆盖回退/缓存/富化数学/上下文
2026-08-30 19:05:31 +08:00
shy3130 cff3b07527 feat(recap): 龙虎榜卡片信息密度与可读性增强
- 摘要行扩为净买/净卖/机构净买/机构净卖各 Top5, 四行药丸左缘固定槽对齐
- fmtVolume 负数按绝对值分级补万/亿单位 (净卖席位原显示裸数字)
- 个股名称后复用 boardTag 加创/科/北板块徽章 (表格/药丸/游资chips)
- 三榜表格数值列头可点击排序 (升降切换, 空值恒垫底, 切tab重置)
- 游资席位金额去掉「净买」前缀
- AI 复盘提示词龙虎榜摘要四段统一 Top5
2026-08-30 19:05:30 +08:00
shy3130 381038e94f feat(recap): 复盘页龙虎榜卡片与 AI 复盘资金动向注入
- fuyao dragon-tiger-list 三榜接入 (非路由数据集, tickflow 无对应能力)
- services.dragon_tiger: 本地日K分区做交易日回退(规避接口非交易日报错), 历史日 JSON 按日缓存(不可变), 当日未发布自动回退上一期
- 卡片视觉对齐市场摘要条: 奖杯徽章/排名药丸/分段式tab/净买额比例条/席位奖牌, 收起两行摘要展开三榜明细, 点股票开日K预览
- AI 复盘 prompt 注入龙虎榜摘要段 (净买/净卖/机构/游资 Top), 未配置 fuyao 时空串不占段
- displayDate 联动: 历史复盘显示当期榜单
2026-08-30 19:05:29 +08:00