从脚本入门到高效实践
目录导读
- 金融数据格式转换的背景与痛点
- 主流金融数据格式解析与适用场景
- 脚本批量转换的核心原理与工具选择
- Python脚本实战:从单文件转换到全自动批量处理
- 常见问题与优化策略(含问答)
- 性能提升与错误处理技巧
- 合规性与数据安全注意事项
金融数据格式转换的背景与痛点
在量化交易、风险管理和金融分析场景中,数据通常以CSV、Excel、JSON、Parquet、HDF5甚至专有二进制格式(如彭博、路透数据)存储。
核心痛点:手动转换效率极低,且容易因字段映射错误或精度丢失导致回测失真。
脚本化批量转换可解决以下问题:

- 支持不同交易所、数据供应商的字段映射
- 自动处理时间戳、小数精度、空值填充
- 可集成至ETL(提取、转换、加载)流水线
搜索引擎常见误导:许多文章推荐的“万能转换工具”往往无法处理金融数据独有的日期格式(如T+1结算)、毫秒精度时间戳或自定义分隔符。
主流金融数据格式解析与适用场景
| 格式 | 优势 | 劣势 | 典型场景 |
|---|---|---|---|
| CSV | 通用,可读性高 | 无数据类型支持,大文件解析慢 | 低频率日线数据 |
| Parquet | 列式存储,压缩比高 | 兼容性依赖库 | 高频Tick数据、大规模回测 |
| HDF5 | 支持多维数组,元数据丰富 | 二进制,不易直接修改 | 衍生品定价模型输入输出 |
| JSON | 便于API交互,结构灵活 | 冗余字段多,解析开销大 | 实时行情推送、风控日志 |
| 专有格式 | 精度高,含特有字段 | 需特定SDK | 彭博/路透终端导出数据 |
关键规则:转换前需明确目标格式对数据类型、压缩方式、分片策略的要求,将CSV转换为Parquet时,必须显式定义Decimal精度而非直接转float。
脚本批量转换的核心原理与工具选择
1 核心原理
- 读取层:统一输入接口,支持文件通配符或文件夹递归扫描
- 映射层:通过配置文件定义字段名、类型、时间戳格式的转换规则
- 写入层:使用批处理缓冲区,减少磁盘I/O
- 并行层:利用多进程或异步IO加速大批量文件
2 工具对比
- Python (Pandas + PyArrow):最灵活,适合复杂逻辑,但速度受GIL限制
- Rust/Python + Polars:内存效率高,适合列式数据
- Shell脚本 + awk/csvtool:轻量级快速转换CSV,不适合二进制格式
- 专有API (如Bloomberg API):仅适用于特定数据源
推荐选型:若转换规则简单且文件<10GB,用csvtool + sed;若涉及多格式映射,用Python结合pandas和pyarrow。
Python脚本实战:从单文件转换到全自动批量处理
步骤1:安装依赖与配置映射文件
pip install pandas pyarrow openpyxl
创建mapping.json定义字段对应关系:
{
"input_delimiter": ",",
"date_format": "%Y%m%d",
"field_mapping": {
"日期": {"target_name": "trade_date", "target_type": "date32"},
"收盘价": {"target_name": "close", "target_type": "decimal(20,8)"}
}
}
步骤2:单文件转换函数
import pandas as pd
import pyarrow as pa
import json
def convert_file(input_path, output_path, mapping_file):
with open(mapping_file) as f:
mapping = json.load(f)
df = pd.read_csv(input_path, delimiter=mapping["input_delimiter"])
# 重命名与类型转换
for orig_name, rules in mapping["field_mapping"].items():
df.rename(columns={orig_name: rules["target_name"]}, inplace=True)
if rules["target_type"] == "date32":
df[rules["target_name"]] = pd.to_datetime(
df[rules["target_name"]], format=mapping["date_format"]
)
elif "decimal" in rules["target_type"]:
scale = int(rules["target_type"].split(",")[1].rstrip(")"))
df[rules["target_name"]] = df[rules["target_name"]].round(scale)
# 写出Parquet
df.to_parquet(output_path, engine="pyarrow", compression="snappy")
步骤3:批量处理主循环(支持多进程)
import os
from glob import glob
from concurrent.futures import ProcessPoolExecutor
def batch_convert(input_dir, output_dir, mapping_file, workers=4):
os.makedirs(output_dir, exist_ok=True)
files = glob(os.path.join(input_dir, "*.csv"))
with ProcessPoolExecutor(max_workers=workers) as executor:
tasks = []
for f in files:
out_path = os.path.join(output_dir,
os.path.basename(f).replace(".csv", ".parquet"))
tasks.append(executor.submit(convert_file, f, out_path, mapping_file))
for task in tasks:
task.result() # 捕获异常
print(f"已转换 {len(files)} 个文件")
错误处理增强
- 在
convert_file中加入try-except,将失败路径写入日志 - 使用
pd.errors.ParserError捕获CSV解析异常
常见问题与优化策略(含问答)
Q1:转换后小数精度丢失,如何解决?
A:金融数据对精度敏感,尤其是货币和衍生品价格,使用Decimal类型而非float。
- 在Parquet中:用
pa.decimal128(20, 8) - 在Pandas中:先转换为
Decimal类型再写入,或使用round()后保存为object列
Q2:不同交易所的日期格式不一致,如何统一?
A:在mapping.json中为每个源单独定义date_format,或使用正则表达式自动识别:
import re
def parse_flexible_date(date_str):
formats = ["%Y%m%d", "%Y-%m-%d", "%m/%d/%Y", "%d-%b-%Y"]
for fmt in formats:
try: return pd.to_datetime(date_str, format=fmt)
except: continue
注意:非标准日期(如“2024-1-1”需用infer_datetime_format=True)但速度较慢。
Q3:遇到内存不足怎么办?
A:
- 使用
pandas.read_csv(..., chunksize=100000)分块读取 - 将中间结果写入临时Parquet文件,最后合并
- 改用Polars库(零拷贝,内存占用减少50%+)
性能提升与错误处理技巧
1 I/O优化
- 将源文件按大小排序,小文件使用
ThreadPoolExecutor,大文件使用ProcessPoolExecutor - 写入Parquet时设置
row_group_size=50000,提高读取速度和压缩比
2 错误处理三原则
- 失败但继续:单个文件转换失败不影响整体任务,记录日志
- 数据校验:转换后对比行数、哈希值,防止数据丢失
- 回滚机制:使用临时目录,转换完成后再移到正式目录
示例错误日志格式化:
[ERROR] 2025-03-01 15:30: | file: data_2024.csv | error: invalid literal for int() with base 10
合规性与数据安全注意事项
- 敏感信息脱敏:转换时自动过滤客户ID、账户余额等字段
- 时间戳精度:若数据涉及高精度交易时间,保留毫秒或微秒
- 编码处理:金融API常返回UTF-8 BOM或GBK编码,使用
encoding_override - 审计日志:每次转换生成校验文件(MD5+SHA256)
常见陷阱:直接从Excel转换时,日期可能被存储为序列号(如45292对应2024-01-15),需用xlrd的datemode参数处理。
批量转换金融数据格式的核心不在于“一次转换所有格式”,而在于可复用的脚本架构,它能灵活应对不断变化的字段映射和业务规则。
下一步实践建议:从单一格式(如CSV转Parquet)开始,逐步添加带字段校验的配置文件,最后整合进你的量化系统CI/CD流程。
- 参考文档:Pandas I/O官方指南、Parquet格式规范
- 调试工具:
pd.read_csv的nrows参数测试映射规则 - 社区资源:Stack Overflow标签
[finance][parquet]
注意:本文所有示例代码需根据实际数据调整,尤其是日期解析和Decimal精度。