数据源配置:美股数据源介绍与Bundle机制

做量化回测,数据就是你的弹药库。没有数据,策略写得再漂亮也是纸上谈兵。今天我们来聊聊Zipline的数据源配置,说白了就是——怎么把美股数据喂给Zipline吃。

一、美股数据源:三大主流选择

我个人习惯把数据源分成三类:免费的、半免费的、付费的。咱们一个一个说。

1. Yahoo Finance

老牌免费数据源。我刚开始做回测时就用它,简单粗暴。但有个问题——Yahoo Finance的数据质量不太稳定。我记得有一次回测结果异常,查了半天发现是某天的OHLC数据里出现了负值。嗯,这你受得了吗?

避坑指南:Yahoo Finance的数据有时会缺失分红、拆股调整。如果你做的是长期回测,建议用调整后的价格(Adjusted Close),而不是原始收盘价。

2. Alpha Vantage

这个数据源我比较推荐。免费额度够用(每分钟5次请求,每天500次),而且数据质量比Yahoo好不少。它提供实时数据和历史数据,支持美股、ETF、外汇等。

不过要注意——Alpha Vantage的API Key需要去官网申请,免费的就行。我曾经帮一个学员调试,他用了别人的Key,结果数据一直报错。所以,自己申请一个,别偷懒。

3. IEX Cloud

付费数据源,但物有所值。IEX Cloud的数据延迟低、质量高,适合做高频或准高频策略。它的免费层只有每月50000次调用,说实话不太够用。我建议如果预算允许,直接上付费版。

数据源 价格 数据质量 推荐场景
Yahoo Finance 免费 中等 学习、原型验证
Alpha Vantage 免费/付费 良好 日常回测
IEX Cloud 付费 优秀 生产环境、高频策略

二、Bundle概念:Zipline的数据仓库

Bundle是什么?你可以把它想象成一个「数据集装箱」。Zipline不会直接去Yahoo或Alpha Vantage拉数据,而是先把数据打包成Bundle,存在本地。回测时直接从Bundle里读,速度快得多。

为什么会这样设计?你想想看,每次回测都去远程拉数据,网络延迟、API限速、数据格式不一致……这些问题够你喝一壶的。Bundle机制说白了就是「一次下载,多次使用」。

核心概念:Bundle = 数据源 + 时间范围 + 股票列表。比如「从Yahoo下载2010-2023年标普500成分股数据」,这就是一个Bundle。

内置Bundle有哪些?

Zipline自带几个Bundle,开箱即用:

  • quandl:老牌Bundle,但Quandl被Nasdaq收购后,免费数据越来越少。我个人已经不推荐了。
  • yahoo:对应Yahoo Finance数据源。简单,但质量一般。
  • csvdir:从本地CSV文件读取数据。这个我经常用,适合自定义数据。

三、使用zipline ingest下载数据

下载数据就一个命令:zipline ingest。但别急着跑,先配置好数据源。

第一步,安装数据包:

pip install zipline zipline-bundle

第二步,注册数据源。以Yahoo为例:

zipline bundles --register yahoo

第三步,下载数据:

zipline ingest -b yahoo

嗯,就这么简单。但我要提醒你——第一次下载可能会很慢。我记得有一次下载标普500的20年数据,花了将近两个小时。所以,建议你晚上睡觉前跑这个命令,第二天醒来数据就好了。

小技巧:如果你只想下载某几只股票,可以在ingest时指定股票列表。比如:zipline ingest -b yahoo --tickers AAPL,MSFT,GOOGL。这样速度快很多。

四、自定义Bundle的准备工作

内置Bundle虽然方便,但总有不够用的时候。比如你想加入自己的因子数据、或者从其他数据源拉数据。这时候就需要自定义Bundle了。

自定义Bundle的核心是写一个Python脚本,告诉Zipline三件事:

  1. 数据从哪里来(数据源地址、API Key等)
  2. 数据长什么样(字段名、数据类型、时间频率)
  3. 数据怎么处理(清洗、对齐、去重)

我给大家一个最简单的模板:

# custom_bundle.py
import pandas as pd
from zipline.data.bundles import register

def my_bundle(environ,
              asset_db_writer,
              minute_bar_writer,
              daily_bar_writer,
              adjustment_writer,
              calendar,
              start_session,
              end_session,
              cache,
              show_progress,
              output_dir):
    # 1. 读取数据(这里假设从CSV读)
    df = pd.read_csv('my_data.csv')
    
    # 2. 写入Zipline格式
    daily_bar_writer.write(df)
    
    # 3. 写入调整数据(分红、拆股等)
    adjustment_writer.write()

# 注册Bundle
register('my_bundle', my_bundle)

然后你就可以用zipline ingest -b my_bundle来下载了。

注意:自定义Bundle的脚本必须放在Python能import到的路径下。我建议放在~/.zipline/custom_bundles/目录里,然后在~/.zipline/extension.py中import它。

五、知识体系总览

说了这么多,咱们用一张图来总结一下本章的核心逻辑:

Zipline数据源配置知识体系 数据源层 Yahoo / Alpha Vantage / IEX Bundle层 内置Bundle / 自定义Bundle 下载层 zipline ingest 命令 本地存储层 ~/.zipline/data/ 目录下的Bcolz文件 回测使用层 get_benchmark_returns / data.history() 数据流方向:数据源 → Bundle → 下载 → 本地存储 → 回测使用

这张图把整个数据流串起来了。你从数据源拉数据,打包成Bundle,用ingest下载到本地,最后在回测时调用。每一步都有坑,但每一步也都有解法。

好了,数据源配置就讲到这里。下一章我们会深入自定义Bundle的完整实现,包括如何写ingest脚本、如何处理分红拆股、如何加速数据下载。到时候我会分享一个我实际项目中用过的Bundle模板,保证你拿来就能用。