Vietnamese 3x Supertrend-Strategie
Diese Strategie stapelt drei SuperTrend-Indikatoren mit unterschiedlichen ATR-Längen und Multiplikatoren. Sie skaliert in Long-Positionen, wenn der langsame Trend bärisch ist und schnellere Trends Pullback-Gelegenheiten zeigen. Ein optionaler Break-Even-Stop schützt Gewinne, sobald sich der Preis günstig entwickelt.
Details
- Einstiegskriterien:
- Langsamer SuperTrend im Abwärtstrend.
- Long 1: Mittlerer Aufwärtstrend und schneller Abwärtstrend.
- Long 2: Mittlerer Abwärtstrend und Preis über der schnellen SuperTrend-Linie.
- Long 3: Schneller Abwärtstrend und Ausbruch über das höchste Hoch während des schnellen Abwärtstrends.
- Long/Short: Nur Long.
- Ausstiegskriterien:
- Alle SuperTrends drehen aufwärts und die Kerze schließt bärisch.
- Durchschnittlicher Einstiegspreis über dem aktuellen Schlusskurs.
- Optionaler Break-Even-Stop wenn aktiviert.
- Stops: Optionaler Break-Even-Stop.
- Standardwerte:
FastAtrLength= 10FastMultiplier= 1MediumAtrLength= 11MediumMultiplier= 2SlowAtrLength= 12SlowMultiplier= 3UseHighestOfTwoRedCandles= FalseUseEntryStopLoss= TrueUseAllDowntrendExit= TrueUseAvgPriceInLoss= True
- Filter:
- Kategorie: Trendfolge
- Richtung: Long
- Indikatoren: SuperTrend
- Stops: Optional
- Komplexität: Moderat
- Zeitrahmen: Beliebig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// Vietnamese 3x SuperTrend strategy.
/// Three SuperTrends (fast, medium, slow) drive a long-only scaling scheme. While the slow SuperTrend is down the strategy adds up to
/// three entries: Long 1 when the medium trend is up and the fast one down, Long 2 when the medium trend is down and the close is above
/// the fast line, Long 3 when the fast trend is down and the close breaks the highest high of that fast downtrend (or of the last two
/// red candles). Positions close when all trends are up on a bearish candle, when the average entry price is above the close, or by a
/// break-even stop once price has moved above the average entry price.
/// </summary>
public class Vietnamese3xSupertrendStrategy : Strategy
{
private readonly StrategyParam<int> _fastAtrLength;
private readonly StrategyParam<decimal> _fastMultiplier;
private readonly StrategyParam<int> _mediumAtrLength;
private readonly StrategyParam<decimal> _mediumMultiplier;
private readonly StrategyParam<int> _slowAtrLength;
private readonly StrategyParam<decimal> _slowMultiplier;
private readonly StrategyParam<bool> _useHighestOfTwoRedCandles;
private readonly StrategyParam<bool> _useEntryStopLoss;
private readonly StrategyParam<bool> _useAllDowntrendExit;
private readonly StrategyParam<bool> _useAvgPriceInLoss;
private readonly StrategyParam<DataType> _candleType;
private decimal? _downtrendHigh;
private decimal? _lastRedHigh;
private decimal? _prevRedHigh;
private bool _long1Done;
private bool _long2Done;
private bool _long3Done;
private int _entryCount;
private decimal _avgEntryPrice;
private bool _breakEvenArmed;
/// <summary>
/// ATR length of the fast SuperTrend.
/// </summary>
public int FastAtrLength
{
get => _fastAtrLength.Value;
set => _fastAtrLength.Value = value;
}
/// <summary>
/// ATR multiplier of the fast SuperTrend.
/// </summary>
public decimal FastMultiplier
{
get => _fastMultiplier.Value;
set => _fastMultiplier.Value = value;
}
/// <summary>
/// ATR length of the medium SuperTrend.
/// </summary>
public int MediumAtrLength
{
get => _mediumAtrLength.Value;
set => _mediumAtrLength.Value = value;
}
/// <summary>
/// ATR multiplier of the medium SuperTrend.
/// </summary>
public decimal MediumMultiplier
{
get => _mediumMultiplier.Value;
set => _mediumMultiplier.Value = value;
}
/// <summary>
/// ATR length of the slow SuperTrend.
/// </summary>
public int SlowAtrLength
{
get => _slowAtrLength.Value;
set => _slowAtrLength.Value = value;
}
/// <summary>
/// ATR multiplier of the slow SuperTrend.
/// </summary>
public decimal SlowMultiplier
{
get => _slowMultiplier.Value;
set => _slowMultiplier.Value = value;
}
/// <summary>
/// Long 3 breaks the highest high of the last two red candles instead of the fast downtrend high.
/// </summary>
public bool UseHighestOfTwoRedCandles
{
get => _useHighestOfTwoRedCandles.Value;
set => _useHighestOfTwoRedCandles.Value = value;
}
/// <summary>
/// Enable the break-even stop.
/// </summary>
public bool UseEntryStopLoss
{
get => _useEntryStopLoss.Value;
set => _useEntryStopLoss.Value = value;
}
/// <summary>
/// Exit when all SuperTrends are up and the candle closes bearish.
/// </summary>
public bool UseAllDowntrendExit
{
get => _useAllDowntrendExit.Value;
set => _useAllDowntrendExit.Value = value;
}
/// <summary>
/// Exit when the average entry price is above the close.
/// </summary>
public bool UseAvgPriceInLoss
{
get => _useAvgPriceInLoss.Value;
set => _useAvgPriceInLoss.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public Vietnamese3xSupertrendStrategy()
{
_fastAtrLength = Param(nameof(FastAtrLength), 10)
.SetGreaterThanZero()
.SetDisplay("Fast ATR Length", "ATR length of the fast SuperTrend", "SuperTrend");
_fastMultiplier = Param(nameof(FastMultiplier), 1m)
.SetGreaterThanZero()
.SetDisplay("Fast Multiplier", "ATR multiplier of the fast SuperTrend", "SuperTrend");
_mediumAtrLength = Param(nameof(MediumAtrLength), 11)
.SetGreaterThanZero()
.SetDisplay("Medium ATR Length", "ATR length of the medium SuperTrend", "SuperTrend");
_mediumMultiplier = Param(nameof(MediumMultiplier), 2m)
.SetGreaterThanZero()
.SetDisplay("Medium Multiplier", "ATR multiplier of the medium SuperTrend", "SuperTrend");
_slowAtrLength = Param(nameof(SlowAtrLength), 12)
.SetGreaterThanZero()
.SetDisplay("Slow ATR Length", "ATR length of the slow SuperTrend", "SuperTrend");
_slowMultiplier = Param(nameof(SlowMultiplier), 3m)
.SetGreaterThanZero()
.SetDisplay("Slow Multiplier", "ATR multiplier of the slow SuperTrend", "SuperTrend");
_useHighestOfTwoRedCandles = Param(nameof(UseHighestOfTwoRedCandles), false)
.SetDisplay("Highest Of Two Red Candles", "Long 3 breaks the highest high of the last two red candles", "Entries");
_useEntryStopLoss = Param(nameof(UseEntryStopLoss), true)
.SetDisplay("Break-Even Stop", "Enable the break-even stop", "Exits");
_useAllDowntrendExit = Param(nameof(UseAllDowntrendExit), true)
.SetDisplay("All Trends Exit", "Exit when all SuperTrends are up and the candle closes bearish", "Exits");
_useAvgPriceInLoss = Param(nameof(UseAvgPriceInLoss), true)
.SetDisplay("Average Price In Loss", "Exit when the average entry price is above the close", "Exits");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).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();
ResetState();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
var fast = new SuperTrend { Length = FastAtrLength, Multiplier = FastMultiplier };
var medium = new SuperTrend { Length = MediumAtrLength, Multiplier = MediumMultiplier };
var slow = new SuperTrend { Length = SlowAtrLength, Multiplier = SlowMultiplier };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(fast, medium, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, medium);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ResetState()
{
_downtrendHigh = null;
_lastRedHigh = null;
_prevRedHigh = null;
ResetEntries();
}
private void ResetEntries()
{
_long1Done = false;
_long2Done = false;
_long3Done = false;
_entryCount = 0;
_avgEntryPrice = 0;
_breakEvenArmed = false;
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue fastValue, IIndicatorValue mediumValue, IIndicatorValue slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!fastValue.IsFormed || !mediumValue.IsFormed || !slowValue.IsFormed)
return;
var fast = (SuperTrendIndicatorValue)fastValue;
var fastUp = fast.IsUpTrend;
var mediumUp = ((SuperTrendIndicatorValue)mediumValue).IsUpTrend;
var slowUp = ((SuperTrendIndicatorValue)slowValue).IsUpTrend;
var fastLine = fast.ToDecimal();
var close = candle.ClosePrice;
var bearish = close < candle.OpenPrice;
// Breakout references come from earlier candles only.
var breakoutLevel = UseHighestOfTwoRedCandles
? (_lastRedHigh is decimal a && _prevRedHigh is decimal b ? Math.Max(a, b) : (decimal?)null)
: _downtrendHigh;
_downtrendHigh = fastUp ? null : Math.Max(_downtrendHigh ?? candle.HighPrice, candle.HighPrice);
if (bearish)
{
_prevRedHigh = _lastRedHigh;
_lastRedHigh = candle.HighPrice;
}
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
var exit = false;
if (UseEntryStopLoss)
{
if (_breakEvenArmed && candle.LowPrice <= _avgEntryPrice)
exit = true;
else if (candle.LowPrice > _avgEntryPrice)
_breakEvenArmed = true;
}
if (UseAllDowntrendExit && fastUp && mediumUp && slowUp && bearish)
exit = true;
if (UseAvgPriceInLoss && _avgEntryPrice > close)
exit = true;
if (exit)
{
SellMarket(Position);
ResetEntries();
return;
}
}
else if (_entryCount > 0)
{
ResetEntries();
}
if (slowUp)
return;
if (!_long1Done && mediumUp && !fastUp)
{
_long1Done = true;
Enter(close);
}
if (!_long2Done && !mediumUp && close > fastLine)
{
_long2Done = true;
Enter(close);
}
if (!_long3Done && !fastUp && breakoutLevel is decimal level && close > level)
{
_long3Done = true;
Enter(close);
}
}
private void Enter(decimal price)
{
BuyMarket(Volume);
_avgEntryPrice = (_avgEntryPrice * _entryCount + price) / (_entryCount + 1);
_entryCount++;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
clr.AddReference("StockSharp.BusinessEntities")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SuperTrend
from StockSharp.Algo.Strategies import Strategy
class vietnamese_3x_supertrend_strategy(Strategy):
"""
Vietnamese 3x SuperTrend strategy.
Three SuperTrends (fast, medium, slow) drive a long-only scaling scheme. While the slow SuperTrend is down the strategy adds up to
three entries: Long 1 when the medium trend is up and the fast one down, Long 2 when the medium trend is down and the close is above
the fast line, Long 3 when the fast trend is down and the close breaks the highest high of that fast downtrend (or of the last two
red candles). Positions close when all trends are up on a bearish candle, when the average entry price is above the close, or by a
break-even stop once price has moved above the average entry price.
"""
def __init__(self):
super(vietnamese_3x_supertrend_strategy, self).__init__()
self._fast_atr_length = self.Param("FastAtrLength", 10).SetGreaterThanZero().SetDisplay("Fast ATR Length", "ATR length of the fast SuperTrend", "SuperTrend")
self._fast_multiplier = self.Param("FastMultiplier", 1.0).SetGreaterThanZero().SetDisplay("Fast Multiplier", "ATR multiplier of the fast SuperTrend", "SuperTrend")
self._medium_atr_length = self.Param("MediumAtrLength", 11).SetGreaterThanZero().SetDisplay("Medium ATR Length", "ATR length of the medium SuperTrend", "SuperTrend")
self._medium_multiplier = self.Param("MediumMultiplier", 2.0).SetGreaterThanZero().SetDisplay("Medium Multiplier", "ATR multiplier of the medium SuperTrend", "SuperTrend")
self._slow_atr_length = self.Param("SlowAtrLength", 12).SetGreaterThanZero().SetDisplay("Slow ATR Length", "ATR length of the slow SuperTrend", "SuperTrend")
self._slow_multiplier = self.Param("SlowMultiplier", 3.0).SetGreaterThanZero().SetDisplay("Slow Multiplier", "ATR multiplier of the slow SuperTrend", "SuperTrend")
self._use_highest_of_two_red_candles = self.Param("UseHighestOfTwoRedCandles", False).SetDisplay("Highest Of Two Red Candles", "Long 3 breaks the highest high of the last two red candles", "Entries")
self._use_entry_stop_loss = self.Param("UseEntryStopLoss", True).SetDisplay("Break-Even Stop", "Enable the break-even stop", "Exits")
self._use_all_downtrend_exit = self.Param("UseAllDowntrendExit", True).SetDisplay("All Trends Exit", "Exit when all SuperTrends are up and the candle closes bearish", "Exits")
self._use_avg_price_in_loss = self.Param("UseAvgPriceInLoss", True).SetDisplay("Average Price In Loss", "Exit when the average entry price is above the close", "Exits")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._downtrend_high = None
self._last_red_high = None
self._prev_red_high = None
self._reset_entries()
def _reset_entries(self):
self._long1_done = False
self._long2_done = False
self._long3_done = False
self._entry_count = 0
self._avg_entry_price = Decimal(0)
self._break_even_armed = False
def OnReseted(self):
super(vietnamese_3x_supertrend_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(vietnamese_3x_supertrend_strategy, self).OnStarted2(time)
self._reset_state()
fast = SuperTrend()
fast.Length = self._fast_atr_length.Value
fast.Multiplier = Decimal(self._fast_multiplier.Value)
medium = SuperTrend()
medium.Length = self._medium_atr_length.Value
medium.Multiplier = Decimal(self._medium_multiplier.Value)
slow = SuperTrend()
slow.Length = self._slow_atr_length.Value
slow.Multiplier = Decimal(self._slow_multiplier.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(fast, medium, slow, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, medium)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_value, medium_value, slow_value):
if candle.State != CandleStates.Finished:
return
if not fast_value.IsFormed or not medium_value.IsFormed or not slow_value.IsFormed:
return
fast_up = fast_value.IsUpTrend
medium_up = medium_value.IsUpTrend
slow_up = slow_value.IsUpTrend
fast_line = fast_value.GetValue[Decimal](None)
close = candle.ClosePrice
bearish = close < candle.OpenPrice
# Breakout references come from earlier candles only.
if self._use_highest_of_two_red_candles.Value:
if self._last_red_high is not None and self._prev_red_high is not None:
breakout_level = max(self._last_red_high, self._prev_red_high)
else:
breakout_level = None
else:
breakout_level = self._downtrend_high
if fast_up:
self._downtrend_high = None
elif self._downtrend_high is None or candle.HighPrice > self._downtrend_high:
self._downtrend_high = candle.HighPrice
if bearish:
self._prev_red_high = self._last_red_high
self._last_red_high = candle.HighPrice
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self.Position > 0:
exit_position = False
if self._use_entry_stop_loss.Value:
if self._break_even_armed and candle.LowPrice <= self._avg_entry_price:
exit_position = True
elif candle.LowPrice > self._avg_entry_price:
self._break_even_armed = True
if self._use_all_downtrend_exit.Value and fast_up and medium_up and slow_up and bearish:
exit_position = True
if self._use_avg_price_in_loss.Value and self._avg_entry_price > close:
exit_position = True
if exit_position:
self.SellMarket(self.Position)
self._reset_entries()
return
elif self._entry_count > 0:
self._reset_entries()
if slow_up:
return
if not self._long1_done and medium_up and not fast_up:
self._long1_done = True
self._enter(close)
if not self._long2_done and not medium_up and close > fast_line:
self._long2_done = True
self._enter(close)
if not self._long3_done and not fast_up and breakout_level is not None and close > breakout_level:
self._long3_done = True
self._enter(close)
def _enter(self, price):
self.BuyMarket(self.Volume)
self._avg_entry_price = (self._avg_entry_price * self._entry_count + price) / Decimal(self._entry_count + 1)
self._entry_count += 1
def CreateClone(self):
return vietnamese_3x_supertrend_strategy()