🚀 AI 一键生成 ptrade 策略代码

PTrade 策略风控:如何实现基于波动率的动态头寸管理?

ptrade | 发布时间: 2025/12/11
以下内容由 EasyQuant 生成。

问题描述

怎样才能让我的策略根据市场风险自动调整每次下单的仓位大小?

解决方案

在量化交易中,根据市场风险自动调整仓位大小是资金管理的核心。最经典且有效的方法是使用 ATR(平均真实波幅) 指标来衡量波动率风险,并据此计算仓位。

核心逻辑:基于波动率的仓位管理

这种方法的核心思想是:当市场波动剧烈(风险高)时,降低仓位;当市场波动平稳(风险低)时,增加仓位。 从而保证每笔交易承担的风险金额是固定的(例如总资金的 1%)。

计算公式:

  1. 单笔风险金额 = 总资产 $\times$ 单笔风险敞口比例(如 1%)
  2. 止损幅度 = $n \times ATR$(通常取 2 倍或 3 倍 ATR)
  3. 买入数量 = 单笔风险金额 $\div$ 止损幅度

PTrade 策略代码实现

以下是一个完整的 PTrade 策略示例。该策略会计算标的股票的 ATR 指标,根据当前的波动率自动计算应该买入多少股,确保每次交易的潜在亏损控制在总资金的 1% 以内。

import talib
import numpy as np

def initialize(context):
    """
    初始化函数
    """
    # 设定要操作的股票,这里以恒生电子为例
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 策略参数设置
    g.risk_ratio = 0.01      # 每次交易愿意承担的风险比例(占总资金的1%)
    g.atr_period = 14        # ATR指标的计算周期
    g.atr_multiplier = 2.0   # 止损宽度系数(风险=ATR * 系数)
    
    # 设置交易费用(回测用)
    set_commission(commission_ratio=0.0003, min_commission=5.0)

def handle_data(context, data):
    """
    盘中运行函数,每日或每分钟调用
    """
    security = g.security
    
    # 1. 获取历史行情数据用于计算ATR
    # 多取一些数据以保证指标计算的稳定性
    count = g.atr_period + 10
    # 获取最高价、最低价、收盘价
    hist = get_history(count, frequency='1d', field=['high', 'low', 'close'], security_list=security, fq='pre')
    
    if len(hist['close']) < count:
        log.info("历史数据不足,跳过本次计算")
        return

    # 将数据转换为numpy数组,供talib使用
    high_prices = np.array(hist['high'])
    low_prices = np.array(hist['low'])
    close_prices = np.array(hist['close'])
    
    # 2. 计算ATR指标 (Average True Range)
    atr_values = talib.ATR(high_prices, low_prices, close_prices, timeperiod=g.atr_period)
    current_atr = atr_values[-1]
    
    # 如果ATR无效或为0,防止除零错误
    if np.isnan(current_atr) or current_atr <= 0:
        log.warning("ATR计算异常: %s" % current_atr)
        return

    # 3. 计算仓位大小
    # 获取当前账户总资产
    total_value = context.portfolio.portfolio_value
    # 获取当前标的价格
    current_price = data[security]['close']
    
    # 计算单笔交易允许的最大亏损金额 (例如 100万 * 1% = 1万)
    risk_money = total_value * g.risk_ratio
    
    # 计算每股的风险金额 (例如 2 * ATR)
    # 这意味着如果价格向不利方向波动 2个ATR,我们就止损,此时亏损额正好等于 risk_money
    risk_per_share = current_atr * g.atr_multiplier
    
    # 计算理论买入股数 = 允许亏损总额 / 每股风险金额
    target_shares = int(risk_money / risk_per_share)
    
    # 向下取整到100的倍数(A股一手为100股)
    target_shares = int(target_shares / 100) * 100
    
    # 4. 执行交易逻辑
    # 获取当前持仓
    position = get_position(security)
    
    # 简单的均线策略作为买卖信号示例:
    # 计算短期和长期均线
    ma5 = talib.SMA(close_prices, timeperiod=5)[-1]
    ma10 = talib.SMA(close_prices, timeperiod=10)[-1]
    
    # 打印日志方便调试
    log.info("当前价格: %.2f, ATR: %.2f, 理论仓位: %d" % (current_price, current_atr, target_shares))
    
    # 金叉买入
    if ma5 > ma10 and position.amount == 0:
        if target_shares >= 100:
            # 检查现金是否足够
            cash = context.portfolio.cash
            cost = target_shares * current_price
            if cash >= cost:
                log.info("买入信号触发 - 波动率调整仓位: 买入 %d 股" % target_shares)
                order(security, target_shares)
            else:
                log.warning("资金不足,无法买入理论仓位")
    
    # 死叉卖出
    elif ma5 < ma10 and position.amount > 0:
        log.info("卖出信号触发 - 清仓")
        order_target(security, 0)

代码关键点解析

  1. 引入 TA-Lib 库
    PTrade 支持 talib 库,这是计算技术指标最高效的方式。我们使用 talib.ATR 来计算平均真实波幅。

  2. 风险金额计算 (risk_money)
    total_value * g.risk_ratio 决定了你这一笔交易最多愿意亏多少钱。例如你有 100 万资金,设定风险比例为 1%,那么你这笔交易的底线是亏损不超过 1 万。

  3. 每股风险计算 (risk_per_share)
    current_atr * g.atr_multiplier 定义了每股的止损宽度。

    • 如果某股票 ATR 很大(波动剧烈),risk_per_share 就会变大。
    • 如果某股票 ATR 很小(波动平缓),risk_per_share 就会变小。
  4. 仓位调整结果
    根据公式 买入数量 = 风险金额 / 每股风险

    • 波动大 -> 分母大 -> 买入数量少(自动降低风险)。
    • 波动小 -> 分母小 -> 买入数量多(在安全范围内放大收益)。

常见问题 Q&A

Q: 为什么使用 ATR 而不是标准差?
A: ATR 考虑了跳空高开或低开的情况(True Range),比单纯基于收盘价的标准差更能反映真实的日内和隔日波动风险,特别适合用于确定止损幅度和仓位大小。

Q: g.atr_multiplier 设置为多少合适?
A: 通常设置为 2 到 3。这意味着你预留了 2-3 倍的日平均波动幅度作为缓冲。如果设置太小(如 0.5),很容易被正常的市场噪音震荡出局;设置太大则会导致仓位过小,资金利用率不足。

Q: 这个策略可以直接用于实盘吗?
A: 该代码是一个框架示例。在实盘前,你需要:

  1. 完善买卖信号逻辑(示例中仅使用了简单的 MA5/MA10 交叉)。
  2. 添加止损逻辑(一旦买入,当价格下跌超过 g.atr_multiplier * ATR 时应触发止损,以闭环风险控制)。
  3. 考虑多只股票的资金分配问题(如果同时操作多只股票,需要防止总仓位超过 100%)。

Q: 如何在 PTrade 中查看 ATR 的数值是否正确?
A: 你可以在 handle_data 中使用 log.info(current_atr) 打印数值,并与同花顺或通达信软件中的 ATR 指标(参数保持一致,如 14 日)进行对比。注意复权方式(fq='pre')可能会导致数值与未复权图表有差异。