3. 金融市场数据基础:数据源介绍、OHLCV格式与预处理
做量化交易,第一件事就是搞数据。没有数据,策略就是空中楼阁。我个人习惯把数据获取比作「做饭前的买菜」——菜不新鲜,厨艺再好也白搭。
这一章,咱们就聊聊数据那些事儿。我会介绍几个常用的数据源,讲讲OHLCV这个标准格式,再分享一些我踩过的数据清洗的坑。
3.1 数据源:从哪里拿数据?
市面上数据源很多,但真正适合个人开发者、小团队的,其实就那么几个。我挑三个最常用的说说。
3.1.1 Yahoo Finance
Yahoo Finance 是老牌数据源了。免费、覆盖全球市场、接口简单。我刚开始学量化时,用的就是它。
优点很明显:美股、港股、ETF、指数,基本都能拿到。缺点嘛,就是国内访问不太稳定,偶尔会抽风。
用 Python 的 yfinance 库,几行代码就能拉数据:
import yfinance as yf
# 下载苹果股票数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
print(aapl.head())
嗯,这里要注意:Yahoo Finance 的数据是调整后的价格,已经考虑了分红、拆股。如果你做回测,直接用就行,不用自己再处理。
3.1.2 Tushare
Tushare 是国内最流行的免费数据源之一。它覆盖A股、期货、基金、宏观经济等。我个人觉得,做A股量化,Tushare 是首选。
不过,Tushare 需要注册获取 token,而且有积分限制。免费用户每天能调用的次数有限。我曾经因为没注意积分,跑回测跑到一半被限流,气得不行。
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())
3.1.3 AKShare
AKShare 是后起之秀,开源、免费、数据源丰富。它把很多公开数据源(比如新浪、东方财富、上交所官网)整合到了一起。
我最近比较喜欢用 AKShare,因为它不需要注册,直接 pip install 就能用。而且它支持的数据类型特别多,连「龙虎榜」、「融资融券」这种都有。
import akshare as ak
# 获取A股日线数据
df = ak.stock_zh_a_hist(symbol="000001", period="daily",
start_date="20230101", end_date="20231231")
print(df.head())
说白了,这三个数据源各有千秋。我的建议是:做美股用 Yahoo Finance,做A股用 Tushare 或 AKShare。如果你刚开始学,AKShare 上手最快。
3.2 OHLCV 数据格式:标准是什么?
OHLCV 是金融数据的标准格式。它代表四个价格和一个成交量:
- Open:开盘价
- High:最高价
- Low:最低价
- Close:收盘价
- Volume:成交量
为什么是这个格式?你想想看,一根K线,就靠这五个数字描述。开盘价告诉你当天从哪开始,收盘价告诉你最终结果,最高最低告诉你波动范围,成交量告诉你市场参与度。
举个例子,一份标准的 OHLCV 数据长这样:
| Date | Open | High | Low | Close | Volume |
|---|---|---|---|---|---|
| 2023-01-03 | 130.28 | 131.74 | 129.89 | 131.25 | 68745900 |
| 2023-01-04 | 131.35 | 132.43 | 130.78 | 131.94 | 66554400 |
这里有个细节:不同数据源对字段命名可能不一样。比如 Yahoo Finance 用 Adj Close 表示调整收盘价,而 Tushare 用 close。我建议你拿到数据后,先统一字段名,省得后面搞混。
3.3 数据清洗与预处理:脏数据怎么处理?
真实世界的数据,没有干净的。我做过一个项目,从三个数据源拉同一只股票的数据,结果三个结果都不一样。嗯,这就是现实。
数据清洗,说白了就是三件事:去重、补缺、纠错。
3.3.1 处理缺失值
缺失值最常见。比如节假日没有交易,或者数据源某天没更新。处理方式有两种:
- 直接删除:如果缺失不多,直接 dropna() 就行
- 向前填充:用前一天的数据填充,适合非交易日的缺失
import pandas as pd
# 读取数据
df = pd.read_csv('stock_data.csv', index_col='Date', parse_dates=True)
# 检查缺失值
print(df.isnull().sum())
# 向前填充
df.fillna(method='ffill', inplace=True)
# 或者直接删除
df.dropna(inplace=True)
3.3.2 处理异常值
异常值更隐蔽。比如某天收盘价突然涨了100倍,这明显是数据录入错误。怎么发现?用统计方法:
# 用 Z-score 检测异常值
from scipy import stats
import numpy as np
z_scores = np.abs(stats.zscore(df['Close']))
outliers = df[z_scores > 3]
print(f"发现 {len(outliers)} 个异常值")
我曾经遇到过一个案例:某只股票因为数据源错误,连续三天收盘价都是0。回测时策略在这三天疯狂买入,结果回测收益高得离谱。后来发现是数据问题,白高兴一场。
3.3.3 统一时间索引
不同数据源的时间格式可能不一样。有的用 2023-01-01,有的用 20230101。我建议统一转换成 pandas 的 datetime 格式:
# 统一时间格式
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
df.sort_index(inplace=True)
3.4 数据存储:CSV 还是 HDF5?
数据清洗完了,得存起来。两种主流格式:CSV 和 HDF5。
CSV 是文本格式,优点是人眼可读、通用性强。缺点是文件大、读写慢。适合小数据量(几千只股票以下)。
HDF5 是二进制格式,优点是压缩率高、读写快。缺点是不方便直接查看。适合大数据量(全市场、多年数据)。
我的建议是:学习阶段用 CSV,方便调试。生产环境用 HDF5,性能好。
# 存储为 CSV
df.to_csv('stock_data.csv')
# 存储为 HDF5
df.to_hdf('stock_data.h5', key='data', mode='w')
好了,数据基础就聊到这儿。下一章咱们开始写第一个策略——别急,先把数据准备好,后面的事就顺了。