第三章:金融数据获取——数据源介绍与实战
做量化交易,第一件事是什么?
不是写策略,不是回测,而是——搞到数据。
我见过太多新手,策略写得天花乱坠,结果数据源没选对,回测结果全是假的。嗯,这坑我踩过。今天咱们就把数据获取这件事彻底讲透。
3.1 主流数据源对比
市面上数据源很多,但真正适合个人量化交易者的,其实就几个。我按自己的使用经验排了个序:
| 数据源 | 适用场景 | 免费额度 | 我的评价 |
|---|---|---|---|
| Yahoo Finance | 美股、ETF、指数 | 完全免费 | 入门首选,但数据偶尔有延迟 |
| Alpha Vantage | 全球股票、外汇、加密货币 | 每天500次请求 | API规范,适合自动化 |
| 交易所API | 实时交易数据 | 按交易所规则 | 做高频必须用这个 |
| ccxt | 加密货币统一接口 | 免费 | 一个库搞定所有交易所 |
核心建议:做回测用Yahoo Finance,做实盘用交易所API。别混着用,数据源不一致会让你怀疑人生。
3.2 使用yfinance获取股票数据
yfinance是我用得最多的库。为什么?因为它简单。一行代码就能拿到数据。
先安装:
pip install yfinance
获取苹果公司股票数据:
import yfinance as yf
# 下载历史数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
print(aapl.head())
输出结果长这样:
Open High Low Close Volume
Date
2023-01-03 129.930000 131.250000 124.169998 125.070000 74629900
2023-01-04 126.889999 128.660004 125.080002 126.360001 58355800
小技巧:我个人习惯把数据存成CSV,避免每次重新下载。尤其是回测时,数据一致性很重要。
aapl.to_csv('AAPL_2023.csv')
获取多只股票也很简单:
tickers = ['AAPL', 'GOOGL', 'MSFT', 'AMZN']
data = yf.download(tickers, start='2023-01-01', end='2023-12-31')
# 只取收盘价
close_prices = data['Close']
为什么会推荐yfinance?因为它的数据结构和pandas完美兼容。你拿到的DataFrame可以直接用于计算均线、波动率等指标。省去了大量数据清洗的时间。
注意:yfinance获取的是调整后的价格(Adjusted Close),已经考虑了分红和拆股。但如果你做期权定价,记得用原始价格。我当初没注意这个,回测结果差了5%。
3.3 使用ccxt获取加密货币数据
加密货币这块,ccxt是事实上的标准。它支持100多家交易所,接口统一。说白了,你学会一个,就等于学会了所有。
安装:
pip install ccxt
从币安获取比特币数据:
import ccxt
import pandas as pd
# 初始化交易所
exchange = ccxt.binance()
# 获取K线数据
symbol = 'BTC/USDT'
timeframe = '1d' # 日线
limit = 100 # 最近100条
ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
# 转换成DataFrame
columns = ['timestamp', 'open', 'high', 'low', 'close', 'volume']
df = pd.DataFrame(ohlcv, columns=columns)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
print(df.head())
输出:
timestamp open high low close volume
0 2023-09-01 00:00:00 25920.00 26050.00 25730.00 25980.00 12500.543
1 2023-09-02 00:00:00 25980.00 26100.00 25800.00 26050.00 11800.221
实战经验:我在做加密货币套利策略时,需要同时从3个交易所拉数据。ccxt的接口统一性帮了大忙。你只需要改一下exchange变量名,代码几乎不用动。
获取多个时间周期:
timeframes = ['1h', '4h', '1d']
data = {}
for tf in timeframes:
ohlcv = exchange.fetch_ohlcv('ETH/USDT', tf, limit=200)
data[tf] = pd.DataFrame(ohlcv, columns=columns)
data[tf]['timestamp'] = pd.to_datetime(data[tf]['timestamp'], unit='ms')
3.4 数据清洗与预处理
拿到原始数据后,千万别直接拿去用。我敢说,90%的数据都有问题。缺失值、异常值、时间戳不对齐……这些都是家常便饭。
我的标准清洗流程:
- 检查缺失值——用isnull().sum()看一眼
- 处理缺失值——前向填充或插值
- 检查异常值——比如价格突然跳涨100倍
- 对齐时间戳——多只股票时尤其重要
- 计算衍生指标——收益率、波动率等
代码示例:
# 1. 检查缺失值
print(df.isnull().sum())
# 2. 前向填充(用上一个有效值填充)
df.fillna(method='ffill', inplace=True)
# 3. 检测异常值(3倍标准差法)
from scipy import stats
z_scores = stats.zscore(df['close'])
df['is_outlier'] = abs(z_scores) > 3
# 4. 计算日收益率
df['returns'] = df['close'].pct_change()
# 5. 删除第一行的NaN
df.dropna(inplace=True)
避坑指南:我曾经在回测时发现策略收益高得离谱,查了半天才发现是数据里有重复的时间戳。建议每次清洗后都做一次:
# 检查是否有重复索引
print(df.index.duplicated().sum())
# 去重
df = df[~df.index.duplicated(keep='first')]
3.5 本章知识体系
下面这张图,是我做数据获取时的完整流程。你照着这个走,基本不会出问题。
这张图的核心逻辑很简单:选对数据源 → 清洗数据 → 预处理 → 得到可用数据。每一步都马虎不得。
最后说一句:数据获取是整个量化系统的地基。地基不稳,上面盖的房子再漂亮也没用。我见过太多人花90%的时间写策略,却只花10%的时间搞数据。结果呢?策略在回测里赚得盆满钵满,一上实盘就亏成狗。
别走这条路。把数据搞扎实了,后面的路自然顺。