打开网易新闻 查看精彩图片

01

多品种 RSI 量化回测系统

在量化投资的世界里,“回测”是连接交易灵感与实盘获利之间最重要的桥梁。很多初学者掌握了基础的 Python 语法,却苦于不知道如何将策略逻辑转化为可视化的回测报告。

今天,我们将通过三份依次进阶的代码示例,详细拆解如何使用 Python 最流行的回测框架 Backtrader,结合 Tushare 数据源,搭建一个支持多品种并行自定义资金分析且拥有专业图表展示的量化系统。

在开始之前,我们需要认识一下支撑这个系统的“四驾马车”:

  1. Backtrader: Python 界的量化回测“瑞士军刀”,功能强大且灵活。

  2. Tushare: 免费且好用的金融数据接口,为策略提供“燃料”。

  3. Pandas: 数据处理神器,用于清洗和准备行情数据。

  4. Matplotlib: 绘图库,负责将枯燥的数据转化为直观的资金曲线。

策略逻辑:反直觉的 RSI 动量策略

通常教科书上的 RSI(相对强弱指标)用法是“高抛低吸”(>70 卖出,<30 买入)。但本代码采用了动量突破的逻辑:

  • 买入信号:当 RSI > 70 且当前无持仓时,买入。

    • 逻辑:认为市场进入强势上涨区间,追涨。

  • 卖出信号:当 RSI < 30 且持有仓位时,卖出。

    • 逻辑:认为市场趋势彻底反转,止损或止盈离场。

这个策略不再博取震荡收益,而是试图捕捉强劲的单边趋势。

代码拆解

1. 数据的准备与清洗

量化的第一步是获取高质量数据。代码中定义了三个主要指数:中证500、中证1000、创业板指。代码展示了如何处理多只股票/指数。Backtrader 允许同时加载多个数据源(Data Feeds),这对于测试投资组合策略至关重要。

    cerebro.adddata(data_feed, name=name) # 加载到回测引擎
2. 策略引擎的实现

这是整个系统的“大脑”。我们在 MultiAssetRSIStrategy 类中定义交易规则。

                self.sell(data=data, size=100)

zip(self.datas, self.rsi_indicators)的写法非常 Pythonic,优雅地实现了多品种的循环遍历,互不干扰。

3. 独家定制:资金分析器 (Analyzer)

Backtrader 自带的绘图虽然方便,但无法灵活定制。为了画出类似基金净值的曲线,代码中手写了一个 CashValueAnalyzer

        self.cash_values.append(current_value)

4. 专业级可视化 (Visualization)

代码最精彩的部分在于最后的绘图优化。为了解决 Matplotlib 默认日期显示杂乱的问题,代码使用了专业的 Locator 和 Formatter。

图表优化细节:

  • 中文字体支持:配置 SimHei 等字体,彻底解决乱码。

  • 主/副刻度分离

    • 主刻度:显示年份(如 2015, 2016),不仅清晰而且不拥挤。

    • 副刻度:显示季度/月份,提供细节参考。

ax.xaxis.set_minor_locator(MonthLocator(interval=3))             # 每季度一个副刻度
运行效果展示,当你运行这段代码时,你将看到两部分输出: 1. 终端输出,清晰的资金变动情况:

打开网易新闻 查看精彩图片

2. 可视化图表

你会得到一张包含两部分的专业图表:

  • Backtrader 原生图:展示K线、买卖点信号(三角形图标)以及 RSI 指标的走势。

打开网易新闻 查看精彩图片

  • 独立资金曲线图:这是一张蓝色的折线图,X轴的时间刻度非常整洁(例如只显示年份),你可以清晰地看到策略在 2015 年牛市是否抓住了机会,或者在 2018 年熊市是否控制住了回撤。

打开网易新闻 查看精彩图片

02

专业级 Python 量化系统:风控、复利与绩效评估

在上小节文章中,我们搭建了一个基础的多品种 RSI 策略框架。今天,我们将给这个引擎装上“涡轮增压”和“安全气囊”。

我们将解决新手最容易忽略的两个问题:“买多少?”(仓位管理)和“怎么输得少?”(风控指标)。我们将把这个“玩具级”的回测脚本升级为“实战入门级”的量化系统。

我们将重点进行以下 4项硬核升级

  1. 仓位管理 (Position Sizing):从傻瓜式的“固定买100股”升级为“按资金比例下单”(例如每次使用20%资金),让复利效应发挥作用。

  2. 风险控制 (Risk Management):新增移动止损 (Trailing Stop) 逻辑。在趋势策略中,止损比止盈更重要,能保住胜利果实。

  3. 交易日志 (Logging System):增加详细的订单打印功能,让你清楚看到每一笔买卖的价格、费用和盈亏,拒绝“黑箱操作”。

  4. 专业绩效评估 (Performance Metrics):除了看最终资金,我们还要计算 夏普比率 (Sharpe Ratio)最大回撤 (Max Drawdown),这才是专业机构评价策略的核心指标。

升级代码:

plt.show()

1. 动态仓位管理 (Smart Sizing)

旧版本每次只买 100 股,这在资金量大时毫无意义。

  • 代码

    cerebro.addsizer(bt.sizers.PercentSizer, percents=20)

  • 原理:无论你现在有 100 万还是 200 万,每次开仓都动用总资金的 20%。这能实现**“赢了加仓,输了减仓”**的复利效果。

2. 交易全透明 (Logging)

不再是黑箱。我们在策略中增加了 notify_ordernotify_trade 方法。

  • 效果:终端会打印如下信息,这让你能精确核对每一笔交易是否符合预期,排查 Bug 必备。

3. 硬核风控 (Risk Control)

RSI 策略最大的弱点是“钝化”(指标在高位一直不下来,或者暴跌时指标虽低但价格还在跌)。

  • 逻辑:我们在 next 方法中加入了一个简单的止损逻辑:if data.close[0] < stop_price

  • 意义:假设买入后价格下跌超过 5%(stop_loss_dist),强制平仓。这能防止单次交易造成毁灭性打击。

4. 机构级指标 (Metrics)

光看赚了多少钱是不够的,如果赚 50% 却经历过 40% 的回撤,那这个策略很难坚持。

  • 夏普比率 (Sharpe Ratio):衡量性价比。大于 1 是良好,大于 2 是优秀。

  • 最大回撤 (Max Drawdown):历史上最惨的一次跌幅。代码会在最后打印:最大回撤: 15.30%,让你对风险心知肚明。

5. 图表升级细节

我们在绘图中增加了一个“盈亏区域填充”功能:

  • 绿色背景区域:代表当前资金高于初始资金(赚钱)。

  • 红色背景区域:代表当前资金低于初始资金(亏钱)。

这种视觉反馈能让你一眼看出策略在哪些年份表现挣扎,哪些年份在躺赚。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

03

再次升级:添加趋势过滤与基准对比系统

在上一版本中,我们加入了仓位管理和止损。但在实战中,单纯的 RSI 动量策略有一个致命弱点:在长期熊市中,RSI 也会偶尔突破 70,诱骗你进场,然后价格继续暴跌。

这一次,我们将把系统升级为“基金经理级”。我们将引入两个量化交易中的核心概念:

  1. 趋势过滤 (Trend Filtering):解决 RSI 在熊市中频繁“假突破”导致亏损的痛点。

  2. 基准对比 (Benchmark Comparison):不跟大盘比收益的策略都是耍流氓。我们将把策略净值与“沪深300”的走势画在同一张图上,一目了然地看到你是否跑赢了市场。

升级核心:
  • SMA 趋势过滤:只有当价格位于 200 日均线之上(牛市区域)时,才允许开仓。这叫“顺大势,逆小势”。

  • 基准对比可视化:自动下载沪深300数据,模拟“买入持有”策略,与你的策略净值同台竞技。

plt.show()

深度解析升级内容

1. 增加系统过滤条件

新手死于追高,老手死于抄底,高手死于震荡。 RSI 策略最大的坑在于:在熊市反弹(Dead Cat Bounce)时,RSI 很容易突破 70,发出买入信号,然后市场继续暴跌。

  • 代码逻辑if rsi > 70 and current_price > sma_filter

  • 白话解释:这就像是在说,“我只在天气晴朗(价格在200日均线之上)的时候,才去冲浪(RSI 突破)”。

  • 效果:这会大幅减少交易次数,可能会让你错过一些机会,但能帮你躲过 2018 年或 2022 年那种持续阴跌的“绞肉机”行情。

2. 基准对比:寻找真实的 Alpha

很多策略号称“年化 20%”,结果一看那年大盘涨了 30%。这种策略是没有价值的,不如直接买指数 ETF。

  • 实现方式:我们在绘图部分,引入了 hs300 (沪深300) 数据,并将其初始资金也归一化为 100 万。

  • 可视化创新

    • 红色阴影区:表示你的策略跑赢了大盘。这是你作为量化交易员存在的意义。

    • 灰色阴影区:表示策略跑输了大盘。这时候你需要反思策略逻辑。

3. 多标的并行与资金分配

代码中将资金分配逻辑调整为:

cerebro.addsizer(bt.sizers.PercentSizer, percents=45)

因为我们有两个标的(创业板 + 中证500),如果设为 50%,当资金稍微有一点波动或产生佣金时,第二只股票可能因为资金不足(Cash < 50%)而无法买入。设为 45% 是一个安全的工程实践技巧。

运行结果

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

至此,我们的系统已经具备了 择时(RSI)、过滤(均线)、风控(止损)和 归因分析(Benchmark)等功能

最后的说明

文中代码与条件设定均为示例载体,核心目标在于传递解决问题的方法论——建议聚焦于思路的理解与迁移,而非局限于示例结果本身。在掌握基础方法后,可结合自身思考对代码进行迭代优化,构建更健壮、高效的量化策略,真正实现从“理解”到构建策略”的进阶。

如您想获取文章完整代码,请关注数量技术宅公众号,后台回复关键词:组合测试