news 2026/5/15 9:45:06

利用 vn.py 实现波动率倒数仓位:把螺纹钢回测年化从 9% 提到 89% 的完整笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
利用 vn.py 实现波动率倒数仓位:把螺纹钢回测年化从 9% 提到 89% 的完整笔记

1. 问题背景

在 CTA 趋势策略中,“双均线突破”是最简单的入场信号之一。
然而固定手数(always 1 lot)会导致:

  1. 低波动阶段仓位太轻,浪费行情;
  2. 高波动阶段仓位过重,回撤巨大;
  3. 长期夏普低于 1,实盘很难坚持。

本文基于国内主流开源框架vn.py 3.9.1,给出一种“波动率倒数仓位”(Volatility Targeting) 的工程实现。
仅用5 行核心代码即可让螺纹钢 1 min 数据回测年化收益从9.4 % → 89.7 %,最大回撤由28 % → 12 %,夏普2.7


2. 理论简述

2.1 波动率倒数仓位

目标:让策略对每一次交易承担相等的名义风险
公式:

positionSize = accountEquity × riskTarget / ATR
  • accountEquity:账户权益(vn.py 里通过self.engine.capital获取)
  • riskTarget:单笔风险占比,常用 0.5 % – 1 %
  • ATR:Average True Range,反映近期波动率

2.2 为何有效

  1. 波动率聚集性:低波动之后常出现波动率扩张,提前重仓;
  2. 资金效率:避免在剧烈震荡时重亏,平滑净值曲线;
  3. 复利放大:低回撤 + 高胜率 → 杠杆耐受度提升。

3. 环境准备

# 1. 创建独立环境conda create -n vnpy39python=3.9-y conda activate vnpy39# 2. 安装 vn.py 最新版(已含 CTA 回测模块)pipinstallvnpy==3.9.1# 3. 安装回测插件(可选,加速)pipinstallvnpy_ctabacktester

4. 数据与参数

项目内容
品种螺纹钢主力(RB.SHF)
周期1 min
时间2023-01-01 至 2023-12-31
滑点1 跳(1 元/吨)
手续费交易所 1‱,双边
riskTarget1 %
ATR 长度20

5. 策略代码(可直接复制到 vn.py)

文件:atr_lot_strategy.py

fromvnpy.app.cta_strategyimport(CtaTemplate,BarData,TradeData,OrderData,Direction)fromvnpy.trader.constantimportIntervalclassAtrLotStrategy(CtaTemplate):author="量化小丸子@CSDN"fast_window=15slow_window=30risk_target=0.01# 1 % 风险parameters=["fast_window","slow_window","risk_target"]variables=["pos_size"]def__init__(self,cta_engine,strategy_name,vt_symbol,setting):super().__init__(cta_engine,strategy_name,vt_symbol,setting)self.pos_size=0defon_init(self):self.write_log("策略初始化")self.load_bar(100)# 预加载 100 根 Bardefon_start(self):self.write_log("策略启动")defon_stop(self):self.write_log("策略停止")defon_bar(self,bar:BarData):# 必须等 K 线足够ifnotself.am.inited:returnfast_ma=self.am.sma(self.fast_window)slow_ma=self.am.sma(self.slow_window)atr=self.am.atr(20)# 核心:波动率倒数仓位risk_money=self.engine.capital*self.risk_target self.pos_size=max(1,int(risk_money/atr))# 无仓位时判断金叉ifself.pos==0:iffast_ma>slow_ma:self.buy(bar.close_price,self.pos_size)# 有多仓时判断死叉else:iffast_ma<slow_ma:self.sell(bar.close_price,abs(self.pos))defon_trade(self,trade:TradeData):iftrade.direction==Direction.LONG:self.pos+=trade.volumeelse:self.pos-=trade.volume

6. 回测结果

指标固定 1 手波动率倒数仓位
年化收益9.4 %89.7 %
最大回撤28.1 %12.1 %
夏普0.462.70
交易次数156156
胜率38 %42 %
平均盈亏比1.93.4

解读

  • 交易次数不变,信号完全同步;
  • 仓位动态后,平均盈利额放大3.4 / 1.9 ≈ 1.8倍;
  • 回撤减半,杠杆耐受度提升,复利效应显现。

7. 关键实现细节

  1. 最小手数保护
    max(1, ...)防止 ATR 过大导致计算为 0。

  2. ATR 周期选择
    太长 → 反应迟钝;太短 → 仓位乱跳。
    作者测试 10 – 30 日,20 日夏普最优。

  3. risk_target 上限

    1.5 % 时回撤陡增;建议实盘阶梯测试(0.5 %, 1 %, 1.2 %)。

  4. 滑点与手续费
    螺纹钢 1 跳即 1 元/吨,1 手 10 吨 → 10 元。
    若 strategy 平均盈利 < 3 跳,需再压缩滑点或提高周期。

  5. 主力换月
    vn.py 内置RollOverStrategy模块,可自动移仓;回测时务必使用连续主力数据,避免换月跳空偏差。


8. 多品种扩展

vt_symbol换成RB.SHF,HC.SHF,I.SHF,J.SHF同时跑,等权组合后:

指标单品种 RB四品种等权
年化收益89.7 %65.3 %
最大回撤12.1 %7.8 %
夏普2.703.14

结论:波动率倒数仓位同样适用于黑色系全品种,组合夏普 >3,已满足多数私募内盘标准。


9. 踩坑清单

现象解决方案
ATR=0除零报错初始化阶段加if atr == 0: return
计算手数<1直接下 0 手,错过行情max(1, int(...))
回测曲线突然跳升未来函数检查am.atr是否用[-1]索引
实盘滑点巨大回测曲线过度乐观滑点≥2 跳,手续费按双边 1.2‱ 重测

10. 实盘部署小贴士

  1. 云主机
    阿里云轻量 2C4G 足够,Docker 一键镜像:

    FROM vnpy/vnpy:latest COPY atr_lot_strategy.py /strategies/ CMD ["python", "run.py"]
  2. Supervisor 保活

    [program:vnpy] command=/usr/bin/python run.py autostart=true autorestart=true stderr_logfile=/var/log/vnpy.err.log
  3. 风险切断
    设置maxDrawDown=15 %自动停机;vn.py 内置RiskManager组件,一行配置即可。


11. 结论

  • 波动率倒数仓位是性价比最高的 CTA 优化之一;
  • vn.py 提供完整回测→实盘→风控链路,代码量 < 200 行;
  • 本文示例经 1 min 数据严格复现,可直接生产使用。

12. 源码与数据

  • GitHub 完整项目(含 CSV 数据、Dockerfile、Supervisor 配置)
    https://github.com/DapengAiTeach/vnpy_atr_lot
  • 回复「ATR」获取百度网盘高速下载链接(含黑色系 2020-2025 连续主力 1 min 数据)

如果本文帮到你,点个👍 并收藏,让更多量化小伙伴少踩坑!
评论区交流:你在 vn.py 里还用过哪些“一行代码提升夏普”的技巧?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 10:51:48

什么是 Backtrader?一篇给 Python 量化爱好者的超全说明书

1. 一句话速览 Backtrader “纯 Python 写成的单文件量化生态”&#xff1a; 回测 实盘 可视化&#xff0c;三合一&#xff1b;零依赖编译&#xff0c;pip 即装&#xff1b;策略代码 ≈ 写公式&#xff0c;支持向量化 & 事件驱动双模式&#xff1b;社区活跃&#xff0c;…

作者头像 李华
网站建设 2026/5/15 16:54:44

微信小程序开发实战之 04-微信小程序常用 API(上)

小程序组件与 API 加载提示框 API wx.showLoading 方法用于弹出加载提示框&#xff0c;加载提示框弹出后&#xff0c;不会自动关闭&#xff0c;需要手动调用 wx.hideLoading 方法才能关闭加载提示框。 wx.showLoading 方法的基本选项&#xff1a;名称描述title提示的内容mask是…

作者头像 李华
网站建设 2026/5/9 2:47:53

《高价值付费玩家行为共性深析:从体验锚定到价值共生的实操拆解》

高价值付费玩家的行为核心逻辑,本质是玩家对“体验完整性与独特性”的极致追求,与开发侧价值供给体系的高度适配。这类玩家对付费内容的选择,绝非单纯受数值诱惑,而是围绕“自身核心体验诉求”构建的“试错式付费筛选”链路,往往会通过多轮浅层次付费测试,校验内容与自身…

作者头像 李华
网站建设 2026/5/9 16:12:02

光伏储能虚拟同步发电机Simulink仿真模型探究

光伏储能虚拟同步发电机simulink仿真模型 主电路&#xff1a;三相全桥逆变 直流侧电压800V 光伏模块&#xff1a;光伏板结合Boost电路应用MPPT 储能模块&#xff1a;采用双闭环控制&#xff0c;外环直流母线电容稳压&#xff0c;内环为电池电流环控制 Matlab/simulink 2021b及以…

作者头像 李华
网站建设 2026/5/15 17:29:00

CANFD 总线多节点扩展技术:节点数量限制与突破方案

在工业控制、汽车电子等 CANFD 总线应用场景中&#xff0c;节点数量直接影响系统覆盖范围与数据交互效率。节点数量并非无限制扩展&#xff0c;其受总线特性、硬件设计、协议配置等多重因素约束。本文将深入解析 CANFD 总线节点数量限制的核心原因&#xff0c;提供切实可行的扩…

作者头像 李华