# 数据层总览(Data Layer) > A 股量化平台 **方案 A 数据层**单一权威记录。采集源 → 权威存储 → Provider → 策略全链路闭环。 > 维护:数据 session。策略层接口对接见本文 §6;策略逻辑本身由策略 session 负责。 > 深读设计依据:[`docs/superpowers/specs/2026-07-21-data-source-fusion-design.md`](../superpowers/specs/2026-07-21-data-source-fusion-design.md)(§14 权威层定稿)。 > 历史中间设计/plan 已归档至 [`docs/archive/data/`](../archive/data/)。 --- ## 1. 架构总览 ``` 采集源(VPS定时任务) 权威存储层(VPS本地) 使用层(Provider) 策略层 ───────────────── ────────────────── ────────────────── ───────── baostock ─┐ get_closes_panel 选股/轮动 xtdata ─┼─► staging ─► 验证 ─► 合并 ─► dbbardata ─►┐ (BulletTrade akshare ─┤ (validator) (merge) ├─ LocalUnifiedProvider 三策略) sina/东财/腾讯─┘ constituent_unified─►┤ filters valuation_baostock ─►┼─► get_fundamentals_df 三表 parquet ─►────┘ get_limit_status_batch bs_adjust_factor ... ``` **核心原则**:Provider 只读 VPS 本地数据,零 online;下载经 staging 隔离 → 验证 → 合并主库,绝不直接写主库。 --- ## 2. 数据布局(VPS 本地,`C:\sanguo_vnpy_v2\data\`) | 存储 | 形态 | 内容 | 关键说明 | |------|------|------|----------| | `dbbardata`(quant_trading.db) | SQLite 表 | **唯一行情表**:日线(raw) + 15min | 含退市股 + ETF + 北交所920;schema `(id,symbol,exchange,datetime,interval,volume,turnover,open_interest,open/high/low/close_price)`;UNIQUE `(symbol,exchange,interval,datetime)`;WAL 模式 | | `bs_adjust_factor` | SQLite 表 | 前复权因子 | `get_closes_panel(fq='qfq')` asof merge | | `constituent_unified` | SQLite 表 | **20 指数成份股** | 9 宽基 + 000985 中证全指(~全市场) + 000928~000937 中证800十行业;`was_removed` 治幸存者偏差 | | `valuation_baostock` | parquet/年 | pe / pb / isST | 2003-2026,按年 | | 三表(akshare) | parquet | balance(221列)/income(170列)/cashflow(316列) | 财报季更新 | | A股日线/分钟 | parquet | 兜底 | 回测 DB 为主,parquet 兜底 | **⚠️ 6 位码同名碰撞**:`000852/000905/000016/000985/000928~000937` 在 SZSE 是股票、在中证是指数点位。dbbardata 用 `exchange` 消歧:**`SSE` = 中证指数点位(约定),`SZSE` = 个股**。指数点位由 `sina_index_eod.py` 拉取入 `exchange=SSE`。 --- ## 3. 采集源职责 | 源 | 职责 | 限制 | |----|------|------| | **baostock** | 个股日线(含退市)+ 15min + pe/pb | 单进程单登录,**不并发**(多连接→封 IP 6-24h);日 ≤ 48000 次 | | **xtdata(miniQMT)** | ETF + 基金 + 北交所 920xxx | 沪深京全覆盖;volume 单位需 ×100 对齐 | | **akshare** | 三表 + events + top10 股东 | 东财瞬时限流(断路器 + 夜间重试兜底) | | **sina→东财→腾讯** | 14 指数点位 | 级联,腾讯兜底 5 个 sina 停更 | --- ## 4. 增量管线(定时任务 schtask,VPS) | schtask | 时间 | 职责 | LOOKBACK | |---------|------|------|----------| | `sanguo-bs-eod` | 18:05 | baostock 个股日线 + 15min + pe/pb | 7 天 | | `sanguo-idx-eod` | 18:30 | 14 指数点位(sina 级联) | — | | `sanguo-ak-eod` | 19:00 | akshare 日线静态 | — | | `sanguo-ak-events` | 19:30 | 事件 | — | | `sanguo-xt-eod` | 21:00+ ⚠️ | ETF/基金/北交所920 | 30 天 | | `sanguo-ak-stock` | 周六 | 个股全量(top10 等) | — | | `sanguo-ak-quarter` | 财报季(APR,MAY,SEP,NOV) | 三表 | — | | `sanguo-index` | 月度 16 号 19:50 | 成份股月度增量 | — | ⚠️ `xt-eod` 原 18:40 与 `bs-eod` 18:05 写锁重叠(WAL 单写)→ 建议 21:00+ 错峰。 `sanguo-index` STEP0:`parse_csindex_announce` 回溯公告治偏差(000852/932000)+ `--indices` 刷 11 新指数;STEP1-3 migrate→merge。 `bs-eod` 已修 CLOSE_WAIT 卡死(per-stock commit + `_with_timeout` + 周期 relogin)。 --- ## 5. 工作流与铁律 **下载链路(用户铁律)**: ``` 下载 → staging 隔离 → validator 验证(成功率95%,扣北交所) → 合并主库 → 推 NAS ``` **绝不直接写主库**(下载质量不可控,曾出现覆盖截断整年)。 **约束**: - baostock 单进程单登录不并发;日 ≤ 48000 次 - 直连不走代理:`unset http_proxy https_proxy all_proxy` - provider 读 VPS 本地,不调 online - 数据层瑕疵报数据 session 根治,不在 provider 适配兜底 - commit ≠ 部署 VPS:改完 `scp` 到 VPS + `findstr` 验证 - VPS Windows:`python -X utf8`、反斜杠路径、GBK 控制台用 ASCII 脚本 - Mac Mini 长任务前 `caffeinate -i -s` 防睡眠 --- ## 6. Provider API(`LocalUnifiedProvider`) 读本地零 online,治偏差(成份股并集 + 前视偏差修复)。14 个公开方法: | 方法 | 用途 | 备注 | |------|------|------| | `get_price(security, start, end, frequency, fields, count, fq)` | 单只行情 | 聚宽兼容 | | **`get_closes_panel(symbols, start, end, interval='d', fq='raw')`** | 批量收盘价宽表 | `fq='qfq'` 批量前复权;UNION ALL 替 OR 链(340×);chunk=400;5128 只 33s | | `get_index_stocks(index, date)` | 指数成份股 | 读 constituent_unified | | `get_constituent(...)` | 成份股详情 | 治偏差 | | **`get_fundamentals_df(stocks, date, fields=None)`** | 基本面 | `fields=` 短路(只算所需源表)+ ThreadPool;300 只 68s→7.4s(9.3×) | | `get_value_metrics(security, date)` | 价值指标(单只) | — | | **`get_value_metrics_batch(stocks, date)`** | 价值指标批量 | ThreadPool 包装 | | `get_trade_days(start, end)` | 交易日历 | — | | `get_security_info(security)` | 证券信息(单只) | — | | **`get_security_info_batch(stocks)`** | 证券信息批量 | 2 SQL 替 N×2(ST/次新过滤提速) | | **`get_limit_status_batch(codes, date)`** | 涨跌停/停牌批量 | 精确算 `high_limit=round(prev_close×(1+幅度),2)`;板块感知(主板10/创业科创20/北交30/ST5,历史ST from valuation_baostock.isST);停牌=volume==0 | | `get_current_tick(security)` | tick | ⚠️ 无 last_price/high_limit 字段,filter 已改用 `get_limit_status_batch` | | `get_split_dividend(security)` | 拆分分红/复权因子 | — | | `get_all_securities(...)` | 全证券列表 | — | **四轮批量接口交付**(commit `f416a17`/`d2cd8fa`/`1cc9126`):行情 `get_closes_panel` / 财务 `get_fundamentals_df fields=` / filters+价值 `get_security_info_batch`+`get_value_metrics_batch` / 涨跌停停牌 `get_limit_status_batch`。 filters(`sanguo_portfolio/filters.py`):`filter_paused/limitup/limitdown` 已接入 `get_limit_status_batch`(向后兼容:无参=保留全部)。 --- ## 7. 已知缺口与定论 | 项 | 状态 | 定论 | |----|------|------| | 行业治偏差(成份股历史调整) | 部分覆盖 | content HTML 解析已做(was_removed 8→99,主要覆盖 2009 + 零星 2016-2022);2010-2025 定期 csindex 无存档,**免费源穷尽**,用户接受残留偏差(不上 wind/choice) | | 北交所 920xxx | ✅ 补全 | xtdata 独占(baostock/akshare 不覆盖),39 只,volume×100 对齐 | | 实盘标的范围 | ✅ 定论 | 只做主板 + 创业板(`filter_kcbj_stock` 排除科创北交,用户未开户 50 万门槛);数据层仍全量补成份股治偏差,两层解耦 | | 行业指数点位 | ✅ 修复 | 14 指数入 `exchange=SSE`,策略 03 不再永远判熊 | | akshare 三表 | ✅ 鲁棒 | 原子写 + `--repair` + `is_parquet_healthy` | --- ## 8. 待办(Phase 2,低优先) - 归档 15min 一次性灌库链(`backfill_15min_baostock` 等被 `tests/data/test_backfill_15min_hardening.py` import,需同步处理测试) - 归档旧回填 import 链 + Mac `.sh` 链(`build_daily_from_xtdata`/`import_vnpy_*`/`raw_redownload` 等被 wrapper 引用,需 VPS `schtasks /query` 确认非活跃后归档) - 行业治偏差 2010-2025(若有 wind/choice 授权再补)