shy3130
|
de51929a44
|
fix(mining): 市场环境数据缺失时挖掘启动即失败并前置提示
用户在未计算市场环境的数据目录跑挖掘: 搜索阶段的 regime 评估被
evaluator 软捕获成 error 字符串, 整轮嵌套搜索照常跑完后, artifacts
阶段的 _regime_date_count 硬抛 ValueError, 计算全部浪费且只在最后
给出指引。
- mining_runtime: require_regime 时在因子面板就绪后立即用与
artifacts 相同的 fold 口径预构建一次 regime mask (required 区间取
全部外层 fold 测试窗并集), 数据为空/覆盖不完整即刻带指引消息终止
- MiningWorkbench: 启动前查询 /api/regime/latest, 未计算时侧栏显示
警告横幅(直达数据页)并在开始时 toast 阻止, 避免产生必败的运行记录
- 测试: 缺数据 fail-fast / 覆盖充足通过 / fold 窗口内缺口报错 三例
|
2026-08-26 12:55:38 +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
|
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
|
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
|
0bb9d64f60
|
merge: 试验性合并 PR #193 (feat/ai-generate-signal) 到最新 main
|
2026-08-23 19:29:44 +08:00 |
|
shy3130
|
ff4274a5ed
|
fix(data): 僵死 enriched 发布标记不再阻塞清空与实时落盘
外部进程(崩掉的脚本/中断的管道)残留 state=publishing 标记且 owner pid
已死时, recover=False 的发布器会永久抛
"another enriched publication is incomplete":
- POST /api/data/clear 因此 500 (用户实测)
- 实时 enriched 落盘被持续挡住, 只能等下一次盘后管道 recover
修复: clear 端点与 repository 三处 enriched 写路径 (日K分区写 + 两处
实时 merge flush) 全部改 recover=True — 死进程残留首次写入即接管自愈;
活进程的发布仍抛 "another publication is active", 写盘竞态保护不变。
测试: 僵死标记+死 pid 下 clear 正常完成且标记回 ready、实时写入接管自愈;
全量 1002 passed。
|
2026-08-23 19:13:03 +08:00 |
|
shy3130
|
e15acddb2f
|
fix(pipeline): 停机缺口检测与自动修复, 防止盘中快照数据永久损坏
场景: 用户盘中停机后次日启动并开实时行情, 实时 flush 写出"今天"分区后,
盘后管道的「今天已有数据→只刷今天」分支会让停机日的半日快照永久留存
(close=停机时刻价, volume=半日累计, 技术指标全错且污染后续 lookback)。
判据 (quote_ts 列, 仅实时 flush 写入真实毫秒时间戳):
- null → batch 拉取/盘后计算的权威历史 → 完整
- 历史交易日时刻 < 15:00 → 盘中快照 → 坏
- ≥ 15:00 → 尾盘定版 → 完整; 今天不校验
读取走 parquet 元数据 statistics, 实测 ~0.5ms/分区。
三个钩子层层设防:
- 启动自检 (main.py): boot 后 30s 后台扫描, 窗口内坏数据自动创建修复任务
(复用 repair_daily 管道 + JobStore, ActiveJobCard 可见进度)
- 开实时门禁 (settings.py): 坏数据在 5 天窗口内 → 自动建修复任务并 409,
前端经现有 toast 机制展示; 窗口外放行不拦
- 盘后管道自愈 (daily_pipeline.py): 分支3前完整性扫描, 坏日 → 降级分支4
从 min(最新日, 坏日) 范围重拉; ETF/指数起点同步提前到各自族最早坏日
修复原语补强: 股票 enriched 的坏分区由 prune_enriched_partitions 先删再
当"新日期"重算 (增量重算只算不存在的日期, 分区已存在虽错也永不重算)。
分钟K缺口经修复管道 Step 2.5 增量同步天然补洞 (start=max(datetime) 幂等)。
测试: 新增 24 个 (判据/门禁/boot/端到端离线集成复刻用户场景),
全量 1002 passed。
|
2026-08-23 19:12:57 +08:00 |
|
shy3130
|
61130cfdff
|
fix(backtest): ETF/指数矩阵链路不再要求股本字段, 修复因子挖掘准备阶段失败
etf 维表(index_sync)物理上只有 symbol/name/code/asset_type, enriched 窄表
也不落盘股本字段; 而 DEFAULT_BASIC_FILTER 与矩阵缓存档 common_filter 均带
非 None 市值界, 依赖解析会无条件要求 total_shares/float_shares, 导致
_resolve_matrix_storage_fields 抛
"matrix parquet fields unavailable: ['float_shares', 'total_shares']"
(用户反馈: ETF 因子挖掘死于「准备共享撮合矩阵」阶段)。
- 新增 _basic_filter_for_asset: 非股票资产将市值/流通市值四项界置 None,
依赖解析前中和; 运行期过滤本就对缺失股本列降级 no-op, 无需改动
- StrategyDependencyResolver.resolve 新增 asset_type 参数(默认 stock,
旧调用行为不变), 四个调用点传入真实资产类型:
build_matrix_cache_profile / prepare_matrix_optimization /
单次回测 / composite 子计划
- mining_runtime._prepare_base_market 两处 resolve 传入 request.asset_type
- 新增回归测试: ETF 计划与缓存档不含股本字段、股票行为不变、
ETF 维表下字段解析成功、反向对照锁定失败模式
验证: 全量 pytest 976 passed; 真实组件端到端复现用户失败路径已转绿
(ETF enriched + 四列维表, 共享矩阵 (280,3) 构建成功)。
|
2026-08-23 17:46:54 +08:00 |
|
shy3130
|
a6a4bcde43
|
fix(sync): 卡死判定改进度停滞 + 协作式取消 + 执行槽所有权
- reap 判定从总时长一刀切改为进度停滞(心跳 last_progress_at),
慢带宽冷启动不再被误杀; 12h 总时长硬上限兜底
- 协作式取消: JobCancelledError(BaseException) 经分块进度回调穿透,
僵尸线程在下一分块自行退出, UI 状态与执行体对齐
- 执行槽带所有权 token, 僵尸 finally 不得误释放新任务的槽
- 手动取消端点同样走协作式终止
- 前端超时卡片文案对齐停滞语义, 失败提示引导调整阈值
- 新增 10 个回归测试(972 passed)
|
2026-08-23 14:57:12 +08:00 |
|
shy3130
|
da3ada28e1
|
feat(v0.2): 功能门槛统一为数据源通用的能力标准
- 后端: 数据集→能力映射增广 (daily/adj_factor/minute/financial),
非 tickflow provider 按声明数据集动态 grant; 数据源偏好更新与
删除数据源后刷新 app.state.capabilities 快照; 新增 8 项测试
- 前端: 通用界面去档位词, 缺能力统一「{能力名} · 不可用」徽章
(capability-labels 新增 MissingCapChip, 点击跳设置→数据源);
StatCard/深度配置/分钟同步/历史扩展/财务页等 20+ 文件对齐;
实时模式判定改用 quoteStatus.mode 与 realtime_allowed,
替代前端 tierRank 推断; 监控设置页放开整页拦截
- 档位词仅保留 TickFlow 专属界面 (Key 配置/端点测速/引导页),
docs/configuration.md 档位表加注解说明
|
2026-08-23 12:34:40 +08:00 |
|
shy3130
|
0f2c7ce9b0
|
fix(backtest): 因子环境统计容忍数据边界=正式首日, 全部/1年范围不再报错
数据边界即正式首日 (本地数据首日=回测起点, 如「全部」/「1年」) 时, 首日
无 T-1 环境属正常。策略回测已有 clamp_formal_start_for_regime 首日让渡,
因子回测的环境分组统计路径漏了同样容差, 会整体报错阻断回测。
- align_regime_t_minus_one 新增 first_day_boundary_ok 参数 (默认 False,
过滤场景 fail-closed 行为不变): 统计场景首日无前驱时跳过首日不参与分组
- 因子 _calc_regime_stats 传入容差, 与策略侧首日让渡同口径;
内部缺口 (次日 T-1 缺环境) 仍 fail-closed 报错
- 回归测试: 边界容忍 + 分桶数正确 / 容差仅放行首日 / 内部缺口仍拒绝
|
2026-08-22 20:57:40 +08:00 |
|
shy3130
|
254e1962d0
|
feat(v0.2): 自选分组监控作用域 + 自选页交互增强 + 弱化默认数据源绑定
后端:
- 监控规则新增 scope=watchlist_group: 规则只存 group_id, 引擎按版本号缓存的
分组成员动态解析, 分组增删标的自动同步监控范围, 无需改规则
- 分组删除 fail-closed (规则暂停+runtime_warning), API 层校验分组存在性
- watchlist 服务增加数据版本号 _REVISION, 读取免锁、写后立即失效引擎缓存
- stock-sdk 插件 display_name 去掉括号合规备注 (说明保留在 description)
前端:
- RuleEditor 分组模式交互 (选择分组/成员预览/动态绑定提示), Monitor 列表分组摘要
- 自选搜索: Plus 快速加当前分组 + FolderPlus 展开分组菜单; 多分组圆点叠瓦显示
- 搜索下拉加宽防名称截断, 创/科/ETF 标签紧贴名称
- 自选筛选新增「排除ST」开关 (默认关, 持久化)
- 个股详情新增异动信息条: 状态着色/窗口偏离/接近度/计算时间 (无数据不显示)
- 引导页: 能力探测按数据源分流 (仅选 TickFlow 才显示 Key/档位), 切换 loading 收进卡片
- 看板空态/首次弹窗按数据源分流文案, 去除 Key/None 档引导注册表述
- 侧边栏实时行情无权限态改为「不可用 + 去配置数据源」
- 设置-数据源页: 新增插件化与配置文档说明块, 内置/插件标识统一改为第三方
测试: test_monitor_group_scope.py 8 例 (动态成员/删除分组/校验/API), 全量 946 passed
|
2026-08-22 20:26:34 +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 |
|
dev
|
8519a2bd16
|
feat(ai): AI 生成自定义信号条件
- 新增 /api/signals/ai/generate 接口:自然语言描述 → 结构化信号条件
- 新增 custom_signals_ai 模块:组装提示词 + 解析校验 AI 返回的 JSON
- 复用 custom_signals.validate() 白名单安全闸门
- 新增输出 token 上限和上下文窗口设置
- 实现 AI 请求 max_tokens 钳制和输入预算检查
- 自定义信号右值字段名容错处理
- 增强 JSON 解析容错(尾随逗号、垃圾字符)
- 前端自定义信号对话框接入 AI 生成
|
2026-08-21 09:55:24 +08:00 |
|
shy3130
|
68ce23370a
|
feat(v0.2): 异动监控全链路 (偏离值计算/监控页/系统告警接入) + 发布锁 Windows 存活修复
|
2026-08-20 22:56:11 +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
|
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
|
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
|
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
|
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
|
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
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
shy3130
|
46ebcd89c8
|
fix(regime): 修复重算无产出并补全 beta 标签
后端
- /recompute 全量分支原本误调 compute_regime_incremental(增量补差),
无缺口/stale 时直接返回 0 行; 改为用 earliest_enriched_date ~ 今天
走 run_regime_batch + upsert 强制覆盖, 真正实现"全量重算"
- _scan_enriched_fallback 原本漏调 compute_limit_signals 的 instruments
参数致慢路径必抛异常 → enriched 缓存未预热时拿不到含信号列数据 → 聚合
返回空; 改用主管道同款 compute_all(df, instruments, historical_shares)
一站式补算, 与 indicators/pipeline.py 对齐
- 新增 enriched_date_set / earliest_enriched_date 辅助函数(抽出复用)
前端
- Regime 重算按钮: 加"重算中…"文字反馈 + 完成 toast(区分有/无新数据) +
catch 捕获错误(原异常被静默吞掉)
- 市场环境菜单加 beta 胶囊标签(对齐 Settings 数据源标签样式)
验证
- 后端 582 passed; 真实数据全量重算产出 986 行(2022-07-08 ~ 2026-07-31)
- 前端 tsc + pnpm build 通过
|
2026-08-02 12:22:48 +08:00 |
|
shy3130
|
4ee55e40c6
|
feat(regime): 新增市场状态识别系统并接入叠加策略回测过滤器
后端
- 新增 services/regime_builder.py:5 档日级市场状态分级(strong/lean_strong/range/lean_weak/weak)
- 新增 api/regime.py:5 个 regime 查询接口
- daily_pipeline 接入 regime 构建(step 2.6,soft-fail + 双检测自愈)
- 回测 strategy.py 新增 regime_filter 过滤:采用 T-1 防未来函数,仅作用于入场信号
在 composite / matrix_native / prepared 三处注入 entry_time_mask
- backtest API 透传 regime_filter(REST + SSE);_make_job_key 纳入 regime_filter 以隔离缓存
- 兼容 _RepoStub 测试夹具(store 属性缺失场景)
前端
- 新增 Regime 页面、路由、导航入口、api 类型与 queryKeys
- 叠加策略回测页新增 regime 过滤器控件
测试
- 新增 tests/test_regime_builder.py(18 项),覆盖分级逻辑、T-1 防未来函数、空值降级、三处 mask 注入
- 全量后端测试 582 passed;前端 pnpm build 通过;git diff --check 无空白错误
|
2026-08-02 12:05:20 +08:00 |
|
shy3130
|
4696fef959
|
feat(composite): 新增叠加策略(composite)支持选股与回测
引入第四种执行后端 composite: 声明式引用多个子策略, 复用现有注册表/缓存/撮合全链路。
核心设计:
- 退出采用来源投影(每个子策略 exit 仅在自己持仓窗口生效, 不串平其他子策略仓位)
- 评分用标准化排名加权(跨子策略可比, 不依赖 per-strategy 的 min-max 量纲)
- 来源归因(entry_signal_code 标记来源子策略)
后端:
- engine.py: CompositeSpec 数据模型, 两阶段引用校验(孤儿移除/嵌套禁止/asset_types 子集/≤8 上限), _run_composite_strategy 选股执行, find_dependents 删除防护, override_loader 注入保证子策略与单独跑同口径
- composite.py(新): 选股 merge_results + 回测 merge_signal_matrices 合并器(退出投影/排名融合/归因)
- backtest/strategy.py: composite 回测分支(特征计划合并/逐子信号/统一风控/basic_filter/归因)
- api/strategy.py: POST /composite/save 端点, _strategy_detail 返回 composite_children(含 name/source), 删除依赖 409 防护
- monitor.py: 实时监控 fail-closed(回退盘后缓存)
- walkforward.py: 对 composite 显式中文报错
- worker.py: _strategy_dirs 补 composite 目录(修复回测子进程找不到 composite 的 bug)
前端:
- CompositeStrategyDialog(新): 创建/编辑弹窗(自动生成 composite_ ID, 权重归一, 类型标签, 增删子策略)
- StrategySettingsDialog: composite 设置面板(子策略增删改/归一/类型标签)
- StrategyBacktest: 回测页 composite 适配(分组/参数区/结果区展示子策略构成)
- api.ts: 类型扩展(source/backend 加 composite, composite_children 含 name/source)
测试: 36 个 composite 专项测试(加载/选股/回测退出投影/排名/归因/override 透传/API/删除防护), 端到端验证真实内置策略回测通过
|
2026-08-02 10:56:03 +08:00 |
|
shy3130
|
e803aa374d
|
chore: 版本号升至 0.1.88
统一升级 4 处版本号至 0.1.88:
- VERSION / backend/app/__init__.py / frontend/package.json: 0.1.87 → 0.1.88
- backend/pyproject.toml: 0.1.83 → 0.1.88 (原已滞后 4 个版本, 一并追上)
本版本包含:
- feat(search): 拼音首字母搜索 + 创业/科创/北交所徽标 (#151)
- fix(security): ext_columns DuckDB SQL 注入修复 (#152, closes #150)
|
2026-07-31 20:03:43 +08:00 |
|
shy3130
|
a4e580e314
|
fix(security): 修复 ext_columns DuckDB SQL 注入 (closes #150)
Issue #150 报告了 ext_columns 功能的 DuckDB SQL 注入, 经核查属实:
field_name 经裸双引号拼进 SQL, 攻击者可借 COPY TO 写文件 (RCE) 或
UNION 读数据。已修复, 详见 PR。
根因: 3 个 SQL sink 用未转义的 f"{field_name}", 仅 screener:147 一处
用 _quote_ident 转义; 且 parser 校验不一致 (screener 校验 config_id,
kline/watchlist 零校验)。
修复方案:
1. 新增 backend/app/db_safe.py 集中定义 quote_ident (双引号转义, 对任意
字符安全) + is_valid_ext_ident (config_id 白名单), 消除不一致根因
2. 3 个 sink 统一改用 quote_ident:
- screener.py:785 (limit_ladder)
- kline.py:376 (_attach_ext, GET /api/kline/daily)
- watchlist.py:279 (watchlist_enriched)
3. kline + watchlist parser 加 config_id 白名单 (screener 已有)
4. screener 复用共享原语, 删除私有 _quote_ident/_EXT_IDENT_RE
关键约束:
- field_name 不能加白名单: FieldDef.name 无校验 + infer_fields_from_df
直接采用原始 CSV/Parquet 列名, 合法可含中文/点。故只在 sink 转义。
- 不关闭 enable_external_access: 实测会同时禁用 read_parquet (项目核心
数据访问方式), 不可行。
对 Issue #150 报告的澄清:
- sink #2/#3/#4 (field_name 注入) 属实, 已修
- sink #1 (screener.py:343 conditions[]/order_by) 不存在, 为误报
(screener.py 无 conditions/order_by/execute 调用)
验证: 后端全量 527 passed (含新增 24 个安全测试, 含 2 个端到端注入
测试: COPY TO 不产生文件 / UNION 不泄漏数据 + 合法特殊字段名回归)
|
2026-07-31 19:56:33 +08:00 |
|