Machine Learning SuperTrend TP SL
Strategy based on SuperTrend indicator with trailing take profit and stop loss.
The stop and profit levels follow the SuperTrend line, aiming to capture sustained moves while locking in gains as momentum fades.
Details
- Entry Criteria: Price crossing the SuperTrend line.
- Long/Short: Both directions.
- Exit Criteria: Opposite signal or hitting trailing take profit/stop loss.
- Stops: Yes, trailing by SuperTrend.
- Default Values:
AtrPeriod= 4AtrFactor= 2.94mStopLossMultiplier= 0.0025mTakeProfitMultiplier= 0.022mCandleType= TimeSpan.FromMinutes(5)
- Filters:
- Category: Trend
- Direction: Both
- Indicators: ATR, SuperTrend
- Stops: Yes
- Complexity: Intermediate
- Timeframe: Intraday (5m)
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
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>
/// SuperTrend strategy with trailing take profit and stop loss.
/// </summary>
public class MachineLearningSuperTrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrFactor;
private readonly StrategyParam<decimal> _stopLossMultiplier;
private readonly StrategyParam<decimal> _takeProfitMultiplier;
private readonly StrategyParam<int> _cooldownBars;
private SuperTrend _superTrend;
private int _prevDirection;
private decimal _stopLoss;
private decimal _takeProfit;
private int _barsFromSignal;
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// ATR period for SuperTrend calculation.
/// </summary>
public int AtrPeriod
{
get => _atrPeriod.Value;
set => _atrPeriod.Value = value;
}
/// <summary>
/// ATR multiplier for SuperTrend.
/// </summary>
public decimal AtrFactor
{
get => _atrFactor.Value;
set => _atrFactor.Value = value;
}
/// <summary>
/// Stop loss multiplier relative to SuperTrend value.
/// </summary>
public decimal StopLossMultiplier
{
get => _stopLossMultiplier.Value;
set => _stopLossMultiplier.Value = value;
}
/// <summary>
/// Take profit multiplier relative to SuperTrend value.
/// </summary>
public decimal TakeProfitMultiplier
{
get => _takeProfitMultiplier.Value;
set => _takeProfitMultiplier.Value = value;
}
/// <summary>
/// Minimum bars between trade actions.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initialize strategy parameters.
/// </summary>
public MachineLearningSuperTrendStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(10).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_atrPeriod = Param(nameof(AtrPeriod), 4)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR length for SuperTrend", "SuperTrend")
.SetOptimize(3, 20, 1);
_atrFactor = Param(nameof(AtrFactor), 2.94m)
.SetRange(0.5m, 10m)
.SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend")
.SetOptimize(1m, 5m, 0.5m);
_stopLossMultiplier = Param(nameof(StopLossMultiplier), 0.01m)
.SetRange(0m, 0.05m)
.SetDisplay("Stop Loss Mult", "Percentage from SuperTrend", "Risk Management");
_takeProfitMultiplier = Param(nameof(TakeProfitMultiplier), 0.03m)
.SetRange(0m, 0.1m)
.SetDisplay("Take Profit Mult", "Percentage from SuperTrend", "Risk Management");
_cooldownBars = Param(nameof(CooldownBars), 8)
.SetGreaterThanZero()
.SetDisplay("Cooldown Bars", "Bars between trade actions", "Risk Management");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_superTrend = null;
_prevDirection = 0;
_stopLoss = 0;
_takeProfit = 0;
_barsFromSignal = CooldownBars;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_barsFromSignal = CooldownBars;
_superTrend = new SuperTrend
{
Length = AtrPeriod,
Multiplier = AtrFactor
};
var dummyEma1 = new ExponentialMovingAverage { Length = 10 };
var dummyEma2 = new ExponentialMovingAverage { Length = 20 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(dummyEma1, dummyEma2, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _superTrend);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal d1, decimal d2)
{
if (candle.State != CandleStates.Finished)
return;
var stResult = _superTrend.Process(new CandleIndicatorValue(_superTrend, candle));
if (!_superTrend.IsFormed || stResult.IsEmpty)
return;
var superTrendValue = stResult.GetValue<decimal>();
var direction = candle.ClosePrice > superTrendValue ? 1 : -1;
var directionChanged = _prevDirection != 0 && direction != _prevDirection;
_barsFromSignal++;
var canTradeNow = _barsFromSignal >= CooldownBars;
_stopLoss = direction == 1
? superTrendValue - superTrendValue * StopLossMultiplier
: superTrendValue + superTrendValue * StopLossMultiplier;
_takeProfit = direction == 1
? superTrendValue + superTrendValue * TakeProfitMultiplier
: superTrendValue - superTrendValue * TakeProfitMultiplier;
if (canTradeNow && directionChanged)
{
if (direction == 1 && Position <= 0)
BuyMarket();
else if (direction == -1 && Position >= 0)
SellMarket();
_barsFromSignal = 0;
}
if (canTradeNow && Position > 0)
{
if (candle.ClosePrice <= _stopLoss || candle.ClosePrice >= _takeProfit)
{
SellMarket();
_barsFromSignal = 0;
}
}
else if (canTradeNow && Position < 0)
{
if (candle.ClosePrice >= _stopLoss || candle.ClosePrice <= _takeProfit)
{
BuyMarket();
_barsFromSignal = 0;
}
}
_prevDirection = direction;
}
}
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 SuperTrend, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class machine_learning_super_trend_strategy(Strategy):
"""
SuperTrend strategy with trailing take profit and stop loss.
"""
def __init__(self):
super(machine_learning_super_trend_strategy, self).__init__()
self._atr_period = self.Param("AtrPeriod", 4).SetDisplay("ATR Period", "ATR length for SuperTrend", "SuperTrend")
self._atr_factor = self.Param("AtrFactor", 2.94).SetDisplay("Multiplier", "ATR multiplier", "SuperTrend")
self._stop_loss_mult = self.Param("StopLossMultiplier", 0.01).SetDisplay("Stop Loss Mult", "Pct from SuperTrend", "Risk")
self._take_profit_mult = self.Param("TakeProfitMultiplier", 0.03).SetDisplay("Take Profit Mult", "Pct from SuperTrend", "Risk")
self._cooldown_bars = self.Param("CooldownBars", 8).SetDisplay("Cooldown", "Bars between trades", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(10))).SetDisplay("Candle Type", "Candles", "General")
self._super_trend = None
self._prev_direction = 0
self._stop_loss = 0.0
self._take_profit = 0.0
self._bars_from_signal = 8
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(machine_learning_super_trend_strategy, self).OnReseted()
self._super_trend = None
self._prev_direction = 0
self._stop_loss = 0.0
self._take_profit = 0.0
self._bars_from_signal = self._cooldown_bars.Value
def OnStarted2(self, time):
super(machine_learning_super_trend_strategy, self).OnStarted2(time)
self._bars_from_signal = self._cooldown_bars.Value
self._super_trend = SuperTrend()
self._super_trend.Length = self._atr_period.Value
self._super_trend.Multiplier = self._atr_factor.Value
dummy1 = ExponentialMovingAverage()
dummy1.Length = 10
dummy2 = ExponentialMovingAverage()
dummy2.Length = 20
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(dummy1, dummy2, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._super_trend)
self.DrawOwnTrades(area)
def _process_candle(self, candle, d1, d2):
if candle.State != CandleStates.Finished:
return
from StockSharp.Algo.Indicators import CandleIndicatorValue
st_result = self._super_trend.Process(CandleIndicatorValue(self._super_trend, candle))
if not self._super_trend.IsFormed or st_result.IsEmpty:
return
st_val = float(st_result)
close = float(candle.ClosePrice)
direction = 1 if close > st_val else -1
direction_changed = self._prev_direction != 0 and direction != self._prev_direction
self._bars_from_signal += 1
can_trade = self._bars_from_signal >= self._cooldown_bars.Value
sl_m = float(self._stop_loss_mult.Value)
tp_m = float(self._take_profit_mult.Value)
self._stop_loss = st_val - st_val * sl_m if direction == 1 else st_val + st_val * sl_m
self._take_profit = st_val + st_val * tp_m if direction == 1 else st_val - st_val * tp_m
if can_trade and direction_changed:
if direction == 1 and self.Position <= 0:
self.BuyMarket()
elif direction == -1 and self.Position >= 0:
self.SellMarket()
self._bars_from_signal = 0
if can_trade and self.Position > 0:
if close <= self._stop_loss or close >= self._take_profit:
self.SellMarket()
self._bars_from_signal = 0
elif can_trade and self.Position < 0:
if close >= self._stop_loss or close <= self._take_profit:
self.BuyMarket()
self._bars_from_signal = 0
self._prev_direction = direction
def CreateClone(self):
return machine_learning_super_trend_strategy()