4. 数据源接入:免费/付费数据源对比与API封装

做量化交易,第一件事就是搞数据。没有数据,策略就是空中楼阁。我见过不少新手,上来就写策略,结果回测跑得飞起,实盘一跑就崩——为什么?数据源不对,或者数据质量太差。

今天咱们就把数据源这件事彻底聊透。我会从免费到付费,从API封装到限流处理,把我在实战中踩过的坑、总结的经验,一次性讲清楚。

4.1 免费数据源:够用吗?

说实话,免费数据源对于学习、回测、甚至小规模实盘,完全够用。但你要知道它的边界在哪里。

Yahoo Finance

我个人最常用的免费数据源。接口简单,覆盖全球股票、ETF、指数、加密货币。用 yfinance 库,几行代码就能拉数据。

import yfinance as yf

# 获取苹果股票数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
print(aapl.head())

但注意,Yahoo Finance 的数据有时会延迟,而且历史数据可能被调整过(比如拆股、分红)。我在项目中遇到过,回测时用的数据跟实际行情对不上,后来发现是 Yahoo 的调整因子没处理好。

⚠️ 注意: Yahoo Finance 的免费接口有频率限制。频繁请求会被封IP。我建议每次请求间隔至少1秒。

Alpha Vantage

这个数据源提供更丰富的金融数据,包括基本面、技术指标、外汇、加密货币等。API 设计得很规范,但免费版有每分钟5次请求的限制。

import requests

API_KEY = 'your_api_key'
symbol = 'IBM'
url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={API_KEY}'
response = requests.get(url)
data = response.json()

Alpha Vantage 的数据质量比 Yahoo 高,但免费版的历史数据只有最近100天。如果你要做长周期回测,就得付费了。

Tushare(国内)

做A股的朋友,Tushare 是绕不开的。它提供股票、基金、期货、宏观经济等数据。免费版有积分限制,积分越高,能调用的数据越多。

import tushare as ts

# 设置token
ts.set_token('your_token')
pro = ts.pro_api()

# 获取日线数据
df = pro.daily(ts_code='000001.SZ', start_date='20230101', end_date='20231231')
print(df.head())

Tushare 的数据更新及时,但免费版每天有调用次数限制。我建议你先用免费版做原型验证,等策略稳定了再考虑付费。

4.2 付费数据源:值不值?

当你的策略开始赚钱,或者你需要更高质量的数据时,付费数据源就是必然选择。

数据源 价格 数据质量 适用场景
Wind(万得) 约2-5万/年 极高 机构级、高频、全品种
Bloomberg 约2万美元/年 极高 全球市场、实时数据
Quandl 按数据包收费 另类数据、宏观经济
聚宽/JQData 约3000-1万/年 A股、期货、回测

Wind 是我在机构工作时最常用的。它的数据覆盖全,更新快,但价格也确实贵。如果你只是个人交易者,我建议先用聚宽或 Tushare 付费版,性价比更高。

💡 我的建议: 先用免费数据源跑通策略,等策略稳定了,再切换到付费数据源。不要一开始就花大价钱买数据,万一策略不赚钱呢?

4.3 API封装:让数据调用更优雅

直接调用原始API,代码会变得很乱。我习惯封装一个统一的数据接口,这样切换数据源时,只需要改一行代码。

class DataSource:
    def __init__(self, source='yahoo', api_key=None):
        self.source = source
        self.api_key = api_key
        
    def get_daily_data(self, symbol, start, end):
        if self.source == 'yahoo':
            return self._get_yahoo_data(symbol, start, end)
        elif self.source == 'alphavantage':
            return self._get_alphavantage_data(symbol, start, end)
        elif self.source == 'tushare':
            return self._get_tushare_data(symbol, start, end)
        else:
            raise ValueError(f'Unknown source: {self.source}')
    
    def _get_yahoo_data(self, symbol, start, end):
        import yfinance as yf
        return yf.download(symbol, start=start, end=end)
    
    def _get_alphavantage_data(self, symbol, start, end):
        # 具体实现略
        pass
    
    def _get_tushare_data(self, symbol, start, end):
        # 具体实现略
        pass

# 使用示例
ds = DataSource(source='yahoo')
data = ds.get_daily_data('AAPL', '2023-01-01', '2023-12-31')

这样封装的好处是,你可以在不同数据源之间自由切换。比如白天用 Tushare 做A股,晚上用 Yahoo 做美股,代码结构完全一致。

4.4 限流处理:别被API封了

免费API都有频率限制。我曾经因为没做限流,直接写了个循环去拉数据,结果IP被封了三天。嗯,从那以后我再也不敢忽视限流了。

限流的核心思路就两个:

  1. 控制请求频率:每次请求后等待固定时间
  2. 重试机制:请求失败后自动重试
import time
import requests
from functools import wraps

def rate_limit(max_calls=5, period=60):
    """限流装饰器:每分钟最多调用 max_calls 次"""
    def decorator(func):
        last_reset = time.time()
        calls = 0
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            nonlocal last_reset, calls
            
            # 重置计数器
            if time.time() - last_reset > period:
                calls = 0
                last_reset = time.time()
            
            # 检查是否超限
            if calls >= max_calls:
                sleep_time = period - (time.time() - last_reset)
                if sleep_time > 0:
                    print(f'达到限流,等待 {sleep_time:.2f} 秒')
                    time.sleep(sleep_time)
                calls = 0
                last_reset = time.time()
            
            calls += 1
            return func(*args, **kwargs)
        return wrapper
    return decorator

@rate_limit(max_calls=5, period=60)
def fetch_data(url):
    response = requests.get(url)
    return response.json()

# 使用
for i in range(10):
    data = fetch_data('https://api.example.com/data')
    print(f'第 {i+1} 次请求成功')

这个装饰器可以复用到任何API调用上。你只需要设置每分钟最大请求次数,剩下的交给它处理。

💡 小技巧: 对于需要大量历史数据的场景,我建议先一次性拉取全量数据存到本地数据库,之后每天只增量更新。这样既避免了频繁请求,又保证了数据完整性。

4.5 知识体系总览

下面这张图,是我对数据源接入的整体理解。你可以把它当作一个决策树,帮你快速选择合适的数据源和封装方式。

数据源接入知识体系 数据源接入 免费数据源 付费数据源 Yahoo Finance Alpha Vantage Tushare Wind Bloomberg 聚宽 API封装 统一接口设计 数据源切换 限流与重试

这张图把数据源接入分成了三层:底层是数据源选择(免费 vs 付费),中间层是API封装,顶层是限流处理。每一层都有对应的技术方案和注意事项。

好了,数据源接入这部分就聊到这里。记住一句话:数据是量化交易的基础,但不要被数据绑架。先用免费数据跑通逻辑,再逐步升级到付费数据源。这样既省钱,又高效。


专注资料整理