在 GitHub 上查看
Exp T3 TRIX 策略 (ID 2946)
Exp T3 TRIX 策略移植自 MetaTrader 5 的同名专家顾问,通过三重平滑的 TRIX 指标捕捉动量反转。策略利用 Tillson T3 平滑获得快慢两条 TRIX 曲线,并根据三种可选模式判定何时进出场。
交易逻辑
- Tillson T3 TRIX 计算
- 为快线和慢线分别构建 6 层指数移动平均,得到 Tillson T3 数值。
- 每条 T3 的导数(当前值与前值之差再除以前值)构成 TRIX 柱状图,作为信号源。
- 模式 = Breakdown
- 做多: 快速 TRIX 从零轴下方上穿零轴且允许做多时触发。若允许平空,会先平掉已有空头。
- 做空: 快速 TRIX 从零轴上方下穿零轴且允许做空时触发。若允许平多,会先平掉已有多头。
- 仅平仓: 若出现穿越但相应入场被禁用,仍会在许可的情况下平掉对向持仓。
- 模式 = Twist
- 做多: 快速 TRIX 的斜率由负转正(即先下行后上行)。其他平仓与权限规则与 Breakdown 相同。
- 做空: 快速 TRIX 的斜率由正转负。
- 模式 = CloudTwist
- 做多: 快速 TRIX 在上一根收盘还位于慢速 TRIX 下方,本根收盘已上穿慢速 TRIX。
- 做空: 快速 TRIX 在上一根收盘还位于慢速 TRIX 上方,本根收盘已下穿慢速 TRIX。
- 下单处理
- 出现反向信号且允许平仓时,策略会优先关闭相反方向的持仓。
- 新开仓的数量为
Volume + |Position|,允许在一次指令中完成反手。
- 启用
StartProtection(),沿用 StockSharp 模板提供的保护机制。
参数
| 参数 |
默认值 |
说明 |
Fast Length |
10 |
快速 Tillson T3 的深度(6 层 EMA 链)。 |
Slow Length |
18 |
慢速 Tillson T3 的深度。 |
Volume Factor |
0.7 |
Tillson T3 平滑系数 (0 ~ 1)。 |
Mode |
Twist |
Breakdown、Twist、CloudTwist 三种信号模式。 |
Allow Long Entry |
true |
是否允许开多。 |
Allow Short Entry |
true |
是否允许开空。 |
Allow Long Exit |
true |
是否允许平多。 |
Allow Short Exit |
true |
是否允许平空。 |
Candle Type |
4 小时时间框架 |
计算所用的蜡烛聚合周期。 |
所有参数都通过 StrategyParam<T> 暴露,可在 Designer 中显示并用于优化。
使用提示
- 策略仅处理收盘完结的蜡烛,请确保数据源提供与
Candle Type 一致的时间框架。
- 由于 TRIX 导数需要历史数据,最初两根完成的蜡烛只用于初始化,不会产生信号。
- 想要复制原版的单向交易或禁止平仓,可关闭相应的
Allow ... 开关。
- 原专家顾问没有内置止损或止盈,本策略同样未实现。需要风险控制时可结合 StockSharp 的资金管理模块。
移植细节
- 来源:
MQL/2156/exp_t3_trix.mq5 以及指标 t3_trix.mq5。
- 移植版保持三种信号模式,并使用 StockSharp 的高阶蜡烛订阅及指标类。
- Tillson T3 通过 6 层 EMA 与可调的
Volume Factor 重建,默认系数 0.7。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// T3 TRIX strategy using TRIX indicator for momentum signals.
/// Trades on TRIX zero-line crossovers.
/// </summary>
public class ExpT3TrixStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private decimal? _prevTrix;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
public ExpT3TrixStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_period = Param(nameof(Period), 14)
.SetGreaterThanZero()
.SetDisplay("Period", "TRIX period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevTrix = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevTrix = null;
var trix = new Trix { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(trix, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
var indArea = CreateChartArea();
if (indArea != null)
{
DrawIndicator(indArea, trix);
}
}
private void ProcessCandle(ICandleMessage candle, decimal trixValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevTrix = trixValue;
return;
}
if (_prevTrix == null)
{
_prevTrix = trixValue;
return;
}
// TRIX crosses above zero → buy
if (_prevTrix.Value <= 0 && trixValue > 0)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
// TRIX crosses below zero → sell
else if (_prevTrix.Value >= 0 && trixValue < 0)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
_prevTrix = trixValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Trix
from StockSharp.Algo.Strategies import Strategy
class exp_t3_trix_strategy(Strategy):
def __init__(self):
super(exp_t3_trix_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._period = self.Param("Period", 14) \
.SetDisplay("Period", "TRIX period", "Indicators")
self._prev_trix = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def Period(self):
return self._period.Value
def OnReseted(self):
super(exp_t3_trix_strategy, self).OnReseted()
self._prev_trix = None
def OnStarted2(self, time):
super(exp_t3_trix_strategy, self).OnStarted2(time)
self._prev_trix = None
trix = Trix()
trix.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(trix, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
ind_area = self.CreateChartArea()
if ind_area is not None:
self.DrawIndicator(ind_area, trix)
def _on_process(self, candle, trix_value):
if candle.State != CandleStates.Finished:
return
tv = float(trix_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_trix = tv
return
if self._prev_trix is None:
self._prev_trix = tv
return
# TRIX crosses above zero
if self._prev_trix <= 0 and tv > 0:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
# TRIX crosses below zero
elif self._prev_trix >= 0 and tv < 0:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_trix = tv
def CreateClone(self):
return exp_t3_trix_strategy()