🚀 AI 一键生成 joinquant 策略代码

JoinQuant 量化策略:TRIX(三重指数平滑平均线)指标交易系统

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

问题描述

帮我写一个基于 TRIX 指标的量化策略

解决方案

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

策略原理

TRIX 指标是一种研究股价趋势的长期技术分析工具。它过滤掉了短期波动的干扰,主要用于判断中长期的趋势。

  1. 计算方法

    • 先计算收盘价的 N 日指数移动平均(EMA1);
    • 对 EMA1 再计算 N 日指数移动平均(EMA2);
    • 对 EMA2 再计算 N 日指数移动平均(EMA3);
    • TRIX 线 = (EMA3 - 昨日EMA3) / 昨日EMA3 * 100;
    • MATRIX 线 = TRIX 的 M 日简单移动平均。
  2. 交易逻辑

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

策略代码

# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np

def initialize(context):
    """
    初始化函数,设定基准、手续费、全局变量等
    """
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定股票类每笔交易时的手续费
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # --- 策略参数设置 ---
    # 要操作的标的(这里以平安银行为例,可修改为其他股票或ETF)
    g.security = '000001.XSHE'
    
    # TRIX指标参数
    g.N = 12  # EMA的周期
    g.M = 9   # TRIX均线(MATRIX)的周期
    
    # 运行频率:每天开盘时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    """
    每日开盘运行的逻辑
    """
    security = g.security
    
    # 1. 获取历史数据
    # TRIX需要三重平滑,需要较长的历史数据才能使计算稳定
    # 获取长度建议为 N * 5 + M 以上
    fetch_len = g.N * 10 + g.M
    
    # 获取收盘价数据
    # 注意:include_now=True 在回测中如果是按天运行,取不到当天收盘价,只能取到昨天及之前的
    # 这里我们取过去 fetch_len 天的数据(不含今天)
    h_data = attribute_history(security, fetch_len, '1d', ['close'], df=True)
    
    if len(h_data) < fetch_len:
        log.info("数据不足,跳过当日")
        return

    close_prices = h_data['close']
    
    # 2. 计算 TRIX 指标
    # 计算三重指数移动平均 (EMA3)
    # span=g.N 对应 alpha=2/(N+1)
    ema1 = close_prices.ewm(span=g.N, adjust=False).mean()
    ema2 = ema1.ewm(span=g.N, adjust=False).mean()
    ema3 = ema2.ewm(span=g.N, adjust=False).mean()
    
    # 计算 TRIX: (EMA3 - Ref(EMA3, 1)) / Ref(EMA3, 1) * 100
    # pct_change() 计算的是 (curr - prev) / prev,正好符合公式,再乘以100
    trix = ema3.pct_change() * 100
    
    # 计算 MATRIX (TRIX的M日简单移动平均)
    matrix = trix.rolling(window=g.M).mean()
    
    # 3. 获取信号判断所需的数值
    # 当前时刻(昨天收盘)的指标值
    curr_trix = trix.iloc[-1]
    curr_matrix = matrix.iloc[-1]
    
    # 前一时刻(前天收盘)的指标值
    prev_trix = trix.iloc[-2]
    prev_matrix = matrix.iloc[-2]
    
    # 检查是否有 NaN 值(数据计算初期可能产生NaN)
    if np.isnan(curr_trix) or np.isnan(curr_matrix) or np.isnan(prev_trix) or np.isnan(prev_matrix):
        return

    # 4. 交易逻辑判断
    # 获取当前仓位
    position = context.portfolio.positions[security]
    cash = context.portfolio.available_cash
    
    # 金叉:TRIX 上穿 MATRIX
    is_golden_cross = (prev_trix < prev_matrix) and (curr_trix > curr_matrix)
    
    # 死叉:TRIX 下穿 MATRIX
    is_death_cross = (prev_trix > prev_matrix) and (curr_trix < curr_matrix)
    
    # 执行交易
    if is_golden_cross:
        # 如果有资金且未持仓(或根据策略加仓),则买入
        if cash > 0:
            log.info("TRIX金叉 (TRIX:%.3f, MATRIX:%.3f),买入 %s" % (curr_trix, curr_matrix, security))
            order_value(security, cash)
            
    elif is_death_cross:
        # 如果持有仓位,则卖出
        if position.closeable_amount > 0:
            log.info("TRIX死叉 (TRIX:%.3f, MATRIX:%.3f),卖出 %s" % (curr_trix, curr_matrix, security))
            order_target(security, 0)

    # 记录指标值以便在回测图中查看
    record(TRIX=curr_trix, MATRIX=curr_matrix)

代码要点解析

  1. 数据获取 (attribute_history)

    • TRIX 指标涉及三次 EMA 平滑,对历史数据的依赖性较强。如果获取的数据长度太短,计算出的 EMA 值在初期会很不准确。因此代码中设置了 fetch_len = g.N * 10 + g.M,获取足够多的历史数据以确保指标收敛。
  2. 指标计算 (pandas.ewm)

    • 使用了 Pandas 的 ewm(span=N, adjust=False) 来计算指数移动平均。adjust=False 是为了更贴近传统股票软件(如通达信、同花顺)的递归计算方式。
    • trix = ema3.pct_change() * 100:利用 pct_change 快速计算变化率。
  3. 信号判断

    • 通过比较“当前值”和“前一值”与信号线的相对位置来判断交叉。
    • prev_trix < prev_matrixcurr_trix > curr_matrix 判定为金叉。
  4. 交易执行

    • 使用 order_value 全仓买入(可根据需求调整仓位管理逻辑)。
    • 使用 order_target 清仓卖出。

如何使用

  1. 在聚宽(JoinQuant)的“我的策略”中新建一个策略。
  2. 将上述代码复制粘贴到代码编辑区。
  3. 点击“编译运行”检查是否有语法错误。
  4. 点击“运行回测”,选择回测时间段(建议选择较长的时间段,如1-2年,因为 TRIX 是中长线指标)。

Q&A

Q: 如何更换要操作的股票?
A: 修改 initialize 函数中的 g.security = '000001.XSHE',将其改为你想要回测的股票代码(例如贵州茅台 '600519.XSHG')。

Q: 如何调整 TRIX 的灵敏度?
A: 修改 g.Ng.M

  • 增大 g.N(如改为 20或30),指标会更平滑,过滤更多噪音,但信号会更滞后(适合长线)。
  • 减小 g.N(如改为 5或8),指标会更敏感,信号更多,但假信号也可能增加(适合短线)。

Q: 为什么回测初期没有交易?
A: 因为 TRIX 需要较长的历史数据来计算 EMA3。虽然我们获取了历史数据,但如果回测开始日期对应的历史数据不足以让 EMA 收敛,或者指标在初期没有发生交叉,就不会产生交易。