数据获取与存储:从零开始搭建你的金融数据仓库

做金融时间序列分析,第一步就是搞到数据。这事听起来简单,但坑不少。

我刚开始做量化研究时,花了一周时间手动下载股票数据,结果发现日期对不上、复权方式搞错了……后来我学乖了,直接用现成的库来获取数据。今天咱们就聊聊怎么用 yfinancepandas-datareader 拿数据,以及存成什么格式最靠谱。

核心观点:数据获取不是简单的"下载",而是要考虑数据源可靠性、频率对齐、存储效率三个维度。选错了存储格式,后面分析时你会想哭的。

2.1 用 yfinance 获取股票数据

yfinance 是我个人最常用的股票数据源。它从 Yahoo Finance 拉数据,覆盖全球主要市场,而且免费。

安装很简单:

pip install yfinance

获取单只股票的历史数据:

import yfinance as yf

# 获取贵州茅台(A股代码:600519.SS)
maotai = yf.download('600519.SS', start='2020-01-01', end='2023-12-31')
print(maotai.head())

这里有个坑——A股代码后面要加后缀。上海交易所加 .SS,深圳交易所加 .SZ。我一开始不知道,查了半天数据都是空的,后来才发现是代码格式问题。

获取多只股票也很方便:

# 获取多只股票
tickers = ['600519.SS', '000001.SZ', 'AAPL', 'TSLA']
data = yf.download(tickers, start='2020-01-01', end='2023-12-31')
# 默认返回多重索引的DataFrame
close_prices = data['Close']  # 只取收盘价

小技巧:如果你只需要收盘价,可以设置 auto_adjust=True,这样返回的数据会自动进行复权调整,省去手动计算的麻烦。

2.2 用 pandas-datareader 获取经济数据

股票数据只是金融分析的一部分。宏观经济数据同样重要,比如 GDP、CPI、利率等。这时候 pandas-datareader 就派上用场了。

它支持多个数据源:FRED(美联储经济数据库)、World Bank、OECD 等。

import pandas_datareader.data as web
import datetime

# 从FRED获取美国CPI数据
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2023, 12, 31)
cpi = web.DataReader('CPIAUCSL', 'fred', start, end)
print(cpi.head())

FRED 的数据代码需要去官网查。比如 GDP 是 GDPC1,失业率是 UNRATE。我建议你建一个代码映射表,方便以后复用。

获取中国宏观经济数据呢?嗯,这个有点麻烦。FRED 里中国数据不全,我一般用 akshare 或者直接爬取国家统计局网站。不过那是另一个话题了。

2.3 数据存储格式:CSV、Parquet、HDF5

数据拿到手了,存哪里?你可能会想:"存 CSV 不就行了?" 嗯,小数据量没问题,但一旦数据量大了,CSV 的缺点就暴露了。

格式 优点 缺点 适用场景
CSV 通用、可读性强、Excel能打开 占用空间大、读写慢、不支持数据类型 小数据集、数据交换
Parquet 列式存储、压缩率高、读写快 二进制格式、不易直接查看 大数据集、分析场景
HDF5 支持复杂数据结构、快速I/O 学习曲线陡、文件易损坏 科学计算、高频数据

我个人习惯:日常分析用 Parquet,长期归档用 HDF5。CSV 只用来做数据交换,比如给同事发数据。

看看代码怎么写:

# CSV
df.to_csv('stock_data.csv', index=False)

# Parquet(需要安装 pyarrow 或 fastparquet)
df.to_parquet('stock_data.parquet', index=False)

# HDF5
df.to_hdf('stock_data.h5', key='stock', mode='w')

注意:HDF5 写入时一定要指定 key 参数,否则会报错。而且 HDF5 文件在写入过程中如果程序崩溃,整个文件可能损坏。我吃过这个亏,后来改用 Parquet 了。

2.4 数据库存储:SQLite 与 InfluxDB

当数据量达到百万级别,文件存储就不够用了。这时候需要上数据库。

SQLite:轻量级关系型数据库

SQLite 不需要单独安装服务器,数据存在一个文件里,特别适合单机分析。

import sqlite3
import pandas as pd

# 创建数据库连接
conn = sqlite3.connect('finance.db')

# 将DataFrame写入数据库
df.to_sql('stock_prices', conn, if_exists='replace', index=False)

# 从数据库读取
query = "SELECT * FROM stock_prices WHERE Date > '2023-01-01'"
result = pd.read_sql(query, conn)

conn.close()

SQLite 的优点是简单,缺点是并发写入性能差。如果你只是一个人做研究,完全够用。

InfluxDB:专为时间序列设计

InfluxDB 是专门为时间序列数据设计的数据库。它的查询语法和 SQL 类似,但针对时间范围查询做了优化。

from influxdb import InfluxDBClient

# 连接InfluxDB
client = InfluxDBClient(host='localhost', port=8086)
client.create_database('finance')

# 写入数据
json_body = [
    {
        "measurement": "stock_price",
        "tags": {"ticker": "600519.SS"},
        "time": "2023-01-01T00:00:00Z",
        "fields": {"close": 2050.0, "volume": 1000000}
    }
]
client.write_points(json_body)

# 查询数据
results = client.query("SELECT * FROM stock_price WHERE time > '2023-01-01T00:00:00Z'")

我的建议:如果你处理的是高频数据(比如分钟级、秒级),InfluxDB 是首选。它的压缩率和查询速度比 SQLite 好太多。但如果是日频数据,SQLite 完全够用,没必要引入额外组件。

2.5 本章知识体系

下面这张图帮你理清数据获取与存储的整体脉络:

金融时间序列数据获取与存储 数据源层 yfinance(股票数据) pandas-datareader(经济数据) 其他API/爬虫 存储层 CSV(通用交换) Parquet(分析首选) HDF5(科学计算) SQLite/InfluxDB 应用层 数据清洗 特征工程 模型训练 回测验证 数据流方向:数据源 → 存储 → 应用

这张图展示了数据从获取到存储再到应用的完整链路。你可以看到,数据源层负责从不同渠道拉取数据,存储层根据数据量和用途选择合适的格式或数据库,最后应用层进行清洗、分析和建模。

实际项目中,我通常这样搭配:用 yfinance 拉股票数据存 Parquet,用 pandas-datareader 拉经济数据存 SQLite。这样既保证了分析效率,又方便后续查询。

一句话总结:数据获取要选对工具,数据存储要选对格式。别让数据获取成为你分析的瓶颈。


专注资料整理