🚀 AI 一键生成 ptrade 策略代码

如何在 PTrade 策略中集成宏观经济指标,构建市场状态过滤器?

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

问题描述

如何在策略中加入一个基于宏观指标的市场风险开关?

解决方案

在PTrade策略中加入基于宏观指标(通常使用大盘指数如沪深300、上证指数作为宏观代理)的市场风险开关,是一种非常有效的风控手段。这通常被称为“大盘择时”或“红绿灯机制”。

其核心逻辑是:在每日开盘前或盘中,计算大盘指数的指标(如均线、RSI、MACD等),如果大盘走势恶化,则停止买入或清仓。

以下是具体的实现步骤和完整的代码示例。

实现思路

  1. 选择宏观标的:通常选择 000300.SS (沪深300) 或 000001.SS (上证指数) 代表市场整体环境。
  2. 定义风险指标:例如,当大盘指数跌破20日均线时,视为高风险(Risk On);站上20日均线时,视为低风险(Risk Off)。
  3. 设置全局开关:在 g 全局对象中设置一个变量(如 g.market_risk_on)。
  4. 交易逻辑控制
    • handle_data 中,如果风险开关开启(高风险),则禁止开仓,并可选择是否清仓。
    • 如果风险开关关闭(低风险),则执行正常的选股和买入逻辑。

完整策略代码示例

以下代码展示了一个完整的策略:当沪深300指数跌破20日均线时,触发风控开关,清空持仓并停止买入;反之则正常交易(示例中简单买入恒生电子)。

def initialize(context):
    """
    初始化函数
    """
    # 1. 设定要操作的股票(策略标的)
    g.security = '600570.SS' 
    set_universe(g.security)
    
    # 2. 设定宏观参考指标(这里使用沪深300指数)
    g.macro_index = '000300.SS'
    
    # 3. 定义风险开关标识 (True表示有风险/禁止买入,False表示安全/允许交易)
    g.is_risk_mode = False
    
    # 4. 设定均线周期
    g.ma_window = 20
    
    log.info("策略初始化完成,宏观风控标的:%s" % g.macro_index)

def before_trading_start(context, data):
    """
    盘前处理:计算宏观指标,更新风控开关状态
    """
    # 获取大盘指数的历史数据(取过去 N+1 天,以确保能算出 N 日均线)
    # 注意:get_history 返回的是 DataFrame
    hist_data = get_history(g.ma_window + 5, '1d', 'close', g.macro_index, fq=None, include=False)
    
    if len(hist_data) < g.ma_window:
        log.warning("历史数据不足,无法计算大盘均线,默认无风险")
        g.is_risk_mode = False
        return

    # 计算大盘的 N 日均线
    # 使用切片取最近的 N 天数据计算均值
    close_prices = hist_data['close'].values
    ma_value = close_prices[-g.ma_window:].mean()
    
    # 获取大盘昨日收盘价
    current_index_price = close_prices[-1]
    
    # --- 核心风控逻辑 ---
    # 如果 大盘价格 < 均线,判定为市场风险高
    if current_index_price < ma_value:
        g.is_risk_mode = True
        log.info("【风控触发】大盘指数(%.2f) 低于 %d日均线(%.2f),今日暂停买入并执行清仓。" % (current_index_price, g.ma_window, ma_value))
    else:
        g.is_risk_mode = False
        log.info("【市场安全】大盘指数(%.2f) 高于 %d日均线(%.2f),策略正常运行。" % (current_index_price, g.ma_window, ma_value))

def handle_data(context, data):
    """
    盘中交易逻辑
    """
    # 1. 检查风控开关
    if g.is_risk_mode:
        # --- 高风险模式下的操作 ---
        
        # 遍历当前所有持仓
        positions = context.portfolio.positions
        for stock in positions:
            # 如果有持仓,全部卖出 (清仓)
            if positions[stock].amount > 0:
                order_target(stock, 0)
                log.info("风控模式:卖出清仓 %s" % stock)
        
        # 直接返回,不执行后续的买入逻辑
        return

    # 2. --- 正常交易模式下的操作 (示例逻辑) ---
    
    # 获取标的股票
    target_stock = g.security
    
    # 简单的示例策略:如果没持仓就买入
    if get_position(target_stock).amount == 0:
        # 全仓买入
        order_value(target_stock, context.portfolio.cash)
        log.info("市场环境安全,买入标的:%s" % target_stock)

def after_trading_end(context, data):
    """
    盘后处理
    """
    pass

代码详解

  1. initialize:

    • 定义了 g.macro_index 为沪深300指数。
    • 初始化 g.is_risk_mode 变量,用于在不同函数间传递风控状态。
  2. before_trading_start:

    • 为什么在这里计算? 盘前计算效率最高,且大盘的日线级别趋势在开盘前就已经确定(基于昨日收盘价)。
    • 使用 get_history 获取大盘指数的收盘价序列。
    • 计算移动平均线(MA),并与最新价格对比。
    • 更新 g.is_risk_mode 的状态。
  3. handle_data:

    • 优先级最高:进入函数的第一步就是检查 if g.is_risk_mode:
    • 清仓逻辑:如果处于风险模式,循环遍历 context.portfolio.positions,使用 order_target(stock, 0) 卖出所有持仓。
    • 阻断逻辑:清仓后使用 return 语句,强制结束当次 handle_data 的执行,防止后续的买入代码被执行。

进阶扩展:其他宏观指标

除了简单的均线,您还可以使用其他指标来定义“宏观风险”:

  1. 大盘成交量萎缩

    # 获取成交量数据
    vol = get_history(10, '1d', 'volume', g.macro_index)['volume']
    # 如果今日成交量小于过去10天均量的80%,视为流动性风险
    if vol[-1] < vol.mean() * 0.8:
        g.is_risk_mode = True
    
  2. RSI 指标过热/过冷

    # 使用内置 get_RSI 函数
    # 注意:get_RSI 需要传入 close 数组
    close_data = get_history(30, '1d', 'close', g.macro_index)['close'].values
    rsi_val = get_RSI(close_data, n=14)[-1]
    
    # 如果 RSI < 30 (超卖) 或 RSI > 80 (超买风险),可触发特定风控
    if rsi_val < 30: 
        # 熊市不抄底逻辑
        g.is_risk_mode = True
    
  3. 多指数共振
    同时判断上证指数(000001.SS)和创业板指(399006.SZ),只有当两者同时处于均线之上时才交易,否则空仓。

常见问题 (Q&A)

Q: 为什么使用 000300.SS 而不是具体的宏观经济数据(如GDP)?
A: PTrade 是量化交易终端,主要提供高频和低频的行情数据。GDP、CPI 等宏观经济数据通常更新频率低(月度/季度),且在 API 中不直接作为标准行情提供。使用大盘指数(Index)的技术形态是衡量市场情绪最直接、最实时的“宏观”代理指标。

Q: 可以在盘中实时监控大盘风险吗?
A: 可以。将 before_trading_start 中的计算逻辑移动到 handle_data 中,并将频率设置为分钟级回测。但要注意,分钟级别的频繁止损可能会造成较高的交易成本(“左右挨打”),通常建议大盘风控以日线级别为准。

Q: 这种风控会影响回测速度吗?
A: 几乎不会。计算一个指数的均线是非常快速的数学运算,相比于策略本身的逻辑,其开销可以忽略不计。