10年24倍的etf轮动策略复现,回测+实盘一体解决方案:backtrader的模块化策略模板,附python代码
原创内容第958篇,专注量化投资,AGI和智能体落地、个人成长与财富自由。
今天来说说回测框架了。
从做量化开始,就在读开源的代码和自己写框架之间做选择。
记得最新看的框架是pyalgotrade。这个框架的优点是功能比较全,基于事件驱动的引擎,且代码量不大,代码比较易读,只是它使用了自定义的数据结构,没有使用pandas的dataframe。——这一点与vnpy有点像,把数据读到一个个bar里。
后来使用backtrader,网上资料比较多,社区的例子也很丰富。只是backtrader的代码元编程不易读。backtrader是回测/实盘一体的。
然后就是vnpy, qlib,pybroker都仔细学习过,读过代码。
回头看选择的标准,如果是初学,从易上手和完整的角度,建议从backtrader开始,然后可以使用bt来提升效率。机器学习的量化看qlib。
从实盘回测一体来看:backtrader和vnpy。
按照bt的“模块化算子”,我用backtrader实现了一下:
我们用下面这个策略模板来复刻咱们网站上这个策略,10年24倍的轮动策略:
import backtrader as bt
import numpy as np
class StrategyTemplate(bt.Strategy):
params = (
('lookback',25),
)
def log(self, txt, dt=None):
dt = dt or self.datas[0].datetime.date(0)
def notify_order(self, order):
"""订单状态通知"""
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.log(f"买入执行, 价格: {order.executed.price:.2f}, 数量: {order.executed.size}, 成本: {order.executed.value:.2f}, 佣金: {order.executed.comm:.2f}")
self.buy_price = order.executed.price
self.buy_date = self.datas[0].datetime.date(0)
elif order.issell():
profit = order.executed.value - order.created.value
self.log(f"卖出执行, 价格: {order.executed.price:.2f}, 数量: {order.executed.size}, 收益: {profit:.2f}, 佣金: {order.executed.comm:.2f}")
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log(f"订单取消/保证金不足/拒绝")
def order_by(self, topK=1, dropN=0, desc=True):
# 步骤1:计算所有资产的当前指标值
ranking = []
for d in self.datas:
# 跳过数据不足的资产
if len(d) < self.p.lookback:
continue
# 获取当前指标值
if 'sorter' not in self.inds[d].keys():
print('order_by==>sorter指标不存在,请检查')
return
ind_value = self.inds[d]['sorter'][0]
# 跳过无效值
if np.isnan(ind_value):
continue
ranking.append((d, ind_value))
# 按指标值降序排序(从大到小)
ranking.sort(key=lambda x: x[1], reverse=desc)
selected = [asset for asset, _ in ranking[dropN:topK]]
return selected
def weight_equally(self,selected):
weights = {}
for data in selected:
weights[data] = 1/len(selected)
return weights
def rebalance(self,weights):
"""根据新权重调整仓位"""
total_value = self.broker.getvalue()
#print(weights)
to_buy = {}
for i, data in enumerate(self.datas):
if data in weights.keys():
# 计算目标市值
target_value = total_value * weights[data]
else:
target_value = 0
# 计算当前持仓市值
current_value = self.getposition(data).size * data.close[0]
# 计算需要交易的数量
size_diff = (target_value - current_value) / data.close[0]
# 执行订单
if size_diff > 0:
to_buy[data] = size_diff
elif size_diff < 0:
self.sell(data=data, size=abs(size_diff))
# self.buy(data=data, size=size_diff)
for data, size in to_buy.items():
self.buy(data=data, size=size)
class RotationStrategyTemplate(StrategyTemplate):
def next(self):
selected = self.order_by()
weights = self.weight_equally(selected)
self.rebalance(weights)
策略就比较简单了:
from collections import defaultdict
from strategy_template import RotationStrategyTemplate
import backtrader as bt
from backtrader_inds import TrendScore
class TrendScoreRotation(RotationStrategyTemplate):
params = (
('lookback',25),
)
def __init__(self):
self.inds = defaultdict(dict) # 存储各资产ROC指标
for data in self.datas:
self.inds[data]['sorter'] = TrendScore(data, period=self.params.lookback)
backtrader是回测/实盘一体的。
backtrader兼顾回测策略开发效率,与实盘无缝切换。
这里按bt的模块化算子思路,封装了轮动策略的模板。
代码已经提
AI量化实验室 星球,已经运行三年多,1700+会员。
aitrader代码,因子表达式引擎、遗传算法(Deap)因子挖掘引擎等,支持vnpy,qlib,backtrader和bt引擎,内置多个年化30%+的策略,每周五迭代一次,代码和数据在星球全部开源。
年化收益548%,回撤才6%,夏普比5.72,这个策略一直很稳定,附python代码
年化30.24%,最大回撤19%,综合动量多因子评分策略再升级(python代码+数据)
创业板+纳指+黄金的轮动,13年70倍 | 年入千万超级个体,才是普通人创业的趋势。