Trix Candle Strategy
This strategy trades reversals based on the Trix Candle indicator, which applies a triple exponential moving average to candle open and close prices and colors each candle depending on whether the smoothed close is above or below the smoothed open.
Details
- Entry Criteria:
- Long: previous candle bullish (color 2) and current candle color < 2
- Short: previous candle bearish (color 0) and current candle color > 0
- Long/Short: Long and Short
- Exit Criteria:
- Long: previous candle bearish (color 0)
- Short: previous candle bullish (color 2)
- Stops: No
- Default Values:
TRIX Period= 14Candle Type= 4hAllow Buy Open= trueAllow Sell Open= trueAllow Buy Close= trueAllow Sell Close= true
- Filters:
- Category: Reversal
- Direction: Both
- Indicators: Triple Exponential Moving Average
- Stops: No
- Complexity: Low
- Timeframe: Medium-term
- Seasonality: No
- Neural networks: No
- Divergence: No
- Risk level: Medium
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// TRIX Candle reversal strategy.
/// Opens long when bullish TRIX candle turns neutral or bearish and closes shorts.
/// Opens short when bearish TRIX candle turns neutral or bullish and closes longs.
/// </summary>
public class TrixCandleStrategy : Strategy
{
private readonly StrategyParam<int> _trixPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<bool> _buyPosOpen;
private readonly StrategyParam<bool> _sellPosOpen;
private readonly StrategyParam<bool> _buyPosClose;
private readonly StrategyParam<bool> _sellPosClose;
private TripleExponentialMovingAverage _openTema = null!;
private TripleExponentialMovingAverage _closeTema = null!;
private int _prevColor;
/// <summary>
/// Period for TRIX smoothing.
/// </summary>
public int TrixPeriod { get => _trixPeriod.Value; set => _trixPeriod.Value = value; }
/// <summary>
/// Candle type to process.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Allow opening long positions.
/// </summary>
public bool BuyPosOpen { get => _buyPosOpen.Value; set => _buyPosOpen.Value = value; }
/// <summary>
/// Allow opening short positions.
/// </summary>
public bool SellPosOpen { get => _sellPosOpen.Value; set => _sellPosOpen.Value = value; }
/// <summary>
/// Allow closing long positions.
/// </summary>
public bool BuyPosClose { get => _buyPosClose.Value; set => _buyPosClose.Value = value; }
/// <summary>
/// Allow closing short positions.
/// </summary>
public bool SellPosClose { get => _sellPosClose.Value; set => _sellPosClose.Value = value; }
/// <summary>
/// Initialize the strategy with default parameters.
/// </summary>
public TrixCandleStrategy()
{
_trixPeriod = Param(nameof(TrixPeriod), 5)
.SetDisplay("TRIX Period", "Period for triple exponential smoothing", "Indicators")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for processing", "General");
_buyPosOpen = Param(nameof(BuyPosOpen), true)
.SetDisplay("Allow Buy Open", "Enable opening long positions", "Trading");
_sellPosOpen = Param(nameof(SellPosOpen), true)
.SetDisplay("Allow Sell Open", "Enable opening short positions", "Trading");
_buyPosClose = Param(nameof(BuyPosClose), true)
.SetDisplay("Allow Buy Close", "Enable closing long positions", "Trading");
_sellPosClose = Param(nameof(SellPosClose), true)
.SetDisplay("Allow Sell Close", "Enable closing short positions", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_openTema = default;
_closeTema = default;
_prevColor = -1;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_openTema = new TripleExponentialMovingAverage { Length = TrixPeriod };
_closeTema = new TripleExponentialMovingAverage { Length = TrixPeriod };
_prevColor = -1;
Indicators.Add(_openTema);
Indicators.Add(_closeTema);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
StartProtection(null, null);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var openResult = _openTema.Process(new DecimalIndicatorValue(_openTema, candle.OpenPrice, candle.OpenTime) { IsFinal = true });
var closeResult = _closeTema.Process(new DecimalIndicatorValue(_closeTema, candle.ClosePrice, candle.OpenTime) { IsFinal = true });
if (!openResult.IsFormed || !closeResult.IsFormed)
return;
var openValue = openResult.ToDecimal();
var closeValue = closeResult.ToDecimal();
var color = 1;
if (openValue < closeValue)
color = 2;
else if (openValue > closeValue)
color = 0;
if (_prevColor == -1)
{
_prevColor = color;
return;
}
var buyOpen = BuyPosOpen && _prevColor == 2 && color < 2;
var sellOpen = SellPosOpen && _prevColor == 0 && color > 0;
var buyClose = BuyPosClose && _prevColor == 0;
var sellClose = SellPosClose && _prevColor == 2;
if (sellClose && Position < 0)
BuyMarket();
if (buyClose && Position > 0)
SellMarket();
if (buyOpen && Position <= 0)
BuyMarket();
if (sellOpen && Position >= 0)
SellMarket();
_prevColor = color;
}
}
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 TripleExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class trix_candle_strategy(Strategy):
def __init__(self):
super(trix_candle_strategy, self).__init__()
self._trix_period = self.Param("TrixPeriod", 5) \
.SetDisplay("TRIX Period", "Period for triple exponential smoothing", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for processing", "General")
self._buy_pos_open = self.Param("BuyPosOpen", True) \
.SetDisplay("Allow Buy Open", "Enable opening long positions", "Trading")
self._sell_pos_open = self.Param("SellPosOpen", True) \
.SetDisplay("Allow Sell Open", "Enable opening short positions", "Trading")
self._buy_pos_close = self.Param("BuyPosClose", True) \
.SetDisplay("Allow Buy Close", "Enable closing long positions", "Trading")
self._sell_pos_close = self.Param("SellPosClose", True) \
.SetDisplay("Allow Sell Close", "Enable closing short positions", "Trading")
self._open_tema = None
self._close_tema = None
self._prev_color = -1
@property
def trix_period(self):
return self._trix_period.Value
@property
def candle_type(self):
return self._candle_type.Value
@property
def buy_pos_open(self):
return self._buy_pos_open.Value
@property
def sell_pos_open(self):
return self._sell_pos_open.Value
@property
def buy_pos_close(self):
return self._buy_pos_close.Value
@property
def sell_pos_close(self):
return self._sell_pos_close.Value
def OnReseted(self):
super(trix_candle_strategy, self).OnReseted()
self._open_tema = None
self._close_tema = None
self._prev_color = -1
def OnStarted2(self, time):
super(trix_candle_strategy, self).OnStarted2(time)
self._open_tema = TripleExponentialMovingAverage()
self._open_tema.Length = self.trix_period
self._close_tema = TripleExponentialMovingAverage()
self._close_tema.Length = self.trix_period
self._prev_color = -1
self.Indicators.Add(self._open_tema)
self.Indicators.Add(self._close_tema)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
open_result = process_float(self._open_tema, candle.OpenPrice, candle.OpenTime, True)
close_result = process_float(self._close_tema, candle.ClosePrice, candle.OpenTime, True)
if not open_result.IsFormed or not close_result.IsFormed:
return
open_value = float(open_result)
close_value = float(close_result)
if open_value < close_value:
color = 2
elif open_value > close_value:
color = 0
else:
color = 1
if self._prev_color == -1:
self._prev_color = color
return
buy_open = self.buy_pos_open and self._prev_color == 2 and color < 2
sell_open = self.sell_pos_open and self._prev_color == 0 and color > 0
buy_close_sig = self.buy_pos_close and self._prev_color == 0
sell_close_sig = self.sell_pos_close and self._prev_color == 2
if sell_close_sig and self.Position < 0:
self.BuyMarket()
if buy_close_sig and self.Position > 0:
self.SellMarket()
if buy_open and self.Position <= 0:
self.BuyMarket()
if sell_open and self.Position >= 0:
self.SellMarket()
self._prev_color = color
def CreateClone(self):
return trix_candle_strategy()