🚀 AI 一键生成 ptrade 策略代码
立即体验

PTrade 量化交易:基于 ATR 自适应动态网格与资金管理策略实现指南(附 Python 源码)

ptrade | 发布时间: 2026/7/31
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: PTrade 网格交易:基于 ATR 自适应动态网格与资金管理策略

Question: 请帮我编写一个根据市场波动率动态调整网格间距的 ptrade 量化策略。

解决方案

PTrade 网格交易:基于 ATR 自适应动态网格与资金管理策略

传统固定间距网格策略在单边行情或波动剧烈变大时易面临破网风险或资金利用率低的问题。本文将介绍如何在 PTrade 量化交易平台上,利用 ATR (Average True Range,真实波幅指标) 实现动态调整网格间距的自适应网格策略,并引入资金管理与风险控制机制。


策略核心逻辑

  1. 自适应网格间距:依据每日计算的 ATR 指标动态调整网格间距(如 间距 = ATR * 倍数),波动率大时扩大间距防止频繁触网,波动率小时缩小间距捕捉微小震荡。
  2. 动态基准价更新:每次成交后更新基准价格,并在价格偏离过远时重新锚定。
  3. 资金管理:单次下单金额严格按可用资金的固定比例分配(如 10%),防止单边下跌导致早早满仓。
  4. 风控机制:设置最大持仓上限与整体组合止损。

PTrade 代码实现

# PTrade 动态网格交易策略示例
import numpy as np

def initialize(context):
    # 1. 设置标的与操作股票池
    g.security = '600570.SS'  # 示例标的:恒生电子
    set_universe(g.security)
    
    # 2. 网格参数配置
    g.atr_period = 14         # ATR 计算周期
    g.atr_multi = 1.5         # ATR 间距倍数
    g.base_price = None       # 网格基准价
    g.grid_levels = 5         # 单边网格层数
    g.position_limit = 0.5    # 最大仓位限制(占总资产比例)
    g.order_ratio = 0.1       # 每次交易使用可用资金比例
    
    # 运行时段设置:每天盘前重置/更新网格参数
    run_daily(context, daily_update, time='9:31')

def daily_update(context):
    """每日开盘更新 ATR 及动态网格间距"""
    # 获取过去 N 天的 K 线数据计算 ATR
    df = get_history(g.atr_period + 10, '1d', ['high', 'low', 'close'], g.security, fq='pre')
    if df.empty or len(df) < g.atr_period + 1:
        log.warning("数据不足,跳过 ATR 计算")
        return
    
    # 计算 TR (True Range)
    highs = df['high'].values
    lows = df['low'].values
    closes = df['close'].values
    
    tr_list = []
    for i in range(1, len(df)):
        tr = max(highs[i] - lows[i], abs(highs[i] - closes[i-1]), abs(lows[i] - closes[i-1]))
        tr_list.append(tr)
    
    # 计算 ATR
    g.current_atr = np.mean(tr_list[-g.atr_period:])
    g.grid_step = round(g.current_atr * g.atr_multi, 2)
    
    # 初始化/更新基准价
    current_price = closes[-1]
    if g.base_price is None:
        g.base_price = current_price
        
    log.info("当日 ATR: %.3f, 动态网格间距: %.3f, 当前基准价: %.2f" % (g.current_atr, g.grid_step, g.base_price))

def handle_data(context, data):
    if g.base_price is None or g.grid_step <= 0:
        return
        
    sid = g.security
    current_price = data[sid]['close']
    
    # 获取当前持仓及资产信息
    pos = get_position(sid)
    current_amount = pos.amount if pos else 0
    portfolio_value = context.portfolio.portfolio_value
    cash = context.portfolio.cash
    position_value = context.portfolio.positions_value
    
    # 仓位比例风控
    current_pos_ratio = position_value / portfolio_value if portfolio_value > 0 else 0
    
    # 1. 买入逻辑:价格低于基准价 - 网格间距
    if current_price <= g.base_price - g.grid_step:
        if current_pos_ratio < g.position_limit:
            buy_cash = cash * g.order_ratio
            if buy_cash >= current_price * 100:
                order_value(sid, buy_cash)
                g.base_price = current_price  # 更新基准价
                log.info("触发向下网格买入,买入金额: %.2f,新基准价: %.2f" % (buy_cash, g.base_price))
                
    # 2. 卖出逻辑:价格高于基准价 + 网格间距
    elif current_price >= g.base_price + g.grid_step:
        if current_amount > 0:
            sell_amount = min(current_amount, int((cash + position_value) * g.order_ratio / current_price / 100) * 100)
            if sell_amount <= 0:
                sell_amount = 100  # 最少卖出1手
            order(sid, -sell_amount)
            g.base_price = current_price  # 更新基准价
            log.info("触发向上网格卖出,卖出数量: %d,新基准价: %.2f" % (sell_amount, g.base_price))

实盘部署注意事项

  1. 标的选择:网格交易适合高波动、有均值回归特性的标的(如 ETF、大盘蓝筹股),避免用于单边下跌趋势的股票。
  2. 复权处理:在调用 get_history 时,务必开通前复权 (fq='pre'),确保 ATR 计算的连续性。
  3. 挂单与单笔精度:股票单笔委托数量需为 100 股(1手)的整倍数,限价单下单时注意保留两位小数。