Estrategia de Cruce TRIX
Esta estrategia utiliza dos indicadores TRIX (Oscilador de Media Móvil Triple Exponencial) con diferentes períodos para detectar posibles reversiones. Se abre una posición larga cuando el TRIX rápido forma un mínimo local mientras el TRIX lento está subiendo. Se abre una posición corta cuando el TRIX rápido forma un máximo local mientras el TRIX lento está bajando.
Parámetros
- Fast TRIX Period – período del indicador TRIX rápido.
- Slow TRIX Period – período del indicador TRIX lento.
- Take Profit – objetivo de beneficio en unidades de precio absolutas.
- Stop Loss – pérdida máxima en unidades de precio absolutas.
- Candle Type – marco temporal o tipo de datos para las velas.
Lógica de Trading
- Suscribirse al tipo de vela seleccionado.
- Calcular los valores de TRIX rápido y lento en cada vela finalizada.
- Entrar largo cuando el valor del TRIX rápido es mayor que su valor anterior, el valor anterior es menor que el valor previo a él, y el TRIX lento está subiendo.
- Entrar corto cuando el valor del TRIX rápido es menor que su valor anterior, el valor anterior es mayor que el valor previo a él, y el TRIX lento está bajando.
- Solo se mantiene una posición a la vez.
- Las protecciones de stop loss y take profit se aplican automáticamente.
Notas
La estrategia es una adaptación de un script MQL5 y demuestra cómo trabajar con indicadores TRIX dentro de StockSharp.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on fast and slow TRIX indicator signals.
/// A long position opens when the fast TRIX forms a local bottom and the slow TRIX is rising.
/// A short position opens when the fast TRIX forms a local top and the slow TRIX is falling.
/// </summary>
public class TrixCrossoverStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<decimal> _minTrix;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<DataType> _candleType;
// Store previous TRIX values for decision making
private decimal _fastTrixPrev1;
private decimal _fastTrixPrev2;
private decimal _slowTrixPrev;
private decimal _prevFastTema;
private decimal _prevSlowTema;
private TripleExponentialMovingAverage _fastTema = null!;
private TripleExponentialMovingAverage _slowTema = null!;
/// <summary>
/// Fast TRIX period.
/// </summary>
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
/// <summary>
/// Slow TRIX period.
/// </summary>
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
/// <summary>
/// Minimum TRIX value required for a signal.
/// </summary>
public decimal MinTrix
{
get => _minTrix.Value;
set => _minTrix.Value = value;
}
/// <summary>
/// Take profit size in absolute price units.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Stop loss size in absolute price units.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes <see cref="TrixCrossoverStrategy"/>.
/// </summary>
public TrixCrossoverStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Fast TRIX Period", "Period for the fast TRIX indicator", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow TRIX Period", "Period for the slow TRIX indicator", "Indicators");
_minTrix = Param(nameof(MinTrix), 0.0005m)
.SetGreaterThanZero()
.SetDisplay("Min TRIX", "Minimum TRIX magnitude for signals", "Indicators");
_takeProfit = Param(nameof(TakeProfit), 1500m)
.SetNotNegative()
.SetDisplay("Take Profit", "Take profit in absolute price units", "Risk Management");
_stopLoss = Param(nameof(StopLoss), 500m)
.SetNotNegative()
.SetDisplay("Stop Loss", "Stop loss in absolute price units", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fastTrixPrev1 = 0m;
_fastTrixPrev2 = 0m;
_slowTrixPrev = 0m;
_prevFastTema = 0m;
_prevSlowTema = 0m;
_fastTema = null!;
_slowTema = null!;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastTrixPrev1 = 0m;
_fastTrixPrev2 = 0m;
_slowTrixPrev = 0m;
_prevFastTema = 0m;
_prevSlowTema = 0m;
_fastTema = new TripleExponentialMovingAverage { Length = FastPeriod };
_slowTema = new TripleExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_fastTema, _slowTema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _fastTema);
DrawIndicator(area, _slowTema);
DrawOwnTrades(area);
}
StartProtection(new Unit(TakeProfit, UnitTypes.Absolute), new Unit(StopLoss, UnitTypes.Absolute));
}
private void ProcessCandle(ICandleMessage candle, decimal fastTemaValue, decimal slowTemaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFastTema == 0m || _prevSlowTema == 0m)
{
_prevFastTema = fastTemaValue;
_prevSlowTema = slowTemaValue;
return;
}
var fastTrix = (fastTemaValue - _prevFastTema) / _prevFastTema;
var slowTrix = (slowTemaValue - _prevSlowTema) / _prevSlowTema;
_prevFastTema = fastTemaValue;
_prevSlowTema = slowTemaValue;
var prevFastTrix = _fastTrixPrev1;
_fastTrixPrev2 = _fastTrixPrev1;
_fastTrixPrev1 = fastTrix;
var slowTrixPrev = _slowTrixPrev;
_slowTrixPrev = slowTrix;
if (_fastTrixPrev2 == 0m || slowTrixPrev == 0m)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var crossUp = prevFastTrix <= 0 && fastTrix > 0;
var crossDown = prevFastTrix >= 0 && fastTrix < 0;
if (crossUp && slowTrix > MinTrix && Position <= 0)
BuyMarket();
else if (crossDown && slowTrix < -MinTrix && Position >= 0)
SellMarket();
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import TripleExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class trix_crossover_strategy(Strategy):
def __init__(self):
super(trix_crossover_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 9) \
.SetDisplay("Fast TRIX Period", "Period for the fast TRIX indicator", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow TRIX Period", "Period for the slow TRIX indicator", "Indicators")
self._min_trix = self.Param("MinTrix", 0.0005) \
.SetDisplay("Min TRIX", "Minimum TRIX magnitude for signals", "Indicators")
self._take_profit = self.Param("TakeProfit", 1500.0) \
.SetDisplay("Take Profit", "Take profit in absolute price units", "Risk Management")
self._stop_loss = self.Param("StopLoss", 500.0) \
.SetDisplay("Stop Loss", "Stop loss in absolute price units", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._fast_trix_prev1 = 0.0
self._fast_trix_prev2 = 0.0
self._slow_trix_prev = 0.0
self._prev_fast_tema = 0.0
self._prev_slow_tema = 0.0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def min_trix(self):
return self._min_trix.Value
@property
def take_profit(self):
return self._take_profit.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(trix_crossover_strategy, self).OnReseted()
self._fast_trix_prev1 = 0.0
self._fast_trix_prev2 = 0.0
self._slow_trix_prev = 0.0
self._prev_fast_tema = 0.0
self._prev_slow_tema = 0.0
def OnStarted2(self, time):
super(trix_crossover_strategy, self).OnStarted2(time)
self._fast_trix_prev1 = 0.0
self._fast_trix_prev2 = 0.0
self._slow_trix_prev = 0.0
self._prev_fast_tema = 0.0
self._prev_slow_tema = 0.0
fast_tema = TripleExponentialMovingAverage()
fast_tema.Length = int(self.fast_period)
slow_tema = TripleExponentialMovingAverage()
slow_tema.Length = int(self.slow_period)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_tema, slow_tema, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_tema)
self.DrawIndicator(area, slow_tema)
self.DrawOwnTrades(area)
self.StartProtection(
takeProfit=Unit(float(self.take_profit), UnitTypes.Absolute),
stopLoss=Unit(float(self.stop_loss), UnitTypes.Absolute))
def process_candle(self, candle, fast_tema_value, slow_tema_value):
if candle.State != CandleStates.Finished:
return
fast_tema_value = float(fast_tema_value)
slow_tema_value = float(slow_tema_value)
if self._prev_fast_tema == 0.0 or self._prev_slow_tema == 0.0:
self._prev_fast_tema = fast_tema_value
self._prev_slow_tema = slow_tema_value
return
fast_trix = (fast_tema_value - self._prev_fast_tema) / self._prev_fast_tema if self._prev_fast_tema != 0 else 0.0
slow_trix = (slow_tema_value - self._prev_slow_tema) / self._prev_slow_tema if self._prev_slow_tema != 0 else 0.0
self._prev_fast_tema = fast_tema_value
self._prev_slow_tema = slow_tema_value
prev_fast_trix = self._fast_trix_prev1
self._fast_trix_prev2 = self._fast_trix_prev1
self._fast_trix_prev1 = fast_trix
slow_trix_prev = self._slow_trix_prev
self._slow_trix_prev = slow_trix
if self._fast_trix_prev2 == 0.0 or slow_trix_prev == 0.0:
return
mt = float(self.min_trix)
cross_up = prev_fast_trix <= 0 and fast_trix > 0
cross_down = prev_fast_trix >= 0 and fast_trix < 0
if cross_up and slow_trix > mt and self.Position <= 0:
self.BuyMarket()
elif cross_down and slow_trix < -mt and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return trix_crossover_strategy()