第三章:金融数据获取——量化系统的“水源”
做量化交易,第一件事不是写策略,而是搞数据。
我见过太多人,策略写得天花乱坠,结果数据源一断,整个系统直接瘫痪。说白了,数据就是量化系统的“水源”。水源不干净,后面再好的管道也白搭。
核心观点:数据获取不是简单的“下载”,而是一个完整的工程流程——选源、清洗、存储、管理。每一步都可能踩坑。
3.1 用Tushare获取A股数据
Tushare是国内用得最多的免费数据源之一。我个人习惯用它来拉A股的日线数据,稳定且字段齐全。
先装包:
pip install tushare
然后注册一个token(去tushare.pro官网申请,免费的)。
看个例子:
import tushare as ts
# 设置token
ts.set_token('你的token')
# 初始化接口
pro = ts.pro_api()
# 获取平安银行日线数据
df = pro.daily(ts_code='000001.SZ', start_date='20230101', end_date='20231231')
print(df.head())
小提示:Tushare的接口有频率限制,普通用户每分钟最多200次。我建议你写个简单的限流器,不然跑着跑着就被封了。
除了日线,Tushare还能拿财务数据、行业分类、龙虎榜等。比如拿个利润表:
# 获取利润表
income = pro.income(ts_code='000001.SZ', start_date='20230101', end_date='20231231')
print(income.columns.tolist())
嗯,这里要注意——财务数据是按季度发布的,不是每天都有。你拉下来之后会发现很多空值,后面清洗的时候要处理。
3.2 用Yahoo Finance获取美股数据
美股数据,我首选Yahoo Finance。免费、覆盖广、历史数据全。不过它有个毛病——经常被墙,需要科学上网。
推荐用 yfinance 这个库,比原生的 pandas-datareader 好用太多:
pip install yfinance
拉取苹果公司的数据:
import yfinance as yf
# 下载苹果公司数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
print(aapl.head())
yfinance返回的是pandas DataFrame,列名是Open、High、Low、Close、Volume、Adj Close。注意,它默认返回的是调整后的价格(Adj Close),这个在回测时很重要。
避坑指南:我曾经在回测时直接用Close价格,结果发现分红除权后价格跳空,策略信号全乱了。后来才意识到要用Adj Close。你想想看,如果不用复权价格,你的回测结果就是错的。
yfinance还能拿财报数据:
# 获取苹果公司财报
aapl_info = yf.Ticker('AAPL')
financials = aapl_info.financials
print(financials.head())
3.3 数据清洗与预处理
数据拉下来之后,千万别直接用。我敢说,90%的原始数据都有问题。
常见的坑:
- 缺失值:停牌日、节假日、数据源漏了
- 异常值:价格突然跳变、成交量少个零
- 时间不对齐:A股和美股交易时间不同,合并时要注意
- 复权问题:前复权还是后复权?不同策略要求不同
我的清洗流程一般是这样的:
import pandas as pd
import numpy as np
# 假设df是原始数据
def clean_data(df):
# 1. 删除全空的行
df = df.dropna(how='all')
# 2. 填充缺失值(用前向填充)
df = df.fillna(method='ffill')
# 3. 删除异常值(比如价格小于0)
df = df[df['close'] > 0]
# 4. 排序(按时间升序)
df = df.sort_index()
return df
# 使用
df_clean = clean_data(df)
重点:前向填充(ffill)是处理金融时间序列最常用的方法。因为停牌日的价格应该等于上一个交易日,而不是0或者空。
还有一个容易被忽略的点——时间对齐。如果你同时做A股和美股,它们的交易时间不一样。A股是9:30-15:00,美股是21:30-04:00(夏令时)。合并数据时,我习惯把时间统一成UTC+8,然后按日对齐。
3.4 数据存储:CSV / HDF5 / 数据库
数据清洗完了,得存起来。三种方式各有优劣:
| 存储方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| CSV | 简单、通用、可读 | 慢、占用空间大 | 小数据量、调试用 |
| HDF5 | 快、压缩率高、支持大数据 | 二进制、不易查看 | 中等数据量、日常回测 |
| 数据库(MySQL/PostgreSQL) | 支持复杂查询、并发访问 | 部署复杂、维护成本高 | 生产环境、团队协作 |
我个人习惯:
- 开发调试时用CSV,方便看数据
- 回测时用HDF5,速度快
- 上线后用数据库,支持多进程读写
存成CSV很简单:
df_clean.to_csv('aapl_data.csv', index=False)
存成HDF5:
df_clean.to_hdf('market_data.h5', key='aapl', mode='w')
存到MySQL:
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://user:password@localhost/mydb')
df_clean.to_sql('stock_data', engine, if_exists='replace', index=False)
小技巧:HDF5支持压缩,存同样的数据,体积只有CSV的1/3左右。而且读取速度比CSV快10倍以上。我建议你回测时都用HDF5。
嗯,数据存储这块,其实没有绝对的好坏。你想想看,如果你只是自己跑跑策略,CSV完全够用。但如果你要搭建一个实盘系统,数据库是必须的。
好了,这一章的内容就到这里。数据获取是整个量化系统的基石,花时间把这一步做好,后面会省很多事。