Commit Graph
16 Commits
Author SHA1 Message Date
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
shy3130 1cb19872db feat: 增加自选列表分时小图 2026-07-06 11:10:36 +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
wshyandshy3130 a23be3822a chore: add cache startup diagnostics (#49)
Co-authored-by: shy3130 <shy3130@users.noreply.github.com>
2026-07-04 18:42:49 +08:00
wshyandshy3130 57f417e6eb fix(sync): 修复同步卡死在26%及启动期视图注册崩溃 (#47) (#48)
三处根因:

1. 限流逻辑失效 (kline_sync.py ×3, index_sync.py ×2)
   条件 `len(chunks) > rpm` 在 free 档恒为 False (56 chunks < 60 rpm),
   导致节流 sleep 永不执行, 请求密集打出触发服务端限流 → 卡死。
   改为始终按 interval (60/rpm) 节流。

2. 卡死看门狗无法自愈 (pipeline_jobs.py, api/pipeline.py)
   原超时检查只在再次点「同步」时触发, 等待中永不回收。
   抽出 JobStore.reap_stale() (STALE_JOB_TIMEOUT_S=600), 在
   /run 和 /jobs/{id} 轮询端点都调用 — 前端每秒轮询, 10分钟后
   必定自动回收卡死 job, UI 不再永久停在 26%。

3. 启动期视图注册异常捕获不足 (repository.py)
   _register_views 只捕获 duckdb.IOException, 跨版本/平台空目录
   可能抛 CatalogException 等炸掉 lifespan。放宽到 Exception。

Co-authored-by: shy3130 <shy3130@users.noreply.github.com>
2026-07-04 15:53:50 +08:00
Gundy a05927baf2 fix(repo): parquet 原子写入 + 分区读-改-写加锁
- 所有分区写入改为「写 .tmp → rename 替换」: 直接 write_parquet
  到最终路径, 进程被 kill (dev.sh 清端口用 kill -9) 或断电时会留下
  半截文件, 之后 scan_parquet glob 整条读链路报错。.tmp 后缀不匹配
  *.parquet glob, 不会被扫描误读。
- merge/flush/_write_daily_partition 加 _write_lock 序列化:
  实时轮询线程、手动 refresh、盘后管道并发对同一分区做读-改-写
  会互相覆盖丢数据。
2026-07-03 14:11:26 +08:00
shy3130 ce5c705ab4 fix: 跨日后连板梯队整体少算一档
根因: live_agg 缓存的昨日连板数 (_prev_consec_up/down) 跨日不失效,
盘中增量计算永远基于前天基准, 导致次日开盘连板数整体 -1。

- get_live_agg() 加跨日失效守卫: date.today() 变化时按需重建
  (fast-path 仅比较 today ~0.24ms/次, 跨日当天一次性磁盘校验)
- cron 盘后管道补 refresh_cache(), 与手动触发 /api/pipeline/run 对齐
  (此前 cron 路径漏了这步, 盘后落盘的新 enriched 不反映到内存缓存)
2026-07-01 11:19:32 +08:00
shy3130 8a8cd746dc feat: — 数据目录/实时监控/定时复盘/老CPU兼容
1. 桌面客户端体验优化,Polars 兼容内核 (老 CPU 兼容)
2. 自选页实时监控优化
3. 个股监控逻辑优化
4. 新增定时复盘
6. 其他: 修复 settings.py 中 HTTPException 未 import 的既有 bug
2026-06-28 18:08:52 +08:00
shy3130 2acaa38a2b feat: release v0.1.60 2026-06-27 23:23:34 +08:00
shy3130 37f4d61e3a fix(backend): 清除数据彻底清空三层内存缓存 + 监控触发记录 + 修复版本号
修复清除数据后看板/监控仍显示旧数据的根因:

数据缓存清理 (repository/screener/overview):
- repository.py: 新增 clear_cache() 无条件清空全部 Polars 内存缓存;
  修复 _refresh_enriched() 磁盘无数据时不清内存导致旧数据残留的 bug
- screener.py: 新增 clear_history_cache() 清进程级 _history_cache (TTL 缓存)
- overview.py: 新增 invalidate_overview_cache() 清看板聚合结果 5s TTL 缓存

清除数据完整性 (data.py):
- clear_data 删除 parquet 后统一调用三层缓存清理
- 新增清除监控运行数据: alert_store.clear() 清 alerts.jsonl + _pending_alerts 内存队列
  (原 clear_data 漏删 user_data/alerts.jsonl, 导致触发记录清不掉)

版本号统一:
- /api/data/version 改为优先读 app.__version__ (与 /health 同源),
  原 pyproject.toml 路径解析有误读不到, 回退到陈旧的 VERSION 文件
- Windows GBK 编码修复: __init__.py 强制 stdout/stderr UTF-8,
  避免 TickFlow SDK 输出含 emoji 的指数名称时崩溃 (gbk codec can't encode)
2026-06-24 23:24:04 +08:00
shy3130 5c492c1825 fix(tier): 乱填 key 误判为 free 档 —— 探测改走付费端点验证 key
根因(鸡生蛋蛋生鸡的循环依赖):
  保存乱填 key 后 detect_capabilities → get_client() 读旧 capabilities.json
  (此时还是 none 档)→ _should_use_free_server() 返回 True → 用
  TickFlow.free() 探测 → free 服务器忽略 key, 日K成功 → 误判为 free 档。

修复:
  _probe_real 改用探测专用客户端, 强制走付费端点(api.tickflow.org)验证
  key 有效性, 不再依赖运行时的 get_client()(受旧缓存档位影响)。
  乱填 key 在付费端点全部 AuthenticationError → 正确判定 none 档 + invalid。

版本: 0.1.37
2026-06-24 17:58:56 +08:00
shy3130 755c114390 feat(tier): API 检测重构为 5 档,新增「无」档 + 修复 CapabilityDenied 返回 500
检测逻辑(复权因子分水岭):
- 无 key / 乱填(连单只日K都拿不到) → none 档,不存 key,走 free-api 服务器
- 免费有效 key(有日K无复权) → free 档,存 key,走 free-api 服务器
- 付费 key(有复权) → starter/pro/expert,走 api.tickflow.org

主要改动:
- save_tickflow_key 改为先探后存:无效 key 不持久化,前端提示「Key 无效」
- none/free 档统一走 TickFlow.free(),实时行情开关置灰
- tiers.yaml 新增 none 档,free 档补 kline.daily.batch
- 注册 CapabilityDenied 全局 handler → 403(此前返 500)
- /health mode 三态化,watchlist 无行情能力时提前 return
- 看板页 none 档显示黄色升级提示(含邀请码超链接)

版本: 0.1.36
2026-06-24 17:44:58 +08:00
shy3130 d89b9068a7 feat: 五档盘口真假涨停修正 + 连板梯队涨跌停切换 + 自动版本管理
连板梯队:
- 新增涨停/跌停方向切换(胶囊式, 涨停红/跌停绿)
- 跌停侧三状态: 跌停/翘板/止跌(对称涨停侧)
- 涨跌停双计数 + 真假板修正/降级标识(问号弹窗)

五档盘口 sealed(真假涨停):
- depth_service 独立旁路线(只读enriched, 不动计算逻辑)
- 涨跌停一体(一次depth.batch双向覆盖)
- 假涨停归炸板/假跌停归翘板, 真封板显示封单量
- 三层防护节流(套餐clamp+限速clamp+接管通知)
- Pro/Expert盘中轮询 + 盘后定版job + 启动补跑
- 收盘job可配置(15:01~18:00, 默认15:02)
- 设置页'连板梯队降级修正'卡片(开关+配置+立即修正)
- 看板页同步应用sealed修正+降级标识

配置/SDK:
- tiers.yaml拆分depth5/depth5.batch, 补全quote.batch
- tickflow SDK升级0.1.21→0.1.23(depth.batch可用)
- 实时行情轮询间隔下限调整(pro 2s/expert 1s)
- capabilities缓存schema版本化(v3)

其他:
- 档位配色抽共享组件TierTag/tierStyle
- Keys页档位问号弹窗(4档位tag+检测说明)
- git hooks自动版本号+0.0.1+打tag
2026-06-19 20:09:09 +08:00
shy3130 a5a04b4dd8 fix: 端点套餐门控/探测重试/分钟K月单位 + 财务页新功能 + localStorage 残留自愈
## Bug 修复
- 端点测速:Expert+ 用户现可选用专线端点(premium),非 Expert 仍锁定(EndpointTestDialog)
- 能力探测:try_call 对瞬时错误(429/5xx/超时)重试,避免抖动误丢 capability(导致"需 Free"误导徽章)
- 数据画像 CapBadge:tierReq='Free' 时不显示无意义的"需 Free"徽章
- 财务同步:用服务端 is_syncing 标志驱动 UI,刷新后仍正确显示"同步中",防重复点击 + 进度提示

## 新功能
- 财务页重设计:中间模糊搜索框(代码/名称),选股后展示 4 标签页详情
  (核心指标/利润表/资负表/现金流),字段格式化(百分点/金额转亿/每股)
- 分钟K向前扩展:Expert+ 新增「月」单位(1~6 月,180 天),Pro 仍只「天」(15 天)

## localStorage 残留自愈(拉新代码后不再显示本地开发残留)
- 策略池:加载后自动清除失效的自定义策略 ID
- 回测页:校验 selectedStrategy 是否存在,失效则重置;result 不跨会话恢复

## 重构
- 提取共享 tier 工具到 capability-labels.ts(TIER_RANK/isExpertOrAbove)
2026-06-19 00:10:01 +08:00
shy3130 7369358d08 Initial release v0.1.19 2026-06-18 17:18:23 +08:00