原创内容第952篇,专注量化投资,AGI和智能体落地、个人成长与财富自由。
这一波涨势,季度最强策略来了:
在Backtrader中实现策略组合(如风险平价父策略 + 行业轮动子策略)可通过以下两种方式实现。这里提供一个完整方案:
方案1:分层策略结构(推荐)
通过主策略管理资金分配,子策略生成交易信号。
import backtrader as bt
import numpy as np
# ---------------------
# 子策略:行业轮动策略
# ---------------------
class SectorRotation(bt.Strategy):
params = (('momentum_period', 126),) # 6个月动量
def __init__(self):
# 计算每个行业的动量
self.ranks = {d: bt.indicators.Momentum(d.close, period=self.p.momentum_period)
for d in self.datas}
def next(self):
# 仅由父策略调用,不自主交易
pass
def get_sector_weights(self):
"""返回行业权重字典"""
# 获取动量排名
momentum_values = [self.ranks[d][0] for d in self.datas]
ranked_data = sorted(zip(self.datas, momentum_values),
key=lambda x: x[1], reverse=True)
# 等权重配置前3行业
top_sectors = [d for d, _ in ranked_data[:3]]
return {d: 1.0/len(top_sectors) for d in top_sectors}
# ---------------------
# 父策略:风险平价策略
# ---------------------
class RiskParity(bt.Strategy):
params = (
('rebalance_days', 21), # 每月调仓
('target_risk', 0.1), # 目标波动率
)
def __init__(self):
self.counter = 0
# 创建子策略实例
self.child_strategy = SectorRotation()
# 风险平价需要的数据:大类资产
self.assets = {
'stocks': self.data0,
'bonds': self.data1,
'commodities': self.data2
}
self.asset_vol = {} # 存储波动率
def next(self):
self.counter += 1
# 每月执行一次调仓
if self.counter % self.p.rebalance_days == 0:
# 1. 计算大类资产波动率 (简化版)
for name, data in self.assets.items():
returns = np.diff(np.log(data.close.get(size=252)))
self.asset_vol[name] = np.std(returns) * np.sqrt(252)
# 2. 计算风险平价权重
inv_vol = {name: 1/vol for name, vol in self.asset_vol.items()}
total_inv_vol = sum(inv_vol.values())
risk_weights = {name: iv/total_inv_vol for name, iv in inv_vol.items()}
# 3. 获取子策略行业权重
sector_weights = self.child_strategy.get_sector_weights()
# 4. 计算最终权重
stock_weight = risk_weights['stocks']
for sector, weight in sector_weights.items():
target_percent = stock_weight * weight
current_percent = self.broker.getvalue([sector]) / self.broker.getvalue()
self.order_target_percent(sector, target_percent)
# 5. 配置其他大类资产
self.order_target_percent(self.assets['bonds'], risk_weights['bonds'])
self.order_target_percent(self.assets['commodities'], risk_weights['commodities'])
# ---------------------
# 执行回测
# ---------------------
if __name__ == '__main__':
cerebro = bt.Cerebro()
# 添加数据 (示例)
# 大类资产
cerebro.adddata(bt.feeds.YahooFinanceData(dataname='SPY', fromdate=...)) # 股票
cerebro.adddata(bt.feeds.YahooFinanceData(dataname='TLT', fromdate=...)) # 债券
cerebro.adddata(bt.feeds.YahooFinanceData(dataname='GSG', fromdate=...)) # 商品
# 行业ETF数据
for ticker in ['XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY']:
data = bt.feeds.YahooFinanceData(dataname=ticker, fromdate=...)
cerebro.adddata(data)
cerebro.addstrategy(RiskParity)
cerebro.broker.set_cash(1000000)
cerebro.run()
其实,策略组合实现还挺复杂的。这里使用标普来代表美股。在A股我们可以使用沪深300来代码大盘,然后风险平价后获得的仓位,使用子策略来行业轮动。
吾日三省吾身
提前担忧的内耗,毫无意义。
逢山开路,遇水架桥,总有办法。
人生的容错能力比想象中的高。
你要遇到的事情,都是来渡你的,为了让你遇见更好的自己。
好好努力,然后允许一切发生,允许一切如其所是。
扩展 • 历史文章
EarnMore(赚得更多)基于RL的投资组合管理框架:一致的股票表示,可定制股票池管理。(附论文+代码)
年化收益200%+的策略集 | 实时板块资金热力图 「aitrader 5.0系统代码发布」
机器学习驱动的策略开发通过流程 | 普通人阶层跃迁的可能路径?