
欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 250+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!
你是否想过,华尔街的量化交易员是如何用算法在市场中寻找盈利机会的?今天,我将带你深入一个完整的量化交易项目——从 ETF 市场分析到策略回测,手把手教你用 Python 构建自己的量化交易工具包。
这个项目涵盖了三大核心功能:市场探索与分析、危机对冲策略(Crisis Alpha)、以及策略回测与模拟。无论你是量化交易新手还是想要提升技能的开发者,这篇文章都能让你收获满满。
这个量化交易框架主要解决三个问题:
首先,我们需要配置 Python 环境并导入必要的库:
# 启用内联绘图,让图表直接显示在 Notebook 中
%matplotlib inline
import numpy as np # 数值计算库
import pandas as pd # 数据处理库
from pandas.io.data import DataReader # 数据读取器
from datetime import datetime # 日期时间处理
import matplotlib as mpl
import matplotlib.pyplot as plt
# 导入在线投资组合选择库
import universal as up
from universal import tools
from universal import algos
# 配置日志,方便追踪算法运行状态
import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
# 调整图表大小和样式
mpl.rcParams['figure.figsize'] = (16, 10) # 增大图表尺寸
mpl.rcParams['legend.fontsize'] = 12# 图例字体大小
mpl.rcParams['lines.linewidth'] = 1# 线条宽度
为什么要记录版本信息? 这是一个好习惯,能确保实验的可重复性:
import sys
print('Python: ' + sys.version) # 打印 Python 版本
print('Pandas: ' + pd.__version__) # 打印 Pandas 版本
import pkg_resources
print('universal-portfolios: ' + pkg_resources.get_distribution("universal-portfolios").version)
我们使用 2005-2012 年的数据进行训练,2013-2014 年的数据进行测试:
# 定义 ETF 组合(斯文森配置)
etfs = ['VTI', 'EFA', 'EEM', 'TLT', 'TIP', 'VNQ']
# 斯文森资产配置比例
# VTI: 美国全市场 30%,EFA: 发达市场 15%,EEM: 新兴市场 10%
# TLT: 长期国债 15%,TIP: 通胀保护债券 15%,VNQ: 房地产 15%
swensen_allocation = [0.3, 0.15, 0.1, 0.15, 0.15, 0.15]
# 基准指数
benchmark = ['SPY']
# 设置训练和测试时间段
train_start = datetime(2005, 1, 1)
train_end = datetime(2012, 12, 31)
test_start = datetime(2013, 1, 1)
test_end = datetime(2014, 12, 31)
# 从 Yahoo Finance 加载数据
train = DataReader(etfs, 'yahoo', start=train_start, end=train_end)['Adj Close']
test = DataReader(etfs, 'yahoo', start=test_start, end=test_end)['Adj Close']
train_b = DataReader(benchmark, 'yahoo', start=train_start, end=train_end)['Adj Close']
test_b = DataReader(benchmark, 'yahoo', start=test_start, end=test_end)['Adj Close']
关键点解析:
Adj Close(调整后收盘价)是因为它已经考虑了股息和拆股的影响将所有 ETF 的价格归一化到同一起点,方便对比表现:
# 归一化价格:将每个 ETF 的价格除以其初始价格
# 这样所有 ETF 都从 1 开始,便于比较相对收益
ax1 = (train / train.iloc[0, :]).plot()
(train_b / train_b.iloc[0, :]).plot(ax=ax1)
这是整个项目的核心——对比多种在线投资组合选择(OLPS)算法:
# 定义所有要对比的算法
olps_algos = [
algos.Anticor(), # 反相关策略
algos.BAH(), # 买入并持有
algos.BCRP(), # 最优固定再平衡组合(事后最优)
algos.BNN(), # 贝叶斯近邻
algos.CORN(), # 相关驱动策略
algos.CRP(b=swensen_allocation), # 固定权重再平衡(斯文森配置)
algos.CWMR(), # 置信加权均值回归
algos.EG(), # 指数梯度
algos.Kelly(), # 凯利准则
algos.OLMAR(), # 在线移动平均回归
algos.ONS(), # 在线牛顿步
algos.PAMR(), # 被动攻击均值回归
algos.RMR(), # 鲁棒均值回归
algos.UP() # 万能组合
]
算法分类解读:
# 获取算法名称列表
algo_names = [a.__class__.__name__ for a in olps_algos]
# 定义要记录的数据列
algo_data = ['algo', 'results', 'profit', 'sharpe', 'information',
'annualized_return', 'drawdown_period', 'winning_pct']
metrics = algo_data[2:] # 只取性能指标列
# 创建训练集结果表格
olps_train = pd.DataFrame(index=algo_names, columns=algo_data)
olps_train.algo = olps_algos
# 运行所有算法(这一步可能需要几分钟)
for name, alg in zip(olps_train.index, olps_train.algo):
olps_train.loc[name, 'results'] = alg.run(train)
真实交易中,每笔交易都有成本。我们设置 0.1% 的交易费用:
# 设置交易费用:每 1000 美元交易支付 1 美元
for k, r in olps_train.results.items():
r.fee = 0.001# 0.1% 的交易费用
定义一个函数来计算各种性能指标:
defolps_stats(df):
"""
计算并填充 OLPS 算法的性能统计指标
参数:
df: 包含算法结果的 DataFrame
返回:
填充了性能指标的 DataFrame
"""
for name, r in df.results.items():
df.loc[name, 'profit'] = r.profit_factor # 盈利因子
df.loc[name, 'sharpe'] = r.sharpe # 夏普比率
df.loc[name, 'information'] = r.information # 信息比率
df.loc[name, 'annualized_return'] = r.annualized_return * 100# 年化收益率(%)
df.loc[name, 'drawdown_period'] = r.drawdown_period # 最大回撤周期
df.loc[name, 'winning_pct'] = r.winning_pct * 100# 胜率(%)
return df
# 计算统计指标并按盈利排序
olps_stats(olps_train)
olps_train[metrics].sort_values('profit', ascending=False)
OLMAR(在线移动平均回归)是一个值得深入研究的策略。我们可以测试不同的参数组合:
# 测试不同的窗口期参数
train_olmar = algos.OLMAR.run_combination(
train,
window=[3, 5, 10, 15], # 测试 3、5、10、15 日窗口
eps=10# 阈值参数
)
train_olmar.plot() # 绘制结果对比图
# 查看详细统计
print(train_olmar.summary())
OLMAR 工作原理:
比较 OLMAR 与固定再平衡策略的表现:
# 选择最佳 OLMAR 配置
best_olmar = train_olmar[1]
# 绘制对比图
ax1 = best_olmar.plot(
ucrp=True, # 显示均匀 CRP 基准
bah=True, # 显示买入持有基准
weights=False,
assets=False,
portfolio_label='OLMAR'
)
# 叠加 CRP 策略结果
olps_train.loc['CRP'].results.plot(
ucrp=False,
bah=False,
weights=False,
assets=False,
ax=ax1[0],
portfolio_label='CRP'
)
了解每个 ETF 对投资组合收益的贡献:
# 绘制收益分解图(对数坐标)
best_olmar.plot_decomposition(legend=True, logy=True)
# 绘制收益分解图(线性坐标)
best_olmar.plot_decomposition(legend=True, logy=False)
分解图告诉我们什么?
验证策略是否过度依赖某一个资产:
# 找出贡献最大的资产
most_profitable = best_olmar.equity_decomposed.iloc[-1].argmax()
# 在剔除该资产后重新运行算法
result_without = algos.OLMAR().run(train.drop([most_profitable], axis=1))
# 打印结果并绘图
print(result_without.summary())
result_without.plot(
weights=False,
assets=False,
bah=True,
ucrp=True,
logy=True,
portfolio_label='OLMAR (剔除最佳资产)'
)
用两个 ETF 展示 OLMAR 的工作方式:
# 加载 SPY(股票)和 TLT(债券)数据
spy_tlt_data = DataReader(
['SPY', 'TLT'],
'yahoo',
start=datetime(2010, 1, 1)
)['Adj Close']
# 运行 OLMAR
spy_tlt_olmar = algos.OLMAR().run(spy_tlt_data)
spy_tlt_olmar.plot(
assets=True, # 显示资产价格
weights=True, # 显示权重变化
ucrp=True,
bah=True,
portfolio_label='OLMAR'
)
# 与 70/30 固定配置对比
spy_tlt_crp = algos.CRP(b=[0.7, 0.3]).run(spy_tlt_data)
将策略应用到 9 个行业 ETF:
# 定义行业 ETF 列表
sectors = [
'XLY', # 可选消费
'XLF', # 金融
'XLK', # 科技
'XLE', # 能源
'XLV', # 医疗保健
'XLI', # 工业
'XLP', # 必需消费
'XLB', # 材料
'XLU'# 公用事业
]
# 加载行业 ETF 数据
train_sectors = DataReader(sectors, 'yahoo',
start=train_start_2010,
end=train_end_2010)['Adj Close']
# 运行 OLMAR
train_olmar_sectors = algos.OLMAR().run(train_sectors)
train_olmar_sectors.plot(
assets=True,
weights=False,
ucrp=True,
bah=True,
portfolio_label='OLMAR'
)
通过这个项目,我们得到了以下重要发现:
本文介绍了一个完整的量化交易框架,包括:
量化交易的核心在于"用数据说话"。通过系统的回测和分析,我们可以在实盘之前发现策略的优缺点,避免踩坑。
记住:历史表现不代表未来收益,但科学的方法可以帮助我们做出更理性的决策。
核心权益如下:
星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐