Commit Graph
614 Commits
Author SHA1 Message Date
shy3130 a8a573a834 feat(watchlist): 分组卡片/统计条完善 + 分组排序 + 监控自选导入 + 前端插槽
分组卡片视图 (WatchlistGroupCards):
- 新增整页卡片总览: 组内按涨跌幅降序, 默认前 N 条可展开
- 头部重排: 名称+指标数值居左, 总数+N涨/N跌居右 (红涨绿跌着色)
- 成员行: 创/科/北板块标识移至名称后; 序号列可开关
- 卡片设置 (GroupStatsSettings): 指标/排序/前N条/头部颜色/序号, 与统计条共享持久化

分组统计条 (WatchlistGroupStatsBar):
- 中轴分叉条形图概览, 指标与排序可配置
- 行尾 N涨/N跌 红绿着色

分组管理:
- 后端分组重排端点 + service + 测试 (9 passed)
- 管理弹窗上移/下移 + 拖拽排序, 顺序贯通标签栏/统计条/卡片/侧栏

自选交互:
- 修复 WatchlistAddMenu 内部滚动误关闭 (capture 目标包含判断)
- 监控规则编辑器: 指定标的支持从自选/自选分组批量导入 (去重合并)

前端扩展插槽:
- 新增 stock-preview.footer / watchlist.toolbar 插槽及 context 契约, 更新二开文档
2026-08-19 22:14:10 +08:00
shy3130 a49c67c5b5 docs(readme): 更新交流群二维码 (TSP个人量化交流) 2026-08-19 16:03:05 +08:00
shy3130 610d52931b docs(readme): 更新交流群二维码 (TSP个人量化交流) 2026-08-19 16:02:55 +08:00
shy3130 687a18e769 refactor(watchlist): 分组涨跌幅最优性复审 — 可见性门控与格式化去重
复审发现两处可优化:
1. 侧栏分组涨跌幅查询原为 groupsInNav 开启即无条件拉取 — 改为
   「侧栏展开 ∧ 自选二级菜单展开」才请求, 收起状态下不再为隐藏 UI
   发 watchlist/enriched 请求(展开即时拉取, 与自选页共享缓存去重)
2. formatGroupPct 与全站 fmtPct(lib/format)逻辑完全重复 — 删除并
   复用 fmtPct, 格式随全局统一; 顺带消除 Layout 中 navCollapsed
   状态声明的位置耦合(上移至查询前)

验证: tsc 通过; 浏览器实测 — 子菜单收起 0 次 enriched 请求, 展开
后 1 次请求即显示; 分组 tab/侧栏数值与优化前逐位一致(全部+0.59%
半导体-1.55% 等), 悬停明细正常。
2026-08-18 21:33:26 +08:00
shy3130 5b4b1d6e24 feat(watchlist): 自选分组等权平均涨跌幅 — 分组 tab 与侧栏子菜单
口径: 组内成员取「实时优先(rt_pct)、收盘兜底(change_pct)」的涨跌幅
(与自选表格同源, 小数单位), 等权平均为分组涨跌幅 — 自选是个人组合
视角, 等权透明且无需市值数据。涨跌家数在悬停明细中给出。

- 新增 watchlistGroupStats: computeGroupPcts 纯函数 + 格式化/配色
  (text-bull 红涨 / text-bear 绿跌, 沿用 A 股惯例)
- 自选页分组 tab: 数量后追加彩色涨跌幅徽标(全部/未分组/自定义组)
- 侧边栏分组子菜单(开启 watchlist_groups_in_nav 时): 复用与自选页
  相同的 watchlist/enriched 查询缓存(盘中随 SSE 刷新), 组名右侧显示

验证: tsc 通过; 浏览器实测分组 tab 与侧栏数值逐组与 API 手算一致
(半导体 -1.55% / 商业航天 -0.79% / 反包备选 +4.34% / 全部 +0.59%),
悬停明细「等权平均 +0.59% · 上涨11 下跌11 平0 (共22只)」正常。
2026-08-18 15:51:11 +08:00
shy3130 0ee3aa8f1f fix(ai): 分析类调用放开 max_tokens 限制 — 修复推理模型正文 0 字失败
根因(实测钉死): deepseek-v4-pro 等推理模型把思考 token 计入
max_tokens 预算。个股分析真实调用(62KB prompt, max_tokens=4500):
usage completion=4500 全是 reasoning, finish=length, 正文 0 字,
流"正常"结束 → 前端兜底报「分析未返回内容」→ 表现为"经常失败"
(推理长度随机, 逼近 4500 即失败)。与 180s 超时无关(实际 65s 结束)。

改动:
- ai_provider: generate/stream 的 max_tokens 支持 None=不传该参数,
  输出上限交给服务端默认; _openai_kwargs None 时省略; codex 提示词
  None 时跳过长度约束行
- 四个分析器(个股/复盘/财务/概念轮动)改传 max_tokens=None;
  新增空正文守卫: 流结束但 0 个 delta → 明确报错+日志(原先静默,
  backend.log 无痕迹无法排查)。策略标题生成(max_tokens=8)等小任务
  保持原限制

对照实测(真实 62KB prompt): 不传 → finish=stop, 推理 3311 token
+正文 2407 字, 59s; max_tokens=16000 → 同样成功但推理撒欢 6239
token/93s — 不限制即最优。

验证: 新增 kwargs/codex 单测, ai_provider 21 通过, 相关 174 通过;
线上接口复测: 修复前 0 delta 直接 done, 修复后 1682 delta/2467 字
正常流式; ruff 相对 HEAD 无新增。
2026-08-17 17:47:46 +08:00
shy3130 6f0786abac feat(regime): 情绪周期时间轴交互完善 — 堆叠柱/色带标签/点击回看当日
- 首板/2板+ 改堆叠柱: 两段之和即当日涨停总数, 总高看宽度、顶段看连板
  厚度(实测 07-01: 126+25=151); 封板率新增序列(右轴绿虚线, 默认关,
  图例可开), 图例五项可自由显隐
- 阶段色带 ≥6 天的宽带标注阶段名, 一眼读出每段是什么
- 点击图表任意日期 → 当日快照条: 阶段/段内第N天/高度/涨停构成/晋级/
  封板/当日主线 top3 + 「回到今日」复位; 选中日蓝色虚线定位(zrender
  级监听+网格命中判定, 图例/dataZoom 点击不误触)
- tooltip 增加阶段第N天/梯队完整度/涨停构成; useEChart 支持 onReady
  暴露实例供事件绑定

验证: tsc 通过; 浏览器实测 — 点击命中 07-01 快照数值与后端完全一致,
回到今日复位正常, 堆叠柱/色带标签/蓝虚线均渲染正常。
2026-08-17 17:16:02 +08:00
shy3130 65f46a1e7f feat(mainline): 主线与情绪周期统计默认剔除风险警示(ST)股
问题: ST板块 241 天中 209 天上主线榜、108 天第一。原因: ① ST 是跨行业
状态桶(416只)非投资题材, 真实主线被概念拆分而 ST 统一聚桶; ② 主板 ST
2026-07-06 前涨跌幅 5%(价格规则已内置切换日), 封板成本减半, 弱市刷板
(7/1 全市场 218 家涨停中 67 家 ST); ③ 概念成分/ST 标记按当前维表快照
回写历史存在归属污染。

改动:
- market_mainline: load_risk_warning_symbols(维表名称含 ST, 与涨跌停
  判定共用 price_limits 权威实现, 600s 缓存); compute_mainline_range
  聚合前剔除, exclude_st 参数可覆盖
- regime_builder: run_regime_batch 汇聚点统一剔除(情绪驱动与主线同
  口径); 宽度类指标同 df 过滤, 占比几乎不受影响
- preferences: sentiment_exclude_st 默认 True; 经 mainline-filter
  API 可读写; 前端过滤面板加开关, 切换时自动全量重算
- 测试: 符号集加载/缓存、主线剔除(计数/龙头/最小涨停门槛交互)、
  regime 剔除 A/B、偏好往返; 说明书 FAQ 24.11

验证: 后端 918 测试通过(新增 5 个); tsc 通过; 全量重算后主线 0 行
ST 上榜(此前 209 天), rank1 变为海工装备/卫星导航/液冷服务器等真实
主题; 7/1 涨停数 218→151 与 ST 占比精确吻合; A/B 对照: 阶段标签
34/242 天变化(rally/ignite→repair 为主, 方向符合预期 — 剔除 ST 灌水
后正面阶段更难触发), repair 主导(78%)为口径切换前既有特征。
2026-08-17 16:49:28 +08:00
shy3130 7c30f5bcac feat(regime): 情绪周期易用性完善 — 阶段指南/历史分位/阶段规律/切换提醒
- 当前阶段卡: 阶段含义 hover 提示 + 应对建议常显 (六阶段操作指引)
- 5 张指标卡: 所选时间窗口内的历史分位徽标 p{N} (≥20 样本才显示)
- 阶段规律卡: 当前阶段历史段数/平均/最长天数 + 下阶段转移分布,
  持续天数超历史平均时给警示徽标
- 时间轴: 今日竖线 markLine + ▲彩色阶段切换点 markPoint
- 后端: regime_builder.latest_phase_transition 检测末两日阶段切换,
  daily_pipeline 计算后经 push_alerts 推送通知 (切入退潮/冰点为 warn,
  其余 info); 软失败不阻断管道

验证: tsc 通过; pytest regime/phase/market 67 通过;
浏览器实测 (截图 + DOM 双重核实): 应对建议/分位徽标 p27~p100/
阶段规律 31段平均50天/今日线与切换点均正常渲染;
ruff 相对 HEAD 无新增问题。
2026-08-17 15:23:32 +08:00
shy3130 867698a696 fix(monitor): 通知进入/移出配色对齐 A 股红涨绿跌惯例
原配色: 进入=绿(emerald)/移出=黄(warning)+列表里移出=红, 语义反直觉。
调整为 进入=红(text-danger)/移出=绿(text-bear), 与买入/卖出、涨跌幅
配色语义一致 (红=正向, 绿=负向)。

- strategyMonitorEvents.ts META: 事件动作短语配色中心定义, 弹窗/监控页/
  看板/语音播报四处共用, 一处修改全局生效
- AlertToast.tsx SOURCE_BADGE: 弹窗顶部"进入/移出"角标同步换色
- Monitor.tsx renderMessage: 正则补"进入"分支 (原只匹配 新入选|移出,
  实际通知文案是"策略「X」进入选股结果…", 进入消息从未着色) + 换色

验证: tsc 通过; 实测监控中心页面 getComputedStyle — 进入选股结果
rgb(242,76,64)/红, 移出选股结果 rgb(38,192,120)/绿。
2026-08-17 13:19:18 +08:00
shy3130 41e99b6974 feat(regime): 阶段×主线表格限高滚动 + 吸顶表头
段数多时(2y 范围 50+ 段)表格把页面拉得很长。改为 max-h-420px 内滚动,
表头 sticky 吸顶保证滚动时列名可见。

实现注意:
- sticky 必须加在 th 而非 tr (后者在 Chromium 不生效)
- 表格改 border-separate border-spacing-0 — Chromium 在 preflight 默认的
  border-collapse:collapse 下表格元素 sticky 完全失效 (computed 为 sticky
  但不粘, crbug.com/702927); separate 模式下 tr 边框不绘制, 行分隔线
  相应从 tr 挪到 td, 视觉不变

验证: tsc 通过; 实测容器 clientH=420/scrollH=1860 (页面少滚 ~1440px),
容器内滚动 1441px 后 th 与容器顶 delta=0 (吸顶生效), 截图确认列名行
固定、数据行正常。截图 gui-test-screenshots/regime-segments-*.png
2026-08-17 13:03:19 +08:00
shy3130 72c56963dd feat(regime): 市场环境/情绪周期 tab 切换 — 减少单页滚动高度
页面原为长滚动: 情绪周期组(阶段概览/时间轴/阶段×主线/主线排行)与
市场环境组(最新日概览/状态时间轴/趋势分布/日历热力图)全部纵向堆叠。

- 头部下方新增「市场环境 / 情绪周期」分段切换 (样式对齐时间范围按钮组),
  副标题随视图切换; 默认市场环境 (基础数据始终有, 情绪周期需重算回填)
- 两组区块分别包 hidden 容器切换显隐 — 保持挂载不销毁 ECharts 实例,
  切回无需重建
- useEChart 在 setOption 后追加 resize(): 容器从 display:none 恢复可见时
  画布尺寸从 0 重算; 三个图表 deps 增加 view 触发

验证: tsc 通过; 实测默认加载/切情绪周期/切回三态 — tab 激活正确、
两组内容互斥显隐、图表 canvas 尺寸随可见性正确变化 (1254x280 /
822x320 / 391x320, 隐藏态 0), 截图存 gui-test-screenshots/regime-tab-*.png
2026-08-17 12:53:53 +08:00
shy3130 5d6669d4f3 fix(regime): 情绪周期时间轴冷加载空白 — useEChart 惰性 init
useEChart 的 init effect 依赖为 [] 仅组件挂载时执行一次, 而情绪周期图的
容器 div 是条件渲染 (hasPhaseData && rows.length > 0)。冷加载/硬刷新时
history 查询异步未返回 → 首帧 rows 为空 → div 不在 DOM → init 扑空且
永不再执行; 数据到达后卡片出现但 ECharts 实例从未创建, 280px 画布永久
空白 (趋势图/分布图容器为无条件渲染故不受影响)。5 分钟缓存内的二次
导航首帧即有数据, 所以表现为"时好时坏"。

修复: init 从挂载 effect 挪入 setOption effect 做惰性创建 — option 变化
时若 div 已挂载且实例不存在则补建, 再 setOption。无条件容器行为不变。

验证: tsc 通过; 新标签页冷加载 /regime 实测 — canvas 数 3 (修复前冷加载
该图为 0), 情绪周期画布 1254x280, 截图确认红线/琥珀柱/蓝虚线/图例/
双轴刻度/缩放滑块/阶段色带全部渲染 (gui-test-screenshots/regime-phase-
chart-after-fix.png)。
2026-08-17 12:43:33 +08:00
shy3130 8929cb310e fix(depth): 五档盘口轮询依赖实时行情开关
depth 盘中轮询原只受「连板梯队监控」开关 + DEPTH5_BATCH 能力门控,
与实时行情开关无关。实时行情关闭时 enriched 内存缓存停留在上一
交易日, 轮询线程整个盘中反复拉取陈旧的涨跌停名单 (如周一开盘仍在
拉上周五的 49 只), 浪费 API 额度且数据无意义。

- start_polling 增加 realtime_quotes_enabled 门控: 三重 AND
  (监控开关 ∧ 实时行情 ∧ 能力), boot 启动/监控开关切换路径自动生效
- update_realtime_quotes 保存偏好后同步启停 depth 轮询: 开实时行情
  → start_polling (仍受监控开关/能力门控), 关 → stop_polling 立即停

盘后 15:02 定版 job 与启动补跑 (boot_check/finalize 单次拉取) 不受
影响, 历史 sealed 数据链路保持完整。

验证: 5 组偏好组合单测门控行为; 13 个 depth 窗口测试通过;
实测重启后 (监控开+实时关) 不再出现「盘中轮询已启动」。
2026-08-17 12:18:17 +08:00
shy3130 697c27bb02 feat(v0.2): 市场阶段与主线识别 + 因子挖掘全链路 + 数据层完善
- 市场环境: 新增情绪周期6阶段(冰点/启动/主升/高潮/退潮/修复, 连板梯队驱动,
  EMA平滑+2日确认+弱档否决, 平均段长9.7天)与概念/行业主线排名(涨停梯队聚合,
  可配置宽基/风格标签过滤); 市场环境页重构, regime 透明加列, 与5档state并存
- 挖掘: 因子与策略挖掘全链路(API/worker/进程锁/候选库/前端工作台/文档),
  周度调度默认关闭且永不自动发布
- 回测: 财务快照因子(点时口径), 批量回测预计算共享下期收益,
  信号路径矩阵列依赖展开修复(consecutive_limit_ups 缺列报错)
- 数据/性能: enriched 生成与预热治理, 重任务限流, 行情/K线缓存复用, 时区修复
- 测试: 后端全量 914 通过; GUI 黑盒验证截图存证 gui-test-screenshots/
2026-08-16 23:39:07 +08:00
shy3130 eb869c7ad2 fix(logging): 开发模式追加文件日志 backend.log
dev 模式 (uvicorn) logging.basicConfig 只有 StreamHandler, 同步/管道等
运行时日志 (daily_pipeline 的 logger.info 等) 仅出现在 dev 终端, 关掉或滚屏
后即丢失, 排查「同步后日志没落」时无处可查。

追加 RotatingFileHandler 落盘到 data/backend.log, 与桌面版
(desktop.py:_setup_logging → desktop.log) 行为对齐。frozen (桌面版) 已由
desktop.py 负责, 此处跳过避免重复落盘。RotatingFileHandler (10MB×3) 防止
长期运行/频繁 reload 导致文件无限增长。

注: 同步进度日志 (job_store JSON, 经 /api/pipeline/jobs 返回) 一直正常落盘,
本次只补应用级日志的文件落盘。
2026-08-14 13:40:57 +08:00
shy3130 a0cb899163 perf(backtest): 因子批量回测预计算共享下期收益并向量化统计
P1 — run_batch 进入因子循环前对 close 有效序列计算一次 _next_return
(仅依赖 symbol/date/close/rebalance, 与因子无关), 通过 left join 附着到
共享面板; _evaluate_panel 检测到预计算列时直接复用, 跳过逐因子 shift/
调仓日 JOIN。因子空值集中在预热期前缀, 过滤后无内部空洞, 故与逐因子
在过滤后面板上重算的结果完全等价 (daily/weekly/monthly 均数值一致)。

P2 — 将 _calc_group_nav / _calc_group_stats / _calc_long_short 三段
逐行 Python 循环改为向量化:
- 分组净值: Polars cum_prod 替代 dict 累乘
- 分组统计: numpy maximum.accumulate 计算回撤, 向量化周期收益序列
- 多空组合: cumprod 合成净值, 向量化峰值/回撤
峰值初值沿用原逻辑 max(1.0, 历史最高), 400 组随机序列 (含 null/负收益)
下与旧实现逐值等价。

测试: tests/backtest 全量 184 passed。
2026-08-14 13:24:24 +08:00
shy3130 2b792dee44 chore(dev): uv run --no-sync 跳过依赖解析
从 --frozen 改为 --no-sync, 直接用已安装的 .venv, 不再校验 lockfile。
避免镜像源 403/网络抖动导致后端起不来。与 main 保持一致。
2026-08-14 13:10:01 +08:00
shy3130 81daf018c5 perf(indicators,kline): 热路径信号缓存 + 日K快路径跳过全量指标
三处性能优化 (后端内部, 不改 API 契约):

1. 增量热路径自定义信号缓存 (pipeline.py)
   compute_enriched_today 每秒级执行, 原每轮 glob + 读所有 JSON + 重编译
   表达式。新增 _custom_signal_exprs_today 模块级缓存 (allow_shift=False),
   与全量版分开缓存, invalidate_custom_signals 统一失效。

2. ETF/指数迷你蜡烛图跳过全量指标 (repository.py)
   get_index_daily/get_etf_daily 增加快路径: 请求列全是 parquet 存储列时
   scan + 列下推直接返回, 跳过 150 天 warmup + 全套指标计算。缺列回退完整路径。

3. 单股日K跳过全量指标 (repository.py)
   get_daily 同样加快路径并保留缓存覆盖最新日。采用最保守的列下推方案,
   不引入 needed 裁剪, 避免依赖闭包漏算金融数据的风险。

验证: pytest 全套 582 passed; Ruff 无新增告警; 快路径功能验证通过。
2026-08-14 13:08:57 +08:00
shy3130 e5b105dd45 chore(dev): uv run --no-sync 跳过依赖解析
dev.sh 后端启动从 uv run 改为 uv run --no-sync, 直接用已安装的 .venv,
不再每次访问镜像源校验 lockfile。避免镜像源 403/网络抖动导致后端起不来。
dev.ps1 本就用 .venv 直起, 不受影响。
2026-08-14 13:04:40 +08:00
shy3130 b3d1435501 perf(indicators,kline): 热路径信号缓存 + 日K快路径跳过全量指标
三处性能优化 (后端内部, 不改 API 契约):

1. 增量热路径自定义信号缓存 (pipeline.py)
   compute_enriched_today 每秒级执行, 原每轮 glob + 读所有 JSON + 重编译
   表达式。新增 _custom_signal_exprs_today 模块级缓存 (allow_shift=False),
   与全量版分开缓存, invalidate_custom_signals 统一失效。

2. ETF/指数迷你蜡烛图跳过全量指标 (repository.py)
   get_index_daily/get_etf_daily 增加快路径: 请求列全是 parquet 存储列时
   scan + 列下推直接返回, 跳过 150 天 warmup + 全套指标计算。缺列回退完整路径。

3. 单股日K跳过全量指标 (repository.py)
   get_daily 同样加快路径并保留缓存覆盖最新日。采用最保守的列下推方案,
   不引入 needed 裁剪, 避免依赖闭包漏算金融数据的风险。

验证: pytest 全套 582 passed; Ruff 无新增告警; 快路径功能验证通过。
2026-08-14 13:04:40 +08:00
shy3130 8fe5dac7bd feat(v0.2): 完善量化研究与二次开发能力 2026-08-13 20:16:02 +08:00
shy3130 57eb641275 fix(backtest): 修复市场环境过滤未生效 2026-08-11 12:43:46 +08:00
shy3130 8c00f7a3fd feat(v0.2): 双击价格创建点位监控 + 分钟K补齐修复 + 超时设置独立
点位监控(双击图表):
- 日K/单日分时/多日分时价格主图支持双击, 自动预填目标价并按最新价判断上穿/下穿
- 成交量区与指标子图不触发; 自动生成通知文案, 用户手改后不再覆盖
- 已启用点位监控以横虚线显示 (上穿红/下穿绿), 并纳入三图 Y 轴范围
- 复用现有 PriceAlertDialog, 未改变后端 close>=/<= 规则语义与冷却机制

分钟K数据:
- 个股补齐强制回溯请求天数 (force_full_days), 修复切换日期范围只显示3天
- 单股并发补齐复用仓库写锁, 修复 Windows Parquet 临时文件替换失败
- DuckDB 读路径改用短生命周期 cursor, 释放对 Parquet 文件的占用

设置页:
- 数据任务超时从 DataSources 抽出为独立"超时设置"页签
- 设置侧栏垂直居中

验证: pytest 38 passed, pnpm build ok, git diff --check ok, 浏览器端到端 GUI 验证通过
2026-08-10 23:32:44 +08:00
shy3130 aaa888347c Merge branch 'pr-169' into v0.2 2026-08-10 17:53:31 +08:00
shy3130 c90b83c3e4 feat: v0.2 UI 重构 + 自选分组侧边栏 + 扩展数据时间窗口 + 个股对话框优化
- 侧边栏美化:品牌改名/菜单 active 指示条/收起展开/底部精简
- 数据源+AI 状态卡:名称替换固定文字/档位 tag 条件显示
- 设置页重构:account 合入数据源 tab/数据源置顶/收起展开菜单
- 自选分组侧边栏:二级子菜单/分组跳转同步/清空分组
- 个股对话框:tab 移顶栏/分时关闭/放大全屏/操作按钮归位
- 扩展数据:定时拉取时间窗口(time_window_start/end)
- 版本号: 0.1.88 → 0.2.1
2026-08-10 17:53:14 +08:00
shy3130 0c5adb0046 Merge remote-tracking branch 'origin/main' into v0.2 2026-08-10 12:37:06 +08:00
shy3130 2a2d3b764e feat: add watchlist groups and multi-day intraday view 2026-08-10 11:39:08 +08:00
Arepeater e1c6aa2a14 fix(config): 收敛 Vite 配置并兼容 AI 可选参数
- 移除重复的 Vite JS 配置并阻止 TypeScript 构建重新生成
- 精确识别 temperature 与 reasoning_effort 的 400 错误并有界降级
- 补充 Docker 只读挂载 .env 的安全边界说明
2026-08-08 15:22:05 +08:00
shy3130 ecfddb451e feat(monitor): 新增板块异动监控 2026-08-06 19:28:39 +08:00
wshy 99bdec875d Merge pull request #170 from shy3130/fix/regime-calendar-weekday-align
fix(regime): 修复日历热力图交易日错位到周末列
2026-08-06 19:13:03 +08:00
shy3130 8b83f9e1bd fix(regime): 修复日历热力图交易日错位到周末列
calendarMonths 只在月初按 dow 算了前导空位, 之后把真实交易日逐个 push,
不按日期补齐缺失的天。当某月数据不是从 1 号连续到月末(最早月份只有
下半月数据或中间缺几天)时, 后续交易日格子整体左移, 被挤到周末列,
看起来像周六周日也有数据。

改为遍历该月每一个自然日: 交易日且有数据填 RegimeRow, 其余日子填 null,
每个格子都对齐到正确的周几列。月内数据不连续不再错位。

验证: pnpm build 通过。
2026-08-06 19:12:04 +08:00
Arepeater fec53bb46f fix(ai): 修复提供商切换与 Codex 自定义端点
- 分离 OpenAI-compatible 与 Codex CLI 的模型和推理配置
- 复用本机 Codex provider、认证与自定义端点,并适配 Docker 回环地址
- 隔离 OpenAI 专属 reasoning_effort,修复自定义预设切换与表单保留
2026-08-05 17:57:34 +08:00
Arepeater 7dad95c4f1 feat(settings): 支持配置数据任务超时
- 在数据源设置页配置普通任务与分钟 K 长任务超时
- 支持秒、分钟、小时输入,持久化时统一换算为秒
- 保留 1200/1800 秒默认值,配置仅影响新创建的任务
2026-08-05 17:57:05 +08:00
Arepeater b43e2fe44a fix(config): 修复 .env 加载与密码初始化
- 统一开发脚本、Vite 代理与 Docker Compose 的 HOST/PORT 配置
- 首次启动按字面值读取 AUTH_PASSWORD,避免 ${VAR} 被环境变量插值
- 已有 auth.json 时继续以 Web 端密码为准,不受 .env 覆盖
2026-08-05 17:56:27 +08:00
wshy c278dd3b02 Merge pull request #164 from shy3130/fix/regime-trend-polish
fix(regime): 趋势图优化(线宽/阈值线/左右轴/涨停默认隐藏)
2026-08-02 23:45:05 +08:00
shy3130 bc2b1ae397 fix(regime): 趋势图优化 — 线宽/阈值线补全/左右轴交换/涨停默认隐藏
- 综合分主线线宽 2.5 → 1.5(更细致)
- 阈值线补全 5 档状态边界: 加偏强55, 偏弱30标签改为「偏弱/弱势30」
- 阈值线醒目化: 灰线→状态色虚线, 标签白字+状态色背景块, 移到图表右侧外侧
- y轴交换: 左轴→涨停数, 右轴→综合分(0-100); series yAxisIndex 同步调整
- 涨停数默认不勾选(selected: false), 页面进入只显示综合分主线
2026-08-02 23:44:13 +08:00
wshy 8735a36a8c Merge pull request #163 from shy3130/feat/regime-page-enhance
feat(regime): 市场环境页完善(顶部改造+日历热力图+趋势图修复)
2026-08-02 23:26:11 +08:00
shy3130 92e5db28fc fix(regime): 趋势图阈值线醒目化 + 标签移到图表右侧外侧
- 强势/震荡/偏弱三条横虚线: 灰色淡线 → 状态色(红/灰/蓝)加粗虚线
- 标签: 灰色小字 → 白字+状态色背景块(加粗10px), 显示分值(强势70/震荡45/偏弱30)
- 标签位置: 图表内部 → 右侧外侧(position: end), 不遮挡曲线
- grid 右侧留白 48→64px 给标签腾空间
2026-08-02 23:25:47 +08:00
shy3130 6646d0a664 feat(regime): 市场环境页完善 — 顶部改造+日历热力图+趋势图修复
顶部 4 卡改造(去掉与看板重复的涨停/涨跌/成交额)
- 状态卡(保留) + 当前势头(连续天数+5日斜率+上次弱势距今)
- 四维拆解(赚钱/投机/抗跌/趋势 迷你水平条, 对应色填充)
- 状态转换(转换次数+节奏标签 稳定/中等/频繁)

日历热力图(纯 CSS 月份网格, 弃用 echarts calendar)
- 单行模式(默认): 月份网格横向排列+滚动条, 默认滚到最新, 月均分 tag
- 展开模式: flex-wrap 自动换行的完整网格
- 每日格子按状态色填充, 月均分用状态色 tag 凸显(不再灰色文字)

修复趋势图切换菜单后不显示(useEChart 容器条件渲染的 ref 时序问题)
- 日历热力图容器改为始终渲染(与趋势图/饼图一致)

其他
- 页面宽度 max-w-6xl → max-w-[1440px](大屏铺满, 与行业分析一致)
- 去掉最强/最弱 Top5 模块(用户反馈没用)
- 新增 scoreToColor 辅助函数(综合分→状态色)

验证: tsc + pnpm build 通过
2026-08-02 23:21:15 +08:00
wshy 201d1b3c33 Merge pull request #162 from shy3130/feat/industry-rotation-and-ext-number-format
feat: 行业轮动分析 + 扩展数据列数字格式化
2026-08-02 19:22:30 +08:00
shy3130 c9f01ba288 feat: 行业轮动分析(参数化复用概念版) + 扩展数据列数字格式化
行业轮动分析(完全对齐概念版)
- 概念轮动逻辑参数化支持 industry 维度, 一套代码服务两个页面(复用 _dimension_field)
- 后端 build_rps_rotation/analyze_rotation_stream 加 kind 参数; 缓存按 kind+level 隔离
- 行业层级: 1/2/3 级可切换, 默认 2 级(与 _dimension_rank 口径一致)
  · 原始 257 个 3 级行业 → level=2 合并成 90 个
- AI 分析 prompt 动态化(概念/行业措辞), _SYSTEM_PROMPT 改为 _build_system_prompt(kind)
- 前端 RpsRotationDialog 加 kind prop; industry 显示层级选择器(1/2/3级默认2)
- IndustryAnalysis 加「涨幅RPS轮动分析」按钮 + dialog(kind=industry)
- ConceptAnalysis 不动(默认 kind=concept 向后兼容)

扩展数据列数字格式化(自选/策略列表)
- 列配置新增 3 项(仅数字类型字段): 千分位逗号 / 单位换算(万/亿/自动) / 小数位
- 新增 formatExtNumber 共享格式化函数(千分位+换算+小数位, 去尾零)
- Watchlist + ScreenerTable 的 number 渲染接 formatExtNumber
- ext source 加 fieldType; 旧列无 fieldType 时默认显示数字配置(放宽判断)
- ExtColumnDisplayConfig 加 thousandSeparator/unitConvert/unitDecimals 字段

验证
- 后端 583 passed; 行业映射实测 257→90(level=2)
- 数字格式化实测: 千分位 1,234,567 / 万换算 123.46万 / 自动 等均正确
- tsc + pnpm build 通过
2026-08-02 19:18:07 +08:00
wshy ed38304577 Merge pull request #161 from shy3130/feat/strategy-settings-apply-and-inputs
feat(backtest): 高级策略设置新增「应用到策略」+ 修复浮点显示与输入体验
2026-08-02 18:26:03 +08:00
shy3130 1f865ced79 feat(backtest): 高级策略设置新增「应用到策略」+ 修复浮点显示与输入体验
新增「应用到策略」按钮
- 底部按钮区(恢复默认/应用到策略/完成)新增按钮, 调用 api.strategySaveConfig
  把当前弹窗的 overrides+params 持久化为策略定义(落盘 strategy_overrides/{id}.json)
- 所有页面加载该策略时都用这些参数(策略页加载的就是这里应用过去的)
- 成功后 toast 提示 + 刷新 detail + 关闭弹窗
- 仅用户自有策略(custom/ai/composite)显示, 内置策略不显示

修复浮点显示(止损 7.0000000000000001% → 7%)
- 根因: 5 个百分比派生变量用 Math.abs(x)*100, 浮点运算产生长尾
- 新增 round4() 辅助截断, 应用到 stopLossPct/takeProfitPct/trailingStopPct/
  trailingTakeProfitActivatePct/trailingTakeProfitDrawdownPct

修复「删除即跳最小值」输入体验
- 根因: 受控 input 的 onChange 立即 clamp(n,min,max), 用户键入低于 min 的
  中间值时立刻被钳到 min, 无法平滑输入/删除重输
- 新增 NumberField 组件: 输入时只更新文本草稿(不钳制), 失焦时才校正到 [min,max]
- 替换抽屉内所有数字输入框: risk tab 6个 + scoring tab 2个 + params tab 动态参数 + filter tab 6个
- 每个 onChange 移除立即 clamp, 业务逻辑(止损负号/回撤联动/整数取整)保留

验证: tsc + pnpm build 通过
2026-08-02 18:22:50 +08:00
wshy f80c5e3ee3 Merge pull request #160 from shy3130/feat/regime-trend-explainable
feat(regime): 趋势图可解释化(综合分主线+子维度曲线+状态背景色带)
2026-08-02 17:29:54 +08:00
shy3130 6a750de722 feat(regime): 趋势图可解释化 — 综合分主线 + 子维度曲线 + 状态背景色带
问题: 原趋势图标题「环境综合分·涨停数趋势」, 但综合分是4维加权结果,
图里只画涨停数一个副指标, 用户无法理解综合分为何涨跌(黑盒)。

后端(regime_builder.py)
- 抽出 _compute_subscores(metrics): 计算4子维度分(赚钱/投机/抗跌/趋势)+综合分
- classify_state 复用 _compute_subscores(逻辑不重复)
- _aggregate_daily 持久化4个子分列: profit_score/speculation_score/
  resilience_score/trend_score(0-100), 供趋势图展示+未来策略按子维度过滤

前端
- RegimeRow 类型加8个可选字段(4子分+4原始指标, 兼容旧数据)
- 趋势图重构:
  · 综合分主线(加粗2.5px置顶) + 半透明面积
  · 4子维度点状曲线(赚钱橙/投机紫/抗跌绿/趋势蓝), 默认隐藏, 点图例展开
  · 状态背景色带(markArea, 连续同状态日期段用状态色低透明度着色)
  · 涨停数柱状降为半透明背景(opacity 0.35)
  · 阈值横虚线更新为新模型 70/45/30
  · 默认 legend.selected 只显示综合分+涨停数(简洁), 子维度按需展开
- 标题改为「环境综合分趋势」+ hint 说明各曲线含义

验证
- 后端 583 passed; 子分加权一致性100%(综合分=Σ子分×权重)
- 实测解释性: weak日(7-30综合23) 赚钱9+抗跌0 清楚显示普跌+大跌股多
- tsc + pnpm build 通过
2026-08-02 17:29:09 +08:00
wshy fa5583c2cb Merge pull request #159 from shy3130/refactor/regime-scoring-model
refactor(regime): 评分模型重新设计对齐看板情绪分
2026-08-02 17:19:36 +08:00
shy3130 3ae7ead21a refactor(regime): 重新设计评分模型对齐看板情绪分 + 修复 schema 迁移 + 饼图标签
评分模型重新设计(regime_builder.py)
- 归一化: _LIN 多点插值 → _score(low,high)(与看板 market_overview_builder 同款, 简洁不易设错)
- 维度: 赚钱效应/指数趋势/板块结构/活跃度 → 赚钱/投机/抗跌/趋势(对齐看板轻量维度)
- 新增「抗跌」维度(原模型完全缺失): 用 strong_down_pct 识别大跌日, 这是 weak 能出现的关键
  原 board_structure(涨停-跌停对比, A股涨停常年>跌停致虚高)移除; activity(成交额曾恒满分)移除
- 权重调整 + _score 参考点用 A股真实分位数校准(非拍脑袋)
- 阈值与看板统一: 75/60/40/25 → 70/55/45/30

_aggregate_daily 增强
- 新增聚合列: avg_pct/median_pct/strong_up_pct/strong_down_pct(供新评分模型 + 未来策略扩展)
- 全部 polars group_by 向量化(不回退逐日 filter)

性能
- _scan_enriched_fallback needed 去掉 vol_ratio_5d(实测 compute_limit_signals 函数体未实际使用)
  → 全量补算数据量 657MB→617MB(省40MB), 配合分批内存峰值维持 ~1.9GB

修复 upsert schema 迁移(导致 recompute 500 的真实 bug)
- _aggregate_daily 新增4列后, 旧 regime parquet(15列)与新产出(19列)concat 报 schema lengths differ
- upsert_regime_history concat 前做 schema 对齐: 以新列名+顺序为权威给旧数据补缺失列(null)
  → 旧 parquet 首次重写时自动迁移到新 schema

前端饼图标签重叠修复(Regime.tsx)
- 状态分布饼图标签外置 + 虚线引导线(labelLine), 解决5个状态标签互相重叠
- labelLayout 防重叠, formatter 从两行改一行

验证
- 后端 583 passed(含新增抗跌维度专项测试)
- 真实数据全量分布: weak 从 0% → 有合理占比(原模型永不出现 weak)
- 内存峰值 ~1.9GB(分批+needed白名单保障)
- tsc + pnpm build 通过
2026-08-02 17:17:19 +08:00
wshy 1d5d18c8be Merge pull request #158 from shy3130/feat/regime-enhance
feat(regime): 市场环境页全面增强(内存可控/开关/画像/美化/分批可配)
2026-08-02 16:26:13 +08:00
shy3130 93558cf3b3 feat(regime): 市场环境页全面增强 — 内存可控/开关/画像/美化/分批可配
后端
- 修复 /recompute 全量分支误调增量函数致 computed 恒 0: 改为 earliest~today
  走 run_regime_batch + upsert 强制覆盖
- 修复 /history 日期范围模式被 limit 默认 120 截断: limit 仅在未传 start/end 时生效
- _scan_enriched_fallback:
  · 修复 compute_limit_signals 漏传 instruments 参数致慢路径必抛异常
  · needed 白名单: 只算 regime 用到的列, 全量峰值 6.8GB→3.2GB
  · 分批 + warmup: 范围超 batch_days 时切片, 每批带 warmup 前缀算后 concat,
    全量峰值再降至 ~1.9GB; batch/warmup 参数从用户偏好读取
- _aggregate_daily: 逐日 filter 扫全表(O(N²))改为 polars 向量化 group_by
- 新增 enriched_date_set / earliest_enriched_date 辅助函数
- 盘后管道 regime 计算加开关(preferences.get_pipeline_regime_enabled), 默认关闭
- 新增偏好: regime_batch_days(默认60, 25~500) / regime_warmup_days(默认40, 35~90)
- 新增 API: PUT /preferences/pipeline-regime-enabled, PUT /preferences/regime-batch-params

前端
- 市场环境页时间范围控件: select 三档 → 4 档按钮组(1年/2年/自定义/全部)
  · 自定义弹窗手动输入天数(1~1000 钳制) + 快捷预设
  · 全部走 regimeCoverage 拿实际日期范围用 start/end 请求
- 市场环境页美化(对齐 Dashboard 设计语言): 渐变条头部/半透明卡片/SectionTitle/
  指标卡进度条/语义色 bull-bear
- 新建 RegimeConfigCard: 盘后自动计算开关 + 全量回填分批参数(每批天数/预热天数/
  快捷预设省内存·默认·更快)
- 数据页画像加市场环境卡片(独立 regimeCoverage 查询, 同步后刷新, 齿轮设置弹窗)
- 菜单排序设置 + 侧边栏 nav 加入市场环境, 默认排在复盘上面
- Layout 市场环境菜单 badge 改用琥珀胶囊(对齐 Settings 数据源标签)

验证
- 后端 582 passed; 真实数据全量回填产出 986 天, 内存峰值 ~1.9GB(原 6.8GB)
- 前端 tsc + pnpm build 通过
- 分批参数实测生效: batch=30 峰值 1896MB / batch=500 峰值 3772MB
2026-08-02 16:25:21 +08:00