shy3130
826eed8cf4
feat(mcp): MCP 服务器 — 开放接口的 AI 工具桥 (Model Context Protocol)
...
mcp-server/ 独立薄桥包 (MCP SDK 2.x, stdio 传输):
- 12 个精选工具: 标的搜索/日K/指数/市场总览/环境阶段/策略清单与定义/
告警/扩展表查读写/策略回测 — 按 TSP_SCOPES 声明暴露, 权限裁决仍在
面板网关 (桥零业务逻辑, 面板升级自动受益)
- 模拟盘交易类端点刻意不包装 (不建议把下单交给 AI)
- smoke_test.py 完整协议冒烟: 握手/tools列表/真实调用; 实测只读 Token
暴露 10 工具、全量 Token 暴露 12 工具, 三次调用 (搜索/总览/环境) 全通
- README: Claude Desktop 等客户端配置示例; features.md 增 MCP 接入小节
2026-09-26 12:47:08 +08:00
shy3130
d3500b1e76
docs(examples): 示例脚本实测修正 — 演示值按字段语义 / 回测走纯 Polars 引擎 / hello 输出规整
...
四个示例以真实 Token 完整跑通: 01 行情 / 02 写入+读回 / 03 策略清单+回测 /
04 票据+事件流 (种告警实时收到 4 条 alert)。
- 02: 演示行不再把占位值写进 date/name, 按字段名给合理值
- 03: POST /api/backtest/run 依赖 vectorbt (可选 extra), 改走所有安装自带
纯 Polars 引擎的 /api/backtest/strategy/run, 近 90 天单标的控制耗时
- 04: hello 帧打印规整
2026-09-26 11:42:22 +08:00
shy3130
f20772d7b7
feat(open-api): 开放能力闭环 — write:ext 数据写入 + SSE 事件流 + 契约守护
...
二开闭环补齐三块: 数据进得来 (写入)、事件推得出 (SSE)、契约有人守 (快照+CI)。
- write:ext scope (第六档): POST /api/ext-data/{id}/ingest 对 Token 开放,
复用管理端同一校验/落盘/视图刷新路径; 结构配置/上传/拉取仍不开放,
外部只能写行数据, 不能改写表结构
- SSE 短期票据 (V2 收尾): POST /api/events/ticket 换 60s 一次性票据 →
GET /api/events?ticket=… 订阅事件流; 票据只继承 Token scope 不放大权限;
进程内事件总线 (services/events.py, 慢消费者丢旧保新), 告警落盘点已挂
(alert_store.append/append_many → bus), 事件按 scope 过滤双向验证
- 契约守护: test_openapi_contract.py 冻结 tier=a 开放面 (61 端点),
增删须显式更新快照; 新增 ci.yml (后端全量测试 + 前端构建) 把契约
变化拦在 PR 上
- examples/open-api: 四个零依赖可运行示例 (行情/写入/回测/事件流) + README
- 菜单设置架构标注: 每页核心/扩展徽标 + 悬停原因 + 图例 (按 open-platform-plan
§2 依赖方向分类, 核心 8 页/扩展 11 页); 顺带补上 MenuSettings 缺失的 模拟盘
- 测试: 网关 write矩阵/票据语义 + 票据生命周期/总线/SSE帧/告警联动 + 契约快照,
全量 2408 passed / 102s; 线上实测: ingest 200 / 票据一次性 / SSE hello+
alert 推送 / scope 过滤双向 / 契约 61 路径
2026-09-26 11:31:11 +08:00
shy3130
4c7f7be484
fix(watchdog): stop() 取消死锁 — CancelledError 不得计入探测失败
...
_loop 的 except BaseException 把 task.cancel() 送来的 CancelledError 当
"探测失败"吞掉并继续循环: 当 cancel 恰好落在 wait_for(to_thread) 内时
(而非轮间的 sleep), 任务永不结束, stop() 的 await self._task 永久挂起 —
生产关闭 (lifespan) 与测试收尾均会死锁, 全量测试偶发卡死 45min+ 的根因。
修复: CancelledError 单独穿透; 新增确定性回归测试 (任务停在探测内时
stop 必须立刻返回)。纯 asyncio 200 次压测复现脚本由必挂转全过。
顺带说明: 本机旧 venv 装的是 polars 1.40/py 慢版本而 lock 早已钉
pytest 9/polars 1.44, fresh clone 同样命中; 现已同步 venv 到 lock 口径,
全量 2395 passed / 96s。
2026-09-26 11:02:46 +08:00
shy3130
559cee7062
chore: uv.lock 同步项目版本 0.3.1 -> 0.3.2
...
pyproject bump 后未更新 lock, uv run/uv sync --frozen 会因 lock 过期
触发重新解析 (开发机撞镜像 403, CI --frozen 直接失败)。
2026-09-26 10:01:02 +08:00
shy3130
7f628816b9
feat(open-api): 0.3.2 开放能力版 — API Token 网关 + Tier A 契约 + 版本清单
...
- Token 域模块: tsp_ 前缀 + SHA-256 哈希存储 (0600), 明文仅创建时返回一次,
吊销立即生效, last_used_at 节流落盘 (≥60s)
- Bearer 网关中间件 (与密码会话并行): 五档 scope 校验 (read:market/read:ext/
read:analysis/run:backtest/paper:trade) + 滑动窗口限流 (默认 120/min,
OPEN_API_RATE_LIMIT_PER_MIN 可调) + X-RateLimit 响应头; 管理接口永不对 Token 开放
- GET /api/openapi.json?tier=a 契约视图: 按网关规则表过滤 OpenAPI 规范 (58 路径),
规则表即唯一契约源
- 设置 → 开放接口: Token 管理 UI (创建表单/scope 说明/明文一次性展示/吊销)
- 设置 → 系统设置 检查更新: 静态链接升级为真实版本对比 (GitHub API 优先,
latest.json 清单兜底), 发现新版本给下载入口
- release.yml 新增 manifest job: Release 附 latest.json (版本/三平台下载地址/sha256),
支持分批发布按实际资产生成
- 版本 0.3.1 → 0.3.2 (后端 __init__/pyproject + 前端 package.json)
- docs: features.md 开放接口章节; open-platform-plan.md V1/V2 标记已实现
- 测试: test_api_gateway.py 8 项 (域模块/scope 映射/E2E 401-403-200 矩阵/
429+Retry-After/吊销即拒), 全量 2394 通过
2026-09-25 22:38:58 +08:00
shy3130
5f39f7dd8d
feat(ext-data): 数据出口强化 + 核心开放设计方案 (0.3.2 起点)
...
- /rows 查询五件套: filter 等值过滤 / sort / offset 分页 /
start_date+end_date 范围合并 (自动补行级 date 列, diagonal 容忍分区
schema 漂移), 快照模式范围查询明确 400
- /values 字段取值枚举端点 (filter 下拉配套, 去重+计数降序)
- 市场级表 (market_level): 行=全市场每日一条, 无标的列; 创建/更新 API、
ingest 与拉取链路放行、创建向导开关跳过标的关联 —— 市场环境类数据
发布为扩展数据的底座
- 拉取分页协议 (仅 GET): page_param/page_size_param/page_size/max_pages,
空页/短页判停; 拉取面板新增分页配置输入
- docs: features.md 分页与 /rows 契约章节; open-platform-plan.md
核心能力开放与插件化改造设计稿 (Token/scope/限流/Tier A/分期路线)
- tests: 22 个新用例 (查询语义/分页判停/市场级全链路/values),
ext 全量 261 通过
2026-09-25 21:29:23 +08:00
shy3130
252160e46f
feat(paper): 账户横向对比/费用可调/默认值记忆/下单与策略ID联想 + 界面美化
...
- 横向对比: 新增 GET /api/paper/compare (逐账户概览+回合统计+定版净值);
前端「账户对比」弹窗 — 归一化净值叠加图 (起点=1) + 12 项指标对比表,
收益领先账户标「领先」徽标, 冻结账户标「冻结」
- 费用可调: update_settings 扩展佣金/印花税/滑点三参数 (范围校验,
仅影响之后的新成交); 头部费用文本改为可点击按钮, 弹窗内与涨跌停排队一起改
- 默认值记忆: 创建账户表单新增费用三输入框, 本次取值存 localStorage
作为下次新建的预填默认
- 联想搜索: 下单代码接 instrumentSearch (代码/中文名/拼音首字母, stock+etf);
自动跟单策略/规则 ID 输入框按中文名/ID 过滤, 聚焦出全量列表;
抽出通用紧凑联想组件 SuggestInput (键盘导航/外点关闭)
- 美化: 统计卡带主题色图标 (盈亏图标随涨跌变色), 悬停强调边框
- tests: settings 费用更新 (含超范围 400) 与 compare 契约 2 个新用例 (51 passed)
2026-09-25 16:21:24 +08:00
shy3130
fa5e5a4ba6
fix(paper): 新建虚拟账户改为草稿态, 支持取消退出
...
旧实现点「+」直接把生成的 id 写进 accId, 刷新后卡在无主初始化向导上无法
退出。改为 draftId 草稿态: 点「+」只进入草稿不动 accId/localStorage,
取消即丢弃; 已有其他账户时顶部保留账户切换, 一个账户都没有才强制向导。
本文件内 text-base 撞名替换随本次一并生效 (同上一提交)。
2026-09-25 14:45:58 +08:00
shy3130
e8f7026adb
fix(ui): 修复 text-base 与色板 token base 撞名
...
色板里定义了颜色 token base, Tailwind 的 text-base 因此生成 color 规则
(文字被涂成 --base 背景色) 而非 16px 字号 —— 标题字号丢失, accent 底按钮
文字与底色同色不可见。全量替换: 字号意图改写 text-[16px] leading-6,
accent 底按钮文字改写 text-white; tailwind.config.ts 注释禁用 text-base。
2026-09-25 14:45:58 +08:00
shy3130
1908173bee
fix(analysis): 补上 market-snapshot 的 SSE 失效条目 ( #419 )
...
290a0f5e 只落了说明注释与设置页开关, SSE_INVALIDATE_PREFIXES 内实际没有
'market-snapshot' 条目, quotes_updated 依旧不会失效该查询, 盘中停留分析页
仍不自动刷新。补上缺失条目使修复真正生效。
2026-09-25 14:34:50 +08:00
shy3130
290a0f5e22
fix(analysis): 概念/行业分析 market-snapshot 接入 SSE 行情刷新 ( #419 )
...
market-snapshot 查询不在 SSE_INVALIDATE_PREFIXES 内, 盘中停留页面时
板块聚合数值(平均涨跌幅/涨跌家数/强度/龙头/成分股行情)不随行情更新,
只有手动刷新才重取。后端快照本身读最新日内缓存是活的, 缺口纯在前端
触发链路。
- SSE_INVALIDATE_PREFIXES 加入 'market-snapshot': quotes_updated 时
失效该查询, 两分析页(及成分成员对话框)打开时自动重取; 仅页面打开
才实际发请求, 推送节奏 6~60s 与看板 overview-market 同档
- 设置页「页面实时刷新」新增「概念/行业分析」开关 (未配置默认开启,
沿用 sse_refresh_pages 偏好体系)
2026-09-25 14:27:43 +08:00
shy3130
d0c474a27b
Merge branch 'feat/paper-trading': 模拟盘 V1/V2/V3 (虚拟账户/自动跟单/成交推送/导出/对比/AI注入)
2026-09-24 22:00:25 +08:00
shy3130
f249856bf7
feat(paper): V3 补全 — 结算成交留痕/自动跟单下单事件推送/AI 持仓注入多账户
...
- paper.day_fill_events: 交易日成交台账 → AlertEvent 同构事件;
daily_pipeline paper_settle 阶段补 alert_store 留痕 (next_open/close
单的成交发生在盘后管道, 盘中钩子覆盖不到; 管道无 SSE 广播器, 留痕即可见)
- paper_auto.auto_order_events: 自动跟单创建的订单 → 推送事件
(rule_id 从 order.source 还原), quote_service 钩子随成交事件一并走
SSE toast / 语音 / 系统通知 / 留痕 / Webhook 既有通道
- stock_analyzer: 虚拟持仓注入改为逐账户收集 (V2 多账户), 空仓账户跳过,
每账户一行标注账户名; raw 口径浮盈不变
- tests: 新增 day_fill_events / auto_order_events / 多账户注入用例,
既有注入用例适配列表签名 (66 passed)
2026-09-24 20:01:14 +08:00
shy3130
508a920ce5
Merge PR #418 from KenNeo730/fix/enriched-publication-commit-idempotent
...
fix(enriched): commit() 幂等, 多日期分区写入不再误报 ownership was lost
与 33c114d7 (#417 ) 同根因的等价修复: 头部「重复提交幂等返回」分支与
尾部「发布后复位 _changed」叠加 — 空提交走顶部守卫, 头部分支转为
_publishing 复位后的防御性兜底。零冲突, 双方回归测试 (18 项) 全绿。
2026-09-24 18:57:54 +08:00
shy3130
4db9c7b6fc
fix(enriched): commit() 发布后复位脏标记, 多分区空提交不再误抛 ownership ( #417 )
...
EnrichedPublication.commit() 发布完成后 _publishing 置 False、标记写回
ready payload (不含 publication_id), 但 _changed 未复位。多日期分区写入
复用同一发布对象 (repository._write_daily_partition), 有变化分区提交后
再遇到无变化分区时, _write_partition_locked 的"无害空提交"带着过期脏
标记命中 ownership 校验, 必然抛 "ownership was lost", 整批写入中断。
e3baba6 让 ETF 增量日K用完整本地历史重算前复权 (单次 245+ 日期分区),
必然出现无变化分区, 该旧缺陷自此恒定复现 (盘后管道 index/etf 阶段失败)。
修复: commit() 发布完成后复位 _changed — 待发布内容已全部落盘, 之后任何
写入都会经 _claim_or_verify 重新认领并再次置位, 语义不变; 空提交经由
既有的是否脏守卫自然幂等。
回归测试: 单对象重复 commit 幂等 + 仓储级「有变化分区在前、无变化分区
在后」两用例, 修复前均失败、修复后通过。
2026-09-24 18:13:26 +08:00
shy3130
51d8083e89
feat(paper): V3 策略候选对比卡 + AI 个股分析注入虚拟持仓
...
- 模拟盘右列新增「策略对比」卡: 统计 vs 策略候选 (回测报告持久化摘要, 同口径标量),
各按己方单位渲染 (候选小数 fmtPct / 模拟盘百分数), 不做数值换算
- api 客户端新增 backtestCandidates + BacktestCandidate 类型 + QK 键
- stock_analyzer: 模拟盘默认账户持有该标的时, 用户提示词注入虚拟持仓上下文
(数量/成本/浮盈, 浮盈优先 raw_close 口径避免除权失真; 注入失败静默跳过)
- 测试: 注入/空仓/raw 口径 3 项 + 既有 46 项全过; 前端 build 通过
2026-09-24 18:13:11 +08:00
shy3130
33c114d736
fix(enriched): commit() 发布后复位脏标记, 多分区空提交不再误抛 ownership ( #417 )
...
EnrichedPublication.commit() 发布完成后 _publishing 置 False、标记写回
ready payload (不含 publication_id), 但 _changed 未复位。多日期分区写入
复用同一发布对象 (repository._write_daily_partition), 有变化分区提交后
再遇到无变化分区时, _write_partition_locked 的"无害空提交"带着过期脏
标记命中 ownership 校验, 必然抛 "ownership was lost", 整批写入中断。
e3baba6 让 ETF 增量日K用完整本地历史重算前复权 (单次 245+ 日期分区),
必然出现无变化分区, 该旧缺陷自此恒定复现 (盘后管道 index/etf 阶段失败)。
修复: commit() 发布完成后复位 _changed — 待发布内容已全部落盘, 之后任何
写入都会经 _claim_or_verify 重新认领并再次置位, 语义不变; 空提交经由
既有的是否脏守卫自然幂等。
回归测试: 单对象重复 commit 幂等 + 仓储级「有变化分区在前、无变化分区
在后」两用例, 修复前均失败、修复后通过。
2026-09-24 17:57:01 +08:00
shy3130
28bd46df2a
feat(paper): V3 成交推送(事件走监控SSE/语音/系统通知/留痕/Webhook) + 成交台账导出 CSV
...
- evaluate_intraday 返回成交事件列表(字段对齐 AlertEvent, source=paper), 域模块只产出不投递
- quote_service 钩子收集事件: SSE toast + alert_store 留痕 + 系统通知(复用既有开关) + 已配置 Webhook 渠道异步投递
- 前端: AlertToast 模拟盘徽章、语音播报 paper 文案分支、模拟盘页成交台账一键导出 CSV(BOM)
- 测试: evaluate_intraday 契约更新(int→list) + 新增事件字段断言, 41 项全过
2026-09-24 17:35:56 +08:00
shy3130
dbb2e6dd14
feat(paper): 模拟盘虚拟账户 — 模拟撮合/自动跟单/多账户/涨跌停排队/统计告警
...
- 撮合域: append-only 成交台账唯一事实源, T+1/涨跌停/停牌顺延/除权调整,
佣金印花税滑点与回测引擎同口径
- 下单: 即时/次日开盘/当日收盘, 盘中快照撮合 + 盘后结算幂等;
涨跌停排队次日重试可选 (账户级开关, 顺延上限 3 日)
- 自动跟单: 监控事件触发按规则下单 (跟策略/跟规则, 固定金额/权益%,
同标的冷却去重), 下单复用撮合域同一把锁与校验
- 多账户: data/paper/accounts/{id}/ 完全隔离, 旧单账户布局自动迁移,
API ?account= 贯穿全部端点, 盘中钩子与盘后结算逐账户执行
- 统计: FIFO 回合/胜率/盈亏比/均持天数/最大回撤; 成交落告警记录
- 前端: 模拟盘页 (净值对比沪深300/持仓/订单/成交台账/下单/规则面板/
账户切换), 买入红卖出绿 A 股配色
- 测试: 域模块 33 项 + API 契约 8 项
2026-09-24 17:19:09 +08:00
shy3130
ecc418bd94
feat: AI 助手推广位、显示细节优化与模拟盘设计方案
...
- AI 助手: RunningHub 推广位(标题行跑马灯、一周静默、无缝循环、悬停暂停), 抽屉头部与侧边栏模型名完整显示
- 测试: mining manager 终态事件轮询收敛, 消除状态先于事件落盘的读侧竞态
- 文档: 新增虚拟账户(模拟盘)功能设计方案 docs/paper-trading-plan.md
2026-09-24 13:59:14 +08:00
shy3130
4743030425
chore: bump version to 0.3.1
2026-09-24 11:53:37 +08:00
shy3130
c37f450e28
feat: 更新 README, 新增快速预设, 调整 AI 默认上下文/输出限制
...
README:
- 更新顶部说明区块, 新增静态展示资源
快速预设 (设置页):
- 新增预设项, 调整官网链接与介绍文案, 高亮样式适配明暗主题
- 模型输入框支持下拉选择: 经后端代理拉取模型列表, 支持关键词过滤
AI 默认配置:
- 输出上限 8192 → 16384, 上下文窗口 64000 → 128000, 对齐当前主流模型能力
- 后端新增模型列表代理接口, 前端 api 同步封装
2026-09-24 11:39:54 +08:00
shy3130
43dfef3e62
fix(backtest): 分钟穿越成交参考线剔除当根收盘, 消除前视 ( #388 )
...
买卖穿越成交共用 rolling_mean(close,5) 作参考线, 该线含当日收盘 —
盘中模拟成交价依赖 15:00 才确定的收盘价, minute_fill 声称的分钟级
精确成交被系统性污染; 卖出信号回放侧 (build_minute_exit_reference)
早已用代数法剔除当根, 双侧纪律不一致。
新增 build_minute_entry_reference: (window·MA - close)/(window-1)
代数剔除当根 = 前 window-1 根均值, 当日开盘即已知; 与卖出侧同住
minute_trigger 模块, 「当日已知参考线」单一实现。strategy.py 三处
调用点统一替换, 无重复公式。回归测试钉住性质: 同一盘中路径只改
当日收盘, 成交价必须不变。
2026-09-22 00:40:49 +08:00
shy3130
efc4e24f17
fix(backtest): 分钟 VWAP 缺 x100 量纲错误, 无参考线成交价放大 100 倍 ( #387 )
...
volume 单位手、amount 单位元, VWAP = amount/(volume*100) — 与 scoring/
intraday_features/matrix 的既有实现同口径。原实现漏乘 100, 无参考线
(参考线 NaN) 的分钟成交价系统性放大 100 倍。夹具同步改为契约口径
(amount = 价 x 手 x 100), 并加量级护栏 — 均价必须落在当日价格区间
量级, 拦住把错误公式断言成规格的回归。
2026-09-22 00:40:42 +08:00
shy3130
b6a7367262
feat(screener): 新建策略「默认基础参数」配置与一键应用全部策略
...
- 策略页头部新增配置入口: 编辑默认基础过滤(价格/流通市值/成交额/换手/板块/ST), localStorage 持久化, 内置默认与原模板一致
- 新建策略两条路径生效: 自定义/matrix 模板注入 + AI 生成 step1 提示词注入(未配置时提示词逐字节不变)
- 对话框内一键应用: 二次确认后分批 PATCH 到全部股票策略, 只动 basic_filter 不碰各策略参数/评分, 应用即所见并同步存为默认配置
2026-09-21 13:46:32 +08:00
shy3130
2488fdc9ed
feat(screener): 分钟策略进入页面自动异步计算命中数, 无需点击
...
- 新增 runAllMinute: 按池批量跑分钟策略(与日线 runAll 串行, 防并发崩 Numba), 结果合入卡片
- 日线摘要整表替换时保留分钟命中数, 不再被摘要刷新冲掉退回「待计算」
- screenerRunAll 支持 timeframe 参数; 自动计算关闭时保留「待计算」点击引导
- 卡片 computing 覆盖分钟批量计算中状态(脉冲占位, 算完点亮)
2026-09-21 13:46:11 +08:00
shy3130
70350ec8b7
fix(quote): stop() 不再持久化关闭实时行情, 容器重启后按用户原开关自动恢复
...
lifespan shutdown (容器停止/重启) 也调用 stop(), 原实现无条件
_save_enabled(False) 会把用户开启的实时行情持久化成关闭, 重启后
boot_check 读到 False 需手动再开。持久化语义移至 disable() (用户主动关闭)。
2026-09-21 12:09:46 +08:00
shy3130
477956fed3
fix(quote): 全空补充列不再进入增量管道, 自定义源实时链路当日换手/振幅不再全空
...
fuyao 等源对未提供字段显式给 None 键, 原样转发全空列会让下游
compute_enriched_today「列存在即直接采用」跳过回退计算, 当日
turnover_rate/amplitude 全空落盘且每轮实时覆写自锁。_build_quote_extra
丢弃整列全空的字段, 下游自动回退 float_shares/价格计算, 已落盘坏数据自愈。
2026-09-21 12:09:24 +08:00
shy3130
8aaf0817d4
fix(brand): logo 去圆角 — 全直角/平头风格
...
方括号折角改 miter 直角、笔帽改 butt 平头、K 线实体去 rx、
徽章底改直角方形; 重新导出全部 19 个 PNG。渐变与几何比例不变。
2026-09-20 18:21:49 +08:00
shy3130
02d662389c
chore(brand): 品牌 logo 资产 (SVG 主文件 x3 + 19 个透明 PNG)
...
方括号 [K] 标记: 沿用应用内 logo 概念的品牌化精修 — 圆角笔帽 +
品牌紫渐变 (#A78BFA→#7C3AED), bullish 姿态。logo.svg=浅底主版,
logo-white.svg=深底纯白版, logo-badge.svg=App 图标/头像徽章版;
PNG 覆盖 32~1024px 常用尺寸, 全部带 alpha 通道。
2026-09-20 17:50:47 +08:00
shy3130
72fc28d813
merge: main (解决 test_kline_daily_latest 追加冲突, 保留双方用例)
...
并按 #369 后的 cn_today 守卫钉死 test_index_daily_live 的日期,
消除非 CST 主机北京 00:00-08:00 的测试闪失
2026-09-20 16:43:08 +08:00
shy3130
5fb4fbd1b3
style(assistant): 走势卡并排两列并加高, 修复长宽比失衡
...
720px 抽屉内日K/分时两卡竖排各占全宽而图高仅 80px (约 8.4:1),
被横向拉成长扁条。改为 ≥2 张图 grid-cols-2 并排 + 图高 80→128px
(实测每卡 336x187, 宽高比 2.6:1); 单张图保持全宽。标题加 truncate、
页脚 flex-wrap, 半宽下长名称与涨跌幅不再溢出。纯样式, 数据链路不变。
2026-09-20 16:07:17 +08:00
shy3130
5fad0da469
fix(kline): 新股上市初期无涨跌幅窗口判定, 修复分时钳制与假涨停信号
...
注册制新股上市前 5 个交易日 (北交所仅首日) 无涨跌幅限制, 此前系统
完全没有该概念 (C沈鼓 601091.SH 09-18 昨收 20.8/盘中 82.59):
- 分时图: 自适应模式不再钳制到 ±rate 涨跌停带内 (y 轴被夹在
18.72~22.88, 曲线全部出界); 涨跌停模式取涨跌停带与实际数据较大者;
上市首日无昨收时 yAxis 加 scale 不再从 0 锚定; 区间过宽时刻度减半
- price_limits: 新增窗口判定单一事实源 (注册制改革分板块 cutoff,
is_no_limit_day 交易日序号精确门控 + 保守日历边际兜底)
- pipeline: _no_price_limit 由「哨兵值且 as_of 命中单日」扩展为
「或 listing_date 命中窗口」; 连板/炸板/翘板/回测撮合约束全部继承;
实时路径同口径兜底
- api: minute 响应 price_limit 新增 no_limit, 前端据此不画假涨跌停虚线
- schemas: list_date → listing_date 命名对齐 (与维表实际字段一致)
测试: 窗口日/第 6 日恢复/北交所首日/实时路径/API no_limit/前端 y 轴
范围/普通股与 ST 回归; 后端全量 2237 passed, 前端 43 passed。
2026-09-20 16:07:07 +08:00
shy3130
e473cfb86f
style(preview): 个股详情弹窗顶栏合并单行, 「自选于」移入信息条
...
纯样式/布局调整, 交互逻辑不变:
- 顶栏由两行并为单行: 个股身份 | 视图/区间控件(紧邻操作按钮) | 操作
按钮组, 窄窗口 flex-wrap 兜底, 省出一行垂直空间
- 「自选于」标注移入 StockInfoBar, 显示在「自定义信息条」按钮左侧;
StockInfoBar 新增可选 addedDate prop, StockPanel(含 infoBarOnly)透传
- 日K/分时 tab 与区间/档位按钮统一分段容器样式, 激活态 accent 高亮
- 图表区增加内衬卡片容器(边框/圆角/微底色), 与弹窗背景分层
pnpm build 通过; 日K/分时两视图截图验收通过。
2026-09-20 14:23:41 +08:00
shy3130
4efc238032
feat(kline): 分钟K原始口径落盘+共享复权因子表, 读取时即时前复权投影
...
解决除权后已落盘分钟数据(前复权口径)与最新数据不可比的问题:
- 新增 minute_adjust 服务: 除权因子表 + 读取路径投影, ratio =
cum_factor(D)/total_factor 作用于价格与成交额, ratio=1 短路直读
- kline_sync/repository: 数据目录存在 .raw_basis 标记时分钟拉取改用
adjust='none' 落盘原始 OHLC; 无标记保持旧前复权行为, 字节级兼容
- api/kline: 新增 POST /api/kline/minute-migrate 幂等迁移, 将混合口径
分区转为原始口径后写入标记启用新架构
- 测试: 新增 test_minute_adjust (9 例); 5 个既有分钟测试适配新口径
全量后端测试通过 (2239 passed, 1 例既有偶发 flaky 与本次无关)。
2026-09-20 14:23:33 +08:00
shy3130
7687278ec6
Merge pull request #360 from kevin9327/fix/assistant-financials-period-order
...
fix(assistant): get_financials 按 period_end 排序后取最近 N 期, 不再依赖文件行序
2026-09-19 11:16:32 +08:00
shy3130
4b8b841f6e
Merge pull request #359 from kevin9327/fix/assistant-intraday-chart-snapshot-date
...
fix(assistant): 分时小图按行情快照所在交易日取分钟K, 周末/节假日/开盘前也能附图
2026-09-19 11:16:32 +08:00
shy3130
a38941a0ce
Merge pull request #358 from kevin9327/fix/assistant-prompt-pct-units
...
fix(assistant): 提示词数据口径改正换手率与指数涨跌幅为百分数, 不再引导模型放大 100 倍
2026-09-19 11:16:32 +08:00
shy3130
42c1075de8
Merge pull request #357 from kevin9327/fix/assistant-tool-call-id-fallback
...
fix(assistant): 流式 tool_calls 缺 id 时补一次并复用, tool 回填的 tool_call_id 与助手消息一致
2026-09-19 11:16:32 +08:00
shy3130
e912bbb000
Merge pull request #356 from kevin9327/fix/assistant-etf-index-quotes
...
fix(assistant): 行情/自选/持仓工具按资产类型取快照, ETF 与指数不再「未匹配到行情」
2026-09-19 11:16:31 +08:00
shy3130
5eafc0ad0e
feat(assistant): 个股问答自动附分时+日K双图(蜡烛/分时两种渲染), 系统提示词结构化优化(口径换算/语法子集/指代消解)
2026-09-18 22:38:18 +08:00
shy3130
1bc5d5b3ac
docs(readme): AI 对话助手章节插入市场总览问答效果图
2026-09-18 22:19:55 +08:00
shy3130
897d0a2b55
feat(assistant): 回答视觉增强 — 日线工具自动附收盘走势小卡, 正文涨跌语义色/涨跌停徽章/方向词着色/金额等宽
2026-09-18 22:17:44 +08:00
shy3130
2678c51642
Merge remote-tracking branch 'origin/feat/ai-assistant-extension'
2026-09-18 21:20:56 +08:00
shy3130
b05bba4237
feat(assistant): AI 对话助手 — 完全解耦扩展模块(流式对话 + 18 个只读工具)
...
后端 app/custom/assistant/ 与前端 src/custom/assistant/ 各自独立, 零核心文件修改,
删除目录即整体卸载(分别由扩展系统启动期自动发现 / 构建期自动挂载)。
- 流式: 模块内自建 SSE + tools 有界循环(核心 generate_ai_text_with_tools 为非流式),
文本逐 token 推送; 工具事件经 asyncio.Queue 外推为 NDJSON 事件流, 含心跳保活与断连取消
- 工具: 14 个页面查询工具(个股行情/日线/关键价位/财务五表/自选/持仓提醒/信号库/看板总览/
指数/板块轮动/市场环境/异动/执行策略/因子排名) + 核心 4 个(因子/策略/数据能力/回测);
全部只读且有界, 大表先过滤再取行, 未知工具名回退核心目录
- 入口: 可拖动悬浮球(位置记忆) / 侧栏 AI 徽标旁入口(DOM 锚定, 无槽位改动) / ⌘K 全局快捷键
- 面板: 页面右缘滑入的非模态面板, 默认 720px, 左缘拖拽调宽并记忆, 会话历史本地持久化
- 合规: 每条回答固定附风险提示与数据口径提示; 无 Key 或不支持工具调用(Codex CLI)时 fail-closed
- 版本: 0.2.4 → 0.3.0(前后端 pyproject/package.json/app.__version__ + uv.lock)
- 文档: README 增补 AI 对话助手章节、扩展机制说明、架构图节点与路线图条目
验证: 受影响模块 pytest tests/test_custom_assistant.py tests/test_extensions.py 21 passed;
全量后端套件 2174 passed(1 例 mining 用例在整套并发下偶发失败, 单跑通过, 与本次改动无关);
ruff 改动文件无新增告警; pnpm build 通过; 浏览器实测逐字流式渲染、工具足迹卡、拖拽调宽与
悬浮球位置记忆、版本显示 v0.3.0
2026-09-18 17:47:49 +08:00
shy3130
51be43e951
feat(watchlist): 自选页新增 今开/最高/最低/昨收/成交量/涨停价/跌停价 列 ( #328 )
...
- open/high/low 后端本就返回, 纯前端加列; prev_close/volume 在 enriched
缓存已有, _WATCHLIST_COLS 白名单补 2 字符串即透传, 零新增 IO
- 涨跌停价在端点内对自选行(几十~几百行)用 polars_price_limit_pct +
polars_limit_price 向量化现算(交易所整数分半进位口径, 含主板 ST
2026-07-06 新老划断), 亚毫秒级; ETF/指数涨跌幅规则不在覆盖范围内,
置 null 由前端渲染 "—"
- 前端 7 列默认隐藏(未开启用户零渲染/排序成本), mergeColumns 对老用户
持久化配置自动补齐新列, renderBuiltinDataCell/getSortValue 各加 7 case,
支持排序与数值筛选; 涨停价红色/跌停价绿色, 成交量按万手/亿手换算
- 测试: watchlist_enriched 契约(含 ST 划断前后两种数据日) + mergeColumns
老配置兼容(vitest)
2026-09-17 16:04:25 +08:00
shy3130
6766930d23
Merge branch 'main' into fix/atomic-parquet-writes
...
解决 ext_data.py import 区冲突: 保留 #314 的 cn_today 与本 PR 的
atomic_write_parquet 双方新增。
2026-09-16 09:47:02 +08:00
shy3130
54739089f3
fix(ai): NDJSON 流式接口空闲心跳保活 + LLM 首包前重试
...
根因: 分析/复盘端点 yield meta 后等 LLM 首包期间流上零字节可达数分钟,
反向代理按空闲超时切断连接, 前端报裸 network error; 且 max_retries=0
使上游(DeepSeek)高峰过载时一次失败即终止。
- 新增 services/ndjson_heartbeat.with_heartbeat: 空闲超 15s 插入
{"type":"ping"} 行保活(间隔与 mining.py SSE 心跳一致)
- 5 个流式端点接入: 复盘/个股/财务/轮动/策略生成; 策略生成端点补齐
Cache-Control 与 X-Accel-Buffering 头
- AsyncOpenAI max_retries 0→2: SDK 重试仅覆盖首包前, 未产出内容, 安全
- 前端事件类型联合加入 'ping'(下游对未知类型静默忽略); 新增
friendlyStreamError 把浏览器裸网络错误翻译为可操作提示, 6 处落点应用
- 新增 test_ndjson_heartbeat.py 覆盖心跳插入/异常透传/断连清理/重试配置
兼容性: ping 为新增事件类型, 旧前端与 daily_pipeline 消费方静默跳过,
前后端可独立发布。
2026-09-15 17:43:56 +08:00
shy3130
056b16aab2
fix(ext-data): 前端 fetch 超时跟随拉取超时配置
...
request() 默认 30s abort 会先于后端超时触发: 配置了 120s 的全量竞价
/day 在浏览器端 30s 就被中止, 用户看到的是前端 '请求超时(30s)' 而
非后端行为 — PR #313 首版只放宽了后端, 漏了这层。
- api.ts 新增 extPullTimeoutMs: 单次超时×1000 + 10s 解析/写盘缓冲
- pull/test、pull/run、detect-url 的客户端超时跟随 timeout_seconds
- backfill 按天数×单日超时估算 (+30s 缓冲), 缺省上限 600s (旧为 30s)
2026-09-14 15:52:55 +08:00
shy3130
72cbf67070
feat(ext-data): 拉取超时进配置, 默认 30 秒与历史行为一致
...
大响应接口 (如全量集合竞价 /day, 实测 ~77s) 在硬编码 30s 超时下必然失败。
- PullConfig.timeout_seconds: 5~300, 默认 30; config.json 缺字段或手改
非法值时归一 30 (fail-closed), 旧配置零迁移
- _request_json (定时拉取/手动拉取/测试/回填共用) 与 detect-url 探测
均读该配置; detect-url 请求体新增同名字段, 创建对话框可随测试识别传入
- 编辑面板 (ExtDataPullPanel) 与创建对话框 (CreateExtDialog) 增加
拉取超时输入框, 创建时随拉取配置一起落盘
2026-09-14 15:38:45 +08:00
shy3130
b4ca8b43ab
fix(screener): 单跑刷新缓存保留 warnings; 分支变基回 main
...
复审发现两处问题:
1. _update_cache_strategy 重建缓存条目时只保留 total/as_of/rows 白名单,
run_preset 单跑会把数据不足提示冲掉 (PR 描述声称随缓存读出, 实际不成立)。
现在携带 warnings 并补回归测试。
2. 分支误基于 #311 分支创建, diff 混入裸符号修复全部改动 — 已变基回 main,
本 PR 只含选股提示相关 4 个文件。
2026-09-14 14:03:46 +08:00
shy3130
cf915c82c4
feat(screener): 数据不足时选股显式提示, 盘后管道薄库 WARN
...
空库首跑/仅当日实时覆写 1 天的库, 指标暖机不足, 选股静默全 0 且
无任何信号 (#303 )。
- enriched_history_days: 按 date=* 分区目录计数本地覆盖交易日数
(目录列举 O(天数), 不读 parquet 内容, 不进指标计算路径)
- ScreenerService.coverage_warnings: 覆盖低于暖机需求时生成人话警告;
策略运行用 engine.required_history_bars 精确值, 自定义 SQL 用通用
30 天窗口
- /run /run_preset /run_all 响应附带 warnings 字段 (1d 周期),
run_preset/run_all 同时写入盘后缓存随 get_cached 读出
- 盘后管道收尾检测 enriched 覆盖过薄 (<30 天) 时打 WARN 引导全量回填,
result 新增 enriched_total_days
Closes #303
2026-09-14 14:02:18 +08:00
shy3130
c5fd3db5ba
fix(kline): 恢复 sync_symbol 的 Query(...) 声明
...
复审发现上一提交误把 symbol: str = Query(...) 改成裸注解 — 行为等价
(FastAPI 对无默认值的单类型参数仍按必填 query 解析), 但属意外改动,
超出本 PR 范围。
2026-09-14 14:01:35 +08:00
shy3130
01b153c28d
fix(kline): 裸符号按维表补全后缀, 批量同步 0 行标的 fail-loud
...
上游对无交易所后缀的裸符号返回 200 空 payload, 本地静默写 0 行且流程
显示成功, 新环境初始化极易踩坑 (#302 )。
- 请求前按 instruments 维表把 600000 补全为 600000.SH; 维表缺失或
无唯一匹配的裸符号显式跳过并告警, 不再带已知无效符号发请求
- 批量同步收尾统计实际入库 0 行的标的(含被跳过的裸符号), 聚合一条
WARNING 并通过 zero_row_out 出参回报, /sync 与 /sync_batch 响应
附带 zero_row_symbols (按调用方原始写法)
- 拉取失败分块与本统计互斥(failed_out 已单独可见), 不重复计入
Closes #302
2026-09-14 13:55:38 +08:00
shy3130
4abe9e9caa
feat(ext-data): 日内序列表 — time_field 配置支持集合竞价等多盘数据接入
...
- PullConfig 新增可选 time_field (空值归一 None, 旧配置兼容); API PullConfigReq 透传, rows 端按时间列升序
- 时序表写入去重键: 配置 time_field 时按 [symbol, 时间列] 去重 (同 symbol 同时刻幂等, 不同盘并存), 未配置行为不变
- enriched/因子链路无需排除: _load_ext_value_maps 与 ext_factors 既有 unique(symbol) 兜底, 多行表确定性收敛
- 前端拉取面板新增时间字段输入框; 配合 hub auction_flow /day 端点逐日回补竞价多盘数据
- 新增 test_ext_time_field.py: 多盘并存/覆盖/默认行为不变
2026-09-13 23:50:10 +08:00
shy3130
257699a6a3
Merge branch 'feat/sector-rotation-monitor-sync' (v0.2.4): 板块轮动六维切换与防污染、指数分时提速、扩展数据按日回补、README 重构
2026-09-13 16:11:12 +08:00
shy3130
89847ab860
chore(release): 版本号统一升级至 v0.2.4
2026-09-13 15:59:24 +08:00
shy3130
64356a0017
style(data): 数据页容器水平居中
2026-09-13 14:14:21 +08:00
shy3130
8a1ed68489
feat(frontend): 板块轮动卡片六维切换+转强转弱面板, 显示模式切换修复, 回补面板日期格式
...
- SectorRotationCard: 活跃前N可选/黑名单编辑(localStorage)/六维板块选项/资金流门控/动态表头;
涨跌切换统计按转强、转弱分行展示; 强度图切换点常显(最强2琥珀+最弱2灰); 走势线端点名称标签+聚焦淡化
- useEChart 生命周期加固(isDisposed/实例残留清理) + 热力图/走势容器分离 key, 修复显示模式切换空白
- 指数分时查询盘中门控(phase===live 才请求), 配合后端快速失败
- api.ts/queryKeys.ts: cross 事件与轮动过滤键入缓存键; 回补配置与面板支持 date_format 选择
2026-09-13 14:14:20 +08:00
shy3130
7cb736e23c
feat(ext-data): 历史回补支持时间戳类日期参数 (date_format)
...
- PullConfig 新增 date_format: iso/compact/ts_s/ts_ms, 非法值归一为 iso
- 时间戳口径为交易日北京时间 00:00:00, ts_s 秒 / ts_ms 毫秒
- 回补逐日请求按配置替换 date 参数值; API configure_pull 接受 date_format
2026-09-13 14:14:07 +08:00
shy3130
63ae2e7fe9
perf(index): /api/index/minute 过去日期快速失败 + 当日 TTL 缓存
...
- 非当日请求不再穿透数据源, 直接返回 {rows:[], source:not_today}, 消除切模式时对历史日期的无效实时拉取
- 当日请求按 (symbol, date) 加 10s 进程内 TTL 缓存, 上限 32 条
2026-09-13 14:14:07 +08:00
shy3130
7e379d717a
feat(sector-rotation): 默认黑名单+成员上限防污染, 六维切换+强弱对半取样+0轴穿越统计
...
- 默认排除融资融券/沪深股通等巨型概念(可替换式自定义), 成员数>300 不参与自动统计, 不足展示行数时回退不过滤
- sort_by 扩展为 activity/score/pct/rank_change/momentum/flow 六维, momentum 前半取最强、后半取最弱
- 分桶 0 轴穿越检测: cross_up/cross_down 计数 + cross_events 事件流(最新在前, 上限 120)
- 响应新增 default_exclude_sectors/max_auto_members; exclude_sectors/auto_rows/sort_by 入参入缓存键, 缓存有界淘汰
2026-09-13 14:14:00 +08:00
shy3130
d33c1e376c
feat(sector-rotation): 展示板块按活跃度 Top10 默认 + 自定义监控(≤20) + 走势线显示模式
...
- 后端: 活跃度 = 近 30 分钟成分股成交额合计 (分钟分区补读 amount 列,
旧 schema 缺列自动降级); 响应新增 universe (全部板块按活跃度降序,
供自定义选择器); series 展示行 = series_names (JSON 数组参数, ≤20
去重、当日无行情剔除) 或活跃度 Top10 (缺量额退化 score 前 10);
缓存键纳入 series_names
- 前端: 板块来源切换 (活跃前10 默认 / 自定义), 自定义模式提供搜索 +
添加/移除 chips 选择器 (上限 20, 超限 toast 提示), 清单按 kind 持久化
localStorage; 显示模式切换 (走势线默认 / 热力图): 走势线为每板块一条
累计涨幅线 (0% 参考轴 + 可滚动图例 + 按值排序 tooltip), 与热力图共用
series 矩阵; 强度图跨实例指针联动、榜单↔展示图双向高亮在两种模式下
均生效
2026-09-12 20:00:17 +08:00
shy3130
23e690d42b
style(sector-rotation): 布局回调两栏结构, 强度图与热力图改跨实例联动
...
合并单图把版面拉成一整列被反馈为丑: 恢复此前两栏布局 (热力图全宽在上,
下方左=切换强度线右=榜单), 对齐改用 echarts.connect 分组实现 — 两图
x 轴窗口一致 (1 分钟桶同步只看最近 60 列), 强度图悬停时热力图同步指针,
tooltip 含指数涨幅; 榜单↔热力图双向行高亮、盘中/回放徽标、未封口桶
琥珀标记均保留。
2026-09-12 19:21:34 +08:00
shy3130
4cd667df2b
feat(sector-rotation): 卡片直观化三连 — 合并图联动/盘中状态/回放徽标
...
- 强度线并入热力图同一 ECharts 实例: 上下两个 grid 共享 x 轴
(axisPointer link), 换血高峰与热力图时段直接对照, 不再靠肉眼跨图估;
1 分钟桶下两个网格同步只看最近 60 列
- 热力图 ↔ 榜单双向联动: 悬停榜单行 → 热力图整行琥珀描边 (dispatchAction
highlight/downplay), 悬停热力图单元格 → 榜单对应行 accent 高亮;
useEChart 增加 events 注入 (经 ref 取最新闭包)
- 盘中/回放状态徽标: 轮动日期 == 北京今天且处于连续竞价时段才标「盘中」,
否则显示「回放 · 日期」; 盘中最后一列桶琥珀描边提示「数据未封口」
(tooltip 同步提示), 避免把进行中的桶当已收盘数据
2026-09-12 19:10:38 +08:00
shy3130
0d94e83c35
feat(sector-rotation): 切换强度图叠加核心指数线, 四只可切默认上证
...
- 卡片头部新增指数选择器 (核心四只, 复用 Layout.CORE_INDEXES 单一前端
清单, 不建副本), 选择按 kind 持久化 localStorage, 默认上证指数
- 指数逐桶涨幅前端聚合: 复用现成 /api/index/minute (当日分钟) +
/api/index/daily (昨收基准, 缺昨收退化首根收盘), bar 涨幅按桶均值,
时间轴对齐 timeline 的 HH:MM, 与全市场线同口径; 查询键集中到 QK
- 蓝线叠加在右百分比轴, 30s 轮询随主查询同步刷新, tooltip 逐点显示;
指数数据不可用时线条自动缺席不影响主图; 后端零改动
2026-09-12 18:28:48 +08:00
shy3130
f22bf7d3e3
fix(sector-rotation): 切换分钟桶/资金流后图表永久空白
...
数据键切换 (1/5/15 分钟桶, 资金流列) 会经过 loading 分支把图表容器
卸载再重挂, 组件本身不卸载: useEChart 的 instRef 仍持有绑在已脱离
DOM 旧节点上的实例, 新数据到达后 setOption 画进离屏节点, 热力图与
切换强度线同时空白。修复: 每次更新前校验实例 dom 与当前 ref 一致,
不一致 (或容器已卸载) 时弃旧实例重建; 浏览器实测 1↔5 分钟往返切换
正常渲染。
2026-09-12 18:07:26 +08:00
shy3130
665c546bb0
feat(sector-rotation): 热度板块分钟轮动热力图 — 卡片直观化
...
- 后端 /api/sector-rotation 响应新增 series: {buckets, sectors, matrix},
热度降序板块 × 分钟桶涨幅矩阵 (数据来自已算好的 per_bucket, 零额外计算),
行与 sectors 同序同截断
- 前端卡片主视觉改为 ECharts 热力图: 行=热度板块 (综合分排序), 列=分钟桶,
红涨绿跌, 色带在行间移动即轮动方向; 色标按 |涨幅| 90 分位钳制,
避免个别小板块单桶 ±10% 撑爆色域导致常见波动近乎透明;
1 分钟桶只显示最近 60 列保证可读; 保留切换强度线与板块榜单
2026-09-12 17:52:26 +08:00
shy3130
2e86b5ae33
Merge branch 'main' into feat/sector-rotation-monitor-sync
2026-09-12 17:29:30 +08:00
shy3130
2402f88df7
fix(minute): 补齐分区只合并触及 symbol, 多日分时缺口按本地落库计算 (issue #305 )
...
- _write_minute_partition 合并时只对本次触及的 symbol 子集 unique,
未触及行原样保留, 消除单股补齐把全市场分区整体读出去重重写的写放大;
尾部全局 sort 保持文件有序不变量, 大幅缩短全局写锁持有时间,
避免看门狗在锁上试探超时误判进程僵死而自杀重启
- 多日分时缺口改为只按本地落库历史 session 数计算, 当日实时 (盘中不落盘)
只参与绘图, 修复缺口被实时数据撑成 0 导致提示条与自动补齐永不触发
- 自动补齐失败后清防重标记, 按 symbol:days 记账并限制最多 2 次自动尝试,
避免死循环刷接口; 提示条手动重试不受限
2026-09-12 17:13:01 +08:00
shy3130
66da3a6657
test(frontend): 维度详情测试只锚定结构顺序, 不再锁死样式类
2026-09-12 16:23:07 +08:00
shy3130
0317b9d6d1
feat(sector-rotation): 盘中板块切换监控 — 全量分钟聚合 + 扩展资金流
...
- 后端 services/sector_rotation: 直读当日全市场分钟分区, 概念/行业二选一,
5 分钟桶等权聚合板块涨幅, rank_change(1h 对照)标记切入/退潮,
top 梯队换血率为切换强度时间线; 资金流按用户选择的扩展列聚合(不写死),
不可用退化为纯涨幅; 30s TTL 结果缓存
- API GET /api/sector-rotation (kind/flow/top/bucket), fail-closed 状态返回
- 前端 SectorRotationCard: 概念/行业分析页共用, 资金流列动态选择(schema-all),
切换强度走势图 + 板块榜单, 30s 轮询实时刷新
- 9 个定向测试: 聚合口径/切换方向/换血指标/资金流读取与降级/参数校验/缓存
2026-09-12 00:11:24 +08:00
shy3130
c8d72b2e6f
fix(settings): 能力矩阵漏传全量分钟路由偏好, 卡片恒显不可用
2026-09-11 23:49:29 +08:00
shy3130
16ac198353
feat(mining): 环境数据覆盖不足时弹窗补算并自动重跑挖矿
2026-09-11 12:07:15 +08:00
shy3130
4bd8af5fde
style(dashboard): 广度条与涨跌分布统一为左绿右红
2026-09-10 22:05:32 +08:00
shy3130
e6cf783417
fix(ext-pull): 拉取循环的状态回写不再清策略缓存
...
上修复 (keep_strategy_cache 沿数据写入链放行) 后线上复现: 每轮拉取
成功后 12ms 缓存仍被清空。clear_cache 新增调用链日志抓到真凶 —
ExtConfigStore.upsert 无条件触发 _invalidate_ext_derived: 调度器每轮
拉取要回写 last_run/last_status/next_run 共 2-3 次配置, 每次都全清
策略结果缓存, 绕过了已放行的数据写入链路。
upsert 增加 keep_strategy_cache 参数 (默认 False 保持 UI 保存配置/
手动变更的全清语义), 拉取循环内 4 处例行回写全部传 True。
2026-09-09 16:30:20 +08:00
shy3130
0d407df219
ops(strategy): clear_cache 记录调用链日志
...
策略页依赖 strategy_cache 秒加载, 缓存被清空即整页回退到全量重算。
今日线上排查: 缓存在扩展表拉取后 12ms 消失, 但三个已知调用方均无
触发记录, 静态分析无法定位。clear_cache 打 WARNING 附最近 5 帧调用
链, 此类问题不再依赖复现现场。
2026-09-09 16:10:03 +08:00
shy3130
23a3dea1ef
fix(strategy): 渐进式 run_all 逐策略隔离失败
...
单个策略执行崩溃 (如自定义策略 filter_history 的数据类型错误) 会杀掉
整批剩余策略: handle 整体 fail, 后台线程结束, 页面剩余卡片永远不亮。
线上实证: 70 策略池跑到第 35 个 (custom_1782999589 pl.DataFrame 构造
schema 混杂) 崩溃, 后 36 个全部没算。
改为单策略 try/except: 失败记入 handle.errors 并移出待算队列, 其余
策略照常算完落缓存; 响应新增 errors 字段 (前端可忽略)。job 级失败
(context 构建崩溃) 仍走整体 500 语义不变。
2026-09-09 15:49:21 +08:00
shy3130
43f2e62cc5
perf(strategy): 渐进式 run_all 只构建一次共享矩阵
...
_run_all_progressive 逐策略调用 engine.run_all(strategy_ids=[sid]),
run_all 不回写 context.market → 每个 matrix_native 策略都重建一次
全市场矩阵 (39 万行, 小服务器单次数秒到十余秒), 6 策略一轮多耗约
1 分钟。
从 run_all 抽出 build_shared_matrix (字段并集语义不变, 非渐进路径
行为一致), 渐进式循环外一次建好放入 context.market 复用。
2026-09-09 15:30:10 +08:00
shy3130
361f77e63c
fix(ext-pull): 定时拉取不再清空策略结果缓存
...
扩展表 PullScheduler 每轮成功写入都会经 invalidate_ext_caches 销毁
strategy_cache, 策略页随之下一次轮询整页空白, 且前端会话级防重入
(runAllDateRef) 不会自动补跑, 小服务器上全量重算需分钟级 → 页面长期黑屏。
例行数据刷新改为只失效扩展帧缓存与注册同步状态 (下次策略运行自然
读到新值); 手动上传/配置变更保持全清 (触发下次全量重算) 旧行为。
keep_strategy_cache 沿 fetch_and_ingest → rows_to_parquet →
write_ext_parquet → invalidate_ext_caches 显式传递。
2026-09-09 15:30:10 +08:00
shy3130
cbebccdd3c
fix(kline): 分钟批量补全识别前部空洞, 重启跨开盘后分时可自愈
...
盘中重启/停机跨开盘后, 本地当日分钟K只剩重启时刻起的连续尾巴。
缺口判定只检查相邻K间隔, 连续尾巴被判"仅尾部落后"走增量 — 增量
锚定本地最新时间, 永远不会回看缺的开头, 上午的洞永久残留, 自选
分时只显示几根K。
- _has_holes 增加前部洞判定: 当日首根 > 开盘+6min 容差即视为洞,
归入全天重拉 (取到即落盘, 一次自愈)。仅根数不足的分支才判定,
稳态零额外请求; 停牌晚开票命中亦幂等无害
- 全量分钟服务健康时不再压制空洞类补拉 (服务增量补不了洞),
纯尾部落后的压制维持不变
实测: 服务器重启窗口后策略页(本地为空)走全天拉取显示完整、
自选页(有连续尾巴)被增量锁死只显示 11 根, 修复后统一自愈。
2026-09-09 12:13:04 +08:00
shy3130
f0f144a254
feat(backtest): 环境数据缺口一键补算并自动重跑
...
- 回测报错横幅识别环境数据缺失文案(提取缺失首日), 显示「补算环境数据并重跑」按钮
- 点击后调用已有 /api/regime/recompute 补算缺口区间, 完成后自动重跑本次回测
- 补算请求超时放宽到 5 分钟(需扫全市场 enriched 数据)
- 预热区间不足的报错变体不显示按钮(补算无法解决, 文案自说明)
2026-09-08 22:16:21 +08:00
shy3130
0a6729fcd2
feat(screener): 叠加策略创建与配置体验优化
...
- 新建默认交集合并模式, 选项顺序对调; 可选策略列表加高
- 策略名称默认子策略名用 + 连接, 手动编辑后停止跟随
- 子策略权重改为滑块 (0-100 百分比), 保存时自动按比例归一, 移除手动归一按钮
- 子策略名可点击弹出其配置编辑 (创建对话框与配置对话框均支持)
- 策略池: 叠加策略并入自定义分组并标记「叠加」徽标, 修复误显示为内置
- 创建策略/修改策略池后自动扫描新增日线策略, 免手动刷新
2026-09-08 21:45:38 +08:00
shy3130
27a019721d
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
2db113f8da
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
4e388c9561
style(screener): 策略设置对话框加宽 980px → 1200px
2026-09-07 15:26:00 +08:00
shy3130
2ff069ba2b
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
8620eec051
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
982d7bef88
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
defba2124e
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
d2bc53c9db
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
d2f97fbdbe
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
348b55c418
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
ddfe57f063
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
ddcfb1dfd5
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
70c102f3d0
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
057d52733a
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
831fe4bfce
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
cf14a65c23
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