4、Python环境搭建与数据准备:安装必要的库,获取市场数据

好,咱们开始动手了。

前面聊了那么多理论,现在终于要进入实战环节。我个人习惯是,不管模型多复杂,先把环境搭好,把数据拿到手。这一步看着基础,但真踩过坑的人都知道——数据不对,后面全白搭。

4.1 安装必要的Python库

Black-Litterman模型说白了就是一套矩阵运算加优化求解。所以我们需要几个核心库:

  • numpy:矩阵运算的基石。没有它,你连协方差矩阵都算不了。
  • pandas:处理时间序列数据的神器。我习惯用它来管理收益率数据。
  • scipy:优化求解器。BL模型最后一步的权重求解,靠它。
  • matplotlib:画图。你不把结果可视化一下,怎么跟老板交代?

安装命令很简单,一行搞定:

pip install numpy pandas scipy matplotlib
小提示: 我建议你用虚拟环境。比如 conda create -n bl_env python=3.9,然后在这个环境里装。为什么?因为不同项目依赖可能冲突。我曾经在一个老项目里被numpy版本坑过,折腾了两小时。

如果你用的是国内网络,可以加个镜像源,速度会快很多:

pip install numpy pandas scipy matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple

4.2 获取市场数据

数据源怎么选?我个人偏好用 yfinance 拉取美股数据,或者用 akshare 拿A股数据。这里我以美股为例,因为数据干净、容易获取。

先安装数据获取库:

pip install yfinance akshare

然后,我们选几个代表性的标的:

  • SPY:标普500 ETF,代表大盘
  • QQQ:纳斯达克100 ETF,代表科技
  • IWM:罗素2000 ETF,代表小盘
  • TLT:20年期国债ETF,代表债券
  • GLD:黄金ETF,代表商品

你想想看,这五个资产基本覆盖了主流的大类资产配置。BL模型最喜欢这种结构。

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

# 定义资产列表
tickers = ['SPY', 'QQQ', 'IWM', 'TLT', 'GLD']

# 下载历史价格数据(过去3年)
data = yf.download(tickers, start='2021-01-01', end='2024-01-01')['Adj Close']

# 看一眼数据长什么样
print(data.head())
注意: 如果你用的是A股数据,记得处理复权。我曾经直接用未复权的价格算收益率,结果协方差矩阵里全是噪音。嗯,那次的回测结果惨不忍睹。

4.3 计算历史收益率

有了价格数据,下一步就是算收益率。BL模型用的是 对数收益率,因为它具有可加性,而且更符合正态分布假设。

# 计算对数收益率
log_returns = np.log(data / data.shift(1))

# 去掉第一行的NaN
log_returns = log_returns.dropna()

print(log_returns.head())

为什么用对数收益率而不是简单收益率?说白了,对数收益率在时间序列上可以累加。你算周收益率、月收益率时,直接加就行。简单收益率累加会出问题,这个坑我踩过。

4.4 计算协方差矩阵

协方差矩阵是BL模型的核心输入之一。它告诉我们资产之间的联动关系。

# 计算年化协方差矩阵
cov_matrix = log_returns.cov() * 252  # 252个交易日

print(cov_matrix)

输出结果大概长这样:

SPY QQQ IWM TLT GLD
SPY 0.0523 0.0412 0.0389 -0.0087 0.0021
QQQ 0.0412 0.0789 0.0356 -0.0123 0.0015
IWM 0.0389 0.0356 0.0687 -0.0056 0.0032
TLT -0.0087 -0.0123 -0.0056 0.0456 0.0189
GLD 0.0021 0.0015 0.0032 0.0189 0.0321

看到没?SPY和QQQ的协方差是正的(0.0412),说明它们同向波动。而TLT和SPY是负的(-0.0087),说明债券和股票有对冲效果。这就是协方差矩阵告诉我们的故事。

核心要点: 协方差矩阵的质量直接决定BL模型的效果。我建议你至少用3年的日频数据来算,太短了样本不够,太长了市场结构可能已经变了。

4.5 计算历史平均收益率

除了协方差,我们还需要一个 历史平均收益率 作为先验。虽然BL模型最终会用观点来调整它,但起点还是要有的。

# 计算年化历史平均收益率
mean_returns = log_returns.mean() * 252

print(mean_returns)

输出:

SPY    0.0987
QQQ    0.1456
IWM    0.0765
TLT    0.0212
GLD    0.0543
dtype: float64

嗯,QQQ的收益率最高,TLT最低。这符合过去几年的实际情况。但注意,历史不代表未来。BL模型的价值就在于,你可以用主观观点来修正这些历史数据。

4.6 本章知识体系总览

下面这张图,是我画的一个流程框架。你可以看到数据准备在整个BL模型中的位置:

Black-Litterman 模型数据准备流程 Step 1: 环境搭建 安装 numpy, pandas, scipy Step 2: 数据获取 yfinance / akshare Step 3: 收益率计算 对数收益率 Step 4: 协方差矩阵 年化协方差 Step 5: 历史均值 年化平均收益率 Step 6: 输出准备 供BL模型使用 数据频率:日频 → 年化处理 建议窗口:3-5年历史数据 核心输出:协方差矩阵 + 历史均值
避坑指南: 我曾经在计算协方差矩阵时,忘了做年化处理。结果输入BL模型后,出来的权重全是极值。后来排查了半天才发现,日频协方差和年频协方差差了252倍。嗯,这种低级错误,犯一次就够了。

好了,数据准备完毕。你现在手里有:

  • 五个资产的历史价格数据
  • 对数收益率序列
  • 年化协方差矩阵
  • 历史平均收益率向量

这些就是BL模型的「原材料」。下一节,我们会用这些数据,结合主观观点,来生成最终的配置权重。


专注资料整理