Commit Graph
15 Commits
Author SHA1 Message Date
shy3130 f1b41ca342 fix(financials): 全部同步改后台异步,修复点击无反应
根因:sync 路由同步阻塞调用 run_now(),全量同步 4 表 × 5500 标的需 ~2 分钟,
HTTP 请求长时间 pending 被浏览器/代理超时掐断,UI 表现为点击无反应。

后端:
- 抽出 _run_body() 同步逻辑本体;新增 trigger() 在后台线程执行,
  并在持锁状态下立即置 _is_syncing=True(消除竞态窗口 + 防重复点击启动多线程)
- sync 路由改调 trigger(),立即返回 {started: bool},前端轮询 /status.syncing 看进度

前端:
- api.ts financialSync 返回类型改为 {started; reason?}
- Financials.tsx 同步状态以 status.syncing 为真值、isPending 兜底乐观态;
  收尾时机改为监听 syncing 变 false(不再依赖瞬间触发的 onSettled);
  被防并发跳过时弹 toast 提示
2026-06-25 15:53:31 +08:00
shy3130 37ebe19f1e refactor(ai): 配置页单列卡片重构 + 移除无用的 Token 预算
- AI 设置页改为单列分卡片布局(Card/Field/Toggle 辅助组件),自定义配置卡
  头部标注「Chat Completions」
- 移除从未实际生效的 ai_daily_token_budget(后端 config/api/settings +
  前端 Settings 接口与保存参数 + UI)
- 测试结果不再展示 token 消耗,仅显示「连通成功 · 模型: xxx」
2026-06-25 15:53:15 +08:00
wshy 7c81a03026 feat(ai): 可配置 User-Agent 绕过 Cloudflare 等 CDN 拦截 (fix #8) (#10)
问题(Issue #8): AI API 反代到 Cloudflare 后,OpenAI SDK 默认 UA
(OpenAI/Python) 被 Bot Fight Mode 拦截,报 'Your request was blocked'。

方案: 后端始终发送浏览器风格 UA,默认内置 Chrome UA(开箱即用);
AI 设置页提供开关 + 随机生成/手动粘贴的自定义 UA。

后端(config.py / settings.py / ai_generator.py / strategy.py):
- 新增 ai_user_agent 配置项,默认桌面 Chrome UA
- 两处 OpenAI client 创建均注入 default_headers={User-Agent}
  (ai_generator 实际生成 + strategy 测试连通性)
- 空 UA 自动回退内置默认,保证默认状态即绕过拦截

前端(api.ts / AI.tsx):
- 自定义 UA 开关:默认关闭(用内置默认),开启才显示输入框
- 随机生成按钮: 产出近期 Chrome 桌面 UA(Win/Mac/Linux 随机)
- 已有自定义 UA 时开关默认开启

不影响直连官方 OpenAI/DeepSeek 的用户(官方不校验 UA)。
2026-06-25 10:49:10 +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 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 7042aca968 fix(ext-data): 上传 CSV 时自动转码 GBK/GB18030,修复 invalid utf-8 sequence
国内行情软件(同花顺/东财/通达信)及 Windows 中文 Excel 导出的 CSV 多为
GBK 系编码,而 Polars read_csv 默认按 UTF-8 解析,遇中文即抛
'invalid utf-8 sequence'。

新增 ensure_utf8_csv():先尝试 UTF-8(合法则原样返回,零副作用),
否则依次尝试 gb18030/gbk/gb2312/big5 转成 UTF-8 临时文件再交给 Polars。
覆盖上传(upload_data)与字段探测(detect_fields、parse_upload_file)三处入口,
无需新增依赖(编码均为 Python 标准库内置)。
2026-06-24 12:05:04 +08:00
shy3130 41be5096dc feat: 桌面客户端打包 (pywebview + PyInstaller) + 系统通知
- 桌面入口: desktop.py (单实例锁 + 端口探测 + uvicorn + pywebview 窗口)
- 配置层: config.py 加 sys.frozen 检测, frozen 下 data_dir 指向用户目录
- 系统通知: notify_adapter.py 三平台 (Win winotify / mac osascript / Linux notify-send)
  接入 quote_service 告警出口, preferences 开关控制, 前端监控设置加 toggle
- 前端: 监控设置加系统通知开关, 系统设置加检查更新入口
- 打包: packaging/tickflow.spec (onedir, collect-all 原生库, 排除 vectorbt)
- CI: .github/workflows/release.yml 手动触发 + 平台可选 (windows/macos/linux)
- 依赖: platformdirs/winotify/plyer 入主依赖, pywebview 入 desktop extras
- README 加桌面客户端下载章节
- bump 版本号到 0.1.33
2026-06-23 21:47:29 +08:00
shy3130 3bedd3e209 fix(limit-ladder): 五档修正后实时刷新连板梯队封单 + 组内按封单排序
问题: 开启「修正」后后台 depth 轮询持续更新封单缓存, 但页面封单/个数不实时
变化。根因是 depth 轮询 (depth_service._poll_loop) 与行情 SSE 刷新是两条
断开链路 — depth 修正后不广播任何事件, 前端刷新完全依赖 quotes_updated
(仅行情轮询发送), 封单数据延迟或读旧值。

修复: 新增独立的 depth_updated SSE 通道。depth 轮询每次 _fetch_and_seal
成功后经 quote_service.notify_depth_updated 触发信号, intraday SSE
event_generator 并行等待三类信号 (行情/告警/修正), 推送 depth_updated;
前端 useQuoteStream 监听后 invalidate limit-ladder + overview-market。
该通道不受实时行情开关限制 (修正轮询独立于行情轮询)。

另: 连板梯队组内排序增强 — 涨停/跌停状态股票按封单从高到低排
(vol/amount 跟随 sealMode), 封单为 null 排末尾, 其他状态不动。
2026-06-23 14:00:29 +08:00
shy3130 3e79f94da8 feat(backtest): 拆分建仓/清仓成交口径并修复退出优先级
成交口径: 单个 matching 拆成 entry_fill/exit_fill, 各自可选 close_t/open_t+1,
默认建仓次日开盘、清仓当日收盘 (最贴近真实交易)。老 matching 参数经
__post_init__ 自动映射为 entry=exit=matching, 完全向后兼容。

退出优先级修复: max_hold 不再抢占卖点信号 (signal 提到 max_hold 之前);
统一为 风控(止损/移动止损/止盈) → signal → max_hold → end, 删除 close/open
模式下风控调用顺序的差异, open_t+1 下到期仓位也能正确触发止损。

新增 3 个测试: signal 优先于 max_hold / open 模式到期触发止损 / 默认口径
买次日开盘卖收盘。现有 13 个测试经兼容映射后行为不变, 全部通过。
2026-06-23 14:00:09 +08:00
shy3130 70e17a9fb5 优化策略监控与 AI 生成流程
- 策略监控从全市场信号扫描改为选股池变更对比(进入/移出)
- 触发记录/看板/弹窗三处统一策略通知格式
- AI 策略模板去掉硬编码信号/止损/评分,补全数据字典
- 创建策略对话框改为 AI生成/自定义编写 双 Tab
- 自定义 Tab 含文件路径说明+模板代码一键复制
2026-06-22 17:42:04 +08:00
shy3130 b5780b5e30 feat: 统一监控引擎 + AlertToast通知 + 声音/角标/看板/Dev页 + 股票名称批量查询
监控引擎 (backend):
- MonitorRuleEngine 统一规则引擎,支持策略/信号/价格/行情四种类型
- JSONL 追加存储 (alert_store.py),支持分页 + 清理
- alert/monitor_rules CRUD API + seed 演示数据
- POST /api/kline/instruments/names 批量股票名称查询
- SSE strategy_alert 事件触发前端通知

前端通知体系:
- AlertToast 自定义弹窗 (Framer Motion + AnimatePresence)
- Web Audio API 合成音效 (12种预设,无需音频文件)
- 侧边栏角标 (monitorBadge.ts) localStorage 持久化未读数
- pendingSeen 机制解决 markSeen/setCurrentTotal 竞态
- 系统设置页: 通知开关 + 最大条数 + 音效选择
- 菜单设置页: 角标数字开关

监控中心 (Monitor.tsx):
- 双栏布局: 左侧实时告警列表 + 右侧规则管理
- RulesList 股票代码后显示中文名称
- RuleEditor 完整规则编辑器组件
- 告警支持查看详情 (StockPreviewDialog)

Dashboard:
- MonitorWidget: Top 10 实时告警卡片

Dev 页面:
- 一键填充演示告警 + 规则 + 分钟探测
- 可视化 SSE 事件流查看

其他:
- v0.1.19 → v0.1.28 (VERSION 从 pyproject.toml 读取)
- dev.ps1/dev.sh 添加 --host 0.0.0.0 (局域网访问)
- 修复 Screener.tsx presets.length 可选链
- README 截图表格更新 (6张) + 监控章节重写
- 删除 MinuteDataProbe 页面 (合并至 Dev)
2026-06-21 14:18:08 +08:00
shy3130 358c04e916 feat: 个股日K信息条支持自定义指标(扩展数据/财务/单独显示)
- 信息条(StockInfoBar)行末加配置齿轮,复用自选列表抽屉自定义显示项
- 新增指标: 成交量/振幅/开高低 + 扩展数据(ext) + 财务(EPS/BPS/ROE/PE/PB等)
- 后端 klineDaily 新增 ext_columns 参数,按 symbol JOIN 扩展数据
- 财务数据前端直拉 useFinancialMetrics, PE/PB 用现价现算
- 每列可设单独显示(standalone),独占一行渲染
- ext 标签支持 maxTags 截断 + 点击 +N 同页展开/收起
- 修复重开弹窗信息条消失(symbol 重置与子组件 onDataChange 竞态)
- 修复 ext 勾选不显示(query key 未含 extColumns 导致缓存命中)
- 配置按钮左侧加监控通知图标占位(BellRing)
- ListColumnCustomizer 新增 showExtColumns/showStandaloneToggle prop
2026-06-20 14:42:54 +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