3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 TRIX(三重指数平滑移动平均) 指标的量化交易策略。
TRIX 是一种动量指标,用于过滤短期价格波动,通过三次平滑处理来显示价格的长期趋势。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np
def init(ContextInfo):
"""
策略初始化函数
"""
# 1. 设置策略参数
ContextInfo.N = 12 # TRIX指标的周期
ContextInfo.M = 9 # TRIX均线(MATRIX)的周期
# 2. 设置股票池 (示例:平安银行)
# 在实际运行时,可以通过界面设置股票池,这里代码演示写死一个
ContextInfo.stock_list = ['000001.SZ']
ContextInfo.set_universe(ContextInfo.stock_list)
# 3. 设置资金账号 (请替换为您自己的资金账号)
ContextInfo.account_id = '6000000000'
ContextInfo.account_type = 'STOCK' # 账号类型:STOCK股票,FUTURE期货
ContextInfo.set_account(ContextInfo.account_id)
# 4. 设置回测参数 (仅回测有效)
ContextInfo.set_slippage(1, 0.0) # 设置滑点
ContextInfo.set_commission(0, [0.0003, 0.0013, 0.0003, 0.0003, 0.0003, 5]) # 设置费率
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 获取当前设置的股票池
stock_list = ContextInfo.get_universe()
# 获取当前周期 (例如 '1d')
period = ContextInfo.period
# 遍历每只股票进行计算
for stock in stock_list:
# 1. 获取历史行情数据
# TRIX经过三次平滑,需要较长的历史数据才能计算准确,这里取 100 根K线
data_len = 100
# 使用 get_market_data_ex 获取数据 (推荐使用 ex 接口)
# subscribe=True 确保实盘时数据自动更新
market_data = ContextInfo.get_market_data_ex(
['close'],
[stock],
period=period,
count=data_len,
dividend_type='front', # 前复权
subscribe=True
)
if stock not in market_data or market_data[stock].empty:
continue
df = market_data[stock]
# 数据长度不足以计算指标时跳过
if len(df) < ContextInfo.N * 3 + ContextInfo.M:
continue
# 2. 计算 TRIX 指标
# 计算步骤 1: 收盘价的 N 日 EMA (EMA1)
ema1 = df['close'].ewm(span=ContextInfo.N, adjust=False).mean()
# 计算步骤 2: EMA1 的 N 日 EMA (EMA2)
ema2 = ema1.ewm(span=ContextInfo.N, adjust=False).mean()
# 计算步骤 3: EMA2 的 N 日 EMA (EMA3, 即 TR)
tr = ema2.ewm(span=ContextInfo.N, adjust=False).mean()
# 计算步骤 4: TRIX = (今日TR - 昨日TR) / 昨日TR * 100
# pct_change() 计算变化率,默认就是 (curr - prev) / prev
trix = tr.pct_change() * 100
# 计算步骤 5: MATRIX (TRIX 的 M 日简单移动平均)
matrix = trix.rolling(window=ContextInfo.M).mean()
# 3. 获取最新的指标值用于判断信号
# prev_trix: 上一根K线的TRIX, curr_trix: 当前K线的TRIX
# iloc[-1] 是当前最新值,iloc[-2] 是前一根K线值
curr_trix = trix.iloc[-1]
prev_trix = trix.iloc[-2]
curr_matrix = matrix.iloc[-1]
prev_matrix = matrix.iloc[-2]
# 检查是否包含无效值(NaN),如果有则跳过
if np.isnan(curr_trix) or np.isnan(curr_matrix) or np.isnan(prev_trix) or np.isnan(prev_matrix):
continue
# 4. 获取当前持仓信息
# 获取持仓对象列表
positions = get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
current_vol = 0
for pos in positions:
if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock:
current_vol = pos.m_nVolume
break
# 5. 生成交易信号并下单
# 金叉:TRIX 上穿 MATRIX
long_signal = (prev_trix < prev_matrix) and (curr_trix > curr_matrix)
# 死叉:TRIX 下穿 MATRIX
short_signal = (prev_trix > prev_matrix) and (curr_trix < curr_matrix)
# 执行买入逻辑
if long_signal:
if current_vol == 0: # 如果当前无持仓
# 示例:全仓买入 (实际策略请做好资金管理)
# 这里简单演示:按最新价买入 1000 股
# 23: 买入, 1101: 单股单账号普通股/手下单, 5: 最新价
passorder(23, 1101, ContextInfo.account_id, stock, 5, -1, 1000, ContextInfo)
print(f"TRIX金叉,买入 {stock}")
# 执行卖出逻辑
elif short_signal:
if current_vol > 0: # 如果当前有持仓
# 卖出所有持仓
# 24: 卖出
passorder(24, 1101, ContextInfo.account_id, stock, 5, -1, current_vol, ContextInfo)
print(f"TRIX死叉,卖出 {stock}")
# 6. 绘图 (可选,用于回测界面展示)
# 注意:paint函数只能画在主图对应的品种上,如果遍历多个股票,这里只演示画当前主图品种
# 获取当前主图代码
main_stock = ContextInfo.stockcode + '.' + ContextInfo.market
if main_stock in market_data:
# 重新计算一遍主图的指标用于绘图
m_df = market_data[main_stock]
m_ema1 = m_df['close'].ewm(span=ContextInfo.N, adjust=False).mean()
m_ema2 = m_ema1.ewm(span=ContextInfo.N, adjust=False).mean()
m_tr = m_ema2.ewm(span=ContextInfo.N, adjust=False).mean()
m_trix = m_tr.pct_change() * 100
m_matrix = m_trix.rolling(window=ContextInfo.M).mean()
# 在副图画线
ContextInfo.paint('TRIX', m_trix.iloc[-1], -1, 0, 'white', 'noaxis')
ContextInfo.paint('MATRIX', m_matrix.iloc[-1], -1, 0, 'yellow', 'noaxis')
数据获取 (get_market_data_ex):
get_market_data_ex 接口,这是 QMT 推荐的高效数据接口。count=100:TRIX 指标涉及三次 EMA 平滑,对历史数据长度有要求,数据太短会导致计算初期的指标值不准确。dividend_type='front':使用前复权数据,保证价格连续性,避免分红除权造成的指标跳变。指标计算 (Pandas):
ewm(span=N) 函数非常方便地计算指数移动平均。pct_change() 用于计算变化率,即 (当前值 - 前值) / 前值,这正是 TRIX 的核心定义。交易执行 (passorder):
23 代表买入,24 代表卖出。1101 代表单股、单账号、按股数下单。5 代表使用最新价下单。绘图 (paint):
paint 函数,可以在 QMT 的回测界面副图中画出 TRIX 和 MATRIX 线,方便验证策略信号。init 函数中的 ContextInfo.account_id 为您真实的资金账号。Q: 为什么 TRIX 指标计算需要较长的历史数据?
A: TRIX 进行了三次指数平滑(EMA)。EMA 是一种递归计算,今天的数值依赖于昨天的数值。如果数据序列太短,初始值的偏差会严重影响后续的计算结果。通常建议数据长度至少是周期 N 的 3-5 倍以上。
Q: 如何调整策略的灵敏度?
A: 修改 init 函数中的 ContextInfo.N 和 ContextInfo.M。
Q: passorder 函数中的 quickTrade 参数有什么用?
A: 在本策略中,passorder 的 quickTrade 参数(倒数第二个参数)默认为 0(代码中未显式写出,使用了默认行为)。在回测中,这意味着信号在 K 线走完后确认,并在下一根 K 线开盘时下单。如果设置为 1,则表示立即下单(非收盘确认),这在实盘中常用于盘中即时信号,但在回测中可能会引入“未来函数”风险,需谨慎使用。