3. 数据源与采集:常用金融数据源、API 数据获取与数据清洗基础

在组合风险归因建模中,数据的质量与广度直接决定模型的有效性。本章聚焦于金融数据的三大核心环节:数据源选择、API 自动化采集以及数据清洗基础。我们将以 Wind、Bloomberg、Quandl 为例,对比其适用场景,并通过代码示例演示如何从 API 获取数据,最后建立标准化的清洗流程。

3.1 常用金融数据源对比

不同数据源在覆盖范围、更新频率、成本与易用性上存在显著差异。下表总结了三大主流数据源的核心特征,帮助你在实际项目中做出合理选择。

数据源 覆盖范围 更新频率 API 支持 典型成本 适用场景
Wind 中国 A 股、债券、期货、基金、宏观经济 实时 / 日频 / 分钟级 WindPy (Python)、Wind API (C++) 高(机构年费) 国内量化投研、组合风控
Bloomberg 全球股票、债券、外汇、衍生品、另类数据 实时 / 日频 / 历史 tick Bloomberg API (blpapi)、BQL 极高(终端 + 数据许可) 跨国组合归因、多资产风险模型
Quandl 全球宏观、期货、指数、另类数据集 日频 / 周频 / 月频 RESTful API (JSON/CSV) 低(部分免费 / 订阅制) 回测研究、学术分析、快速原型
选型建议:若主要面向 A 股市场且团队已具备 Wind 终端,优先使用 WindPy;若涉及全球多资产且预算充足,Bloomberg 是行业标准;Quandl 适合初创团队或学术研究,其免费数据集(如 FRED、Yahoo Finance)可快速验证模型。

3.2 API 数据获取实战

API(应用程序接口)是实现数据自动化采集的核心手段。以下以 Quandl 和 WindPy 为例,展示如何通过 Python 获取金融时间序列数据。

3.2.1 使用 Quandl RESTful API

Quandl 提供简洁的 REST 接口,支持 JSON 和 CSV 格式。你需要先注册获取 API Key。

import requests
import pandas as pd

# 配置 API Key 与数据集代码
API_KEY = "your_quandl_api_key"
DATASET = "WIKI/AAPL"  # 苹果公司历史股价

# 发送 GET 请求
url = f"https://www.quandl.com/api/v3/datasets/{DATASET}.json?api_key={API_KEY}"
response = requests.get(url)
data = response.json()

# 转换为 DataFrame
df = pd.DataFrame(
    data['dataset']['data'],
    columns=data['dataset']['column_names']
)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
print(df.head())
关键参数说明:
  • api_key:身份验证,免费版有调用频率限制(通常 50 次/分钟)。
  • dataset:格式为“数据库/代码”,如 WIKI/AAPL 表示 Wiki 数据库中的苹果股票。
  • 返回 JSON 结构包含 dataset.data(二维数组)和 dataset.column_names(列名)。

3.2.2 使用 WindPy 获取 A 股数据

WindPy 是 Wind 金融终端的 Python 接口,需先安装并启动 Wind 客户端。

from WindPy import w
import pandas as pd

# 启动 Wind 连接
w.start()

# 获取贵州茅台(600519.SH)2023年日频收盘价
data = w.wsd(
    "600519.SH",           # 证券代码
    "close",               # 指标:收盘价
    "2023-01-01",          # 开始日期
    "2023-12-31",          # 结束日期
    "Fill=Previous"        # 缺失值填充方式:前值填充
)

# 解析返回结果
df = pd.DataFrame(
    data.Data,
    index=data.Fields,
    columns=data.Times
).T
df.index = pd.to_datetime(df.index)
print(df.head())
注意事项:
  • WindPy 必须在安装了 Wind 客户端的 Windows 机器上运行,且需保持终端登录状态。
  • w.wsd 返回的是 WindData 对象,包含 Times(时间列表)、Data(数据列表)、Fields(字段列表)。
  • 参数 Fill=Previous 用于处理停牌或非交易日导致的缺失值,避免数据断裂。

3.3 数据清洗基础

原始金融数据通常存在缺失值、异常值、重复记录、格式不一致等问题。数据清洗是风险归因建模前的必要步骤。以下展示一个标准化的清洗流程。

3.3.1 清洗流程概览

下图展示了从原始数据到可用特征集的清洗流水线,包含五个核心阶段。

数据清洗流水线 原始数据 缺失值处理 异常值检测 去重与对齐 格式标准化 清洗后数据 各阶段核心操作: • 缺失值处理:前值填充、线性插值、删除缺失率 > 30% 的列 • 异常值检测:Z-score 法(|Z| > 3)、IQR 法(Q1-1.5IQR / Q3+1.5IQR) • 去重与对齐:按时间戳去重、多资产时间戳对齐(重采样至统一频率) • 格式标准化:日期统一为 YYYY-MM-DD、价格保留 2 位小数、代码统一为 ISIN

3.3.2 缺失值处理示例

金融时间序列的缺失值通常由停牌、非交易日或数据源中断引起。以下代码演示了三种常用填充策略。

import pandas as pd
import numpy as np

# 模拟含缺失值的日频数据
dates = pd.date_range('2023-01-01', periods=10, freq='D')
prices = [100, 101, np.nan, 103, 104, np.nan, np.nan, 107, 108, 109]
df = pd.DataFrame({'close': prices}, index=dates)

# 策略 1:前值填充(适用于停牌场景)
df['ffill'] = df['close'].fillna(method='ffill')

# 策略 2:线性插值(适用于短期缺失)
df['interp'] = df['close'].interpolate(method='linear')

# 策略 3:删除缺失率超过 30% 的列
threshold = 0.3
if df['close'].isna().mean() > threshold:
    df.drop(columns=['close'], inplace=True)
    print("列 'close' 因缺失率过高被删除")

print(df)

3.3.3 异常值检测:IQR 法

异常值会严重扭曲风险指标(如波动率、VaR)。IQR 法是一种稳健的检测方法,不假设数据服从正态分布。

def detect_outliers_iqr(series, factor=1.5):
    """
    使用 IQR 法检测异常值
    :param series: pandas Series
    :param factor: IQR 倍数,默认 1.5(标准),3.0(严格)
    :return: 布尔型 Series,True 表示异常值
    """
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - factor * IQR
    upper_bound = Q3 + factor * IQR
    return (series < lower_bound) | (series > upper_bound)

# 示例:检测收益率异常值
returns = pd.Series([0.01, -0.02, 0.03, -0.15, 0.02, 0.01, -0.03, 0.04, -0.12, 0.02])
outliers = detect_outliers_iqr(returns, factor=1.5)
print("异常值索引:", returns[outliers].index.tolist())
print("异常值:", returns[outliers].values)
清洗最佳实践:
  • 始终保留原始数据副本,清洗操作在副本上进行,便于回溯。
  • 对收益率序列进行异常值检测时,建议使用 factor=3.0 避免过度剔除。
  • 多资产组合中,先按时间戳对齐,再统一清洗,避免因频率不一致导致偏差。

3.4 数据源与清洗的集成架构

在实际生产环境中,数据采集与清洗通常被封装为可复用的 ETL 管道。下图展示了从多源采集到清洗入库的完整架构。

数据采集与清洗集成架构 数据源层 Wind (A 股) Bloomberg (全球) Quandl (宏观/另类) 采集层 WindPy / blpapi RESTful API 定时任务 (Cron/Airflow) 清洗层 缺失值处理 异常值检测 去重 / 对齐 / 格式化 存储层 Parquet / HDF5 / SQL 架构设计要点: • 采集层与清洗层解耦:采集失败不影响已有清洗逻辑 • 清洗层输出标准化格式(统一列名、频率、时区) • 存储层使用列式格式(Parquet)提升 I/O 性能 • 所有操作记录日志,便于审计与问题排查

3.5 本章小结

  • 数据源选择需综合考虑覆盖范围、成本与 API 易用性:Wind 适合 A 股、Bloomberg 适合全球多资产、Quandl 适合快速原型。
  • API 采集应封装为可重用的函数,处理认证、限流、重试与错误日志。
  • 数据清洗是风险归因建模的基石,缺失值填充、异常值检测、时间戳对齐是三大核心操作。
  • 建议将采集与清洗流程集成到 ETL 管道中,确保数据质量可追溯、可复现。