社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

10年24倍的etf轮动策略复现,回测+实盘一体解决方案:backtrader的模块化策略模板,附python代码

七年实现财富自由 • 3 周前 • 59 次点击  
1.原创内容第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 btimport 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 RotationStrategyTemplateimport backtrader as btfrom 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量化实验室——2025量化投资的星辰大海
吾日三省吾身
代码和数据下载:AI量化实验室——2025量化投资的星辰大海

AI量化实验室 星球,已经运行三年多,1700+会员。

aitrader代码,因子表达式引擎、遗传算法(Deap)因子挖掘引等,支持vnpy,qlib,backtrader和bt引擎,内置多个年化30%+的策略,每周五迭代一次,代码和数据在星球全部开源。

点击 “查看原文”,直接访问策略集合

扩展  •  历史文章   


年化收益548%,回撤才6%,夏普比5.72,这个策略一直很稳定,附python代码


年化30.24%,最大回撤19%,综合动量多因子评分策略再升级(python代码+数据)


创业板+纳指+黄金的轮动,13年70倍 | 年入千万超级个体,才是普通人创业的趋势。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/185109
 
59 次点击