shy3130
|
aea694ee83
|
fix(strategy): keep AI-generated strategies in AI pool
|
2026-07-08 18:38:14 +08:00 |
|
wshy
|
cf53953c8d
|
fix(realtime): ensure final quote sync and badge init (#79)
|
2026-07-08 18:18:55 +08:00 |
|
 Jinfeng SunandClaude Opus 4.8
|
9aa96edbd7
|
改进: 并发韧性 + 数据性能 + 死代码清理 + 前端 UX + ST/Sharpe 修复 (#78)
* fix(concurrency): 共享缓存/任务表加锁, 全局限速, depth 原子写, 认证热路径缓存
修复多线程下的竞态与阻塞:
- overview/strategy_cache/PanelCache/StrategyMonitor._watching 四处共享状态加锁,
消除 "dict/OrderedDict mutated" 与丢更新/半写读取
- strategy_cache/depth parquet 改临时文件 + os.replace 原子写
- rate_limits 改进程级共享时间轴限速, 并发同步不再聚合超过单能力 rpm;
scheduler 令牌账目与 sleep 分离, sleep 不再独占锁串行化其他请求
- auth.is_configured() 内存缓存, 认证中间件不再每请求读盘阻塞事件循环
- api/backtest 任务清理/取消全程持 _jobs_lock, 并用 Semaphore(2) 限并发重回测
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* perf(data): limit_ladder 去 N+1 全市场重算, 指标裁剪, factor 向量化
- limit_ladder 前一日 consecutive 改窄读单日 parquet 存储列 (谓词/投影下推),
替代 range(1,10) 逐日 _load_enriched_for_date 全市场指标重算 (最坏 9x)
- compute_indicators 新增可选 needed 裁剪 (默认 None 行为逐位不变, 已对照验证),
factor 只算所需因子列
- factor._calc_period_return 用 Polars join 替代 Python 逐行 price_map 循环,
_add_groups 去 map_elements 改纯表达式 (输出逐位一致)
- screener ext value_map 按 parquet mtime 记忆化, 免每请求磁盘重读
(DuckDB 过滤仍用隔离 :memory: 连接, 不扩大注入面)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(backend): 报表存储去重, 删死代码, DuckDB 视图重建收敛, 管道失败如实标记
- 三份近乎逐字复制的 *_reports.py 收敛到共享 JsonReportStore (原子写 + 锁),
各模块公有 API/id 格式/上限/落盘 schema 完全保持不变
- 删除 ext_pull.py 中字节相同的死 _run_loop (Python 只绑第二个) 及无用 import
- 13 张 DuckDB 视图重建收敛为唯一权威 repository.rebuild_views(),
daily_pipeline 与 /api/data/clear 改为调用 (修好 clear 路径漏挂视图的漂移)
- daily_pipeline 累积 stage_errors 并在末尾抛出, 部分失败不再误报成功;
free/None 模式的能力门控跳过不计入失败
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(frontend): SSE 连接态, 路由代码分割, 查询失效修复, 三态与无障碍
- 实时行情 SSE: 连接态 store + 指数退避 + 断线徽标/toast (避免静默丢告警);
回测 SSE 断线有界重连 + 可重试, 不再永久卡住进度条
- router 全部 React.lazy + Suspense, vite manualChunks 拆图表库
(echarts 变独立 1MB 懒加载 chunk, 首屏包显著减小)
- 修 Data 清库后其它页显示旧数据 (改回广域失效); 修 Watchlist kline 失效键
永不匹配; query key 收敛到 QK 工厂 (新增 strategyDetail)
- Monitor/Analysis/StockAnalysis/ExtPages/CustomSignals 补 loading 门控与
error/empty 三态区分
- 新增共享 Modal 原语 (焦点陷阱/ESC/焦点还原/aria), 改造 3 个高频弹窗;
Toast/AlertToast 加 aria-live 与键盘可达; Watchlist/LimitUpLadder 卡片 memo
修复本轮 review 发现的缺陷:
- Modal 焦点 effect 依赖 onClose 致每次输入抢焦点 → 改 ref 只装一次
- StrategySettingsDialog 删除确认框被 Modal 面板裁剪 → 移出作兄弟节点
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(quant): 修正 ST 板块限价套错 与 因子 Sharpe 年化频率
两个不报错但会算错数的领域 bug:
1. ST 5% 涨跌停限幅被无条件套到创业板/科创板 ST 股:
注册制改革后 创业板(300/301)、科创板(688/689) 的风险警示股仍执行 20%,
北交所 30%, 只有主板 ST 才是 5%。原代码 _is_st 先判且覆盖板块限幅, 导致
创业板/科创板 ST 的涨停价按 5% 计算 → +5% 被误报涨停、真 +20% 涨停被漏报,
污染 signal_limit_up / consecutive_limit_ups / 连板梯队 / near_limit_up。
修正: ST 5% 仅在 ~(创业板|科创板|北交所) 时生效 (EOD + 盘中两条路径 + near_limit_up)。
2. 因子回测 Sharpe 一律乘 √252, 但 group_nav 每点是一个调仓周期收益:
月频调仓下是月收益, 乘 √252 会把 Sharpe 高估 √(252/12) ≈ 4.6x (周频 ≈2.2x),
使无效因子显示成明星因子, 废掉"先筛无效指标"的用途。
修正: 年化系数按 config.rebalance 取 √252/√52/√12。
新增 tests/test_st_limit_and_sharpe.py (5 例) 覆盖两处修正。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-08 18:10:19 +08:00 |
|
wshy
|
f0a082b01a
|
chore: 数据获取耗时诊断日志 + 指数卡片涨跌着色 (#76)
* chore(diag): 数据获取全链路加分段耗时日志, 定位 WSL 卡死
用户反馈 WSL 下数据获取超时 800s 疑似卡死。在三个可能卡住的环节
加轻量诊断日志(不改业务逻辑), 复现一次即可从日志定位根因:
- policy.py: 能力探测每个 cap 的开始/完成/耗时/结果 + 探测总耗时
(启动期 13 次串行探测是首要嫌疑)
- client.py: 3 个 SDK 客户端创建时记录端点 + 标注 SDK 默认超时
(timeout=30s, max_retries=3, 单次最坏 127s)
- quote_service.py: 全市场行情/核心指数拉取的条数 + 耗时
- bridge.py: stock-sdk 桥接 subprocess 的 op + 耗时 + 超时上下文
* style(sidebar): 指数卡片价格按涨跌着色, 与涨跌幅同色
|
2026-07-08 15:15:30 +08:00 |
|
wshy
|
8e56f3efb8
|
feat(monitor): 推送渠道拆分为飞书/企业微信独立勾选 (#74)
把监控推送从单一总开关 webhook_enabled(bool)升级为渠道数组
webhook_channels(list),飞书与企业微信各自独立勾选,做到「勾哪个
推哪个」。沿用项目已有的 review_push_channels 渠道数组模式。
后端:
- RuleModel 新增 webhook_channels 字段;normalize() 兼容老规则,
webhook_enabled=True 自动迁移为 ['feishu','wecom']
- _maybe_send_webhook 按 channels 判断:'feishu' in channels 才推
飞书,'wecom' in channels 才推企业微信
- 新增偏好 webhook_default_channels + PUT 接口;老 webhook_enabled_default
保留兼容
前端:
- RuleEditor 飞书/企业微信勾选各自绑数组 includes/toggle
- 设置页推送通知卡片飞书/企业微信默认勾选独立
- 连板梯队封单弹窗「飞书」单胶囊改为飞书+企业微信双胶囊
- api.ts 类型 + updateWebhookDefaultChannels
|
2026-07-08 13:48:22 +08:00 |
|
 Jinfeng SunandClaude Opus 4.8
|
e5a94c42d5
|
feat: ETF 支持(选股 / 回测 / 监控) (#61)
* feat(screener): 选股引擎支持 ETF
- 12 个内置策略打 asset_types 白名单 + strategy_supports_asset;涨停类
(连板/断板反包)仅股票,其余 10 个技术类对 ETF 开放
- ScreenerService(repo, asset_type) 分流取数,ETF 复用 kline_etf_enriched,
跳过股票专用历史缓存与涨停信号;进程级 _history_cache key 含 asset_type
- API /run、/run_preset 透传 asset_type;/strategies 按资产过滤;
股票专有策略在 ETF 下返回空
- 新增 enriched_dirname(asset_type) 共享 helper;get_enriched_latest_asset
增 refresh 参数(供轮询线程避免冷缓存同步重算)
- 前端「策略」页加 股票/ETF 切换,ETF 走实时单跑(空日期→用 ETF 自身最新日);
QK.screenerStrategies 按 asset_type keyed
- 测试:test_screener_etf.py
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(backtest): 回测支持 ETF(个股/因子/策略组合)
- 三条回测路径 + 共用 BacktestEngine 面板加载按 asset_type 路由到
kline_etf_enriched(复用 enriched_dirname);PanelCache key 隔离资产;
ETF 跳过股票专用 get_enriched_range 缓存
- 面板 compute_all/名称 JOIN 按 asset_type 取维表(get_instruments_asset),
修复 ETF 策略回测用错股票维表致名称为空/涨停信号算错
- BacktestConfig/FactorConfig/StrategyBacktestConfig 增 asset_type
- 三个回测 API + SSE stream 透传 asset_type;_make_job_key 纳入 asset_type
(修复 stream 与 cancel job_key 不对齐致取消失效的回归)
- 前端策略组合页/因子页加 股票/ETF 切换,标的搜索与策略列表跟随资产;
assetType 持久化
- 测试:test_backtest_etf.py(含 job_key 一致性回归);既有回测测试替身同步
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(monitor): 监控规则支持 ETF
- engine.evaluate(df, asset_type) 按规则 asset_type 分轮评估;quote_service
增开 ETF 评估轮(用 ETF enriched 快照),股票轮不受影响、不重置其策略结果
- ETF 评估轮独立 try(异常不丢弃已算出的股票告警)+ refresh=False(不在轮询
线程触发 ETF 冷缓存同步重算)
- ETF 版历史加载器(main.py 注入)+ 按规则 asset_type 选加载器
- _strategy_pools 按 (sid, asset_type) 键,避免同策略股票/ETF 规则互相覆盖
- name_map 仅在有 ETF 规则时补 ETF 维表, setdefault 保股票名优先
- RuleModel/normalize 增 asset_type(默认 stock,持久化往返)
- 前端 RuleEditor 加 股票/ETF 选择,策略列表与标的搜索跟随资产
- 测试:test_monitor_etf.py
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(etf): 前端 API 绑定透传 asset_type + 文档
- api.ts: screener/backtest 绑定加 assetType 参数,MonitorRule 类型加 asset_type
- docs/features.md: 标注选股/回测/监控的 ETF 支持范围与前提
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(reliability): 管道并发/原子写/能力探测/监控告警多处加固
后端可靠性专项修复(均带回归测试, backend 全套 64 passed):
并发与数据完整性:
- 盘后管道单飞: JobStore.create() 去重纳入 pending∨running, 关闭"两次快速点击"
并发双跑窗口; 新增 _heavy_run_lock 执行槽挡住 reap 后僵尸线程并发写 parquet
- adj_factor/minute 全部改走原子写(tmp+replace), 消除 kill/断电致 all.parquet 损坏
- 分块拉取失败聚合 WARNING 可见化(不再静默当成功); 复权失败标的会保持旧价已提示
能力探测:
- 周期重探(60min)热更新 app.state.capabilities, 付费 Key 过期/续费无需重启即可见
- 瞬时探测失败(超时/连接/5xx, 按 _is_transient 判定)不降级、保留旧付费档;
真 401/无权限仍正常降级回落 free-api
监控告警:
- 评估仅在连续竞价(9:30-11:30/13:00-15:00)+ 快照当日新鲜度下进行, 避开集合竞价/
收盘后陈旧价与节假日误告警
- scope=sector fail-closed(validate 拒绝新建 + _apply_scope 返回空), 修复板块规则
对全市场刷屏
- 飞书 webhook 加退避重试并移到独立线程池 fire-and-forget, 不再阻塞行情轮询线程
单标的新鲜度: 新增 repo.symbols_lagging() 检测掉队标的并 WARNING + 计入 job 结果
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-08 12:12:29 +08:00 |
|
Lytem
|
9c730e4b69
|
fix: 修复因子回测分层错误问题 (#63)
* fix: force LF for uv.lock
* Fix factor backtest grouping stability
|
2026-07-08 12:11:03 +08:00 |
|
im47cn
|
3a5f3e05b6
|
feat(backtest): 稳健性指标 Sortino + 蒙特卡罗回撤分位 + per-trade 明细 (#67)
* feat(backtest): 新增稳健性指标 Sortino + 蒙特卡罗回撤分位 + per-trade 明细
回测原本只有 Sharpe/Calmar/最大回撤, 缺防过拟合视角。本 PR 补三类:
1. Sortino 比率: 用下行偏差 (MAR=0 目标半方差) 替代总标准差, 只惩罚负
收益波动。无亏损时约定返回 None (不虚报 0/inf)。各 stats 函数用与自身
Sharpe 相同的收益基准 (逐笔 or 日频)。
2. 蒙特卡罗最大回撤分位: 对逐笔收益有放回重抽样 1000 次, 估计回撤分布,
报 P50(中位) 与 P95(95% 置信最坏)。回答"仅因成交顺序运气回撤能有多坏",
单次样本内回撤看不到这个。固定种子 (42) 保证可复现/可测。
3. per-trade 明细: best/worst/median_pnl/avg_holding_days, 补 _calc_stats
与 _calc_portfolio_stats 原本缺失的逐笔视角。
三个 stats 函数 (_calc_stats / _calc_independent_candidate_result /
_calc_portfolio_stats) 全部接入, 用共享静态 helper (_sortino_ratio /
_mc_drawdown_percentiles / _per_trade_block) 避免重复。纯 additive, 既有
字段不变, 空交易安全。
前端 StrategyBacktest 结果区新增 索提诺 / 蒙卡回撤(中位) / 蒙卡回撤(95%最坏)
三个指标卡 (stats 为 Record<string,any>, 无需改类型)。
新增 tests/backtest/test_robustness_metrics.py 11 用例: Sortino 手算校验/
无下行 None/优于 Sharpe/样本不足; 蒙卡确定性/P95≤P50≤0/全正零回撤/样本不足;
_calc_stats 与 portfolio 字段集成 + 空交易安全。
注: upstream main 既有 test_trailing_take_profit_exits_after_activation
失败与本 PR 无关 (改动前后一致复现)。
* test+fix(backtest): 子代理审查修复 — 补 full 主路径覆盖 + finite 护栏 + 内存上限
子代理审查发现的缺口, 本次补全:
覆盖 (测试):
- [关键] full 模式主路径 _calc_independent_candidate_result 原无集成测试,
漏拼 sortino/mc 字典展开会导致前端指标卡空值却测试全绿。新增该分支断言。
- MC 确定性测试从"两次相等"升级为钉死快照值 (p50=-0.0976/p95=-0.2108),
一旦有人把种子改成系统熵立即红。
- p95 断言从恒真的 p95<=p50 (percentile 单调性数学恒成立, 无信息) 改为
p50<0 且 p95<p95 严格更差, 真正验证数值。
- 补全盈利交易 → sortino 集成层为 None 的用例 (原仅 helper 层覆盖)。
健壮性 (实现):
- 三个 helper 入口 finite 过滤: inf/nan 收益会让 cumprod 传播 nan → 分位 nan
→ asdict 直出非法 JSON (项目 _safe 只洗 rows 不洗 stats)。剔除后与纯净输入
结果一致 (加测试守护)。
- MC 内存护栏: full 模式可数千笔, n_sims×n×8B×4 数组瞬时可达数百 MB。
按 2M 单元上限压降模拟次数 (小样本 n_sims=1000 不变, 快照稳定)。
注: 逐笔年化口径 (_calc_stats 对 pnls ×√252) 落在死路径 simulate() (无 app
调用方) 且复刻既有 Sharpe, 不在本 PR 范围。两条活路径 (portfolio/independent)
均用日频基准, ×√252 正确。
|
2026-07-08 12:10:05 +08:00 |
|
wshy
|
3820b35921
|
fix(watchlist): 自选页 enriched 改为 LEFT JOIN, 修复不在缓存 universe 的自选股被静默丢弃 (#70)
后端 watchlist_enriched 原以 enriched 缓存为主表执行 inner filter
(df_e.filter(is_in(stock_symbols))), 方向反了: 不在缓存 universe 里的自选
标的 (新股/冷门股/新用户未同步) 被整行丢弃. 改为以自选列表为主表 LEFT JOIN
enriched, 缺失标的指标为 null, 前端已有 '—' 占位渲染兜底. ETF 分支同理.
前端 Watchlist 顶部胶囊区原 hiddenCount = allSymbols - sortedRows, 把 '数据
未返回' 误算为 '被筛选隐藏'. 拆分为两个口径:
- hiddenCount: rows.length - sortedRows.length (真正被筛选条件隐藏)
- pendingCount: sortedRows 中 close 为 null 的行数 (指标未就绪)
并新增 '待数据 N' 灰色提示与原 '已过滤 N' 区分.
新增 4 个回归测试覆盖核心契约.
|
2026-07-08 11:06:56 +08:00 |
|
wshy
|
5b2282f8cb
|
feat(ext-data): 新增扩展数据支持 URL 创建并调整设置弹窗 tab (#64)
- 新建扩展数据弹窗加入 URL/文件/手动 三种接入方式, URL 模式支持探测字段、预览、保存拉取配置并可选立即导入或定时拉取
- 后端新增 /api/ext-data/detect-url 探测接口, 自动识别 JSON 行数组路径、字段类型与 symbol/code 候选列
- 抽出 infer_fields_from_df / detect_symbol_candidates / apply_config_mapping 公共逻辑, 文件上传与 URL 探测复用
- 拉取写入支持仅含 code 的数据, 按 code_map 自动生成标准 symbol
- 设置弹窗 tab 顺序调整为 拉取/推送/上传, 默认显示拉取
|
2026-07-07 18:04:49 +08:00 |
|
shy3130
|
f8914c9140
|
feat: 新增企业微信推送、个股分析页重构、价位算法优化及多处交互改进 (v0.1.82)
- 推送: 新增企业微信群机器人通道(与飞书并列), 监控告警/复盘报告多渠道分发
- 个股分析: 历史报告改为右侧常驻栏(展示全部股票报告), 进页面自动恢复上次选股
- 价位算法: 成交密集区改用换手率衰减模型(国内主流筹码分布); 缺口回补判定修正(必须完全穿越缺口)
- 回测: 回撤止盈改纯峰值口径(与 trailing_stop 一致); 佣金/印花税/滑点合并一行; 建仓口径加问号气泡说明
- 分时图: 自选列表迷你分时图加渐变填充(对齐个股对话框风格)
- 图表: 个股分析日K图右侧标签适配浅色主题; 价位标签与下方文字行双向 hover 高亮联动
|
2026-07-07 17:56:25 +08:00 |
|
shy3130
|
9b22030166
|
fix: 数据源切换按 datasets 动态分流, 修复切换到 stock-sdk 后分钟K仍走 tickflow
- DataSources.tsx switchProvider 非 tickflow 分支原只传 4 个字段(漏 minute_data_provider),
后端 exclude_none 保留旧值导致 minute 永远停在 tickflow。改为按源声明的 datasets
动态构建: 支持的数据集切到该源, 不支持的显式写 tickflow(消除 UI/后台不一致)
- README License 段补充 stock-sdk (ISC) 协议声明
|
2026-07-07 12:39:23 +08:00 |
|
shy3130
|
fb7cf921a9
|
feat: 看板刷新按钮改为后端缓存重载
原「刷新」只重新请求前端数据(overview.refetch), 不动后端缓存, 跨天
残留时拿到的是旧数据。改为「重载」:
- 新增 POST /api/data/refresh-cache 端点: clear_cache + refresh_cache
重建 enriched 内存缓存, 同时清 overview 聚合缓存 + screener TTL 缓存
- 看板按钮先调后端重建缓存, 再刷新看板数据
- 与设置页「清理并刷新」(清前端 react-query)互补, 这个重建后端 Polars 缓存
|
2026-07-07 11:43:39 +08:00 |
|
shy3130
|
9f78fdebd4
|
style: 主题切换只保留图标, 与设置同行
左侧菜单底部: 主题切换(纯图标)+ 设置同一行排列, 更紧凑。
原来上下两行各占满宽, 现在左边小图标按钮 + 右边设置占满剩余空间。
|
2026-07-06 17:45:25 +08:00 |
|
shy3130
|
9ef9b4e6ec
|
chore: bump to 0.1.81
|
2026-07-06 17:42:19 +08:00 |
|
Aliang
|
7627df9b60
|
fix(stock-analysis): 修复带鱼屏布局留白
|
2026-07-06 17:30:09 +08:00 |
|
 Jinfeng SunandClaude Fable 5
|
b0d1f2f742
|
feat: 自选/个股分析/K线查询接入 ETF (#58)
* feat: 自选/个股分析/K线查询接入 ETF
数据层此前已完成 ETF 同步与存储 (instruments_etf / kline_etf_* /
adj_factor_etf), 但查询侧仍只走股票路径。本次把已有的 ETF 读取能力
接到面向用户的接口上:
- repository: 新增 get_etf_symbol_set / resolve_asset_type 按 symbol
判定资产类型; get_minute / get_minute_batch / latest_minute_date
增加 asset_type 参数切换 ETF 分钟K存储
- kline API: instruments/search 增加 asset_types 参数 (默认 stock,
既有调用方行为不变), 结果附 asset_type; instruments/names 合并
ETF 名称; /daily /minute /minute-batch 按资产类型分流
- watchlist API: /enriched 合并 ETF enriched 缓存行, 名称补齐支持 ETF
- 个股分析: /levels 与 AI 分析按资产类型分流, ETF 无财务数据走
已有兜底提示
- 前端: 自选搜索框传 asset_types=stock,etf 并显示 ETF 标记
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: 修复 ETF 接入的审查发现问题
多智能体代码审查确认的 9 处问题修复:
- watchlist /enriched: 仅自选实际含 ETF 时才加载 ETF enriched 缓存,
避免无 ETF 用户在缓存冷启动时触发全量懒加载阻塞请求; 恢复股票
enriched 预热期间 all-or-nothing 旧契约 (不再返回只有 ETF 的部分结果);
as_of 取股票/ETF 两类缓存中较旧者, 不再把旧 ETF 行标成股票缓存日期
- repository: refresh_cache 失效 _etf_enriched_cache, 盘后管道跑完
ETF 行不再停留在旧日期; get_etf_symbol_set / get_index_symbol_set
增加 memo (随 instruments 缓存失效), 热路径不再每请求重建全量集合;
新增 get_name_map 统一股票+ETF 名称解析, 收敛三处重复合并逻辑
- kline /daily: 实时蜡烛注入改为资产感知, ETF 开启实时拉取时同样
注入今日 bar (未开启时由"非今日不注入"守卫自然跳过)
- kline search: 空关键词早退提前到数据处理之前; symbol 列 dtype
归一到 Utf8, 防两份缓存来源 dtype 不一致导致 concat SchemaError
已知限制 (不在本次范围): kline_etf_minute 目前无盘后同步写入方,
ETF 分时依赖"本地缺失 → TickFlow 实时补拉"路径, 与其他未同步分钟K
标的行为一致。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-06 17:26:40 +08:00 |
|
Aliang
|
bb562cbdff
|
feat(ai): 更新炸鸡中转站 API 地址
|
2026-07-06 17:18:09 +08:00 |
|
shy3130
|
966d94ab03
|
feat: 数据源插件化架构 + stock-sdk 首个插件
将可选数据源改为插件化架构: 插件代码放 backend/app/plugins/<name>/,
用户在设置页点击安装依赖, 主仓库不背运行时依赖(nodejs 等)。
架构:
- loader.py 新增 _load_builtin_plugins() 扫描 plugins/ 目录, 通过
plugin.yaml 清单动态发现并注册插件(委托自检 + 优雅降级)
- runtime 字段支持 node/python, 安装/卸载分别用 npm/pip
- 现有 tickflow + YAML 自定义源逻辑 100% 保留, 插件是叠加层
stock-sdk 插件 (plugins/stocksdk/):
- 原始实现来自 @forrany 的 PR #57, 迁移到插件化架构, 署名保留
- Node 桥接 (bridge.py/mjs) + Python provider, 覆盖日K/除权/分钟/实时
- 设置页主列表直接显示: 未装灰显+安装按钮, 装完可切换/卸载
配套:
- instrument_sync: 通用增强, 任何 provider 都能提供标的维表
- install/uninstall: uv 优先回退 pip, 容错坏 uv.toml + 国内镜像
- 10 例单测全过, tsc 零错误
|
2026-07-06 17:00:56 +08:00 |
|
shy3130
|
cc697e8ea4
|
fix: 分时图跟随实时行情自动轮询
实时行情开启后(realtimeRunning), 自选列表分时图自动按 15s 轮询刷新,
无需用户单独开启 minute_intraday_refresh 开关。
|
2026-07-06 17:00:55 +08:00 |
|
shy3130
|
1cb19872db
|
feat: 增加自选列表分时小图
|
2026-07-06 11:10:36 +08:00 |
|
weikejia
|
a86da75eff
|
feat: 看板涨幅榜/跌幅榜/成交额榜/活跃榜/领涨领跌概念个股可点击查看弹窗
|
2026-07-06 10:39:18 +08:00 |
|
lytem28
|
3ac35a816a
|
feat: make builtin strategy filters configurable
|
2026-07-06 10:26:16 +08:00 |
|
shy3130
|
f7b56ec3c8
|
docs: 自定义数据源新增 AI 映射 prompt 模板
|
2026-07-05 23:16:18 +08:00 |
|
shy3130
|
fa08981851
|
feat: 自定义数据源扩展 + 限频集中化 (v0.1.80)
|
2026-07-05 22:57:46 +08:00 |
|
 wshyandshy3130
|
e524ea4893
|
perf: 指标计算移出启动关键路径, 后台异步预热 (#51)
启动时 instruments/index/ETF 同步刷新(<0.1s), enriched 的 compute_indicators
(107万行, 低配Linux 50s+) 推 daemon 线程异步完成。应用秒级 ready, 前端不再
报 ECONNREFUSED。预热期间上层走空表降级, 完成后自动替换缓存。
- repository: _enriched_warming 标志 + warmup 线程 + 懒加载守卫
- main: refresh_cache(background=True) + app.state.indicators_ready
- data API: status 端点加 indicators_ready 字段
- 前端: Data 页指标计算中提示 + 加快轮询
Closes #47
Co-authored-by: shy3130 <shy3130@users.noreply.github.com>
|
2026-07-04 21:55:03 +08:00 |
|
im47cn
|
1fd7e84785
|
feat(backtest): 成本模型拆分为佣金+印花税(仅卖出)+滑点 (#46)
* feat(backtest): 成本模型拆分为佣金+印花税(仅卖出)+滑点
MatcherConfig 新增 commission_pct/stamp_tax_pct 及 buy_cost_pct()/
sell_cost_pct() 方法, 撮合三处现场统一改用方法计算。
印花税单边(仅卖出)是 A 股与美股的本质差异: 旧的 fees_pct 双边模型
把印花税摊到买卖两腿, 会高估买入成本、低估卖出成本。拆分后买入腿=
佣金+滑点, 卖出腿=佣金+印花税+滑点。
commission_pct 未设时回退 fees_pct, 印花税未设时为 0, 完全向后兼容,
既有 12 个 portfolio 测试不变。strategy/api(含 SSE + 缓存键)全链透传。
新增 tests/backtest/test_cost_model.py 覆盖向后兼容/拆分/印花税仅卖出/
优先级/撮合传导 5 个用例。
* fix(backtest): 打通成本模型前端链路并修复 cancel 缓存键
子代理审查发现 PR3 半成品缺陷, 本次补全:
C1 (正确性): /strategy/cancel 的 _make_job_key 漏传 commission_pct/
stamp_tax_pct, 一旦用户设成本参数, cancel 算出的 job_key 与 stream 失配
导致取消静默失败。补 None-aware 解析对齐两侧口径。
C2 (完整性): 前端 SSE/sync 链未透传新字段, 新成本模型从 UI 够不到。
- backtestTask.ts / api.ts: 类型 + query 透传 commission_pct/stamp_tax_pct
- StrategyBacktest.tsx: 佣金映射到 commission_pct, 新增印花税(千分之)输入,
默认 1 (A股千1), 映射 stamp_tax_pct; 状态持久化
- storage.ts: stampTax 类型声明
测试加固:
- test_stamp_tax_only_deducts_on_sell_leg: 去掉硬编码 shares=9900,
改为断言两次运行 shares 相等 (守护买入腿 sizing 不受卖出成本污染)
+ 从结果反推卖出市值校验差额
- 新增 commission_pct=0.0 非 None 边界 (防 falsy 回退)
- 新增 job_key 区分成本参数的回归测试 (守护 C1)
后端 26 测试全绿; 前端 tsc 仅剩既有 baseUrl deprecation (非本次引入)。
|
2026-07-03 23:15:32 +08:00 |
|
shy3130
|
60dec142ea
|
Merge PR #45: feat 亮色主题 — 明暗切换 + 全部图表主题化
|
2026-07-03 14:12:13 +08:00 |
|
Gundy
|
1d8b93cc42
|
fix: 一批低危问题修复
- alert_store: 删除 delete_one 里不可达的 return count 死代码;
list_recent/count 持锁读, 防与 prune/clear 整文件重写并发读到截断内容
- ai_generator: import 校验从黑名单改为白名单 (仅 polars/__future__),
黑名单挡不住 ctypes/importlib/builtins/pickle 等未列出模块;
_extract_meta 改用 ast.literal_eval 替代 compile+eval
- frontend api.ts: request() 合并调用方 headers (此前被整体覆盖丢弃)
- VERSION 同步至 v0.1.70 (与 pyproject/package.json 一致)
|
2026-07-03 14:11:27 +08:00 |
|
Gundy
|
2cbcd53538
|
fix(theme): 连板梯队亮色可读性 — 卡片股票名与概念/行业标签
用户反馈亮色下连板梯队看不清, 根因是三处按暗底设计的写死颜色:
- 卡片股票名 text-rose-50/text-green-50 (近白) → 亮色深酒红/深绿
(text-rose-900/emerald-900 + dark: 变体保持原暗色效果)
- 顶部概念/行业标签云: 亮黄[250,204,21]/亮蓝[96,165,250]文字元组
按暗底设计 → TagStats 增加 textLight 深色阶 (黄700/蓝700),
选中态亮色下不再用白字 (黄底白字不可读), 底色透明度同步调淡
- 梯队分组内的概念/行业小标签: 同样的黄/蓝 rgba 硬编码, 同方案修复
实测: 亮色下股票名/代码/标签全部清晰, 暗色截图对比无回归
|
2026-07-03 13:51:36 +08:00 |
|
Gundy
|
abd17f53ca
|
fix(theme): 亮色模式实测修正 — 看板雷达图/近白文字/图例颜色
用浏览器实测双主题后的修正:
- 看板情绪雷达 (SVG): 网格/中心渐变/描边从写死的深 slate 色改为
hsl(var(--surface/elevated/border)) CSS 变量, 亮暗自动切换
(亮色下原来是一块突兀的深色六边形)
- 回测统计卡: 中性值文字写死近白色 #f8fafc → inherit (亮色下不可见)
- ExtDimensionAnalysis 装饰图形 white/xx → foreground/xx
- 情绪页图表: 折线补 itemStyle, 图例色块与线色一致
(原用 ECharts 默认调色板, 与线对不上, 双主题都存在的旧瑕疵)
实测覆盖: 看板/个股分析(K线)/市场情绪 亮暗双向切换 + 刷新持久化
(预渲染脚本生效, body 背景 #FAFAFA), 暗色无回归
|
2026-07-03 13:51:36 +08:00 |
|
Gundy
|
8abf7e338a
|
feat(theme): 亮色主题基础设施 + 全部图表主题化
- lib/theme.ts: localStorage 持久化 + useTheme hook (本页/跨标签页
同步) + ChartTheme 图表调色板 (ECharts/lightweight-charts 画布
不吃 CSS 变量, 统一从这里取色)
- index.html: 去掉写死的 class=dark, 换预渲染内联脚本 (默认暗色,
切过亮色则保持), 避免首屏闪烁
- Layout: 侧边栏底部亮/暗切换按钮 (设置入口上方)
- 图表主题化 (切换即时生效, 无需刷新):
· EChartsIntraday / EChartsCandlestick / CandlestickChart
(lightweight-charts applyOptions) / AnalysisKChart
· 回测 4 图 (StrategyNav/FactorIC/FactorGroupNav/ReturnDistribution)
· Sentiment 页双图
序列颜色 (红涨绿跌/MA线) 双主题通用保持不变; 轴/网格/十字线/
tooltip/信息栏背景按主题切换
CSS 变量亮色板 index.css 里本就有 (:root), 首次真正启用
|
2026-07-03 13:51:17 +08:00 |
|
shy3130
|
574b163cb3
|
docs: README 与首次引导页增加"非 TickFlow 官方项目"声明
- README 顶部加醒目声明 badge(红+绿)+ 声明正文,功能介绍改为按页面分组的清单
- Onboarding 引导页新增 Step 0"使用前请知悉"声明步骤(个人开源/与官方无关/盈亏自负/不建议商用),原 4 步顺延为 5 步
|
2026-07-03 13:31:40 +08:00 |
|
shy3130
|
7c51bf5054
|
refactor(docs): 策略提示词文档统一归入 prompts/,docs/ 专放使用指南
将 4 个策略运行时文档(strategy-guide/step1/step2/example)从 docs/
迁至 backend/app/strategy/prompts/,与运行时加载路径一致;docs/
回归「项目使用指南与配置说明」定位。
- prompts/ 现自包含 4 个 md,guide 内对 example 的相对链接可正确解析
- 更新 README 与前端 StrategyBuilderDialog 的引用路径
- docs/ 保留 deploy-password.md / screenshots / zhihu 等面向人类的文档
承接 #41 Docker 文档缺失修复
|
2026-07-03 11:03:24 +08:00 |
|
shy3130
|
c7ad860dba
|
fix: 修复自定义策略删除导致策略池清空及删除失败静默问题
- bug2(删除后策略全没): prune 仅在拉取成功且非空时执行,加载中/失败/空列表不碰池
根因: 删除触发 engine.reload() 重扫所有文件,任一文件 import 失败被静默跳过,
前端拿到残缺列表后 prune 把池中有效 ID 永久清除并写 localStorage
- bug1(自定义策略删不掉): handleDelete 不再静默吞错误,失败时显式提示并保持弹窗打开
- ai_save 守卫回归: 放宽前缀允许 ai_/custom_,保留 path traversal 字符白名单(安全核心未动)
修复「AI 修改 custom 策略」因 strategy_id 非 ai_ 前缀被 400 拒绝
- 引擎加载失败可见化: _load_all 收集 load_errors,/api/screener/strategies 返回,
前端 toast 提示具体失败文件,不再静默消失
- 同步补全 ai_generator _SYSTEM_PREFIX 三条铁律(与 bbc92c4 docs 一致)
|
2026-07-02 22:19:46 +08:00 |
|
shy3130
|
d4dcbb1797
|
chore: 版本号升至 0.1.70
|
2026-07-02 17:45:30 +08:00 |
|
shy3130
|
e283d487ce
|
feat: Free 档实时行情监控限制提示
实时行情开关区新增 Free 档限制提示「监控自选股前 5 只,
全市场监控需 Starter+」,位于交易时段状态上方,可手动关闭
(不持久化,刷新后恢复显示)。
|
2026-07-02 17:40:41 +08:00 |
|
shy3130
|
fca0e261db
|
feat: 系统工具页新增封单监控触发验证
- 新增封单监控 tab: 模拟触发 (纯条件判断) 与真实触发 (落盘+推送)
供验证规则是否生效
- 页面标题与文案中性化, 避免暴露内部调试性质
|
2026-07-02 17:22:52 +08:00 |
|
shy3130
|
33a7be0deb
|
feat: 连板梯队封单监控卡片 UI 与 API
- monitor_rules API: RuleModel 加 metric/threshold 字段; ladder 类型
需 DEPTH5_BATCH 能力校验; 加模拟触发与真实触发端点供验证
- 连板梯队卡片: 右上角监控按钮 + 设置菜单 (段控指标/阈值+单位/
胶囊推送/权限提示); 开启监控的卡片置顶 + 背景区分
- 推送默认取全局设置; 单位默认万手/亿元
- 非付费用户可见功能入口但保存禁用, 提示后续适配免费数据源
|
2026-07-02 17:22:42 +08:00 |
|
shy3130
|
255688fab4
|
feat: 概念涨幅轮动 AI 分析
- 新增 concept_rotation_analyzer: 从涨幅排名矩阵预计算轮动信号
(主线/新晋/退潮/机构vs游资), 结合大盘背景生成分析报告
- rps API 加 /rotation-analyze 流式端点 (NDJSON)
- 轮动对话框: AI 占位替换为流式 Markdown 报告区 + 自动滚动
- 删除搜索框, 新增选中概念排名行 (前10红/后10绿)
|
2026-07-02 17:22:16 +08:00 |
|
shy3130
|
c394a365e1
|
revert: 撤回连板梯队 queryKey 扁平化修复
撤回 e7615fb 中 [...QK.limitLadder(...)] 改写, 恢复为 [QK.limitLadder(...)]
嵌套写法。
|
2026-07-02 12:28:16 +08:00 |
|
shy3130
|
e7615fb9e6
|
fix: 扩展数据拉取修复与连板梯队queryKey修复
|
2026-07-01 23:02:37 +08:00 |
|
shy3130
|
5a9fa9b255
|
feat: 概念涨幅RPS轮动分析
|
2026-07-01 17:48:28 +08:00 |
|
shy3130
|
14070c24b3
|
fix: 切页时 onboarding 守卫整屏 logo 闪烁
后台重取 (isFetching) 期间本地已有 stale 缓存可展示, 无需整屏占位。
仅首次加载 (isLoading) 才显示占位, 消除切页 logo 闪烁。
|
2026-06-30 22:36:07 +08:00 |
|
shy3130
|
e4f0a95ca2
|
fix: 升级 Expert Key 后财务页「全部同步」无反应
启动时无 FINANCIAL 能力导致调度器 _capset 为 None, 后续在设置页更新 Key
时 app.state.capabilities 已刷新但调度器未同步, trigger() 仍报
no FINANCIAL capability 而拒绝同步。新增 update_capabilities 并在设置 API
刷新能力时同步推给调度器; 前端对 started:false 一律给出提示, 不再静默。
|
2026-06-30 22:30:52 +08:00 |
|
shy3130
|
68841af662
|
feat: 定时复盘飞书推送 + SSE 实时进度
- 定时复盘支持推送到飞书(卡片消息, 完整报告), 渠道多选(飞书可选, 微信开发中)
- 推送开关独立常驻, 与定时/实时行情解耦; 手动/定时生成都可推送
- 定时复盘改流式生成, 通过 SSE(review_progress)实时推给前端, 开着页面可见边生成边显示
- 修复定时任务协程未 await 的 bug(lambda 包裹 async → 改传函数对象 + args)
- LLM 断流自动重试(最多2次), 后端归档 + 飞书推送, 异常兜底通知前端
- 复盘定时下限改为 15:00, 默认 15:10
- 版本号 0.1.66 → 0.1.67
|
2026-06-30 17:28:18 +08:00 |
|
wshy
|
35b20d6317
|
Merge pull request #32 from lzwaang/feature/codex-cli-ai-provider
Add Codex CLI AI provider
|
2026-06-30 10:17:06 +08:00 |
|
Lzwaang
|
2d86dea721
|
Avoid copying Codex env file
|
2026-06-29 22:53:36 +08:00 |
|
shy3130
|
b315e531df
|
feat: 回测页加预热期说明徽标与滑点配置
- 回测区间旁加「预热≥120天」徽标,点击弹泡说明开头无交易原因
- 佣金旁新增滑点(万分之)输入,持久化并接入回测请求
- Auth 设密码页加访问密码部署文档链接
|
2026-06-29 22:45:16 +08:00 |
|
Lzwaang
|
ec6380376d
|
Add Codex CLI AI provider
|
2026-06-29 22:32:58 +08:00 |
|