4. 金融数据获取:使用 Tushare/Akshare 获取股票日线数据、数据清洗与预处理
在量化策略灰度回测中,数据是模型训练的“原材料”。本章将系统讲解如何通过 Tushare 和 Akshare 两个主流 Python 金融数据接口获取股票日线数据,并完成数据清洗与预处理,为后续 LightGBM 特征工程和模型训练奠定基础。
4.1 数据源选型对比
选择合适的数据源是策略开发的第一步。下表从数据覆盖、更新频率、免费额度、接口稳定性四个维度对比 Tushare 与 Akshare:
| 对比维度 | Tushare Pro | Akshare |
|---|---|---|
| 数据覆盖 | A 股、港股、期货、基金、指数、宏观经济 | A 股、港股、期货、基金、外汇、债券 |
| 更新频率 | 交易日 17:00 后更新当日数据 | 实时行情 + 盘后数据 |
| 免费额度 | 注册即送 200 积分,日调用 200 次 | 完全免费,无调用次数限制 |
| 接口稳定性 | 高,需 token 鉴权 | 中,依赖上游数据源 |
| 适用场景 | 专业回测、因子研究 | 快速原型、教学演示 |
选型建议: 本课程以 Tushare Pro 为主数据源,因其数据质量高、字段规范,适合构建生产级回测流水线。Akshare 作为备选方案,用于快速验证或补充特殊数据。
4.2 数据获取流程
数据获取遵循“初始化 → 参数配置 → 请求 → 存储”的标准流程。以下为使用 Tushare 获取沪深 300 成分股日线数据的核心步骤:
- 注册与鉴权: 在 Tushare 官网注册账号,获取个人 token。
- 安装与导入:
pip install tushare,并设置 token。 - 参数配置: 指定股票代码、起始日期、结束日期、复权类型。
- 数据请求: 调用
pro.daily()或pro.daily_basic()接口。 - 本地存储: 保存为 CSV 或 Parquet 格式,便于后续读取。
import tushare as ts
import pandas as pd
# 设置 token(请替换为你的实际 token)
ts.set_token('your_tushare_token_here')
pro = ts.pro_api()
# 获取平安银行(000001.SZ)2023年日线数据
df = pro.daily(
ts_code='000001.SZ',
start_date='20230101',
end_date='20231231',
fields='ts_code,trade_date,open,high,low,close,vol,amount'
)
# 查看数据前5行
print(df.head())
字段说明:
open(开盘价)、high(最高价)、low(最低价)、close(收盘价)、vol(成交量,手)、amount(成交额,千元)。
4.3 数据清洗与预处理
原始数据通常存在缺失值、异常值、非交易时间戳等问题,必须经过清洗才能用于模型训练。清洗流程包括以下五个环节:
- 缺失值处理: 检查
isnull(),对缺失的 OHLC 数据采用前向填充或插值法。 - 异常值检测: 使用 Z-score 或 IQR 方法识别价格突变、成交量异常。
- 时间序列排序: 按
trade_date升序排列,确保时间顺序正确。 - 复权处理: 调用
pro.adj_factor()获取复权因子,计算后复权价格。 - 数据类型转换: 将
trade_date转为 datetime 类型,数值列转为 float。
# 数据清洗示例
def clean_daily_data(df):
# 1. 排序
df = df.sort_values('trade_date').reset_index(drop=True)
# 2. 日期转换
df['trade_date'] = pd.to_datetime(df['trade_date'])
# 3. 缺失值处理(前向填充)
df = df.fillna(method='ffill')
# 4. 异常值处理(成交量异常)
q1 = df['vol'].quantile(0.25)
q3 = df['vol'].quantile(0.75)
iqr = q3 - q1
df = df[(df['vol'] >= q1 - 1.5 * iqr) & (df['vol'] <= q3 + 1.5 * iqr)]
# 5. 添加复权价格(示例:后复权)
# 实际需合并 adj_factor 表
return df
df_clean = clean_daily_data(df)
print(f"清洗后数据量: {len(df_clean)} 行")
4.4 数据预处理流程架构
下图展示了从原始数据到模型可用特征矩阵的完整预处理流水线:
4.5 数据质量检查清单
在将数据送入 LightGBM 模型之前,建议逐项核对以下质量指标:
| 检查项 | 合格标准 | 处理方法 |
|---|---|---|
| 缺失值比例 | < 5% | 前向填充 / 删除 |
| 日期连续性 | 无交易日跳空 | 补全交易日历 |
| 价格合理性 | open/high/low/close 逻辑一致 | 修正或删除异常行 |
| 成交量非负 | vol >= 0 | 替换为 NaN 后填充 |
| 复权因子 | 与原始价格匹配 | 重新计算复权因子 |
常见陷阱: 使用 Tushare 时,
daily 接口返回的是未复权数据,直接用于计算收益率会导致偏差。务必先获取 adj_factor 表,计算后复权价格后再进行特征工程。
4.6 数据存储与版本管理
为支持灰度回测的多次迭代,建议采用分层存储策略:
- 原始层(raw): 保存从 Tushare 获取的原始 CSV,按日期分区。
- 清洗层(clean): 经过缺失值、异常值处理后的 Parquet 文件。
- 特征层(feature): 包含衍生特征和标准化后的最终矩阵,直接供模型调用。
# 分层存储示例
import os
base_path = './data/'
os.makedirs(f'{base_path}raw', exist_ok=True)
os.makedirs(f'{base_path}clean', exist_ok=True)
os.makedirs(f'{base_path}feature', exist_ok=True)
# 保存原始数据
df.to_csv(f'{base_path}raw/000001_SZ_2023.csv', index=False)
# 保存清洗后数据
df_clean.to_parquet(f'{base_path}clean/000001_SZ_2023.parquet')
# 保存特征矩阵(示例)
# X_train.to_parquet(f'{base_path}feature/X_train.parquet')
通过本章的学习,你已经掌握了从数据获取到清洗预处理的完整流程。下一阶段将基于清洗后的数据,构建 LightGBM 所需的特征工程体系。