Commit Graph
100 Commits
Author SHA1 Message Date
shy3130 0b4bde6dda feat(fuyao): 快照单页 limit=6000 一次拉完全市场
实测服务端单页 6000 不截断(全市场 ~5600 只), 一轮轮询从 11 请求降到
1 请求, 大幅降低 4001 限频压力; 分页循环保留作未来扩容/服务端截断兜底。
插件开发文档重写并补充单页上限实测结论与页间隔自限速要求。
2026-08-30 19:05:20 +08:00
shy3130 b8fa08f027 fix(worker): 消除回测子进程结果消息丢失竞态
现象: 整年区间回测偶发 'backtest worker exited without result (exitcode=0)'。
根因: 子进程 event_queue.put 只是把消息交给后台 feeder 线程, 主线程随即退出,
feeder 随进程销毁, 大结果/高负载下消息尾部未刷入管道; 父进程 0.1s 轮询
恰在 Empty+进程已死时跳出循环, 未读到的 result 被丢弃。

修复 (双侧):
- 子进程 finally 中 close+join_thread 队列, 保证退出前消息完整刷入管道
- 父进程在判定无结果前做一次兜底排空 (join 后 1s×2 轮 get)
2026-08-30 19:05:19 +08:00
shy3130 d4aa9ed6ad test(backtest): 分钟回测守卫与六项语义测试
- _guard_minute_strategy_backtest: 非股票资产与回测起点早于本地分钟K起点
  均返回 400 并提示「扩展分钟K历史」, 覆盖 run 与 SSE stream 两入口
- 合成分钟分区+日线面板夹具, 断言: 触发分钟收盘成交价/日线窗口严格止于
  T-1 的因果性/涨停拒买计数/缺分区日跳过/离场走日K次日开盘/入口守卫
2026-08-30 19:05:18 +08:00
shy3130 d9f7bc645d feat(backtest): 回测页支持分钟策略与分钟级成交展示
- 策略下拉改取 'all' 时段, 分钟策略入列表并加 sky 色「分钟」徽章
- 选中分钟策略条件化 UI: 隐藏分钟成交开关与 signal_next_minute,
  建仓口径固定显示「信号分钟收盘」, 展示本地分钟K覆盖提示与起始日越界警告
- 交易明细买入列渲染 HH:MM 分钟徽章 (entry_date 携带 YYYY-MM-DD HH:MM)
- SSE 连接前先 fetch 探测, HTTP 400 直接展示后端 detail,
  不再误入 EventSource 无限重连
2026-08-30 19:05:17 +08:00
shy3130 0559632de6 feat(backtest): 分钟策略回测 v1 — 逐交易日回放信号分钟收盘入场
- 新增 MinuteSignalReplayer: 枚举区间内分钟分区日, 逐日组装 StrategyDataContext
  (timeframe=1m, 日线窗口严格止于 T-1) 并复用 strategy_engine.run, 与实盘选股同路径
- 缺分区日显式跳过并记入 skipped_days, 不回退最近分区
- 涨停拒买: 信号分钟收盘 >= 当日涨停价(T-1 raw_close + 板块幅度)剔除并计数
- MarketMatrix 新增 entry_price 覆盖矩阵, 引擎在有限值处优先于 open/close 惯例
- repository.list_minute_dates 按目录名枚举分钟分区日, 零 parquet 扫描
- strategy.run 增加 minute_filter 分支: 入场 delay 0/离场沿用日K matcher,
  trades.entry_date 补全为 YYYY-MM-DD HH:MM (北京时间)
2026-08-30 19:05:16 +08:00
shy3130 d9ff91fa12 fix(dialog): 日K视图左右双栏同步实时刷新 — 蜡烛与内嵌分时接入独立轮询
上个提交只覆盖了「分时」标签页 (StockMultiDayIntradayChart); 默认日K视图
的 StockPanel 双栏仍不刷新:
- 左侧蜡烛 (StockDailyKChart): 日K查询挂载后从不轮询, 今日实时蜡烛
  (后端 _maybe_inject_live_candle 注入) 不随行情更新 → 透传
  refetchIntervalMs 到 StockDailyKChart 接入同一轮询
- 右侧内嵌分时 (StockIntradayChart): 对话框漏传 refetchIntervalMs 给
  StockPanel 日K分支, 且请求未带 live → 补传参数; 轮询上下文中
  klineMinute 带 live=1, 当日盘中直接实时拉取 (历史日期后端自行忽略)

浏览器实测 (实时行情关闭): 日K视图下 kline/daily 与
kline/minute?date=当日&live=1 均以约 6s 节奏持续轮询
2026-08-30 19:05:16 +08:00
shy3130 974a3dccd2 chore(dialog): 移除 StockPreviewDialog 残留的 useQuoteStatus 导入 2026-08-30 19:05:15 +08:00
shy3130 08701f8886 fix(kline): 个股详情分时图独立轮询, 盘中直接实时拉取最新K
- /api/kline/minute 新增 live 参数: 当日连续竞价时段跳过本地优先直接
  实时拉取, 避免盘中分钟增量落盘后 90% 完整度启发式让详情分时图停在
  上一增量轮 (>=60s 滞后), 与行情列表节奏脱节
- StockPreviewDialog 打开即独立轮询 (间隔沿用偏好, 默认 6s), 不再要求
  「分时刷新开关 + 实时行情运行」双条件 — PR #114 引入的门槛默认冻结详情图
- market_time 抽出公共 in_continuous_session, minute_refresh 复用同一实现
- 新增 12 个单测覆盖 live 路径, 本地回退与连续竞价时段边界
2026-08-30 19:05:14 +08:00
shy3130 7ceddc0669 docs(test): 分钟红7夹具注明与运行时副本的双位置关系 2026-08-30 19:05:13 +08:00
shy3130 68579f1b10 style(screener): 分钟周期徽章换 sky 色系, 与 AI 来源徽章的紫色区分 2026-08-30 19:05:12 +08:00
shy3130 9593883c59 refactor(strategy): 分钟红7由内置策略改为自定义策略
按用户要求, 分钟红7不再是产品内置形态, 以自定义策略形态交付:
- 移除 app/strategy/builtin/minute_red_streak.py; 运行时副本落在
  data/strategies/custom/ (gitignore, 用户可自行修改调参)
- 策略 id (minute_red_streak) 不变: 参数覆盖 / 策略池引用 / minute_filter
  契约 (daily_history_bars + daily= 注入) 全部不受位置影响
- 仓库保留参考实现作为测试夹具 (tests/fixtures/strategies/),
  25 个行为测试改由夹具加载, 引擎加载测试同时断言 source == "custom"
- builtin 相关不变量更新: 内置 19 个全部 matrix_native, 无 minute_filter

本地验证: /api/strategies/reload 后 source=custom, 08-25 分区分钟扫描
命中 5 只 (用户实盘参数: 6根开5红+最高2红+20日涨停过+沪深主板50-200亿)。
2026-08-30 19:05:11 +08:00
shy3130 8ccb681214 feat(settings): 补全设置卡片定位闪烁锚点体系
此前「从业务页引导去设置」只有 depth-fix 一处孤例 (SealedBadge → 连板
梯队修正卡片闪烁), 其余 8 个引导链接只带 tab 参数跳转, 用户落地后要
自己在设置页里找目标卡片。

- 通用锚点机制: useCardFlash hook (/settings?tab=X&highlight=<anchor>
  打开时目标卡片 scrollIntoView 居中 + ring 高亮 2s, 一次会话仅触发
  一次防 StrictMode 重放) + AnchorWrap 包裹层 (无统一 Card 组件的面板用)
- Settings 把 highlight 传给全部面板 (面板类型本就声明了 highlight?: string)
- 锚点落位: 监控页 Card 组件 anchor 化 — quotes(行情轮询)/webhooks(推送
  通知)/minute-refresh(盘中分钟增量)/intraday-refresh(分时图刷新)/
  depth-fix(原实现迁移到统一机制); AI ai-connection; 数据源 data-sources;
  信号库 signals
- 8 个引导链接补 &highlight=: RuleEditor/Review webhook 未配置提示 →
  webhooks; Layout 实时无权限/监控入口 → data-sources/quotes; Data 页
  数据源入口 → data-sources; 信号触发器 → signals

验证: pnpm build 通过; 浏览器实测 8 个锚点全部滚动定位+闪烁; 顺带补验
40e54ea 统一策略池欠的界面项 (双池→统一迁移 17/33、分钟徽章、三态筛选
只过滤显示不动池、ETF 视角无分钟策略、分钟卡片实时单跑)。
2026-08-30 19:05:10 +08:00
shy3130 a342d94238 feat(screener): 策略池统一 — 日线/分钟合并单池, 执行按策略声明周期路由
原设计: 日线/分钟双池隔离 (strategy-pool / strategy-pool-1m), 页面按
周期开关切换两套世界。拆池根因是列表按周期过滤 + 页面级周期切换: 分钟
视角下池内日线策略解析不到才显示「失效」, 属于修补表象而非消除根因。

- 池合并: 双 key 一次性迁移为单池 (日线在前、分钟在后、按 ID 去重,
  完成后删旧分钟 key 保证幂等, StrictMode/HMR 重放安全)
- 执行路由真相来源从 UI 开关改为策略自身 timeframes 声明: 日线走盘后
  缓存/runAll, 分钟走本地分钟K分区实时单跑 (卡片点击/参数保存重跑均
  按各自周期传参)
- 周期开关降级为三态显示筛选 (全部/日线/分钟, 默认全部), 只过滤卡片
  显示, 不影响池与执行; runAll 自动跑仅覆盖池内日线子集
- ETF 置灰移除: 分钟策略 asset_types 仅股票, ETF 列表自然不含
- 池对话框取全量列表, 待选/已选两侧显示「分钟」徽章; 失效判定回归
  全周期合并列表, 消解「切视角整池失效」问题类别
- 后端零改动: /api/strategies 的 timeframe 为空本就不过滤, 前端 'all'
  时省略参数; 其余依赖默认日线过滤的 strategyList 调用方行为不变

验证: pnpm build 通过; git diff --check 干净; 3 处 run.mutate 调用点
均带周期参数; 迁移幂等路径 (双池/仅分钟/空池) 走查通过。界面手工验证
待实机执行 (池迁移/分钟徽章/筛选空态/ETF 视角)。
2026-08-30 19:05:10 +08:00
shy3130 b82c4eaedb feat(minute): 分钟红7新增「N日内涨停过」条件 + minute_filter 日线窗口契约
分钟策略此前只能访问当日分钟窗口, 无法叠加日线维度条件。本次为
minute_filter 后端扩展可选日线历史契约:

- 契约: 策略声明 META["daily_history_bars"] (0-250) + filter_minute_history
  接受 daily 关键字 (加载期校验, 纯分钟策略零改动); 引擎聚合各策略声明
  (minute_daily_history_bars) 后由 ScreenerService 1m 分支装配
  context.daily_history (enriched 日线窗口), run() 以 daily= 注入
- 分钟红7: require_limit_up (默认开) + limit_up_days (5-60, 默认20) 参数;
  涨停判定复用 enriched 预计算信号 signal_limit_up (收盘封板) 或
  signal_broken_limit_up (炸板盘中触及), 任一命中即算涨停过, 输出
  recent_limit_ups 次数列; 日线窗口缺失时失败闭合 (宁可漏过不可错报)
- 测试 25 项: 涨停信号过滤/炸板计数/回看窗口边界(第20日含第21日不含)/
  失败闭合/开关旁路/加载校验(缺 daily 关键字与超范围)/引擎注入/服务装配

实盘验证: 用户参数(bars=6)基线 24 只 → 要求涨停过后 6 只, 全部带
recent_limit_ups; 全量 1112 项后端测试通过。
2026-08-30 19:05:09 +08:00
shy3130 bfa87d1f0b fix(screener): 策略池按日线/分钟周期隔离, 修复分钟视角下整池显示失效
原设计: 日线/分钟共用一份策略池。切到分钟模式后, 池中 15 个日线策略
在分钟策略列表里解析不到, 策略池对话框右侧全部标成「失效」; 此时确认
还会把混合名单回写全局池, 日线池同样被污染。

- 池按周期隔离: 'strategy-pool' (日线, 沿用原 key 存量无损) +
  'strategy-pool-1m' (分钟, 新 key); useStrategyPool(timeframe) 返回
  当前周期的池, 任一池变更幂等落库双 key, 切换周期不会交叉写
- 「失效」徽章回归本义: 仅当策略真被删除 (不在本周期列表) 时出现
- prune 解除仅日线限制: 各周期用自身策略列表清理各自的池, 互不误删
- 策略构建器/叠加策略创建的是日线策略, 固定入日线池 (即使分钟页保存)

验证: 分钟对话框无失效列表、可正常添加分钟红7; 日线 15/31 ↔ 分钟 1/1
往返切换稳定; 刷新后双池持久。

注: 开发中 vite HMR 热替换瞬间曾把本地日线池写空 (旧代码对话框与新
模块混布的开发态一次性产物, 生产构建无 HMR 不受影响); 已从用户截图
复原原 15 策略及顺序 (boll_breakout → five_consecutive_yang)。
2026-08-30 19:05:08 +08:00
shy3130 1746a0e305 feat(minute): 分钟红7改用开盘窗口 + 盘中增量卡片移至设置右列
分钟红7: 检查窗口从「最近7根」改为「当日最早7根(开盘7根)」—
捕捉开盘急拉形态, 窗口在早盘即固定, 不随盘中新K线漂移;
close 取开盘窗口末根收盘价 (基础过滤口径同步更新)。

- 窗口选择: tail → head (sort 后 int_range < bars), 输出列契约不变
- 新增两个区分性测试: 开盘命中后转绿仍命中且 close 取窗口末根;
  开盘不足红K数、尾盘转红不救回 (旧最近窗口口径会命中)
- 实盘验证: 252 只命中, 每只窗口末时间均为 9:36 (开盘第7根)
- 设置页「盘中分钟增量」卡片从左列顶部移至右列 (连板梯队修正之后)

注: 本地 runtime 覆盖文件 minute_red_streak.json 的 description
快照已同步新文案 (gitignored, 不入库)
2026-08-30 19:05:07 +08:00
shy3130 2f8d1e5e60 refactor(settings): 盘中分钟增量刷新开关迁至实时监控设置
该功能是交易时段常驻运行的实时服务, 心智模型归实时行情设置更合理;
数据页分钟K弹窗还原为纯盘后批量同步语义。

- 配置端点归属迁移: minute_refresh_enabled/interval 由 PUT
  /api/settings/preferences/realtime-monitor 拥有 (set_realtime_monitor_config
  写入 + getter 返回, clamp [60,300] 不变); minute-sync 端点还原原状
- 前端 Monitoring.tsx 新增「盘中分钟增量」卡片 (开关/间隔滑杆 60-300s/
  运行轮次状态行), 沿用 Card/ToggleRow/滑杆防抖既有模式
- MinuteSyncConfig 移除盘中增量区块; api.ts updateMinuteSync 还原 3 参签名
- 新增归属测试: realtime_monitor_config 拥有 refresh 键且越界 clamp

验证: 28 项分钟相关测试通过; UI 开关双向回路 (curl 置开→UI 显示开,
UI 点击→偏好翻转 False 且服务 gate_reason=disabled); 数据页弹窗无残留
2026-08-30 19:05:06 +08:00
shy3130 5e2358ce48 feat(minute): 分钟策略执行后端 + 分钟红7策略 + 盘中增量落盘 (Expert)
一期 · 分钟策略执行链路:
- 引擎新增 minute_filter 执行后端: 策略声明 filter_minute_history(df, params),
  timeframes 必须且仅为 ["1m"]; 输入为当日分钟K窗口, 命中行事后联表 enriched
  快照补基础过滤列 (name/total_shares/change_pct), close 用最新分钟价
- 内置策略「分钟红7」(minute_red_streak): 最近 N 根(默认7)分钟K至少 5 根
  close>open, 且按最高价排序的最高的 2 根全红; 全向量化, 671k 行约 230ms;
  参数 bars/min_red/top_red/rank_by_close, 不足 N 根不触发, 同值取更晚K线
- ScreenerService 1m context: 优先读 as_of 当日 kline_minute 分区, 缺失回退
  全市场最近分区; 单分区直读与全量 glob 解耦
- run_preset/run_all 分钟周期结果不写日线盘后缓存 (语义隔离)

二期 · 盘中分钟增量落盘 (Expert 专有):
- kline_sync.fetch_intraday_full_market_burst: intraday.batch 独立限流池,
  全市场 5546/200=28 块线程池一次打出, 轮内不重试
- MinuteRefreshService: 后台线程, 门控链 = 开关→自定义分钟源让位→INTRADAY_BATCH
  能力→连续竞价时段(9:30-11:30/13:00-15:00); 固定节奏 next=max(起点+间隔,完成),
  不补跑; 每轮单次合并落盘 (_write_minute_partition unique 幂等)
- 偏好 minute_refresh_enabled(默认关)/minute_refresh_interval([60,300]s 默认60);
  GET /api/settings/minute-refresh/status 状态端点

前端:
- 策略页日线/分钟周期切换 (1m 下 ETF 置灰、不触发盘后 runAll、prune 仅日线),
  策略卡片「分钟」徽章, 策略池对话框按周期拉取
- 数据页分钟K设置弹窗新增盘中增量区块: 开关/间隔(60-300s)/能力缺失置灰/
  服务状态行(运行中·时段暂停·最近一轮)

测试: 26 项新增 (形态7/引擎4/context4/服务11), 更新 3 个 matrix 不变量测试;
全量 1112 passed; 前端 build 通过; 浏览器端到端实测通过
2026-08-30 19:05:05 +08:00
shy3130 196af2fa06 feat(monitor): 策略监控新建规则默认通知事件改为选股结果
DEFAULT_STRATEGY_NOTIFY_EVENTS 从买/卖信号改为进入/移出选股结果,
新建规则、类型切换、策略页创建监控三处默认随之生效; 与后端省略
notify_events 字段时的回填口径一致。旧规则空值回退(LEGACY)不变。
2026-08-25 09:52:56 +08:00
shy3130 0eb3e54b67 fix(data): 自定义源实时行情百分制涨跌幅截面自动归一为小数制
契约要求 change_pct/amplitude/turnover_rate 小数制(0.0366=3.66%),
但 a-stock-data 等第三方接口返回 3.66 表示 3.66%, 原样透传导致行业/
概念统计与前端展示整体放大 100 倍(用户反馈)。get_realtime 摄取边界
按截面中位数判定(|值|中位数>0.31 必为百分制, 小数制受 30cm 涨跌停
约束不可能超过), 整批归一; 小样本退用最大值; 附 7 项回归测试与文档说明。
2026-08-24 17:14:55 +08:00
shy3130 9883208847 fix(mainline): 维度映射返回值按形态取用, 修复重算偶发 Series 报错
用户反馈市场环境点重算偶发 'Series' object has no attribute 'group_by':
若 _load_concept_map_df 返回裸 DataFrame, 元组解包会把两列拆成 Series
(Series.is_empty 可通过, group_by 不存在)。改为按 tuple/DataFrame 实际
形态取值, market_mainline 与 build_rps_rotation 两处解包点同修,
附回归测试(裸 DataFrame 假实现端到端不炸)。
2026-08-24 17:14:48 +08:00
shy3130 b14ffda1bd feat(ui): 数据源能力卡片显示 TickFlow 订阅档位要求与全档位标识
每张能力卡右上角显示该能力所需最低档位(全档位/Starter+/Pro+/Expert+,
配色与左侧菜单档位体系一致, 当前档位不足时琥珀描边提示), 替代原
"当前提供方"徽标(信息已由下方高亮标签承载)。TickFlow 详情头部与
列表卡片在"第三方"后增加 Expert 三色渐变的"已适配全档位"标识。
2026-08-24 17:14:48 +08:00
shy3130 971b4376d1 fix(ai): Codex CLI 状态检测实跑 --version 并移除老版本不支持的 --ephemeral
状态检测原为浅检查, 误报已连接; 改为 codex --version 实测。
--ephemeral 在 codex 0.58 等老版本不存在(unexpected argument),
隔离已由临时 CODEX_HOME 保证, 移除该参数。
2026-08-24 17:14:39 +08:00
shy3130 46635074e8 fix(ai): PR #193 新增 AI 调用放开 max_tokens 限制
合并 #193 引入的 3 处显式 max_tokens(信号生成 2000/策略代码 3000×2)
重新踩中 0ee3aa8 修过的问题: 推理模型思考 token 计入 max_tokens 预算,
显式限制挤占正文导致 JSON/代码截断。统一改为 None(请求不传该参数,
输出上限交给服务端默认)。四个分析器本就是 None, 标题生成 max_tokens=8
为刻意保留的小任务限制, 均不动。
2026-08-24 14:21:55 +08:00
shy3130 6c7c7088a9 feat(ui): 数据源能力卡片标签式路由 — 每个数据集单独选择提供方
- 每个数据源详情展示能力卡片, 卡片上以可点标签列出所有具备该能力的
  数据源(TickFlow 恒为候选), 点标签即刻切换该数据集路由, 跨源自由组合
- 右上角徽标显示当前提供方; 除权因子含「跟随日K」标签(默认态)
- TickFlow 详情含全部能力 + 恢复默认; 插件 Key 配置区对齐 TickFlow 布局
- 插件详情「整体切换为该源」= 一键套用其全部适配能力, 其余回退 TickFlow
2026-08-24 14:21:45 +08:00
shy3130 ea746b97c7 feat(plugins): 新增 fuyao 同花顺官方实时行情插件(默认 hidden)与插件 Key 界面配置
- fuyao 插件: 全市场实时快照分页拉取, 字段对齐数据契约(pct 百分制÷100),
  兼容官方文档与实际返回两种信封/字段名; 优化完成前 plugin.yaml 标记
  hidden: true, 加载器跳过注册不展示, 删除该行即可开放
- plugin.yaml 新增 api_key_env 约定: 设置页提供 Key 输入框, 先探后存
  (POST/DELETE /api/settings/plugin-key), secrets.json 优先于 .env
- secrets_store.get_env_backed_secret(field, env_name) 支持插件取 Key
- loader: 插件状态透出 api_key_env, 新增 probe_plugin_key 委托探测
- 31 个插件测试; docs/plugin-development.md 补充约定说明
2026-08-24 14:21:38 +08:00
shy3130 a4554794fc fix(dev): macOS 下 dev.sh 启动失败修复
- bash 3.2 空数组在 set -u 下展开报 unbound variable, 加 ${arr[@]+...} 守卫
- 全局 /usr/local/bin/uvicorn (Xcode python3.9) 劫持 venv, 改用 python -m uvicorn
2026-08-24 14:21:27 +08:00
shy3130 f856b4a8f8 回测「全部」范围与环境过滤冲突时自动顺延正式起点
正式首日 = 面板首日 (数据边界, 如「全部」范围从本地数据第一天开始) 时,
T-1 环境校验所需的上一交易日不在面板内, fail-closed 直接报错且用户
无法补更早数据。新增 clamp_formal_start_for_regime: 首日让渡为预热,
正式起点顺延到第二个交易日 (首日环境即成为次日 T-1), 仅损失 1 个
正式交易日。接入 run() 三条数据分支与优化器共享矩阵路径, 结果 config
回显实际生效起点。
2026-08-21 17:41:42 +08:00
shy3130 21260f1053 异动监控修复与规则口径对齐 (上交所交易规则 2026 修订)
- 盘中增量路径补算偏离列: compute_enriched_today 补 momentum_3d,
  live_agg 新增 _close_3d_ago 递推状态, 增量/全量回退两路径统一附着
  今日偏离 (基准 = 历史帧昨收 × (1+指数实时涨跌) 外推, 排除盘中
  写入的今日指数行), 修复盘中异动列表恒为空的问题
- 主板 ST 口径统一: 2026-07-06 起风险警示股票涨跌幅 10% 且异常波动
  特别规定废止, 删除原 ±15%/10日+50%/30日+100% 从严表, ST 与普通
  主板同标准
- 严重异常波动负向阈值对齐官方不对称口径: 10日 +100%(-50%),
  30日 +200%(-70%), 跌方向更早触发; 前端规则表/窗口徽标同步双侧显示
2026-08-21 17:41:35 +08:00
shy3130 bcb5cedd9a 引导页改为选择第三方数据源并弱化品牌关联
- 欢迎语改为 TSP, 声明页措辞通用化, 去掉品牌链接
- 数据源步骤不再配置 Key: 卡片选择第三方源, 复用设置页切换逻辑与自有源编辑器
- 第三方/自有标识徽标, 第三方为黄色胶囊
- 新增插件化提示框: 两条接入路径与文档指引 (docs/custom-data-source.md / plugin-development.md)
- 侧栏数据源徽标图标换为 DatabaseZap
2026-08-20 17:34:20 +08:00
shy3130 5374d8dc85 收起的图表列表头保留文字标签 (仅靠 nowrap 防折行) 2026-08-20 16:40:57 +08:00
shy3130 3b2fcfcb67 修复收起图表列时表头换行顶高的问题
- 根因: 收起时列宽压到 44px, 分时表头「眼睛按钮+排序箭头+内边距」
  约 62px 放不下, 排序箭头被挤到第二行, 表头行被顶到 63~81px
- 修复: 表头单元格统一 whitespace-nowrap (表头不应折行, 长标签同样
  受益); 日k/分时列收起态隐藏文字标签只留眼睛按钮, 列保持紧凑
- 验证: 收起态行高 43px 单行(日k 44px/分时 56px), 展开态 41px
2026-08-20 16:37:08 +08:00
shy3130 df0c24a0fa 数据源徽标图标换为 Activity 波形 2026-08-20 16:27:46 +08:00
shy3130 a9b6724d5a 自选搜索下拉支持已加标的继续加入其他分组
- 搜索结果中已加自选的标的: 禁用对勾改为「已加自选 ✓ + 分组勾选面板」,
  可直接勾选加入/移出分组 (走 members 端点, 不重排列表、不覆盖备注)
- 分组勾选弹层标记 data-watchlist-group-menu, 搜索下拉的
  点击外部关闭逻辑对其豁免, 两组浮层可并存操作
2026-08-20 16:21:52 +08:00
shy3130 83b96e2088 自选分组支持多组并存 (M:N)
- 后端: watchlist 条目 group_id 单值列迁移为 group_ids 列表列, 首次
  写入前自动备份 .bak; 新增 add_to_group/remove_from_group 及
  POST/DELETE /groups/{gid}/members/{symbol} 端点
- 前端: 分组选择器改为勾选式弹出面板, 触发器显示多色点(最多3+N);
  移除语义收窄为仅移出当前分组, 移出全部后提示标的仍在自选
- 适配: 分组页签计数/筛选、等权涨跌幅、分组卡片、监控自选导入、
  回测/挖掘两页分组导入均按 group_ids 归属计入每个所属分组
2026-08-20 16:15:13 +08:00
shy3130 0f423f5455 style(layout): 数据源徽标图标 Database → ChartLine
Database 圆柱图标观感笨重且与「数据」菜单项撞图标。先试 K 线图标
(chart-candlestick) 但与品牌 logo 的 K 线图案上下重复, 最终采用
折线图标 ChartLine — 干净、金融数据语义、与全站图标无冲突。

验证: tsc 通过; 浏览器实测渲染 lucide-chart-line。
2026-08-20 15:46:31 +08:00
shy3130 b5229f3dc5 style(layout): 数据源状态卡图标 Key → Database
侧栏「TickFlow Expert」数据源徽标左侧的钥匙图标改为数据库图标,
与「数据源」语义一致(点击跳转数据源设置)。Key 导入随之移除。

验证: tsc 通过; 浏览器实测渲染为 lucide-database。
2026-08-20 15:32:56 +08:00
shy3130 420a362bcd fix(monitor): 作用范围对齐 — 导入标的后下拉框仍与控件同行
根因: 外层容器 items-center, 「已加入」出现后右侧列变为两行,
下拉框被垂直居中到两行中间, 观感错位下沉。
- 外层改 items-start: 下拉框永远对齐第一行(导入/搜索行)顶部,
  与 h-7 等高 → 始终同一水平线
- 控件行去掉 flex-wrap、搜索框 min-w-0: 任何宽度都不换行

验证: tsc 通过; 导入 22 只后实测三控件 top 均为 348px、高均 28px,
胶囊在下方 6px 独立成行, 截图确认无错位下沉。
2026-08-20 15:23:49 +08:00
shy3130 3630653342 fix(monitor): 作用范围布局 v2 — 三控件同行等高, 汇总单独成行
按用户反馈重排:
- 行1: 范围下拉(h-9→h-7) + 自选导入 + 搜索框 — 始终同一 flex 行,
  三者统一 28px 高度(下拉框不再偏高), 字号统一 11px
- 行2: 「已加入 N 只 ▾」单独一行, 与控件列左对齐(展开态为标签管理区)

验证: tsc 通过; 浏览器实测三控件 top 一致/高度均 28px, 导入 22 只后
汇总胶囊位于控件行下方独立成行, 截图确认无错位。
2026-08-20 15:10:27 +08:00
shy3130 11345815b6 fix(monitor): 作用范围区布局 — 自选导入与搜索框同行等高
上一轮标签重构把容器改为纵向堆叠, 自选导入按钮和搜索输入各自占一
行且输入框窄(w-32), 视觉散乱。调整为两行结构:
- 行1: 范围下拉 + 「已加入 N 只」汇总胶囊(或展开态的标签管理区)
- 行2: 自选导入按钮 + 搜索输入框 — 同一 flex 行等高(均 h-7), 输入框
  flex-1 占满剩余宽度, 搜索下拉宽度同步跟随

验证: tsc 通过; 浏览器实测同行(sameRow)等高(sameHeight=28px),
导入 22 只后布局整洁无错位。
2026-08-20 14:46:24 +08:00
shy3130 dc2758a150 feat(monitor): 新建监控标的展示重构 — 汇总+展开管理 名称/板标/代码 tag
原「从自选导入」后逐个显示纯代码 chip, 长列表难读且无名称。改为:
- 收起态(默认): 「已加入 N 只」汇总胶囊, 点击展开管理
- 展开态: 标签流「名称 [创/科/北板标] 代码 ×」— 板标复用 boardTag
  (搜索下拉同款样式), 每个可单独删除, 附「清空」「收起」操作;
  数量多时容器限高滚动
- 名称解析: 本地缓存(搜索结果/自选数据, 即时) + 批量名称接口
  api.instrumentNames 兜底(编辑旧规则等本地无名称场景), key 随
  标的集变化, staleTime 5min

验证: tsc 通过; 浏览器实测 — 自选导入 22 只 → 「已加入 22 只」汇总,
展开后 tag 显示「捷捷微电·创·300623.SZ」等(名称+板标+代码), 删除
单只后计数 22→21, 清空/收起可用。
2026-08-20 14:36:03 +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 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 2a2d3b764e feat: add watchlist groups and multi-day intraday view 2026-08-10 11:39:08 +08:00
shy3130 ecfddb451e feat(monitor): 新增板块异动监控 2026-08-06 19:28:39 +08:00
shy3130 8b83f9e1bd fix(regime): 修复日历热力图交易日错位到周末列
calendarMonths 只在月初按 dow 算了前导空位, 之后把真实交易日逐个 push,
不按日期补齐缺失的天。当某月数据不是从 1 号连续到月末(最早月份只有
下半月数据或中间缺几天)时, 后续交易日格子整体左移, 被挤到周末列,
看起来像周六周日也有数据。

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

验证: pnpm build 通过。
2026-08-06 19:12:04 +08:00
shy3130 f8fca96f42 修复停复牌股票实时涨跌停漏算 2026-07-30 13:09:07 +08:00
shy3130 4b6e94e020 修复回测风控参数恢复旧缓存的问题 2026-07-29 21:27:02 +08:00
shy3130 6e4d6b9784 docs: 完善项目贡献与复审指南 2026-07-28 18:55:05 +08:00
shy3130 b29efebe68 docs: 新增项目完整操作说明书 2026-07-28 13:34:03 +08:00
shy3130 60fe9e6fa6 修复回测指标数据缺失提示问题 2026-07-22 13:30:02 +08:00
shy3130 a12e49d66d 修复实时行情下策略图表闪烁问题 2026-07-22 11:42:57 +08:00
shy3130 2d9fe4a4af 修复策略文件无法删除问题 2026-07-22 11:21:13 +08:00
shy3130 2c14fde788 完善个股点位提醒并发布0.1.87 2026-07-21 22:14:07 +08:00
shy3130 b4dae4bca1 修复股票与ETF切换误清策略池 2026-07-21 21:39:05 +08:00
shy3130 0ac6d6f56c 修复分析报告复制按钮兼容性 2026-07-21 20:50:34 +08:00
shy3130 0cb0b38437 修复看板监控通知个股弹窗 2026-07-20 17:10:15 +08:00
shy3130 c8c1a01d55 更新交流群二维码 2026-07-20 13:56:04 +08:00
shy3130 72918fe602 优化策略卡片结果加载性能 2026-07-20 13:01:03 +08:00
shy3130 0635698a08 修复策略监控开启后结果归零 2026-07-20 11:12:19 +08:00
shy3130 e1dbd1cafb 修复监控中心涨跌停信号误报 2026-07-20 10:33:06 +08:00
shy3130 ed41f7b950 修复:个股详情量比开关显示异常 2026-07-20 09:59:14 +08:00
shy3130 4df3062002 fix: 完善自定义分钟数据源配置与异常处理
- 补齐资产类型和周期参数在 API、YAML 与前端编辑器中的保存回读

- 权限判断和分时监控统一复用安全的数据源解析边界

- 增加配置往返及解析异常回归测试
2026-07-19 17:01:33 +08:00
shy3130 b1b2494db9 merge: 合并 PR #128 自定义分钟数据源支持 2026-07-19 16:52:52 +08:00
shy3130 b17c882e27 feat: 完善历史换手率重算入口
- 财务数据统计纳入历史股本,并在数据页提供分批重算入口

- 缺少股本历史时阻止重算,并接入现有任务进度

- 财务分析卡片使用更新图标,明确数据拉取语义
2026-07-19 16:42:03 +08:00
shy3130 8e4258cf20 feat: support historical price limits and share capital 2026-07-18 23:37:54 +08:00
shy3130 e462c63b45 fix: align AI strategy prompt constraints 2026-07-18 18:31:02 +08:00
shy3130 ff12790042 feat: add trading-day volume comparison 2026-07-18 17:46:58 +08:00
shy3130 44ab51e65d feat: improve strategy scoring and backtest execution 2026-07-18 16:59:53 +08:00
shy3130 a1e8be58db feat: release v0.1.86 2026-07-18 00:49:28 +08:00
shy3130 34eaba3010 fix: handle uncovered walk-forward folds 2026-07-17 14:00:16 +08:00
shy3130 1e38c8cebb fix: reset strategy builder identity 2026-07-16 16:12:06 +08:00
shy3130 c763a6970f fix: restore strategy and data compatibility 2026-07-16 14:34:07 +08:00
shy3130 77876c7ee4 fix(data): avoid destructive enriched rebuild cleanup 2026-07-15 21:34:44 +08:00
shy3130 0b3b769ca8 fix(strategy): clear saved strategy drafts 2026-07-15 20:51:07 +08:00
shy3130 f317377bef fix(strategy): apply saved params to builtin screeners 2026-07-15 20:06:11 +08:00
shy3130 89115e6f73 fix(strategy): apply saved parameters during execution 2026-07-15 19:03:48 +08:00
shy3130 de1b1713fa fix(backtest): 参数优化页日期选择器被布局遮挡
根容器缺少高度约束, 配置列内容撑高后整页在外层滚动容器滚动,
DatePicker 弹层 (absolute 内联) 被裁剪无法完整显示。

对齐 StrategyBacktest 的布局: 根容器加 h-full min-h-0 overflow-hidden
使整页不滚动, 配置列/结果列各自 overflow-y-auto 内部滚动, 日期弹层
向下展开时在可视区完整显示。
2026-07-10 17:31:07 +08:00
shy3130 e61c228002 fix(ai): base_url 归一化保留非 v1 版本段, 修复 GLM /v4 被 404
normalize_openai_base_url 旧实现只检查「是否以 /v1 结尾」, 不是就强制补 /v1。
智谱 GLM 的 OpenAI 兼容地址是 /api/paas/v4, 被补成 /api/paas/v4/v1,
SDK 再拼 /chat/completions → 不存在路径 → 404。

改用正则检测 URL 末尾已有的版本段 (/v1、/v2、/v4、/v1.1 等):
- 已有版本段 → 保持原样
- 无版本段 → 补 /v1 (无版本号网关行为不变)
- 去 /chat/completions 后缀逻辑保留

补 4 条单测覆盖 GLM /v4 场景, 原有 v1/无版本网关回归不变。

Closes #60
2026-07-10 17:06:17 +08:00
shy3130 fd0a83b276 polish(layout): SSE 断连提示移至底部居中 + 文案调整 2026-07-10 16:37:31 +08:00
shy3130 d9fe050b1f fix(realtime): 策略页实时行情闪烁 + 策略结果刷新机制
策略页开启实时行情时, 被监控的策略列表反复闪烁 (变 0 → 全部失效 → 又出现),
非监控策略不受影响。

根因: 每个行情周期后端先广播 quotes_updated 再重算策略, 重算时先清空内存结果
再逐个回填 (非原子窗口)。前端 quotes_updated 与 strategy_results_updated 两个
SSE 事件都刷新 screener-cached, 第一次撞上清空窗口拿到空结果, 第二次拿到重算
结果, 每周期重复 → 闪烁。

修复:
- 前端: 从 SSE_INVALIDATE_PREFIXES 移除 screener, quotes_updated 不再刷新策略页,
  每周期只剩 strategy_results_updated (重算完成后才发) 触发一次刷新。
- 后端: monitor.evaluate 改为临时容器收集结果, 算完后整体替换 _latest_strategy_results,
  /cached 并发读取永远拿到完整结果, 不会读到空中间态。

配套:
- 新增 strategy_results_updated SSE 事件 + subscriber 合并通知机制
- 策略卡片 loading 时不显示旧命中数, 避免刷新时数字跳动
2026-07-10 16:37:11 +08:00
shy3130 9c6c1fce61 fix(watchlist): 支持重置全部筛选 2026-07-10 15:18:40 +08:00
shy3130 fdee661d47 fix(watchlist): 保留冷缓存自选占位行 2026-07-10 15:07:14 +08:00