shy3130
|
e6fc60078f
|
chore(release): v0.3.21 版本号同步
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 10:39:58 +08:00 |
|
shy3130
|
2c0141f3eb
|
fix(ai): 修复 Codex 连接测试与自定义源鉴权
使用草稿模型执行连接探测,并向自定义 provider 传递其声明的鉴权环境变量。认证续期仍需单独处理。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 10:38:03 +08:00 |
|
shy3130
|
1c57c54bad
|
fix(ui): 切换 fuyao 后刷新实时行情权限
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 10:25:40 +08:00 |
|
shy3130
|
e975f78240
|
fix(ui): 同步和修复期间不再误判无数据
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 10:25:29 +08:00 |
|
shy3130
|
dd589733ec
|
fix(ui): 看板预热期不再误弹"立即获取数据"引导
v0.3.20 回归: /api/data/status 忙时降级 (977248ce) 在启动指标预热期
(indicators_ready=false, 低配机 50s+) 且 stale 缓存为空时, daily/enriched
返回 null; 看板 hasNoData 判定把 null 当 trading_days=0, 导致升级后有
数据的老用户打开客户端即被误弹"当前暂无数据/立即获取数据"卡片与欢迎
弹窗, 且 staleTime 60s 无轮询, 预热完成后提示也不会自动消失。
修复: 判定提取为 resolveHasNoData — 预热中视为"未知"而非"无数据";
预热期间每 5s 轮询 /status, 预热完成 busy 解除后自动恢复正常判定并停
轮询。老后端无 indicators_ready 字段时行为不变; 新用户引导不受影响。
验证: Dashboard.test.tsx 7 条回归 (修复前 7 failed → 修复后 passed,
覆盖预热 null/预热完成/无字段兼容/部分数据); pnpm build 通过; 全量
vitest 328 passed; 后端契约 test_data_status_busy.py 7 passed。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 09:49:20 +08:00 |
|
shy3130
|
a17742c97d
|
chore(release): v0.3.20 版本号同步 (package.json 单源派生)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-28 13:40:30 +08:00 |
|
shy3130
|
c9f4b0e351
|
fix(ui): 深色主题滚动条发白 — color-scheme 声明
声明标准 scrollbar-color 会让 WebKit 忽略 ::-webkit-scrollbar 伪样式回退
浅色默认 (WKWebView 实测), 现有伪元素方案在 Safari/WebKit 上失效。
:root/html.dark 显式声明 color-scheme: light/dark, Chromium/Firefox/WebKit
三引擎一致取深色滚动条。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-28 12:47:12 +08:00 |
|
shy3130
|
9edaac28b8
|
fix(ui): 轮动走势图线端名称 ≤10 全显, 高密模式封顶 Top10
旧防叠规则 >8 条只显最新值前 6 名, 默认「前10」下有 4 条线常年无名。改为
≤10 条全部常显 (默认行数所见即所名); 15/20 行高密模式按最新值封顶 Top10,
其余靠悬停聚焦与图例 (endLabel 无引导线, 汇聚区推离会与线端脱钩, 不宜全显)。
验证: SectorRotationCard.test 9 条全显/前20 封顶 Top10 断言; 前端 321 测试全绿。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-28 12:47:12 +08:00 |
|
shy3130
|
313be43de4
|
feat(ui): 行业分析/概念分析更名行业板块/概念板块, 财务分析→财务概况
菜单/页面标题/引导文案统一更名; 轮动图默认图表源未设置 (或旧默认值) 时回退
强弱切换而非综合分, 显式选择过的用户不受影响; 文档截图替换为新版概念板块
页面 (旧截图为过期版本)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-28 12:46:59 +08:00 |
|
shy3130
|
b6c35a9b64
|
feat(ext-data): 扩展序列粒度 auto/intraday/daily — 日级近N日序列
扩展表此前只有日内多盘一种时序形态; 无时间列的每日快照表 (板块成员/评分等)
无法画趋势。新增序列粒度:
- PullConfig.granularity 三态 (auto/intraday/daily, 默认 auto): auto 按时间列
值形态判定 — 含非零 HH:MM:SS 判 intraday, 日期形态/00:00:00/无 time_field
判 daily; 显式声明优先于判定。schema/list 透出 granularity_effective。
- series 端点日级分支: 无需 time_field, 取近 N 日分区按日聚合 (末次非空),
支持标的过滤与 chartDays; 日内分支响应带 granularity 标识。
- 前端拉取配置加「序列粒度」选择 (auto 显示判定结果), 列自定义器按 effective
粒度分流: 日内保持现状, 日级提供近N日柱/线/文本与图宽高配置。
- ExtSparkChart 修全等值退化: min===max 时归一化柱形无意义 (全负值画满格、
全正值画 1px 线), 改回退文本直显。
auto 默认与旧行为完全一致 (向后兼容); 无 time_field 不再 400 而按日级处理。
验证: test_ext_granularity 16 条 + 快照/时间列契约适配; 前端 build + 321 测试。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-28 12:46:51 +08:00 |
|
shy3130
|
81611cefac
|
feat(ui): 轮动图四项改版 — 全天时间轴/并排布局/图例换行/配色统一 (#518)
- 盘中时间轴铺全天 09:30–15:00 (桶起点逐格对齐: 上午止于 11:25、下午含 15:00, 并集兜底), 数据止于当前桶右侧留白, 一眼看进度; 1 分钟桶最近 60 列滑动窗口不铺; 两图指针联动轴窗口一致; showMaxLabel 保证 15:00 末刻度可见
- 宽屏改左右并排: 走势图 aspect 9:5 随列宽 (此前全宽 4.4:1 压扁), 右列=切换图+榜单; 右列内层 xl 下绝对定位脱离行高计算, 榜单列内滚动两列底齐; 窄屏退回堆叠
- 图例 scroll→plain + width 94% 自动换行, 不再「◀1/2▶」翻页
- 配色: 调色板去掉两组近绿/三组琥珀/蓝青近似对; colorForSector 按板块名稳定分配并缓存 — 走势线/易主圆点/切换图标注/榜单圆点四点同源, 切排序不漂; 切换图易主标注走 markPoint (强 8px/弱 5px), 函数式 formatter (字符串会让 markPoint 不渲染)
- 开局领涨也算事件点 (原从 index 1 起算, 开盘即领涨的板块整段无标记); 标签像素级 AABB 碰撞避让 (密集簇隐藏后到标签只留圆点, 最强大点优先占位); 圆点底色描边贴线可辨; 榜单未进矩阵板块给灰色占位点
- 测试 13/13 (6 新增: 刻度边界/并集/稳定配色/铺轴 null 对齐/markPoint 语义/开局事件)
|
2026-10-27 22:54:49 +08:00 |
|
shy3130
|
dc9badc2ff
|
fix(ui): AI 助手悬浮球开关跨端口持久化 — 不再「关了过一会又开」
- 根因: 开关只存 localStorage 且默认开启; 桌面版 _find_free_port 换端口即换 origin, 旧值读不到 → 闪回默认开 (uiPrefs 基建正是为此而生, 该键此前漏接)
- assistant.fab.enabled 入 uiPrefs SPECS + 后端 _UI_PREFS_KEYS 白名单 (assistant_fab_enabled), setFabVisible 走 setUiPref 本地+后端双写
- hydrateUiPrefs 改共享 Promise 的幂等实现: main.tsx 与后进的 assistant store 无论先后, await 到的都是同一次回填; 回填完成后刷新 store 内存态
- 依赖方向保持 扩展→核心, 核心零依赖扩展; 新增白名单回归测试锁住该键
|
2026-10-27 21:07:29 +08:00 |
|
shy3130
|
568a0d69ef
|
chore(release): v0.3.19 版本号同步 (package.json 单源派生)
|
2026-10-27 18:45:27 +08:00 |
|
shy3130
|
e71ca39b25
|
feat(bundle): 策略包导出/导入 — 依赖闭包一键迁移
- 导出: 策略设置「导出策略包」(.zip), 按依赖闭包打包策略源码 + 引用的自定义信号/因子定义 + 用户调参; 叠加策略递归展开子策略与 overrides
- StrategyDef 增 scoring_columns, meta.scoring / module SCORING 引用列进入闭包
- 导入: 策略池「导入策略」同时接受 .py 与 .zip; 条目路径与配置备份白名单形态一致, 复用 apply_archive 安全校验/导入即冒烟/热重载; 包外路径 400 拒绝; 缺失依赖预览黄色预警
- API: GET /api/strategies/{id}/bundle, POST /api/strategies/bundle/inspect|apply
- engine.py 同时携带 #517 的 expected_generation 读 attempts 1→2 (服务级重试见后续 fix 提交)
|
2026-10-27 18:44:51 +08:00 |
|
shy3130
|
a402b93fc8
|
feat(position): 仓位策略 — 用户自定义资金分配规则
- 新增 PositionSizingPolicy: data/user_data/position_policies/*.py, 设置→定义→仓位策略 创建 (表单 META + 只写一个 compute(ctx), 模板起步)
- ctx 只含当日及以前信息 (候选评分/近60日收益/已平仓快照/组合状态/参数), 输出 weights + budget_scale; 引擎侧单仓上限/现金/敞口钳制不变
- 保存/备份导入过 AST 安全校验 → 结构解析 → 合成冒烟 三关; 回测「买入权重→自定义策略」选用, 引用失效 400, 运行期异常当日回退等权并计入统计
- 配置备份白名单新增 position_policies 分类; 回测候选 config 字段同步
|
2026-10-27 18:44:47 +08:00 |
|
shy3130
|
b08a267a87
|
chore(release): v0.3.18 版本号对齐 release 流水线
|
2026-10-26 22:22:36 +08:00 |
|
shy3130
|
5909155fb1
|
feat(ext): 盘中多盘表增量续传 — pull.since_param 游标免全量重拉
拉取前读本地目标日分区 time_field 列最大值, 以 ?{since_param}={值} 附到
请求, 源只返回新于本地的盘次; 缺口感知天然成立 (本地缺多少源补多少)。
未配置/首拉/分区缺失/schema 漂移/文件损坏一律不带参数回退整日全量,
回退方向永远安全; 历史回补与 fanout 两级拉取不注入游标。
- PullConfig 归一: 未配置 time_field 时 since_param 失效
- 分页拉取每页携带 since 过滤器
- API since_param 参数名合法性校验
- 前端拉取面板/统计卡片与 features.md 同步
|
2026-10-26 22:10:39 +08:00 |
|
shy3130
|
5d06af60b2
|
feat(definitions): 统一定义选择器前端 + 冒烟 API 按 id 复检 + 备份导入冒烟展示
- POST /api/definitions/smoke 支持 id 直查已存定义 (smoke_stored),
统一选择器逐条冒烟无需回传原始定义; 不存在 fail-closed 404
- DefinitionPicker 可复用组件: 跨 kind 目录 (21 内置信号实测) +
kind 筛选/搜索/依赖 chips/预热/坏定义隔离展示 + 逐条冒烟
- 设置页新增「定义目录」页签; Backup 导入结果新增「导入冒烟」小节
(apply 响应 smoke 逐条渲染, 失败条目带 issue 编码)
- 验收: pnpm build 过; 浏览器 E2E 导出→覆盖导入 275 项→
冒烟 21/21 通过零 issue; 后端 36 契约测试过
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 15:54:03 +08:00 |
|
shy3130
|
2892c644f1
|
feat(backup): 配置备份与迁移 — 18 类别 ZIP 导出导入, 彻底解决多设备配置丢失
- 后端 config_backup service + /api/config-backup 三端点: 按类别导出/预览/导入
- 覆盖策略/监控/信号/因子/偏好/自选/持仓/模拟盘/挖掘候选/数据源/菜单/扩展页面/扩展数据集/语音包/历史记录
- 密钥与访问凭证默认脱敏不导出, 显式勾选才打包; 偏好/密钥 merge 写入
- ZIP 白名单路径 + 防炸弹 + 策略 AST 安全校验, 冲突默认跳过可选覆盖
- 监控徽标/导航形态/回测列表高度/设置页收起接入 uiPrefs 跨端同步
- 设置页新增「配置备份」标签页, 导出/导入向导式 UI; 16 个专项测试
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 12:13:19 +08:00 |
|
shy3130
|
b1a4dc6e38
|
chore: v0.3.17
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 09:59:09 +08:00 |
|
shy3130
|
b573ca43eb
|
feat(mining): 挖掘锁撞锁降级启动 + 持有者诊断 + 一键强制释放
复现的原始问题: 旧实例挂死在 shutdown (热重载撞上挖掘运行) 或 worker
成为孤儿后, `.mining_process.lock` 被无限期占用, 后续所有后端实例
在 lifespan 抢锁时直接启动失败, 用户只能对着笼统报错手动找进程。
- 锁文件记录持有者 {pid, started_at, role, host} (flock 仍是唯一
事实, 内容只是诊断线索; 旧格式 "0" 兼容, 视为持有者未知);
新增非阻塞探测, 无需抢锁即可判断是否被持有。
- 撞锁降级启动: lifespan 抢锁失败不再上抛, 面板照常可用; 挖掘
启动入口 (手动/自动/周度调度) 返回 409 并指引到挖掘页; 桌面版
预检从「秒退失败页」改为留日志继续启动; 守护复验不受影响。
- 挖掘页锁占用横幅: 显示持有者 pid/角色/挖掘存储静默时长; 满足
陈旧判定时可一键「强制停止并接管」(SIGTERM→SIGKILL→当前后端
获取锁, 挖掘入口立即恢复)。
- 陈旧判定全部 fail-closed: 持有者信息可读、进程存活且 pid 未被
复用 (POSIX 比对进程实际启动时间)、无进行中的挖掘运行、挖掘
存储 10 分钟内无写入 — 任一不满足即拒绝并给出原因。不做启动
时自动清理, 终止进程必须人工确认。
测试: 新增 test_mining_lock_admin (含真实外部持锁进程的强停回路与
五类拒绝路径), 重写 lifespan 降级契约与桌面预检继续启动契约;
后端全量 3239 通过, 前端 308 通过, ruff 零新增; 沙盒 E2E 完整
复刻「持锁→降级→强停→接管→恢复」事故场景通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 00:01:20 +08:00 |
|
shy3130
|
e01fe96241
|
chore: v0.3.16
本次发布包含自动策略实验室 (feat(lab): 守护复验 + 稳健选冠/权重
精调 + 组合建议 + 闭环编排), 让挖掘发布的策略在真实新数据上被
持续验证 (健康/观察/退役), 冠军按稳健分选出并做权重精调, 健康
冠军间低相关可一键生成组合策略, 实验室战报聚合守护/挖掘/名额。
版本号同源: VERSION / frontend/package.json / backend/pyproject.toml /
backend/app/__init__.py 的 _FALLBACK_VERSION / release.yml 的 inputs
默认值; uv.lock 仅改项目自身条目。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 23:43:45 +08:00 |
|
shy3130
|
21279ecfa2
|
feat(lab): 自动策略实验室 — 守护复验 + 稳健选冠/权重精调 + 组合建议 + 闭环编排
在既有挖掘链路之上补齐「发布后持续验证与持续组合」闭环
(设计: docs/auto-strategy-lab-plan.md):
- P1 策略守护: 挖掘发布自动落 mining_gate 基线 (天然 OOS); 每日收盘
数据更新后在新数据上切 K 段真实回测复验, 按稳健分对比基线判定
健康/观察/退役三态 (段回测失败只降级观察不退役; 新数据 <30 交易日
跳过本轮; retired 不再自动复验)。任意策略可手动入护 (尾随参考基线,
判定只针对入护后新数据)。回测页稳健性验证新增「策略守护」子页。
- P2a 稳健选冠: 冠军排序分从外层折 Sharpe 均值改为 0.6×中位+0.4×最差
(复用 robust_score); artifact 新增可选列 oos_worst_sharpe (v2 旧档
兼容读取); strict 档发布额外要求最差折 Sharpe>0; 算法版本升
mining-v3 并进数据指纹, 防止升级后 claim 幂等复用旧口径结果。
- P2b 权重精调: 冠军组合在 {0.5,1.0,1.5,2.0} 比率网格 (首因子固定
1.0, 截面分位打分天然尺度不变) 两段式精调 — 外层测试窗选优 + 全窗
复验退化>20% 放弃; 消耗 run 剩余预算 (不足自动跳过); 产物为独立
签名候选行, run summary 带 refinement 摘要。
- P2d 组合建议: 守护运行时扫描健康冠军间近 126 个交易日日收益 Pearson
相关性 (≥30 共同交易日, ≤0.7 入选); 前端人工确认后生成等权
composite 策略 (fail-closed 建议对校验 + blake2b 幂等) 并自动以
尾随参考基线入护。
- P3 闭环编排: lab_mined_slot_limit 偏好 (默认 10, 0=不限) 在发布
门槛通过后校验, 名额满则新冠军停在 pending 等位;
/api/backtest/lab/report 聚合守护/挖掘/名额战报 (前端总览卡);
lab_schedule 单入口编排周度挖掘 + 日度守护 (失败互不阻断)。
测试: 新增 guardian 判定/运行时/存储/调度/API/组合与挖掘 v3 选冠/
精调用例; 后端全量 3224 通过, 前端 308 通过; 真实数据沙盒 E2E
(挖掘 v3 全链路 / 发布门槛 / 名额边界 / 复验语义 / 组合扫描 /
战报核对 / 性能延迟) 通过。P2c (overlay 候选) 按设计稿按需启动,
默认不做。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 23:43:34 +08:00 |
|
shy3130
|
797f0c5f70
|
chore(frontend): 清理 klineBatchLimits 测试未用导入
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
5e2c1f76eb
|
feat(frontend): 回测页策略选择区支持拖拽调高
策略列表底部新增拖拽手柄 (指针捕获, 80-480px, 键盘上下方向键微调),
高度记忆到 localStorage, 刷新自动恢复。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
df9d178060
|
feat(assistant): 中断提示可点击重试 + 历史会话显示时间
- 生成中断后的"已中断, 可点击重试"提示此前是纯文本, 现在是可点击按钮,
点击即携带原上下文重发
- 历史会话列表每项增加时间行 (今天/昨天 HH:MM, 更早 MM-DD / YYYY-MM-DD)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
fff52f93cc
|
feat(settings): 自定义提示音语音包上传
设置页可上传/试听/删除自定义提示音 (mp3/wav/ogg 等 8 类, ≤4MB),
存储 data/sound_packs/, 键名 custom:<文件名> 复用现有 alert_sound
偏好通道, 零新配置项; 删除当前正在用的语音包时自动回退默认提示音。
后端 6 项测试 + 前端 3 项测试。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:17 +08:00 |
|
shy3130
|
da9dbca422
|
feat(backtest): 稳健参数筛选与滚动样本外检验重构 (P1-P4)
参数排名从单窗样本内得分改为 K 段折外稳健分 R = 0.6×中位 + 0.4×最差
(设计: docs/robust-optimizer-plan.md), 四阶段全部落地:
- guards 共享护栏: 主目标白名单 + 最小交易数门槛 (fail-closed, 缺交易数
按不达标处理), 两模式一处实现
- robust_optimizer: 等分切窗 (2-6 段, 每段≥14天) / 稳健分 / 冠军收敛诊断
(unanimous/majority/scattered) / Top-20 全窗 IS 细化与退化率 /
高原判据 (邻域得分衰减, 零额外回测); worker 接线 robust_optimize 任务
- 滚动样本外检验补强: 每折 OOS 最小交易数门槛 (无效折透明跳过),
前端折预览 / 参数漂移轨迹 / 采用最新折参数
- 前端: 冠军卡 (收敛/高原徽章/乐观偏差) + K 段排名表 + 验证窗预览 +
应用参数闭环 (POST /strategies/config, 可逆); SSE 重连与跨设备接回
- P4 摒弃旧路径: 删 /optimize/stream 与 /optimize/cancel 端点及 worker
optimize 任务类型; 白名单全面生效 (optimizer.VALID_OBJECTIVES 收敛到
guards; walkforward 端点校验退化目标 400)
- 附带修复: 叠加条件×矩阵路径 SignalMatrix 只读违规 (np.where 产物
可写), optimizer_trial 轻量统计恒保留 n_trades
实测: 126 组合全市场网格 1.71× 旧版耗时 (视图复用优化自 2.01×; 差额
为引擎层每 run 固定开销, 详见方案文档第九节); 全量回归 3131 通过。
api.ts 同时带入稳健优化折预览客户端与声效语音包 API 客户端
(语音包功能随后续提交落地界面)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 20:14:10 +08:00 |
|
shy3130
|
7f6cad0f8f
|
feat(factors): 因子生命周期状态下发 + 发现页三视图重构 (批量/单因子/挖掘)
- 因子注册表按 id 合并下发完整生命周期 status (draft/active/watch/retired),
registry 的 stability 降为其二元投影; asset_type 过滤适用资产
- FactorDiscovery 重构为 批量/单因子/挖掘 三视图 (MiningWorkbench),
标的列表解析兼容中英文逗号/分号/顿号/空白分隔
- FactorLibrary/FactorEditor/回测页配套调整
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:16 +08:00 |
|
shy3130
|
6c8805204e
|
feat(assistant): 动作免确认开关 + create_strategy 工具 + 毛玻璃遮罩
- 动作工具免确认开关 (助手界面, 默认关): 只影响动作确认, 轮次检查点
安全阀不受影响; 偏好读取失败一律按关闭处理
- 新增 create_strategy 动作工具: 写入 ai_ 策略草稿, 发布后才生效
- 助手打开时页面毛玻璃遮罩, 点击遮罩关闭助手 (可开关)
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:11 +08:00 |
|
shy3130
|
d43a3021da
|
feat(kline): 批量上限可配置(前后端同源) + 响应懒净化与 Polars 直出
- 日K/分时批量单请求上限改为系统设置可配 (默认 400), 后端守卫与前端分块
读同一偏好值, 不再发出必然被拒的请求; 两档独立 (分时成本约为日K 20 倍)
- _gzip_payload 懒净化: 无 NaN/inf 常态跳过 _json_safe 整树深拷贝,
峰值 -65% (40→14MB/块), CPU -25%
- minute-batch/daily-batch 全程持有 Polars 帧直出 JSON (write_json 行式),
不再构建 Python dict: 96k 根序列化 1222ms→26ms, 峰值 69→18MB;
字节级等价由 tests/test_kline_batch_frames_json.py 锁定 (含 inf/NaN/None)
- 白盒测试改为解析 Response body (HTTP 真实契约)
- 随 kline.py 同文件: minute-batch 门控在全量分钟服务健康时放行本地读,
补拉限速改走 resolve_limit (×0.8, 与盘后同步同 rpm 桶)
实测: 300 只分时(7.2万根)整请求 191ms; 20 并发尖峰 +728MB→+60MB
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-25 17:31:01 +08:00 |
|
shy3130
|
5f70eb9ef2
|
chore: v0.3.15
本次发布包含三组修复:
- fix(ext-data): 资金流等当日快照接口不再被日期一致性校验误拒写;
schema 端点恢复返回真实列类型 (DuckDB 1.5 的 DESCRIBE 列名变更);
拉取配置的分页参数不再保存后静默丢失。
- fix(settings): 系统设置的通知弹窗/声效/语音播报/外链模板/界面缩放
改后端持久化, 修复桌面版换端口 (origin 变化) 后配置丢失。
- fix(minute): 残缺分钟分区不再被当作无数据丢弃; 新增分钟缺口体检
面板, 让「同步完成≠数据完整」可见。
同时引入 DCO 贡献来源声明与再许可授权条款, PR 须逐提交带
Signed-off-by (CI 由 .github/workflows/dco.yml 检查)。
版本号同源 5 处: VERSION / frontend/package.json / backend/pyproject.toml /
backend/app/__init__.py 的 _FALLBACK_VERSION / release.yml 的 inputs 默认值;
uv.lock 仅改项目自身条目 (上次升版误改 pytesseract 的问题不再复现)。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:56:37 +08:00 |
|
shy3130
|
cce38f2ce7
|
fix(settings): 系统设置改后端持久化, 修复换端口后配置丢失
用户反馈系统设置里部分配置保存后重新打开又变回之前的状态。
根因不是保存逻辑坏了, 而是存储位置错。系统设置页有 9 项只写浏览器
localStorage: 通知弹窗开关/最大弹窗个数/声效开关/声效选择/语音播报
开关/音色/语速/个股外链模板/界面缩放。而浏览器按 origin (协议+主机+
端口) 隔离 localStorage, 桌面版启动时用 _find_free_port(3018) 从 3018
起取第一个空闲端口再以 http://127.0.0.1:{port} 打开窗口 —— 端口一变,
对这个应用就是另一个站点, 此前存的设置全部读不到。走 preferences.json
的那些设置一直正常, 所以现象是「有些配置会丢」。
修复: 后端权威副本 + localStorage 本地缓存的双写方案。
- preferences.py 新增 ui_prefs: 9 个键的白名单、只接受 JSON 标量、
null 表示删除、16KB 上限;
- 新增 PUT /api/settings/preferences/ui-prefs, GET /preferences 带上
ui_prefs;
- 新增 lib/uiPrefs.ts: setUiPref 写本地后 300ms 合并上推后端,
hydrateUiPrefs 启动时从后端回填;
- 系统设置页 7 处 localStorage 直写、外链模板、界面缩放改走 setUiPref;
- main.tsx 启动触发回填并重放一次缩放。
保留 localStorage 而非全部搬到后端, 是因为通知/语音/缩放等模块在非
React 路径 (SSE 回调、index.html 首帧脚本) 同步取值, 不能等网络。
回填规则为本地优先: 本地已有值上推后端, 不被启动时的旧副本覆盖; 只有
本地缺失的键才用后端值补 —— 升级用户首次启动即完成迁移。
验证: 端到端模拟「清空 localStorage 换端口」后重载, 三项设置在 ~330ms
内全部恢复且稳定, UI 正确反映 (弹窗数 5 / 语音开启 / 缩放 110%);
后端 test_ui_prefs 8 passed (stash 实现后 8 个全失败, 确认用例有效);
tsc --noEmit 与 pnpm build 通过; ruff 告警数与基线持平。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:41 +08:00 |
|
shy3130
|
a40c0780d7
|
fix(ext-data): 快照接口误拒写 + schema 类型丢失 + 分页配置静默丢弃
用户反馈资金流扩展表点「手动拉取」报错、板块轮动的资金流下拉为空。
排查出三个独立缺陷:
1. 日期一致性校验用错判据 (ext_pull.py)
报错: 「接口返回的日期与请求日期不一致, 已拒绝写入该分区」。
_assert_rows_date 无条件校验响应 date 必须等于请求日期, 但该契约的
目的只是防「接口忽略 ?date= 却把当日值写进历史分区」, 仅对按日查询
接口有意义。资金流/人气等当日快照接口只有最新一个交易日的数据,
周末/节假日/数据源 T+1 时响应日期本就落后于请求日期, 被误判成
「接口忽略日期参数」而整表拒写。
修复: 新增 _assert_rows_date_if_dated, 仅在 pull.date_param 已配置
时校验; 历史回补的 fail-closed 防污染契约不变。
2. schema 端点一直抛异常走兜底 (api/ext_data.py)
「SELECT column_name, data_type FROM (DESCRIBE ...)」在 DuckDB 1.5
抛 BinderException —— 该版本输出列名是 column_type (1.4 及以前才是
data_type)。异常被吞后回退到配置字段, 那些对象只有 dtype 没有 type,
前端按 type 判断数值列的资金流下拉因此永远为空。
修复: 按实际输出列名取值, 两个版本都可用; 兜底分支键名统一为 type。
同时关掉 hive 分区推断 —— date=YYYY-MM-DD 目录会让 DuckDB 凭空多出
一个 date 列, 污染列选择器。
前端 NUMERIC_TYPES 由写死的 5 个简写改为类型族匹配, 覆盖 DOUBLE /
BIGINT / DECIMAL 等 Parquet 真实类型名。
3. 分页配置保存后被静默丢弃 (api/ext_data.py)
PullConfigReq 缺少 page_param / page_size_param / page_size /
page_start / max_pages, 前端「拉取设置」提交这些值后 Pydantic 直接
忽略, 保存后再打开退回默认的单次请求, 且不报错。
修复: 补齐请求模型字段并透传到 PullConfig。
验证: 三处均先写复现用例 (未修复代码上 7 个用例失败), 修复后全绿;
扩展相关后端测试 202 passed; 前端 SectorRotationCard 7 passed;
pnpm build 通过; 真实接口验证 —— 修复前 400「日期不一致」, 修复后
200 写入 5580 行, schema-all 返回 DOUBLE/BIGINT/VARCHAR 真实类型。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:40 +08:00 |
|
shy3130
|
7812c02ec4
|
fix(minute): 残缺分钟分区不再丢弃 + 新增缺口体检面板
用户反馈自选/策略列表分时列「今天能看、昨天不能看、前天又能看」。
根因有两处:
1. /api/kline/minute 把「不完整」等同于「无数据」直接丢弃, 转而请求
分钟源; 而分钟源通常只提供最近 N 天历史, 补拉历史残缺日期恒为空,
前端白屏 —— 用户看到「同步完成却显示不出来」。
修复: 历史日期本地有行时优先返回已有行 (source=local_partial), 不再
为补不回来的缺口丢弃可用数据; 分时图顶部提示「不完整 x/240 根」并
提供「尝试补齐」。当日盘中保持原行为: 本地落后于实时源是常态, 仍走
补拉 (见 test_minute_lunch_break_still_pulls_when_morning_incomplete)。
2. 「同步完成」不等于「数据完整」, 缺口只能靠用户撞见白屏才被发现。
新增 GET /api/kline/minute-gaps 体检: 扫描本地 kline_minute 分区,
列出不完整的 (symbol, 交易日), 判定口径与 /api/kline/minute 的
is_complete 一致 (>= expected*0.9 视为完整; 当日按已开盘分钟折算,
不误报盘中进度)。只做发现不做批量补齐 —— 超出上游窗口的缺口补不
回来, 盲目重试只是白等, 面板如实标注可补/超窗。
前端: 数据页分钟K卡片新增「数据体检」区块 (MinuteGapPanel), 按交易日
汇总缺口并支持按需补拉单只。
验证: 后端 65 passed (含新增缺口扫描/当日折算/窗口外标注用例);
前端 pnpm build 通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-24 22:52:36 +08:00 |
|
shy3130
|
aa29522484
|
fix(intraday): 竞价图不再整幅铺满 + 手动刷新无分钟数据
- AuctionOnly: 无分钟K时竞价限左侧窄栏 (按宽度档, 默认 30%), 右侧留「暂无分时」占位,
不再整幅渲染竞价曲线让人误以为就是分时
- 增量 since 逐 symbol 计算并按 since 分组发请求: 块内混有未缓存 symbol 时不再被裁到 1 根
- 残序列自愈: 缓存不足 2 根时视为未缓存全量重取, 修复「1 根卡死 → 刷新永远只回 1 根」
- 测试: 逐 symbol since 拆分/残序列自愈回归 + 竞价窄栏布局断言
|
2026-10-24 17:50:53 +08:00 |
|
shy3130
|
ceb1b70a4b
|
perf(watchlist): 大列表内存优化 — 批量K线视口化+分块+缓存收敛
- 后端: minute-batch/daily-batch 单次 symbols 上限 400, 挡千只自选整表直发的服务端 dict 峰值 (test_kline_batch_symbol_cap 4 例)
- 分时批量视口化: 表格视图接入视口上报 (StockDataTable onVisibleRowsChange), 分钟数据只拉视口集合, 缓存 LRU 淘汰封顶 500 只; 列表 ≤300 只行为不变
- 请求分块: 自选/选股/中签页批量日K统一 300/块串行拉取合并 (klineBatchChunked)
- queryKey 收敛: minute-batch/kline-batch 去掉全量 symbols 拼串 (增删自选不再整批重拉/双份共存); Layout 与自选页 enriched 缓存合一
- SSE watchlist-enriched invalidate 5s 节流 (leading+trailing), 消除每秒整表重拉
- 单测 16 例新增: 分块/since 增量/LRU 淘汰/节流器
|
2026-10-24 11:28:26 +08:00 |
|
shy3130
|
13ac689427
|
feat(pages): 扩展页面新增「新建 URL 页」快捷入口 — 一键以 URL 嵌入模板打开表单
|
2026-10-23 22:27:39 +08:00 |
|
shy3130
|
14391914e3
|
feat(analysis): 轮动卡可读性优化 — 领涨易主标注/末端板块名/热力图领涨轨迹/图例条与头部分层
- 走势线: 新王接管时点圆点+板块名标注 (computeLeaderReigns, 按在位时长截断), 线末端常显板块名 (shiftY 防叠)
- 热力图: 配色两端饱和+可见中性色, 领涨轨迹亮琥珀描边+辉光, 未封口列白描边, 格间细缝
- 三图段落说明改为真实色块图例条; 头部拆分 标题/状态 行与数据塑形工具行, 显示模式改胶囊分段
- x 轴刻度 hideOverlap+间隔放宽, 修复末尾刻度与强制最大刻度叠字
- 新增 SectorRotationCard.test.tsx (纯函数+渲染断言 6 例)
|
2026-10-23 15:03:10 +08:00 |
|
shy3130
|
a747d1f615
|
chore: v0.3.14
|
2026-10-23 11:37:41 +08:00 |
|
shy3130
|
b0022a088b
|
chore: v0.3.13
|
2026-10-22 22:24:11 +08:00 |
|
shy3130
|
74e3934495
|
wip(list-columns): 列配置底座 + 默认方案快照 + series-identity (自 stash 恢复)
自已删除的 feat/list-column-config 分支 WIP 暂存恢复 (stash 曾是唯一副本):
列自定义面板底座扩展、默认列方案快照、series-identity 稳定键。
验证: vitest 278 passed (另 2 个失败文件为存量空占位), tsc -b 通过。
|
2026-10-22 22:13:33 +08:00 |
|
shy3130
|
01257c83ee
|
feat(pages): 设置三页合一为「页面管理」+ 源码扩展删除/URL 嵌入页/源码导入
- 菜单设置/扩展页面/页面插件三个设置 tab 合并为「页面管理」(?tab=pages, 旧链接与 /analysis 重定向兼容)
- 源码扩展页(frontend/src/custom/<ns>/)支持界面内物理删除: 先自动备份 zip 到 data/backups/pages/(可下载)再删目录, 命名校验+防穿越, 产物部署无源码树 409
- 扩展页面新增 URL 嵌入模板: 仅填菜单名+网址生成 iframe 内嵌页, 复用看板外链安全约定(仅 http(s)/拒同源/sandbox 白名单/新窗口兜底)
- 页面插件新增源码导入: 上传 .tsx 或从本项目 custom/ 选择, 后端用自带 esbuild 编译+契约适配(component→mount, 独立 react 实例自挂 Provider/Router, 图标映射白名单), 产物即标准页面插件; 无工具链部署 409
|
2026-10-22 17:47:59 +08:00 |
|
shy3130
|
b3dc03707d
|
fix(settings): 语音音色下拉选中后被「默认偏好」吞掉
「默认偏好」选项的 value 动态绑定 getCurrentVoiceURI(), 而它的解析优先级是
用户手选 > 默认偏好 —— 手选音色 X 后该选项 value 变成 X 的 voiceURI, 同时
filter 又把 X 从列表移除。受控 select 匹配到 value 相同的「默认偏好」,
回显立即弹回默认项; 再点「默认偏好」拿到的也是 X 的 URI, 被当成长选存回,
从此无法恢复默认。
修复: 「默认偏好」用固定空值 value=""(与 onChange 既有的空串=清空手选约定
对齐), 列表不再过滤, 下拉值直接用 voiceConfigured 状态, 移除派生的
voiceURI 状态。播放侧 resolveVoice 逻辑不变。
|
2026-10-22 10:34:18 +08:00 |
|
shy3130
|
463729ea5e
|
chore: v0.3.12
|
2026-10-21 21:07:35 +08:00 |
|
shy3130
|
78d8d54282
|
feat(recap): 复盘系统提示词支持自定义配置
复盘页「定时」弹窗新增提示词编辑区块: 完整系统提示词可编辑,
支持填入默认模板/恢复默认; 偏好键 market_recap_system_prompt 持久化,
空值回退内置默认模板, 超 32k 字符拒绝。自定义后不再跟随版本默认模板更新。
|
2026-10-21 18:05:36 +08:00 |
|
shy3130
|
59e2772f51
|
chore: v0.3.11
|
2026-10-21 09:07:40 +08:00 |
|
shy3130
|
5d44b2af23
|
chore: v0.3.10
|
2026-10-20 16:22:39 +08:00 |
|
shy3130
|
aca12675e6
|
feat(screener): 分时列新增成交量带、集合竞价叠加与涨跌停纵轴
分时缩略图此前只有价格线, 无法看出量能结构, 也看不到集合竞价情况。
- 成交量带: 底部量柱, 按列配置开启; 与价格共用时间轴
- 集合竞价叠加: 左侧窄栏画竞价价格/匹配量/未匹配量, 三项取自同一张时序
扩展表 (跨表拼接会对不齐时间网格); 支持窄/标准/宽三档宽度并持久化
- 纵轴模式: adaptive(实际价格区间) / limit(按涨跌停带), 策略页与自选页
各自持久化; 涨跌停幅度按板块推导 (主板 10%, 创业板/科创板 20%, 北交所
30%), ETF/指数不套用
- 策略页与自选页共用 same-origin 的 intraday-auction 数据加载与列配置,
避免两处各写一套
验证: 新增 54 条前端测试 (竞价窄栏 25 / 涨跌停 5 / 成交量带 9 / 列配置
15); pnpm build 通过。
|
2026-10-20 16:16:38 +08:00 |
|
shy3130
|
5f6444277d
|
fix(screener): 列表涨跌幅改用实时行情, 与个股详情对齐
策略结果缓存只记录「计算那一刻」的价格。盘中跑完 run_all 后, 列表里的
close/change_pct 会一直停在那时, 而点开个股详情走的是实时 enriched 缓存,
同一只票在两处显示不同涨幅。实测 002543.SZ: 13:27 扫描时 2.49%, 收盘
4.48%, 缓存里 279 行中有 271 行与实时值不一致。
后端:
- /api/screener/cached 与 /cached-result 返回前, 用当前实时快照覆盖纯展示
字段 (open/high/low/close/prev_close/volume/amount/change_pct/
change_amount/turnover_rate/raw_*/quote_ts)
- 指标与信号列 (ma20/score/signal_* 等) 保持计算时点值: 用新价格重算会让
「为什么入选」不可解释
- 仅覆盖同日结果 (优先结果级 as_of, 行级 date 兜底), 历史回看不被今日行情
污染; 实时缓存为空时原样返回, 不伪造价格
- 覆盖只发生在响应层, 不写回 strategy_cache.json (写回会让 mtime 指纹失效,
等于每轮触发一次全量重读)
前端:
- 明细查询在交易时段 6s 重取、收盘后 60s 兜底, 让覆盖真正反映到页面
验证: 新增 4 条回归 (实时覆盖生效且指标保留/历史日期不覆盖/实时缓存空时
不变/cached-result 同口径); 后端全量 2926 passed; pnpm build 通过;
运行实例上两接口均返回实时价, 缓存文件仍保存原值。
|
2026-10-20 16:06:43 +08:00 |
|