🚀 AI 一键生成 ptrade 策略代码

PTrade 策略开发:TRIX 指标计算与金叉死叉策略实现

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

问题描述

请帮我写一个 TRIX 指标的交易策略

解决方案

这是一个基于 TRIX(Triple Exponential Average,三重指数平滑移动平均) 指标的 PTrade 量化交易策略。

策略原理

TRIX 是一种动量指标,通过对收盘价进行三次指数平滑处理,过滤掉频繁的短期波动,从而反映股价的长期趋势。

  1. TRIX 线:收盘价的三重指数移动平均线(EMA3)的变化率。
  2. MATRIX 线:TRIX 线的 M 日简单移动平均线(信号线)。

交易信号

  • 金叉买入:当 TRIX 线由下向上穿过 MATRIX 线时,视为买入信号。
  • 死叉卖出:当 TRIX 线由上向下穿过 MATRIX 线时,视为卖出信号。

策略代码

import pandas as pd
import numpy as np

def initialize(context):
    """
    初始化函数,设置股票池和参数
    """
    # 设置要操作的股票,这里以恒生电子为例
    g.security = '600570.SS'
    set_universe(g.security)
    
    # TRIX 指标参数
    g.N = 12  # 计算 EMA 的周期
    g.M = 9   # 计算 MATRIX(信号线)的周期
    
    # 设置滑点和佣金(回测常用设置)
    set_commission(commission_ratio=0.0003, min_commission=5.0)
    set_slippage(slippage=0.002)

def handle_data(context, data):
    """
    按周期运行的策略逻辑
    """
    security = g.security
    
    # 1. 获取历史收盘价数据
    # TRIX 需要三次平滑,建议获取足够长的数据以消除初始值的偏差
    # N=12, M=9,获取 100 条数据通常足够稳定
    hist_data = get_history(100, frequency='1d', field='close', security_list=security, fq='pre')
    
    if hist_data is None or len(hist_data) < 50:
        log.info("数据不足,跳过计算")
        return

    # 2. 计算 TRIX 指标
    # 将数据转换为 Series 方便计算
    close_prices = hist_data['close']
    
    # 计算 TRIX 和 MATRIX
    trix, matrix = calculate_trix(close_prices, g.N, g.M)
    
    # 确保指标数据有效(去除 NaN)
    if np.isnan(trix.iloc[-1]) or np.isnan(matrix.iloc[-1]) or \
       np.isnan(trix.iloc[-2]) or np.isnan(matrix.iloc[-2]):
        return

    # 获取当前和前一时刻的指标值
    current_trix = trix.iloc[-1]
    current_matrix = matrix.iloc[-1]
    prev_trix = trix.iloc[-2]
    prev_matrix = matrix.iloc[-2]
    
    # 3. 获取账户持仓和资金情况
    position = get_position(security)
    cash = context.portfolio.cash
    current_price = data[security]['close']
    
    # 4. 生成交易信号
    # 金叉:上个周期 TRIX < MATRIX,当前周期 TRIX > MATRIX
    golden_cross = (prev_trix < prev_matrix) and (current_trix > current_matrix)
    
    # 死叉:上个周期 TRIX > MATRIX,当前周期 TRIX < MATRIX
    death_cross = (prev_trix > prev_matrix) and (current_trix < current_matrix)
    
    # 5. 执行交易
    # 买入逻辑:金叉且当前无持仓
    if golden_cross and position.amount == 0:
        log.info("TRIX 金叉形成 (TRIX: %.3f, MATRIX: %.3f),买入 %s" % (current_trix, current_matrix, security))
        order_value(security, cash)
        
    # 卖出逻辑:死叉且有持仓
    elif death_cross and position.amount > 0:
        log.info("TRIX 死叉形成 (TRIX: %.3f, MATRIX: %.3f),卖出 %s" % (current_trix, current_matrix, security))
        order_target(security, 0)

def calculate_trix(series, n, m):
    """
    手动计算 TRIX 指标
    :param series: 收盘价序列 (pandas Series)
    :param n: EMA 周期
    :param m: 信号线周期
    :return: trix, matrix (pandas Series)
    """
    # 1. 计算第一次 EMA (EMA1)
    ema1 = series.ewm(span=n, adjust=False).mean()
    
    # 2. 计算第二次 EMA (EMA2)
    ema2 = ema1.ewm(span=n, adjust=False).mean()
    
    # 3. 计算第三次 EMA (EMA3)
    ema3 = ema2.ewm(span=n, adjust=False).mean()
    
    # 4. 计算 TRIX: (EMA3 - 昨日EMA3) / 昨日EMA3 * 100
    # pct_change() 计算的是 (curr - prev) / prev,默认不乘 100,所以手动乘以 100
    trix = ema3.pct_change() * 100
    
    # 5. 计算 MATRIX (TRIX 的 m 日简单移动平均)
    matrix = trix.rolling(window=m).mean()
    
    return trix, matrix

代码说明

  1. 数据获取 (get_history)

    • TRIX 指标涉及三次指数平滑,对历史数据的依赖性较强。为了保证计算结果的准确性,我们获取了 100 天的历史数据。如果数据量太少,早期的 EMA 值会不稳定。
    • 使用 fq='pre'(前复权)数据,以避免分红派息导致的价格跳空影响指标计算。
  2. 指标计算 (calculate_trix)

    • PTrade 的 API 文档中没有直接提供 get_TRIX 函数,因此我们使用 pandas 库手动实现。
    • ewm(span=n, adjust=False).mean() 用于计算指数移动平均(EMA)。
    • pct_change() 用于计算变化率。
    • rolling(window=m).mean() 用于计算简单移动平均(MA),即 MATRIX 线。
  3. 交易逻辑

    • 金叉prev_trix < prev_matrixcurrent_trix > current_matrix
    • 死叉prev_trix > prev_matrixcurrent_trix < current_matrix
    • 使用 order_value 全仓买入,使用 order_target 清仓卖出。
  4. 兼容性

    • 代码避免了 Python 3.6+ 的 f-string 语法,使用了 % 格式化字符串,确保在 PTrade 的 Python 3.5 环境中也能正常运行。

Q&A

Q: 为什么 TRIX 指标适合中长期趋势?
A: 因为 TRIX 对价格进行了三次平滑处理,极大地过滤了短期的高频噪音。这使得它对价格变化的反应比 MACD 或 RSI 更滞后,但也更稳定,不容易产生虚假信号,因此更适合捕捉中长期的主要趋势。

Q: 如何调整策略的灵敏度?
A: 修改 initialize 函数中的 g.Ng.M

  • 减小 g.N(例如改为 5 或 9):指标会更敏感,信号更多,但假信号风险增加。
  • 增大 g.N(例如改为 20 或 30):指标更平滑,信号更少,适合捕捉大趋势,但滞后性会增强。

Q: 可以在分钟级别回测吗?
A: 可以。只需在回测设置界面将频率选为“分钟”,并将 get_history 中的 frequency 参数改为 '1m', '5m', '30m' 等即可。代码逻辑无需修改。