Commit Graph
99 Commits
Author SHA1 Message Date
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
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 6a74fa9963 fix(desktop): 修复 console=False 下 exe 打不开
PyInstaller windowed 启动器 (runw.exe, console=False) 不分配控制台,
sys.stdout/stderr 为 None。desktop.py / main.py 的 logging.basicConfig
默认建 StreamHandler(sys.stderr), stderr 为 None 时首次写日志调用
None.write() 抛 AttributeError, 崩在导入早期, 进程被 OS 直接终止,
try/except 都拦不住 → 用户看到「双击一闪退出、查无日志」。

修复:
1. _guard_streams() - 启动最早期把缺失的 stdout/stderr 换成丢弃写入的
   _NullStream, 让 logging/reconfigure/print 全部安全落地 (windowed 标准修法)
2. _setup_logging() - 追加 FileHandler 到 data/desktop.log, console=False
   下不再吞日志, 事后可查
3. _run_uvmicorn() - except Exception 捕获后端导入/运行崩溃并写 traceback,
   不再静默死亡 (主线程只报「超时」却查无原因)
4. main() - except Exception 顶层兜底: 崩溃时 logger.exception + 弹原生
   MessageBox 显示完整堆栈, 让用户能截图反馈

验证: console=False 包本地能正常打开 (修复前打不开)
2026-07-03 22:02: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 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
Gundy 9452351edb fix(sse): 每个 SSE 连接独立订阅者队列, 修复多客户端告警丢失
此前行情/告警/五档/复盘四通道共用服务级 Event + pending 列表,
pop 是「取走」语义: 开多个标签页或设备时, 告警只会被先醒来的那条
连接消费, 其余连接永远收不到; 共享 Event 的 clear/wait 也存在互相
吞信号的竞态。

- 新增 QuoteSubscriber: 每连接独立 Event + 队列, 生产侧广播
- /api/intraday/stream 改为 subscribe → wait/pop → finally
  unsubscribe, 单事件等待替代原先每轮 4 个 to_thread 任务
  (被 cancel 的 to_thread 线程实际仍在跑, 多客户端会耗尽线程池)
- 背压上限不变 (告警 1000 / 复盘 200, 每订阅者独立)
2026-07-03 14:11:26 +08:00
Gundy 4e332c42a6 fix(monitor): 规则表并发迭代加快照, 防评估线程与 API 线程竞态
evaluate()/has_rule_type() 跑在行情轮询线程, 直接迭代 self._rules
时若 API 线程并发 add_rule/remove_rule 会抛 RuntimeError
(dictionary changed size during iteration), 该轮全部告警被上层
except 吞掉静默丢失。统一 list() 快照后迭代; set_rules 改为构建
完整 dict 后原子替换, 避免读到半装载状态; remove_rule 重建
_last_fire 同理。
2026-07-03 14:11:26 +08:00
Gundy 3f17e58908 fix(quotes): change_pct fallback 统一小数制; enable() 补返回值; 拉取加锁
- change_pct: API ext 缺失时的 fallback 原先乘 100 (百分制), 与
  ext.change_pct 的小数制 (0.0366=3.66%) 及 enriched 全项目约定
  (pipeline.py 小数制) 相差 100 倍, 会导致策略过滤大面积误命中、
  监控消息显示 366% 之类的异常值。两处 fallback 去掉 *100。
- enable(): docstring 承诺返回 bool, 成功路径此前隐式返回 None,
  补 return True。
- _fetch_quotes: 加 _fetch_lock 串行化, 防手动 POST /refresh 与
  后台轮询线程并发写同一批 parquet/缓存互相覆盖。
2026-07-03 14:11:26 +08:00
Gundy ad83a5f960 fix(realtime): 交易时段判断与落盘日期显式使用北京时间
quote_service/depth_service 的 _is_trading_hours 原用 naive
datetime.now() 取服务器本地时间; Docker 镜像 (python:slim) 默认
UTC, 北京 9:15-15:05 = UTC 1:15-7:05, 轮询窗口完全错开——Docker
部署的实时行情/五档监控在真实交易时段一次都不会跑。

- 新增 app/market_time.py: CN_TZ 固定 UTC+8 (A股无夏令时,
  不依赖系统 tzdata, Windows 桌面版同样可用)
- 两个服务的 _is_trading_hours / date.today() 全部切换
- monitor.py 的 as_of 日期同步对齐
- Dockerfile 加 ENV TZ=Asia/Shanghai 兜底 (日志时间戳)
2026-07-03 14:11:26 +08:00
Gundy 3d4d20de3b fix(auth): 仅在直连 peer 为内网时信任 X-Forwarded-For, 防伪造绕过认证
公网请求带 X-Forwarded-For: 127.0.0.1 可冒充内网, 绕过三道防线:
- 未设密码时的「仅本机/内网可访问」中间件闸门 (main.py)
- /api/auth/setup 的本机限制 (公网抢占设密码)
- 登录限流按 IP 计数 (轮换 XFF 无限暴破)

另修复限流器: 锁定过期后重置失败计数 (原先过期后每失败一次
立刻再锁 5 分钟), 并在条目超 1000 时清理过期记录防内存膨胀。
2026-07-03 14:11:26 +08:00
shy3130 c1a5a6c367 Revert "fix: 修复海外服务器部署后交易时段时区误判为休市"
This reverts commit f02a88ebaa.
2026-07-03 14:07:26 +08:00
shy3130 f02a88ebaa fix: 修复海外服务器部署后交易时段时区误判为休市
- 新增 backend/app/timezone.py 统一上海时区入口(ZoneInfo + UTC+8 兜底)
- quote_service / depth_service 的 _is_trading_hours() 改用显式 Asia/Shanghai
- Dockerfile 加 ENV TZ=Asia/Shanghai + tzdata,docker-compose.yml 加 TZ 环境变量
- 代码与容器双保险,解决裸 datetime.now() 在 UTC 容器下永远判为休市的问题
2026-07-03 13:31:33 +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 56276384e5 fix(strategy): 修复 Docker 镜像中 AI 策略提示词文档缺失
将运行时依赖的 3 个提示词文档(strategy-guide.md / step1 / step2)
从 docs/ 复制到 backend/app/strategy/prompts/,使其随 COPY backend/app
自动进入镜像;并将 GUIDE_PATH/_DOCS_DIR 改为相对当前文件的 prompts/,
路径在开发环境与 Docker 容器中解析一致。

修复 #41
2026-07-03 09:51:30 +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 b203e07e22 chore: 更新 uv.lock 2026-07-02 17:46:31 +08:00
shy3130 d4dcbb1797 chore: 版本号升至 0.1.70 2026-07-02 17:45:30 +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 000a9ead77 feat: 连板梯队封单监控规则引擎
- monitor_rules 新增 ladder 类型 (封单量/封单额 <= 阈值预警)
- monitor 加 _evaluate_ladder: 封单判断 + 炸板/翘板预警, message 体现封单量
- monitor 加 has_rule_type 供评估前判断是否需注入特殊数据
- quote_service: 有 ladder 规则时从 depth_service 注入封单量到 enriched
2026-07-02 17:22:32 +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
Yuki Noah d4a834e942 Normalize OpenAI-compatible AI base URLs (#35) 2026-07-02 12:35:06 +08:00
shy3130 09ec2a55c3 fix: 当日涨跌停判定改用维表 limit_up/limit_down 权威值
原逻辑用 _limit_price(prev_close, 推断涨幅) 自算理论涨停价, 涨幅靠 symbol
前缀 + ST 名字匹配推断, 存在两类缺陷:
1. 浮点精度: 自算涨停价比真实价多 0.01, 超出 0.005 容差导致漏判 (12 只)
2. ST 匹配漏洞: 名字含 "S" 不含 "ST" (如 S佳通) 被漏判 ST 5% 档 (1 只)

改为优先读 instruments 维表的 limit_up/limit_down (交易所级别精确价),
仅新股 (limit_up 为 null 或哨兵 100000) 回退自算。输出 schema 不变,
下游 depth_service/screener/market_overview 零改动。

历史路径 compute_limit_signals 不动 (instruments 仅存当天 as_of)。
2026-07-02 12:28:13 +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 ff9d7a9ac4 fix: filter_history 策略(反包等)实时监控可触发通知 2026-07-01 14:38:40 +08:00
shy3130 8127bd3c99 chore: 版本号升至 0.1.68 2026-07-01 11:27:30 +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 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
Lzwaang 2d86dea721 Avoid copying Codex env file 2026-06-29 22:53:36 +08:00
Lzwaang ab9480b3f3 Harden Codex CLI workspace isolation 2026-06-29 22:44:31 +08:00
Lzwaang ec6380376d Add Codex CLI AI provider 2026-06-29 22:32:58 +08:00
shy3130 5d4d643bd8 fix: 同步后端 __version__ 到 0.1.66 2026-06-29 17:53:29 +08:00
shy3130 ec941e1eb1 chore: bump version to 0.1.66 2026-06-29 17:50:12 +08:00
shy3130 47a87fca2b feat: 环境变量预置访问密码 + 飞书推送文档 2026-06-29 17:41:32 +08:00
shy3130 73490fdf5e chore: bump version to 0.1.65 2026-06-29 17:21:01 +08:00
shy3130 a72445d782 fix(pipeline): 修复盘后管道除权因子拉取范围逻辑
daily_pipeline 除权因子改用日K范围回填 (实时增量模式兜底最近数日),
移除 max_date/incremental 依赖;kline_sync 修复 _normalize_adj_factor
重复列重命名崩溃, 新增 fetch_adj_factor_single 单股拉取;
kline.py fallback 改用 compute_enriched 应用复权;
index_sync 指数/ETF 日K同步增加批次进度回调;
同步指数日K步骤输出详细日志。
2026-06-29 17:17:44 +08:00
shy3130 37934091ac feat(notify): 推送通知接入飞书 Webhook
新增 webhook_adapter 飞书群机器人推送 (含签名校验);preferences/settings
增加 feishu_webhook_url/secret 与 webhook_enabled_default (新建规则默认推送)
配置与端点;Monitoring 设置页重构为「推送通知」卡片 (渠道列表+飞书地址折叠
+默认渠道勾选);RuleEditor 规则编辑器支持单条规则勾选飞书。
QMT/ptrade 渠道文案统一改为「待定」。
2026-06-29 17:17:33 +08:00
shy3130 9dbd32246c feat(backtest): 风控新增固定止盈 + 优化回测范围
风控: MatcherConfig 增加 take_profit_pct, 单标的与组合引擎风险检查新增
涨破止盈线卖出逻辑 (退出原因 take_profit);strategy.py 透传 overrides,
api/strategy.py 与前端类型暴露 take_profit;风控 tab 增加止盈输入框,
摘要/结果头/退出标签同步展示;修复未设止损时止盈检查被跳过的 bug。

回测范围: StockPoolPicker 输入框右侧增加「导入自选」「清空」按钮与
「当前范围」指示器, 移除冗余的「留空=全市场」提示。
2026-06-29 17:17:20 +08:00
shy3130 cd76796a5c feat(monitor): 触发记录展示命中条件与当前价位
告警事件落盘时增加 conditions + logic 条件快照, 经 quote_service 透传到
SSE 推送;前端触发记录详情行渲染命中条件与现价, 替代原先仅显示
「信号触发」的通用文案。
2026-06-29 17:17:08 +08:00
shy3130 d123fa723e chore: bump version to 0.1.64 2026-06-28 20:11:35 +08:00
shy3130 69cd7af8d9 feat: 新增访问密码认证(首次本机设密码 + 公网防护)
- 后端: PBKDF2 密码哈希 + 会话 token(auth.json 存储, 零数据库)
- 中间件: 未设密码时本机可设/公网拒绝(防裸奔+防抢占), 已设密码后 401 拦截
- 5个 API: status/setup/login/logout/change-password, 含本机限制+登录限流
- 前端: 登录页/设密码页 + 全局 401/403 拦截跳转
- 安全: HttpOnly cookie + 5次失败锁5分钟 + 改密码清会话
2026-06-28 20:02:00 +08:00
shy3130 5585f445fc chore: bump version to 0.1.63 2026-06-28 18:20:57 +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 b79fe60a56 ci(docker): 优化镜像构建工作流 + 清理未启用的版本自增脚本
#22 (Docker 镜像构建工作流) 基础上的三点优化:

1. CI 关闭国内镜像源(USE_CN_MIRROR=0): GitHub runner 在海外,
   让构建直连官方 npm/PyPI 反而更快更稳; 本地/国内手动 docker build
   仍走 Dockerfile 默认的 CN 镜像。
2. 新增 .dockerignore: 排除 .git/data/node_modules/docs/screenshots 等
   非构建必需文件, 减小上下文体积、加速传输。
3. 叠加 tag 触发 + build-push-action v5→v6: 打 v* tag 时额外产出
   带版本号镜像(如 :v0.1.62), 便于固定回溯。

清理:
- 删除 scripts/bump_version.py (prepare-commit-msg hook 从未实际安装,
  属于死代码; 发版版本号改为手动维护, 与方案 B 一致)。
- 同步修正 backend/app/api/data.py 中对该脚本的过时引用注释。
2026-06-28 16:18:46 +08:00
shy3130 014ff15766 chore: 更新 uv.lock 依赖锁 2026-06-28 16:01:54 +08:00
shy3130 76431b588e feat: 概念/行业数据改为用户手动获取
将内置概念(ext_gn_ths)/行业(ext_hy_ths)数据源从「自动拉取」改为
「用户在页面手动点获取」, 避免启动时网络请求阻塞, 也符合用户自主控制预期。

后端:
- ext_presets.py (新增): 内置预设配方 + 结构转换 (接口 concepts/industries
  数组 → 拼接成字符串) + ensure_builtin_presets(只建config不拉数据) +
  fetch_preset(手动拉取, 供 API 调用)
- ext_data.py: 新增 POST /api/ext-data/presets/{config_id}/fetch 专用接口
  (放在动态路由前避免被当 config_id); 走结构转换保证 schema 一致
- main.py: lifespan 改为只 ensure_builtin_presets 创建 config, 不自动拉取

安全保证: 已存在则完全跳过, 绝不覆盖用户已有数据; 行业表去掉无用的
thscode/time 列。
2026-06-28 16:01:39 +08:00
shy3130 2d4befb8a2 fix: data 目录脱离 git 跟踪, 修正桌面版数据落位
解决「更新后数据丢失」问题的根因: ext_data 种子文件被 git 跟踪,
push/pull 时会覆盖用户本地数据。

变更:
- .gitignore: 整个 data/ 纳入忽略, 移除 ext_data 放行规则
- git rm --cached: 移除 ext_gn_ths/ext_hy_ths 4 个种子文件跟踪 (本地保留)
- config.py: 桌面版数据目录改为 exe 同级 TickFlowStockPanel_Data/
  (在 {app} 外, 覆盖安装/卸载都碰不到; 不在 C 盘, 用户可见)
- tickflow.iss: 卸载询问逻辑指向新数据目录 {app}\..\TickFlowStockPanel_Data

种子数据改由首次启动从远程接口拉取 (见后续 commit)。
2026-06-28 16:01:29 +08:00
shy3130 eaaf923d7b 修复看板显示bug 2026-06-28 13:49:18 +08:00