3. 汇率数据获取:使用 Yahoo Finance API (yfinance) 获取历史汇率数据,数据清洗与初步探索

做量化交易,数据就是命根子。这话我常跟团队里的人讲。

数据质量不行,后面模型再花哨也是白搭。今天咱们就聊聊怎么把汇率数据搞到手,并且把它收拾得干干净净。

3.1 为什么选 Yahoo Finance?

市面上能拿汇率数据的渠道不少,比如 Bloomberg、Reuters,还有央行官网。但说实话,对于个人学习和研究来说,Yahoo Finance 是最友好的选择。

它免费、稳定,而且通过 yfinance 这个 Python 库,几行代码就能搞定。我在做早期原型验证时,经常用它来快速获取数据。当然,如果你要上生产环境,那还是得考虑 Bloomberg 这类专业数据源。

核心优势:

  • 完全免费,无需 API Key
  • 覆盖主流货币对,数据历史久
  • Python 接口简单,上手快

3.2 安装与导入 yfinance

先装包。这个很简单,一行命令搞定:

pip install yfinance

装完之后,在代码里导入:

import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime

嗯,这里要注意一点。yfinance 依赖 pandas,所以最好先把 pandas 也装上。我个人习惯把 numpy 也带上,后面做数值计算方便。

3.3 获取汇率数据:以 EUR/USD 为例

汇率在 Yahoo Finance 里是用特定的代码表示的。比如欧元兑美元,代码是 EURUSD=X。记住这个格式:货币1货币2=X

来看代码:

# 定义货币对
ticker = "EURUSD=X"

# 获取数据
data = yf.download(ticker, start="2020-01-01", end="2024-12-31")

# 看一眼
print(data.head())

跑完之后,你会得到一个 DataFrame,里面包含 OpenHighLowCloseVolumeAdj Close 这几列。

你想想看,对于汇率来说,Volume 其实没什么意义,因为外汇市场是场外交易,没有统一的成交量数据。所以后面我们一般只用 Close 或者 Adj Close

小技巧: 如果你只需要收盘价,可以直接用 data['Close'] 提取。这样数据更干净,也省内存。

3.4 数据清洗:把脏数据扔掉

数据拿到手,别急着用。先看看有没有坑。

我曾经有一次,模型跑出来结果特别离谱,查了半天才发现是数据里有几个空值没处理。从那以后,我养成了一个习惯:拿到数据先做清洗。

常见的清洗步骤:

  1. 检查缺失值
  2. 处理异常值
  3. 统一时间索引

来看代码:

# 检查缺失值
print(data.isnull().sum())

# 删除缺失值(或者用前向填充)
data_clean = data.dropna()

# 或者用前向填充
# data_clean = data.fillna(method='ffill')

# 检查索引是否连续
print(data_clean.index.is_monotonic_increasing)

这里我多说一句。对于金融时间序列,用前向填充(ffill)通常比直接删除更合理。因为市场在非交易时段没有数据,用前一个交易日的价格填充,逻辑上说得通。

注意: 如果缺失值太多(比如连续几天没有数据),那就要小心了。可能是节假日,也可能是数据源本身有问题。这时候我建议去 Yahoo Finance 网页上手动核对一下。

3.5 初步探索:数据长什么样?

数据洗干净了,接下来就是看看它到底长什么样。这一步叫 EDA(探索性数据分析)。

我一般会做三件事:

  • 看统计摘要
  • 画价格走势图
  • 看收益率分布

先看统计摘要:

print(data_clean.describe())

这个会告诉你均值、标准差、最大最小值等。如果发现最大值异常高,那就要怀疑是不是数据有误。

然后画个走势图:

import matplotlib.pyplot as plt

data_clean['Close'].plot(figsize=(12, 6), title='EUR/USD 历史走势')
plt.xlabel('日期')
plt.ylabel('汇率')
plt.show()

走势图能让你直观地看到趋势和波动。比如 2020 年疫情初期,EUR/USD 有一波剧烈波动,这就是典型的黑天鹅事件。

最后看收益率分布:

# 计算日收益率
data_clean['Return'] = data_clean['Close'].pct_change()

# 画直方图
data_clean['Return'].hist(bins=50, figsize=(10, 6))
plt.title('EUR/USD 日收益率分布')
plt.xlabel('收益率')
plt.ylabel('频次')
plt.show()

收益率分布如果接近正态分布,那说明市场比较正常。如果出现厚尾(极端值多),那就要小心了——这往往是风险事件的前兆。

3.6 知识体系总览

下面这张图,是我自己梳理的本章知识结构。你可以把它当作一个路线图,方便回顾。

汇率数据获取与清洗知识体系 数据获取 数据清洗 初步探索 yfinance 安装 货币对代码格式 下载历史数据 缺失值检查 异常值处理 时间索引统一 统计摘要 走势图 收益率分布 干净、可用的汇率数据集 数据获取 → 数据清洗 → 初步探索 → 可用数据集 ⚠️ 避坑提示 注意节假日缺失数据,建议用前向填充而非直接删除

3.7 多货币对同时获取

实际项目中,我们往往需要多个货币对。比如做套利策略,可能要同时看 EUR/USD、GBP/USD、USD/JPY。

yfinance 支持一次性下载多个代码:

# 定义多个货币对
tickers = ["EURUSD=X", "GBPUSD=X", "USDJPY=X"]

# 下载数据
multi_data = yf.download(tickers, start="2020-01-01", end="2024-12-31")

# 提取收盘价
close_prices = multi_data['Close']

print(close_prices.head())

这样拿到的数据,每一列就是一个货币对的收盘价。方便做相关性分析。

小技巧: 如果你发现某个货币对的数据经常缺失,可以试试用 auto_adjust=True 参数。它会自动调整价格,有时候能解决一些数据对齐问题。

3.8 数据保存:别每次都重新下载

yfinance 下载数据虽然快,但每次跑脚本都重新下载,既浪费时间,又可能触发 Yahoo 的反爬机制。

我一般会把数据存成 CSV 文件,下次直接读取:

# 保存到 CSV
data_clean.to_csv('eur_usd_data.csv')

# 下次读取
data_loaded = pd.read_csv('eur_usd_data.csv', index_col=0, parse_dates=True)

这样既快又稳。而且 CSV 文件方便分享,团队里其他人也能直接用。

3.9 常见问题与避坑

做数据获取这么多年,踩过的坑不少。挑几个典型的说说:

  • 代码失效: Yahoo Finance 偶尔会调整接口。如果发现 yf.download 报错,先升级 yfinance 试试:pip install --upgrade yfinance
  • 时区问题: Yahoo 返回的时间是 UTC 时区。如果你在国内,记得转换成北京时间,否则日期对不上。
  • 数据延迟: Yahoo 的数据不是实时的,有 15-20 分钟延迟。做回测没问题,做高频交易就别想了。

重要提醒: 如果你发现某一天的数据突然变成 0 或者 NaN,别慌。先检查那天是不是节假日。外汇市场在圣诞节、元旦等节日是休市的。

好了,数据获取和清洗这部分就聊到这儿。记住一句话:数据质量决定模型上限。花 80% 的时间在数据上,一点都不亏。


专注资料整理