4. 数据格式规范:CSV、Parquet、HDF5、数据库表结构设计原则
在量化回测实验中,数据格式的选择直接影响存储效率、读写速度以及后续分析的便捷性。本章将系统梳理四种主流数据格式(CSV、Parquet、HDF5、数据库表)的适用场景、核心差异与设计原则,帮助你在不同实验阶段做出合理的技术选型。
4.1 四种格式的核心特性对比
下表从存储效率、读写性能、类型支持、元数据管理四个维度进行横向对比,为后续的格式选择提供决策依据。
| 特性维度 | CSV | Parquet | HDF5 | 数据库表 |
|---|---|---|---|---|
| 存储效率 | 低(纯文本,无压缩) | 高(列式压缩,支持多种编码) | 中高(支持压缩与分块) | 中(依赖存储引擎) |
| 读写性能 | 写快读慢(全表扫描) | 读快写中(列裁剪、谓词下推) | 读快写快(分块I/O) | 读快写快(索引优化) |
| 类型支持 | 弱(仅字符串,需后处理) | 强(原生支持时间、嵌套结构) | 强(支持复合数据类型) | 强(严格模式约束) |
| 元数据管理 | 无(需外部维护) | 内嵌(Schema与统计信息) | 内嵌(Group/Dataset结构) | 系统级(Catalog与字典) |
| 适用阶段 | 原始数据采集、快速预览 | 大规模分析、特征工程 | 科学计算、多维数组存储 | 生产环境、多用户并发 |
选型建议: 在回测实验的早期探索阶段,优先使用 CSV 进行快速验证;当数据量超过 1GB 或需要频繁读取特定列时,立即迁移至 Parquet;若涉及多维时间序列或矩阵运算,HDF5 是更优选择;生产级回测系统必须使用数据库表来保证事务一致性与并发控制。
4.2 CSV 格式规范与陷阱
CSV 是量化回测中最通用的交换格式,但其缺乏类型约束的特性容易引入数据质量问题。以下是经过实践检验的 CSV 规范清单:
- 列名规范: 使用小写字母 + 下划线,避免空格与特殊字符。例如
close_price而非Close Price。 - 时间列格式: 统一使用 ISO 8601 标准(
YYYY-MM-DD HH:mm:ss),避免歧义。 - 缺失值处理: 使用空字符串或
NaN,禁止使用N/A、null等混合标记。 - 浮点数精度: 价格字段保留 4 位小数,成交量字段保留 2 位小数,避免无意义的长尾数字。
- 文件编码: 强制使用 UTF-8 without BOM,避免跨平台乱码。
# 符合规范的 CSV 示例
timestamp,symbol,open,high,low,close,volume
2024-01-02 09:30:00,AAPL,185.5000,186.2000,184.8000,185.9000,1250000.00
2024-01-02 09:31:00,AAPL,185.9000,186.5000,185.7000,186.1000,980000.00
常见陷阱: 不要依赖 CSV 的隐式类型转换。例如,
volume 列如果包含逗号分隔符(如 1,250,000),会被解析为字符串而非数值。始终在读取时显式指定数据类型。
4.3 Parquet 列式存储设计
Parquet 是当前大数据生态中回测数据存储的事实标准。其列式存储结构允许只读取需要的列,大幅减少 I/O 开销。设计 Parquet 数据集时需关注以下原则:
- 分区策略: 按日期或 symbol 进行分区,避免单文件过大。推荐分区粒度:日频数据按
year/month/day分区,高频数据按year/month/day/hour分区。 - 压缩算法: 优先使用
snappy(平衡压缩比与解压速度)或zstd(更高压缩比)。避免使用gzip在回测场景中造成性能瓶颈。 - Schema 演进: 允许新增列时使用
NULL默认值,避免破坏已有数据文件。 - 行组大小: 设置为 512MB ~ 1GB,兼顾内存占用与并行读取效率。
性能基准: 在相同硬件条件下,读取 100 列中的 5 列时,Parquet 比 CSV 快 10~20 倍,磁盘占用减少 60%~80%。对于包含 3 年 tick 级数据的回测库,建议全量迁移至 Parquet。
4.4 HDF5 多维数据存储
HDF5 在量化回测中主要用于存储多维时间序列数据(如期权隐含波动率曲面、因子暴露矩阵)和模型参数快照。其核心设计原则包括:
- Group 组织: 使用
/market/equity/、/factors/alpha/等层级结构管理数据集,避免扁平化命名。 - Chunk 设置: 根据访问模式设置分块大小。按时间序列读取时,设置
chunks=(10000, 1);按截面读取时,设置chunks=(1, 500)。 - 压缩与缓存: 启用
complib='blosc:lz4'获得最佳读写平衡;设置chunk_cache_mem_size为 1GB 以上以加速重复访问。 - 版本管理: 在 Group 属性中记录数据生成时间、回测版本号、参数哈希,便于实验追溯。
# HDF5 数据集创建示例(Python)
import h5py
import numpy as np
with h5py.File('vol_surface.h5', 'w') as f:
# 创建 Group 层级
grp = f.create_group('/options/SPX/2024')
# 创建数据集:行=时间,列=行权价
ds = grp.create_dataset(
'implied_vol',
shape=(10000, 50),
dtype='f4',
chunks=(1000, 50),
compression='blosc:lz4',
shuffle=True
)
# 写入元数据
ds.attrs['generated_at'] = '2024-06-01T00:00:00'
ds.attrs['model_version'] = 'v2.3.1'
ds.attrs['param_hash'] = 'a1b2c3d4'
适用场景: 当你的回测需要频繁读取 3 维或 4 维数据(如时间 × 标的 × 行权价 × 波动率)时,HDF5 的块存储和部分 I/O 能力远优于 Parquet。但注意 HDF5 不适合多进程并发写入,生产环境需加锁或使用只读模式。
4.5 数据库表结构设计原则
生产级回测系统通常使用关系型数据库(PostgreSQL、ClickHouse)或时序数据库(InfluxDB、TimescaleDB)来管理实验数据。以下是经过验证的表结构设计原则:
- 范式化与反范式化平衡: 基础行情数据采用 3NF 减少冗余;回测结果宽表采用反范式化,避免频繁 JOIN 影响性能。
- 分区与索引: 按时间范围分区(如按月分区),在
timestamp和symbol上建立复合索引,覆盖 90% 以上的查询模式。 - 数据类型精简化: 价格字段使用
DECIMAL(12,4)而非FLOAT,避免浮点误差;成交量使用BIGINT;状态字段使用SMALLINT枚举。 - 审计字段: 每张表必须包含
created_at、updated_at、batch_id三个审计字段,支持数据回溯与问题排查。
-- 回测结果表结构示例(PostgreSQL)
CREATE TABLE backtest_results (
result_id BIGSERIAL PRIMARY KEY,
strategy_id INTEGER NOT NULL REFERENCES strategies(id),
symbol VARCHAR(10) NOT NULL,
trade_date DATE NOT NULL,
entry_price DECIMAL(12,4),
exit_price DECIMAL(12,4),
position_size BIGINT,
pnl DECIMAL(16,4),
commission DECIMAL(10,4),
slippage DECIMAL(10,4),
status SMALLINT DEFAULT 0, -- 0:待结算, 1:已结算, 2:异常
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
batch_id UUID NOT NULL
) PARTITION BY RANGE (trade_date);
-- 创建月度分区
CREATE TABLE backtest_results_202401 PARTITION OF backtest_results
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
-- 复合索引
CREATE INDEX idx_results_date_symbol ON backtest_results (trade_date, symbol);
4.6 格式选型决策流程
在实际项目中,数据格式的选择往往不是单一的,而是根据数据生命周期不同阶段采用混合策略。以下决策流程可帮助你快速定位:
- 数据采集阶段: 使用 CSV 作为原始数据落地格式,保留最原始的文本形态,便于人工校验与第三方工具导入。
- 数据清洗阶段: 转换为 Parquet,利用列式存储加速特征工程与缺失值处理。
- 回测计算阶段: 高频多维数据使用 HDF5,低频宽表数据使用 Parquet,结果数据写入数据库表。
- 结果分析阶段: 从数据库表或 Parquet 中读取聚合结果,使用 CSV 导出用于报告与可视化。
最佳实践: 在回测实验管理系统中,建议建立统一的
data_catalog 元数据表,记录每个数据集的格式、分区信息、生成时间与校验哈希。这样无论底层使用何种格式,上层分析代码都可以通过目录服务透明访问,实现存储格式与业务逻辑的解耦。