# 行情历史补档（最近 60 个交易日）

用于修复 `dashboard_snapshots` 断档导致情绪周期 / 主题轮动 / 智能选股只剩当天的问题。
保留 `latest_contiguous_history` 连续性规则；通过真实交易日历回补缺失交易日快照。

## 适用场景

- 库中已有稀疏历史快照，但最近一个真实交易日缺失，接口 `available_days=1`。
- 需要可重复执行、可审计、可回退的补档，而不是迁库或放宽算法。

## 前置

1. 使用与线上一致的代码分支。
2. 管理员账号已配置可用的公共 Tushare Token。
3. 只操作目标环境自己的 `data/review.db`；禁止 `.36` 与 `.11` 互拷。

## 上线步骤（总工执行）

在目标环境容器内执行（应用根目录；宿主机也可直接跑，脚本已自带仓库根 `sys.path` 引导）：

```bash
# 1) 只读规划：区分已有、真正缺档；不会写入
docker compose exec xiaobai-review python tools/backfill_recent_snapshots.py --account <管理员账号> --lookback 60 --dry-run --json

# 2) 正式补档：先走 SQLite backup API 写 data/backups/review-pre-recent-backfill-*.db
#    再对缺失交易日调用现有 sync_dashboard
docker compose exec xiaobai-review python tools/backfill_recent_snapshots.py --account <管理员账号> --lookback 60 --json

# 3) 验证
#    GET /api/sentiment/history?trade_date=YYYY-MM-DD&limit=60
#    期望 available_days >= 20，且不再只有 1 天
```

管理端日期区间回补（`/api/backfill`）已改为只处理交易日历中的开市日，周末/节假日会进入
`skipped_non_trading_days`，不再当成错误；单次仍限制 15 个交易日。最近 60 日请用本工具。

## 写入边界

只会通过现有同步路径写入：

- `dashboard_snapshots`
- 同步审计表 `sync_runs`
- 必要时的 `data_snapshots`（仅当请求日被解析到其他交易日）

不得改动用户、Token、模型绑定或系统配置表。

## 回滚

1. 优先按审计结果的 `created_dates` 精确删除新增行：

```sql
DELETE FROM dashboard_snapshots WHERE trade_date IN ('YYYYMMDD', ...);
```

2. 若需整库回退，停止写入后用补档前备份覆盖：

```bash
# 示例：把 data/backups/review-pre-recent-backfill-YYYYMMDD-HHMMSS.db
# 复制回 data/review.db 后重启容器
```

3. 代码回退：对该提交执行 Git revert 后重新部署镜像。

## 验收要点

- dry-run 与正式执行可重复跑；已有交易日默认跳过。
- 周末、节假日出现在 `skipped_non_trading_days`，不计入失败。
- 部分交易日同步失败时，其他日期仍会继续，并在审计结果中标 `failed`。
- 情绪周期、主题轮动 9 列、智能选股置信度随连续交易日恢复。
