auto-sync: 2026-05-06 08:45:17
This commit is contained in:
@@ -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改为1m;vnpy DB写入改为本地构建+rsync;新浪API已挂移除;多源fallback机制重构 | 赵云 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、评审结果(2026-05-03 司马懿评审)
|
||||
|
||||
### 评审结论:有条件通过
|
||||
### v1.1 评审结论:有条件通过(已完成)
|
||||
|
||||
**2个阻塞项(已解决)**:
|
||||
1. ✅ interval="1m" → "15m":采用方案B(vnpy加MINUTE_15枚举 + monkey patch)
|
||||
@@ -547,12 +548,207 @@ sanguo_vnpy/
|
||||
3. ✅ DB轮转备份(保留7天,`quant_trading_{YYYYMMDD}.db.bak`)
|
||||
4. ✅ 失败率>5%告警标记 + 源终止告警
|
||||
|
||||
**8个待评审项确认**:
|
||||
1. SMB性能:V1方案A(Mac→SMB),V1.1切方案B(NAS本地执行)
|
||||
2. DB同步Docker:V1手动,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万条)
|
||||
|
||||
#### 变更3:15min 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"
|
||||
# 合并写入...
|
||||
```
|
||||
|
||||
#### 变更5:overview增量更新
|
||||
|
||||
**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`,每次运行独立进度
|
||||
|
||||
#### 变更7:Cron 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无需,备源保留原有措施 | 司马懿 |
|
||||
|
||||
Reference in New Issue
Block a user