Py学习  »  Python

绝对型收益的策略,backtrader从零实现风险平价,年化8.69%,夏普1.61,附python代码

七年实现财富自由 • 2 月前 • 156 次点击  
原创内容第957篇,专注量化投资,AGI和智能体落地、个人成长与财富自由。
昨天我们分享了:普通人如何赚到1000万?
今天我们继续来聊聊,这个年化10%是不是比较容易获得。
大类资产配置里,风险平价是一个有效的组合方式。下面我们用backtrader来实现一下。
import backtrader as btimport ffnimport pandas as pdimport numpy as np
class RiskParityStrategy(bt.Strategy):    params = (        ('lookback'60),       # 计算协方差矩阵的历史数据天数        ('rebalance_freq'22),  # 再平衡频率(天)        ('covar_method''ledoit-wolf'),  # 协方差矩阵计算方法        ('max_iter'100),       # ERC最大迭代次数        ('tol'1e-08)           # 收敛容忍度    )
    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"订单取消/保证金不足/拒绝")
        self.order = None
    def log(self, txt, dt=None, doprint=True):        """日志记录函数"""        if doprint:            dt = dt or self.datas[0].datetime.date(0)            print(f"{dt.isoformat()}{txt}")
    def __init__(self):        # 跟踪再平衡日期        self.day_counter = 0        self.assets = self.datas[0:]  # 第0个数据是基准/现金,资产从1开始        self.initial_weights = np.ones(len(self.assets)) / len(self.assets)  # 初始等权重        self.last_month = -1  # 初始化为无效值
    def next(self):        self.day_counter += 1
        # 到达再平衡日        #if self.day_counter % self.params.rebalance_freq == 0:        current_date = self.datetime.date(0)        current_month = current_date.month
        # 检查月份是否变化(包括跨年情况)        if current_month != self.last_month:            # 更新记录月份            self.last_month = current_month            # 准备收益率数据             returns = self._prepare_returns()            if returns is None:                return  # 数据不足时跳过
            # 计算ERC权重            weights = self._calculate_erc_weights(returns)            #print(self.datetime.date(),weights)
            # 调整仓位            self._rebalance_portfolio(weights)
    def _prepare_returns(self):        """收集历史数据并计算收益率"""        prices = []        valid_length = True
        # 检查所有资产是否有足够数据        for i, data in enumerate(self.assets):            if len(data) < self.params.lookback + 1:                valid_length = False                break            # 获取收盘价(从当前时刻回溯)            prices.append(data.close.get(size=self.params.lookback + 1))
        if not valid_length:            return None
        # 转换为DataFrame并计算收益率        price_df = pd.DataFrame(np.array(prices).T)        returns = price_df.pct_change().dropna()        return returns
    def _calculate_erc_weights(self, returns_df):        """调用ffn计算ERC权重"""        try:            # 确保输入是pd.DataFrame            if not isinstance(returns_df, pd.DataFrame):                returns_df = pd.DataFrame(returns_df)
            weights = ffn.core.calc_erc_weights(                returns=returns_df,                initial_weights=None,#self.initial_weights,                covar_method=self.params.covar_method,                risk_parity_method='ccd',                maximum_iterations=self.params.max_iter,                tolerance=self.params.tol            )            return weights.values*0.995        except Exception as e:            print(f"计算ERC权重失败: {e}")            return self.initial_weights  # 失败时使用初始权重
    def _rebalance_portfolio(self, weights):        """根据新权重调整仓位"""        total_value = self.broker.getvalue()
        to_buy = {}        for i, data in enumerate(self.assets):            # 计算目标市值            target_value = total_value * weights[i]
            # 计算当前持仓市值            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)


代码已经发布到星球:
代码+数据下载:AI量化实验室——2025量化投资的星辰大海
吾日三省吾身
关于个人成长,其实思考了很多,也写了不少。
总结起来,就如同投资的基础原则一样就几句话:
有目标,为目标建立一个系统
系统就是每天都会做的事情,持续去做,这里其实是建立一个复利效应的系统。
你也许不知道何时能成,这里有运气的成分。但日积月累,从量变到质变。
无论是减肥,还是阅读,皆是如此。
但如果要与收益产生联系,你需要建立一个“输出型”爱好
就是做生产者,阅读是消费者,你把读后感写出来,对一些人有用,这就是生产者,日积月累,你就在某一个领域有了自己的影响力。
你影响的人越多,财富效应就越强。
写作,做短视频,直播都是生产者。
创业的本质是什么呢?
本质也是生产一个用户需要的产品,只不过,这个产品的研发过程,可能需要大量的人和资本,这时候,需要以公司化的方式去运作,甚至需要大资金的支持。
作为普通人,在公司化运作的机制里,充当一个角色。
现在很多人开始“觉醒”,未必需要依靠一个特定的组织去创造收益。
代码和数据下载:AI量化实验室——2025量化投资的星辰大海

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

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


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

扩展  •  历史文章   

EarnMore(赚得更多)基于RL的投资组合管理框架:一致的股票表示,可定制股票池管理。(附论文+代码)

年化收益200%+的策略集 | 实时板块资金热力图 「aitrader 5.0系统代码发布」

机器学习驱动的策略开发通过流程 | 普通人阶层跃迁的可能路径?

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

三秒钟创建一个年化28%,夏普比1.25的策略(python系统已开放源代码下载)

会员专属策略可以直接下载了,多个十年年化30+%策略集|polars重构因子引擎(代码+数据下载)

6年年化收益46%,最大回撤率为16%的策略(附python代码)

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/185064