迭代 138 数据格式规范¶
版本: v1.0 | 日期: 2026-02-28
1. Tick 数据格式¶
1.1 CSV 格式¶
文件名*:
{symbol}_ticks_{date}.csv字段定义*:
timestamp,price,volume,direction,trade_id,symbol
1609459200.123,50000.50,1.234,buy,T123456,BTC/USDT
1609459200.456,50001.00,0.567,sell,T123457,BTC/USDT
```bash
| 字段 | 类型 | 说明 | 必填 |
|------|------|------|------|
| timestamp | float | Unix 时间戳(秒,支持毫秒) | ✅ |
| price | float | 成交价格 | ✅ |
| volume | float | 成交量 | ✅ |
| direction | string | 成交方向:'buy'或'sell' | ✅ |
| trade_id | string | 交易 ID | ❌ |
| symbol | string | 交易对符号 | ❌ |
- *示例**:
```python
import pandas as pd
# 生成测试数据
df = pd.DataFrame({
'timestamp': [1609459200.0 + i*0.1 for i in range(1000)],
'price': [50000 + i*0.5 for i in range(1000)],
'volume': [0.1 + i*0.01 for i in range(1000)],
'direction': ['buy' if i % 2 == 0 else 'sell' for i in range(1000)],
'trade_id': [f'T{i}' for i in range(1000)],
'symbol': ['BTC/USDT'] *1000
})
df.to_csv('BTC_USDT_ticks_20210101.csv', index=False)
```bash
- --
## 2. OrderBook 数据格式
### 2.1 JSONL 格式
- *文件名**: `{symbol}_orderbook_{date}.jsonl`
- *格式定义**:
```jsonl
{"timestamp": 1609459200.123, "symbol": "BTC/USDT", "bids": [[50000, 1.5], [49999, 2.0]], "asks": [[50001, 1.2], [50002, 1.8]]}
{"timestamp": 1609459200.456, "symbol": "BTC/USDT", "bids": [[50000.5, 1.3], [49999.5, 2.1]], "asks": [[50001.5, 1.1], [50002.5, 1.9]]}
```bash
- *字段定义**:
| 字段 | 类型 | 说明 | 必填 |
|------|------|------|------|
| timestamp | float | Unix 时间戳(秒) | ✅ |
| symbol | string | 交易对符号 | ✅ |
| bids | array | 买单深度 [[price, qty], ...] 降序 | ✅ |
| asks | array | 卖单深度 [[price, qty], ...] 升序 | ✅ |
- *示例**:
```python
import json
# 生成测试数据
orderbooks = []
for i in range(100):
ob = {
'timestamp': 1609459200.0 + i,
'symbol': 'BTC/USDT',
'bids': [
[50000 - j*0.5, 1.0 + j*0.1]
for j in range(10)
],
'asks': [
[50001 + j*0.5, 1.0 + j*0.1]
for j in range(10)
]
}
orderbooks.append(ob)
# 写入 JSONL
with open('BTC_USDT_orderbook_20210101.jsonl', 'w') as f:
for ob in orderbooks:
f.write(json.dumps(ob) + '\n')
```bash
- --
## 3. FundingRate 数据格式
### 3.1 CSV 格式
- *文件名**: `{symbol}_funding_{date}.csv`
- *字段定义**:
```csv
timestamp,symbol,rate,mark_price,next_funding_time,predicted_rate
1609459200,BTC/USDT,0.0001,50000.5,1609488000,0.00012
1609462800,BTC/USDT,0.00015,50100.2,1609488000,0.00018
```bash
| 字段 | 类型 | 说明 | 必填 |
|------|------|------|------|
| timestamp | float | Unix 时间戳(秒) | ✅ |
| symbol | string | 交易对符号 | ✅ |
| rate | float | 当前资金费率 | ✅ |
| mark_price | float | 标记价格 | ✅ |
| next_funding_time | float | 下次结算时间 | ✅ |
| predicted_rate | float | 预测费率 | ❌ |
- *示例**:
```python
import pandas as pd
df = pd.DataFrame({
'timestamp': [1609459200 + i*3600 for i in range(24)],
'symbol': ['BTC/USDT'] * 24,
'rate': [0.0001 + i*0.00001 for i in range(24)],
'mark_price': [50000 + i*10 for i in range(24)],
'next_funding_time': [1609488000] * 24,
'predicted_rate': [0.00012 + i*0.00001 for i in range(24)]
})
df.to_csv('BTC_USDT_funding_20210101.csv', index=False)
```bash
- --
## 4. Bar 数据格式
### 4.1 CSV 格式(兼容现有格式)
- *文件名**: `{symbol}_bars_{timeframe}_{date}.csv`
- *字段定义**:
```csv
datetime,open,high,low,close,volume
2021-01-01 00:00:00,50000,50100,49900,50050,123.45
2021-01-01 00:01:00,50050,50150,49950,50100,234.56
```bash
| 字段 | 类型 | 说明 | 必填 |
|------|------|------|------|
| datetime | string/float | 时间(ISO 格式或 Unix 时间戳) | ✅ |
| open | float | 开盘价 | ✅ |
| high | float | 最高价 | ✅ |
| low | float | 最低价 | ✅ |
| close | float | 收盘价 | ✅ |
| volume | float | 成交量 | ✅ |
- --
## 5. 数据质量要求
### 5.1 时间戳要求
- **格式**: Unix 时间戳(秒),支持毫秒精度
- **顺序**: 必须严格递增(允许相同时间戳)
- **范围**: 2010-01-01 ~ 2100-01-01
- **精度**: 建议毫秒级(小数点后 3 位)
### 5.2 价格要求
- **范围**: > 0
- **精度**: 根据交易所规则(如 BTC/USDT 为 0.01)
- **合理性**: 相邻价格变化 < 10%(异常检测)
### 5.3 成交量要求
- **范围**: >= 0
- **精度**: 根据交易所规则
- **合理性**: 单笔成交量 < 日均成交量的 10%
### 5.4 OrderBook 要求
- **深度**: 至少 5 档
- **排序**: bids 降序,asks 升序
- **价差**: best_ask > best_bid
- **数量**: 每档数量 > 0
- --
## 6. 数据验证工具
### 6.1 验证脚本
- *文件**: `tools/validate_data.py`
```python
import pandas as pd
import json
def validate_tick_data(filepath):
"""验证 Tick 数据"""
df = pd.read_csv(filepath)
errors = []
# 检查必填字段
required = ['timestamp', 'price', 'volume', 'direction']
for field in required:
if field not in df.columns:
errors.append(f"Missing required field: {field}")
# 检查时间戳顺序
if not df['timestamp'].is_monotonic_increasing:
errors.append("Timestamps not in ascending order")
# 检查价格
if (df['price'] <= 0).any():
errors.append("Invalid price (<=0) found")
# 检查成交量
if (df['volume'] < 0).any():
errors.append("Invalid volume (<0) found")
# 检查方向
if not df['direction'].isin(['buy', 'sell']).all():
errors.append("Invalid direction found")
return errors
def validate_orderbook_data(filepath):
"""验证 OrderBook 数据"""
errors = []
with open(filepath) as f:
for i, line in enumerate(f):
ob = json.loads(line)
# 检查必填字段
if 'timestamp' not in ob or 'bids' not in ob or 'asks' not in ob:
errors.append(f"Line {i}: Missing required fields")
continue
# 检查 bids 降序
bids = ob['bids']
for j in range(len(bids) - 1):
if bids[j][0] < bids[j+1][0]:
errors.append(f"Line {i}: Bids not in descending order")
break
# 检查 asks 升序
asks = ob['asks']
for j in range(len(asks) - 1):
if asks[j][0] > asks[j+1][0]:
errors.append(f"Line {i}: Asks not in ascending order")
break
# 检查价差
if bids and asks:
if bids[0][0] >= asks[0][0]:
errors.append(f"Line {i}: Bid >= Ask")
return errors
if __name__ == '__main__':
import sys
if len(sys.argv) < 3:
print("Usage: python validate_data.py <type> <filepath>")
print(" type: tick, orderbook, funding")
sys.exit(1)
data_type = sys.argv[1]
filepath = sys.argv[2]
if data_type == 'tick':
errors = validate_tick_data(filepath)
elif data_type == 'orderbook':
errors = validate_orderbook_data(filepath)
else:
print(f"Unknown type: {data_type}")
sys.exit(1)
if errors:
print(f"Found {len(errors)} errors:")
for error in errors:
print(f" - {error}")
sys.exit(1)
else:
print("✅ Data validation passed!")
```bash
- *使用方法**:
```bash
# 验证 Tick 数据
python tools/validate_data.py tick tests/data/btc_ticks_1day.csv
# 验证 OrderBook 数据
python tools/validate_data.py orderbook tests/data/btc_ob_1day.jsonl
```bash
- --
## 7. 数据生成工具
### 7.1 模拟数据生成器
- *文件**: `tools/generate_test_data.py`
```python
import pandas as pd
import numpy as np
import json
from datetime import datetime, timedelta
def generate_tick_data(symbol, start_time, duration_hours, ticks_per_second=10):
"""生成模拟 Tick 数据"""
total_ticks = int(duration_hours *3600*ticks_per_second)
# 生成价格随机游走
base_price = 50000
price_changes = np.random.randn(total_ticks)*10
prices = base_price + np.cumsum(price_changes)
# 生成时间戳
timestamps = [start_time + i / ticks_per_second for i in range(total_ticks)]
# 生成成交量
volumes = np.random.exponential(0.5, total_ticks)
# 生成方向
directions = np.random.choice(['buy', 'sell'], total_ticks)
df = pd.DataFrame({
'timestamp': timestamps,
'price': prices,
'volume': volumes,
'direction': directions,
'trade_id': [f'T{i}' for i in range(total_ticks)],
'symbol': [symbol]*total_ticks
})
return df
def generate_orderbook_data(symbol, start_time, duration_hours, updates_per_second=1):
"""生成模拟 OrderBook 数据"""
total_updates = int(duration_hours*3600*updates_per_second)
orderbooks = []
base_price = 50000
for i in range(total_updates):
timestamp = start_time + i / updates_per_second
# 价格随机游走
base_price += np.random.randn()* 5
# 生成 10 档深度
bids = [[base_price - j*0.5, np.random.exponential(1.0)] for j in range(10)]
asks = [[base_price + j*0.5, np.random.exponential(1.0)] for j in range(10)]
orderbooks.append({
'timestamp': timestamp,
'symbol': symbol,
'bids': bids,
'asks': asks
})
return orderbooks
if __name__ == '__main__':
# 生成 1 天的 Tick 数据
start = datetime(2021, 1, 1).timestamp()
tick_df = generate_tick_data('BTC/USDT', start, 24, ticks_per_second=200)
tick_df.to_csv('tests/data/btc_ticks_1day.csv', index=False)
print(f"Generated {len(tick_df)} ticks")
# 生成 1 天的 OrderBook 数据
orderbooks = generate_orderbook_data('BTC/USDT', start, 24, updates_per_second=1)
with open('tests/data/btc_ob_1day.jsonl', 'w') as f:
for ob in orderbooks:
f.write(json.dumps(ob) + '\n')
print(f"Generated {len(orderbooks)} orderbook snapshots")
```bash
- --
## 8. 数据存储建议
### 8.1 文件组织
```bash
data/
├── BTC_USDT/
│ ├── ticks/
│ │ ├── 2021-01-01.csv
│ │ ├── 2021-01-02.csv
│ │ └── ...
│ ├── orderbook/
│ │ ├── 2021-01-01.jsonl
│ │ └── ...
│ ├── funding/
│ │ ├── 2021-01.csv
│ │ └── ...
│ └── bars/
│ ├── 1m/
│ ├── 5m/
│ └── 1h/
└── ETH_USDT/
└── ...
```bash
### 8.2 压缩建议
- **Tick 数据**: 使用 gzip 压缩(.csv.gz)
- **OrderBook 数据**: 使用 gzip 压缩(.jsonl.gz)
- **压缩比**: 通常可达 5-10 倍
### 8.3 性能优化
- **分块读取**: 使用 pandas 的 chunksize 参数
- **列式存储**: 考虑使用 Parquet 格式
- **索引**: 为 timestamp 建立索引
- --
## 9. 常见问题
### Q1: 时间戳格式不一致怎么办?
- *A**: 使用统一的转换函数:
```python
def normalize_timestamp(ts):
"""统一时间戳格式"""
if isinstance(ts, str):
# ISO 格式
return pd.to_datetime(ts).timestamp()
elif ts > 1e12:
# 毫秒时间戳
return ts / 1000.0
else:
# 秒时间戳
return float(ts)
```bash
### Q2: 如何处理缺失数据?
- *A**: 根据数据类型选择策略:
- **Tick**: 跳过缺失的 tick
- **OrderBook**: 使用上一个快照填充
- **Funding**: 线性插值
### Q3: 数据量太大怎么办?
- *A**:
1. 使用流式加载(StreamingEventQueue)
2. 压缩存储(gzip)
3. 分时间段处理
4. 使用更高效的格式(Parquet)
- --
## 10. 附录
### A. 数据源推荐
| 交易所 | Tick | OrderBook | Funding | API |
|--------|------|-----------|---------|-----|
| Binance | ✅ | ✅ | ✅ | REST + WS |
| OKX | ✅ | ✅ | ✅ | REST + WS |
| Bybit | ✅ | ✅ | ✅ | REST + WS |
### B. 相关工具
- **ccxt**: 统一交易所 API
- **pandas**: 数据处理
- **pyarrow**: Parquet 格式支持
- **gzip**: 数据压缩