auto-sync: 2026-05-06 08:45:17

This commit is contained in:
cfdaily
2026-05-06 08:45:17 +08:00
parent f374aa1a13
commit 8e78f3c569
+209 -13
View File
@@ -2,9 +2,9 @@
**项目**: sanguo_vnpy 数据平台
**作者**: 赵云(数据总管)
**日期**: 2026-05-03
**版本**: v1.1
**状态**: 评审通过,代码已修改
**日期**: 2026-05-06
**版本**: v2.0
**状态**: 评审(重大架构变更)
---
@@ -530,12 +530,13 @@ sanguo_vnpy/
| 2026-05-03 | v1.0-draft | 初始版本 | 赵云 |
| 2026-05-03 | v1.1 | 司马懿评审后修改:interval→15m, 严格增量追加, 日线进度文件, 全局源检测, DB轮转备份, 失败率告警 | 赵云 |
| 2026-05-05 | v1.2 | 东方财富集成:日线主源切换为东方财富(amount真实,反爬策略4s/请求+随机抖动), 腾讯降为备源 | 赵云 |
| 2026-05-06 | v2.0 | **重大架构变更**:BaoStock替代所有主源(无反爬、全量历史、amount真实);15min interval改为1mvnpy DB写入改为本地构建+rsync;新浪API已挂移除;多源fallback机制重构 | 赵云 |
---
## 十三、评审结果(2026-05-03 司马懿评审)
### 评审结论:有条件通过
### v1.1 评审结论:有条件通过(已完成)
**2个阻塞项(已解决)**
1. ✅ interval="1m" → "15m":采用方案Bvnpy加MINUTE_15枚举 + monkey patch
@@ -547,12 +548,207 @@ sanguo_vnpy/
3. ✅ DB轮转备份(保留7天,`quant_trading_{YYYYMMDD}.db.bak`
4. ✅ 失败率>5%告警标记 + 源终止告警
**8个待评审项确认**
1. SMB性能:V1方案AMac→SMB),V1.1切方案BNAS本地执行)
2. DB同步DockerV1手动,V2用cron job
3. 数据源标记:V1不加
4. amount为0:V1保留腾讯0值,记录告警
5. interval:已改为"15m"
6. 部署整合:P2不急
7. DB备份:已实现轮转备份
8. 错误告警:已实现失败率阈值
---
## 十四、v2.0 重大架构变更(2026-05-06
### 14.1 变更背景
v1.2运行暴露了5个根本性问题:
| # | 问题 | 根因 | 影响 |
|---|------|------|------|
| 1 | vnpy DB写入报`no such table: dbbardata` | SMB文件锁与SQLite ATTACH不兼容 | 日线+15min数据不入DB |
| 2 | 新浪15min API已失效 | 返回Error 0,所有请求失败 | 15min无法增量更新 |
| 3 | BaoStock 15min回补已完成但未入库 | 原脚本interval=`15m`与vnpy不兼容 | 5193只×8992条数据闲置 |
| 4 | 日线跨年写入bug | `year=datetime.now().year`硬编码 | 年初数据会写错目录 |
| 5 | overview全表聚合 | 1.4G DB上GROUP BY全表扫描 | NAS上可能超时/锁死 |
### 14.2 数据源重新调研
#### 数据源实测对比
| 数据源 | 15min可获取量 | 日线可获取量 | amount | 反爬 | 频率 | 当前状态 |
|--------|-------------|-------------|--------|------|------|----------|
| **BaoStock** | 无限制(按日期) | 无限制(按日期) | 真实(5.54亿) | **无** | 0.12s/只, 100只0错误 | ✅ 稳定 |
| **东方财富** | ~496条(7周) | 多年(~1046条) | 真实(5.54亿) | 4-5s/请求+UA+Referer | 中 | ✅ 可用 |
| **腾讯** | Connection reset | 按日期范围 | 有时为0 | 无 | 快 | ⚠️ 不稳定 |
| **新浪** | Error/2条 | Error/2条 | - | - | - | ❌ 已挂 |
**关键结论**:BaoStock在所有维度都最优(无反爬、全量历史、amount真实、速度快),应作为首选源。
#### v1.2 BaoStock压力测试
```
15min: 100只连续请求, 总耗时11.9s, 平均0.12s/只, 0错误
日线: 10只连续请求, 总耗时1.6s, 平均0.16s/只
全历史: sh.600000 2010-2026日线 3963条, 0.68s
```
#### v1.2 SQLite本地写入性能
```
100万条INSERT OR REPLACE: 2.0s
预估4600万条(15min全量): ~91s ≈ 1.5分钟
```
### 14.3 v2.0 核心架构变更
#### 变更1:数据源降级链重构
**设计原则**:按数据质量排序,质量最好的源排第一。每个源封装独立函数,统一返回DataFrame。主循环挨个尝试,成功即用,失败试下一个。
```
v1.x(旧):
日线: 腾讯(主) → 新浪(备)
15min: 新浪(主) → 无备源
v2.0(新):
日线: BaoStock(主) → 东方财富(备) → 腾讯(三备)
15min: BaoStock(主) → 东方财富(备) → 新浪(三备,当前已挂)
```
**Fallback机制**
```python
SOURCES_DAILY = [
("baostock", fetch_baostock_daily), # 最优:全量历史+无反爬+amount真实
("eastmoney", fetch_eastmoney_daily), # 备用:多年历史+amount真实+4s限频
("tencent", fetch_tencent_daily), # 三备:amount有时为0
]
SOURCES_15MIN = [
("baostock", fetch_baostock_15min), # 最优
("eastmoney", fetch_eastmoney_15min), # 备用:7周
("sina", try_sina_15min), # 三备:当前已挂
]
def fetch_with_fallback(sources, code, start, end):
for name, fetch_fn in sources:
try:
data = fetch_fn(code, start, end)
if data is not None and len(data) > 0:
return data, name
except Exception:
continue
return None, None
```
#### 变更2:vnpy DB写入策略改为本地构建+rsync
**v1.x方案(ATTACH via SMB**:直接在Mac上ATTACH NAS DB → SMB文件锁导致失败
**v2.0方案(本地构建+rsync**
1. 每日更新时,从NAS cp当前DB到本地`/tmp/`
2. 所有增量数据写入本地DB
3. 验证完整性后,rsync覆盖NAS DB
4. 备份旧DB(轮转7天)
```python
def sync_db_to_nas():
# 备份
backup = f"quant_trading_{today}.db.bak"
shutil.copy2(str(VNPY_DB_PATH), str(VNPY_DB_PATH.parent / backup))
# rsync本地→NAS
os.system(f"rsync -av --progress {LOCAL_DB_PATH} {VNPY_DB_PATH}")
```
**性能预估**
- cp NAS DB到本地:~15秒(1.4G
- 增量写入本地DB:<1秒(日线)
- rsync覆盖NAS~15秒
- 全量15min导入(首次):~1.5分钟(4600万条)
#### 变更315min interval统一用`1m`
**v1.x**interval=`15m`(与vnpy 4.x不兼容)
**v2.0**interval=`1m`(姜维确认vnpy 4.x Interval.MINUTE.value=`1m`
**数据格式(姜维确认)**
- symbol: `000001`(纯代码)
- exchange: `SSE` / `SZSE`
- interval日线: `d`
- interval分钟线: `1m`
#### 变更4:日线跨年写入修复
**v1.x bug**`year = datetime.now().year`,年初数据写错目录
**v2.0**:按数据日期分目录
```python
def update_daily_parquet(code, new_data):
for yr in new_data["date"].str[:4].unique():
year_data = new_data[new_data["date"].str[:4] == yr]
parquet_path = DAILY_DIR / yr / f"{prefix}{clean}_daily.parquet"
# 合并写入...
```
#### 变更5overview增量更新
**v1.x**`SELECT ... FROM dbbardata GROUP BY` 全表扫描(1.4G DB上很慢)
**v2.0**:只更新本次涉及的symbol
```python
for sym, exc, ivl in affected_keys:
c.execute("""INSERT OR REPLACE INTO dbbaroverview
SELECT ?,?,?,COUNT(*),MIN(datetime),MAX(datetime)
FROM dbbardata WHERE symbol=? AND exchange=? AND interval=?""",
(sym, exc, ivl, sym, exc, ivl))
```
#### 变更6:进度文件加日期
**v1.x**:进度文件不区分日期,跨天可能跳过
**v2.0**`daily_20260506_progress.json`,每次运行独立进度
#### 变更7Cron fallback模型
**v1.x**:只用默认模型,配额用完则任务失败
**v2.0**:设置fallback模型(zhipu/glm-5.1),配额不足时自动降级
### 14.4 执行计划
#### 第1步:灌入现有数据到本地vnpy DB
```
1. cp NAS quant_trading.db → /tmp/quant_trading_import.db
2. import_vnpy_daily_fast.py --start-year 2026 # 补3/28~今天的日线增量
3. import_vnpy_minute.py --scope all # 全量导入5193只15min
4. 验证数据完整性
5. rsync本地DB → NAS
```
#### 第2步:重构daily_all_update.py
按14.3的7个变更点重构代码。
#### 第3步:Cron更新+测试
- 更新cron任务配置
- 手动触发一次全量更新验证
- 确认日志无错误
### 14.5 与v1.x的兼容性
| 变更 | 向后兼容 | 影响 |
|------|---------|------|
| interval 15m→1m | ❌ 需要DB迁移 | 现有15m数据需UPDATE为1m |
| DB写入策略 | ✅ 无影响 | Parquet不受影响 |
| 数据源顺序 | ✅ 无影响 | 只是重试顺序变化 |
| 跨年写入 | ✅ 修正bug | 未来数据不再错 |
| overview增量 | ✅ 无影响 | 只是优化 |
> ⚠️ **DB迁移注意**v1.x如果有`interval='15m'`的记录,需要一次性UPDATE为`'1m'`。当前DB中实际无15min数据(v1.x的写入全部失败),所以无需迁移。
---
## 十五、v2.0 评审待确认项
| # | 问题 | 建议方案 | 待确认 |
|---|------|---------|--------|
| 1 | BaoStock作为全主源是否合适? | 无反爬+全量+amount真实,建议通过 | 司马懿 |
| 2 | 本地构建+rsync替代ATTACH | 姜维确认推荐,比ATTACH稳定 | 司马懿 |
| 3 | interval=1m而非15m | 姜维确认vnpy 4.x规范 | 司马懿 |
| 4 | 是否需要DB迁移脚本? | 当前无15m数据,无需迁移 | 司马懿 |
| 5 | Fallback顺序是否合理? | BaoStock→东方财富→腾讯/新浪 | 司马懿 |
| 6 | 日常更新全市场耗时预估? | BaoStock: ~10min(15min)+~8min(日线)+rsync | 司马懿 |
| 7 | 是否需要额外反爬措施? | BaoStock无需,备源保留原有措施 | 司马懿 |