Files
ProStock/docs/db_sync_guide.md

268 lines
6.1 KiB
Markdown
Raw Normal View History

# DuckDB 数据同步指南
ProStock 现已从 HDF5 迁移至 DuckDB 存储。本文档介绍新的同步机制。
## 新功能概览
- **自动表创建**: 根据 DataFrame 自动推断表结构
- **复合索引**: 自动为 `(trade_date, ts_code)` 创建复合索引
- **增量同步**: 智能判断同步策略(按日期或按股票)
- **类型映射**: 预定义常见字段的数据类型
## 核心模块
### 1. TableManager - 表管理
```python
from src.data.db_manager import TableManager
# 创建表管理器
manager = TableManager()
# 从 DataFrame 创建表(自动创建复合索引)
import pandas as pd
data = pd.DataFrame({
"ts_code": ["000001.SZ"],
"trade_date": ["20240101"],
"close": [10.5],
})
manager.create_table_from_dataframe("daily", data)
# 确保表存在(不存在则自动创建)
manager.ensure_table_exists("daily", sample_data=data)
```
### 2. IncrementalSync - 增量同步
```python
from src.data.db_manager import IncrementalSync
sync = IncrementalSync()
# 获取同步策略
strategy, start, end, stocks = sync.get_sync_strategy(
table_name="daily",
start_date="20240101",
end_date="20240131",
stock_codes=None # None = 所有股票
)
# 返回值:
# - strategy: "by_date" | "by_stock" | "none"
# - start: 同步开始日期
# - end: 同步结束日期
# - stocks: 需要同步的股票列表None = 全部)
# 执行数据同步
result = sync.sync_data("daily", data, strategy="by_date")
```
### 3. SyncManager - 高级同步
```python
from src.data.db_manager import SyncManager
from src.data.api_wrappers import get_daily
# 创建同步管理器
manager = SyncManager()
# 一键同步(自动处理表创建、策略选择、数据获取)
result = manager.sync(
table_name="daily",
fetch_func=get_daily, # 数据获取函数
start_date="20240101",
end_date="20240131",
stock_codes=["000001.SZ", "600000.SH"] # 可选:指定股票
)
print(result)
# {
# "status": "success",
# "table": "daily",
# "strategy": "by_date",
# "rows": 1000,
# "date_range": "20240101 to 20240131"
# }
```
## 便捷函数
### 快速同步数据
```python
from src.data.db_manager import sync_table
from src.data.api_wrappers import get_daily
# 同步日线数据
result = sync_table(
table_name="daily",
fetch_func=get_daily,
start_date="20240101",
end_date="20240131"
)
```
### 获取表信息
```python
from src.data.db_manager import get_table_info
# 查看表统计信息
info = get_table_info("daily")
print(info)
# {
# "exists": True,
# "row_count": 100000,
# "min_date": "20240101",
# "max_date": "20240131",
# "unique_stocks": 5000
# }
```
### 确保表存在
```python
from src.data.db_manager import ensure_table
# 如果表不存在,使用 sample_data 创建
ensure_table("daily", sample_data=df)
```
## 同步策略详解
### 1. 按日期同步 (by_date)
**适用场景**: 全市场数据同步、每日增量更新
**逻辑**:
- 表不存在 → 全量同步
- 表存在但空 → 全量同步
- 表存在且有数据 → 从 `last_date + 1` 开始增量同步
```python
# 示例: 表已有数据到 20240115
strategy, start, end, stocks = sync.get_sync_strategy(
"daily", "20240101", "20240131"
)
# 返回: ("by_date", "20240116", "20240131", None)
# 只需同步 16-31 号的新数据
```
### 2. 按股票同步 (by_stock)
**适用场景**: 补充特定股票的历史数据
**逻辑**:
- 检查哪些请求的股票不存在于表中
- 仅同步缺失的股票
```python
# 示例: 表中已有 000001.SZ请求两只股票
strategy, start, end, stocks = sync.get_sync_strategy(
"daily", "20240101", "20240131",
stock_codes=["000001.SZ", "600000.SH"]
)
# 返回: ("by_stock", "20240101", "20240131", ["600000.SH"])
# 只同步缺失的 600000.SH
```
### 3. 无需同步 (none)
**适用场景**: 数据已是最新
**触发条件**:
- 表存在且日期已覆盖请求范围
- 所有请求的股票都已存在
## 完整示例
```python
from src.data.db_manager import SyncManager, get_table_info
from src.data.api_wrappers import get_daily
# 1. 查看当前表状态
info = get_table_info("daily")
print(f"当前数据: {info['row_count']} 行, 最新日期: {info['max_date']}")
# 2. 创建同步管理器
manager = SyncManager()
# 3. 执行同步
result = manager.sync(
table_name="daily",
fetch_func=get_daily,
start_date="20240101",
end_date="20240222"
)
# 4. 检查结果
if result["status"] == "success":
print(f"成功同步 {result['rows']} 行数据")
print(f"使用策略: {result['strategy']}")
elif result["status"] == "skipped":
print("数据已是最新,无需同步")
else:
print(f"同步失败: {result.get('error')}")
```
## 类型映射
默认字段类型映射:
```python
DEFAULT_TYPE_MAPPING = {
"ts_code": "VARCHAR(16)",
"trade_date": "DATE",
"open": "DOUBLE",
"high": "DOUBLE",
"low": "DOUBLE",
"close": "DOUBLE",
"pre_close": "DOUBLE",
"change": "DOUBLE",
"pct_chg": "DOUBLE",
"vol": "DOUBLE",
"amount": "DOUBLE",
"turnover_rate": "DOUBLE",
"volume_ratio": "DOUBLE",
"adj_factor": "DOUBLE",
"suspend_flag": "INTEGER",
}
```
未定义字段会根据 pandas dtype 自动推断:
- `int``INTEGER`
- `float``DOUBLE`
- `bool``BOOLEAN`
- `datetime``TIMESTAMP`
- 其他 → `VARCHAR`
## 索引策略
自动创建的索引:
1. **主键**: `(ts_code, trade_date)` - 确保数据唯一性
2. **复合索引**: `(trade_date, ts_code)` - 优化按日期查询性能
## 与旧代码的兼容性
原有 `Storage``ThreadSafeStorage` API 保持不变:
```python
from src.data.storage import Storage, ThreadSafeStorage
# 旧代码继续可用
storage = Storage()
storage.save("daily", data)
df = storage.load("daily", start_date="20240101")
```
新增的功能通过 `db_manager` 模块提供。
## 性能建议
1. **批量写入**: 使用 `SyncManager` 自动处理批量写入
2. **避免重复查询**: 使用 `get_table_info()` 检查现有数据
3. **合理选择策略**: 全市场更新用 `by_date`,补充数据用 `by_stock`
4. **利用索引**: 查询时优先使用 `trade_date``ts_code` 过滤