TrueSort 1001-Strategie
TrueSort 1001 ist ein striktes Trendfolgesystem, das den ursprünglichen Expertenberater MQL widerspiegelt. Die Strategie überwacht fünf einfache gleitende Durchschnitte und reagiert nur, wenn sie drei aufeinanderfolgende abgeschlossene Kerzen lang perfekt geordnet bleiben. Ein steigender durchschnittlicher Richtungsindex (ADX) bestätigt die Dynamik, bevor ein Handel eröffnet wird. Sobald die Position auf dem Markt ist, wird sie durch einen adaptiven Trailing Stop geschützt, der in Preisschritten gemessen wird, und der Handel wird geschlossen, sobald die gleitenden Durchschnitte ihre Ausrichtung verlieren.
Logik
Trend- und Momentumfilter
- Für den ausgewählten Zeitrahmen werden fünf SMAs (standardmäßig 10, 20, 50, 100 und 200 Perioden) berechnet.
- Bei langen Setups müssen die schnellen SMAs bei jeder der letzten drei abgeschlossenen Kerzen streng über den langsameren liegen:
SMA10 > SMA20 > SMA50 > SMA100 > SMA200.
- Für kurze Setups ist die umgekehrte Reihenfolge für dieselben drei Kerzen erforderlich.
- ADX mit der Periode
AdxPeriod muss über AdxThreshold bleiben und der aktuelle Wert muss höher sein als die vorherige Kerze, um sicherzustellen, dass die Trendstärke zunimmt.
Teilnahmebedingungen
- Es ist keine Position offen.
- Drei historische Kerzen erfüllen die oben beschriebene Ordnungsregel.
- Der ADX-Filter ist erfolgreich.
- Eine Marktorder von
Volume Lots wird sofort beim Schließen der aktuellen Kerze gesendet.
Ausstiegsbedingungen
- Desynchronisierung des gleitenden Durchschnitts: Wenn die aktuelle Kerze schließt und der MA-Stapel nicht mehr streng in Richtung des Handels geordnet ist, wird die Position liquidiert.
- Trailing Protection:
StopLossPoints werden durch Multiplikation mit dem Instrument PriceStep in den absoluten Preisabstand umgewandelt. Bei Long-Trades wird der Stop auf das Maximum zwischen SMA100 und Close - distance initialisiert. Bei Kurzfilmen liegt der Mindestwert zwischen SMA100 und Close + distance. Nach jeder Kerze wird der Stopp in Richtung des Preises angezogen, aber nie gelockert. Wenn der Preis den Stop überschreitet, wird die Position zum Marktwert geschlossen.
Zusätzliche Hinweise
- Alle Entscheidungen werden nur für fertige Kerzen getroffen; Unfertige Kerzen werden ignoriert.
- Der Algorithmus speichert die letzten drei SMA-Werte intern, um die
shift-Logik aus dem ursprünglichen MQL-Skript zu replizieren, ohne den Indikatorverlauf anzufordern.
- ADX-Werte werden über
BindEx verarbeitet und der Handel wird nur versucht, wenn die Strategie online ist und die Daten vollständig gebildet sind.
Parameter
| Name |
Standard |
Beschreibung |
Volume |
0.1 |
Bestellgröße in Losen für jeden Markteintritt. |
StopLossPoints |
100 |
Trailing-Stop-Distanz, ausgedrückt in Instrumentenpreisschritten. 0 deaktiviert das Trailing. |
Sma10Length |
10 |
Zeitraum der schnellsten SMA. |
Sma20Length |
20 |
Zeitraum der Sekunde SMA. |
Sma50Length |
50 |
Zeitraum des Mediums SMA. |
Sma100Length |
100 |
Zeitraum, der sowohl für die Ausrichtung als auch für die anfängliche Stoppreferenz verwendet wird. |
Sma200Length |
200 |
Langsamster SMA, der den langfristigen Trend bestätigt. |
AdxPeriod |
14 |
Zeitraum des ADX-Indikators. |
AdxThreshold |
25 |
Mindestniveau ADX und steigende Bedingung vor Einträgen erforderlich. |
CandleType |
TimeSpan.FromHours(1).TimeFrame() |
Kerzenreihe, die für alle Indikatorberechnungen verwendet wird. |
Details zur Implementierung
- Der Code basiert auf dem High-Level-Kerzenabonnement StockSharp und bindet sechs Indikatoren (fünf SMAs und ADX) in einer einzigen Pipeline.
- Verlaufspuffer mit der Länge drei speichern die neuesten SMA-Werte, vermeiden Aufrufe von
GetValue() und wahren gleichzeitig die exakte Parität mit den MQL-Verschiebungen.
- Trailing Stops werden manuell verwaltet;
StartProtection() ist weiterhin aktiviert, sodass die Standardinfrastruktur bereit ist, falls weitere Schutzmaßnahmen erforderlich sind.
- Kommentare im Code erklären jeden Schritt auf Englisch, um die Wartung zu erleichtern.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trend-following strategy requiring strict moving average alignment
/// and rising volatility (ATR) before entering trades.
/// Exits when alignment is lost.
/// </summary>
public class TrueSort1001Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _midLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevMid;
private decimal _prevSlow;
private decimal _prevAtr;
private decimal _entryPrice;
public TrueSort1001Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastLength = Param(nameof(FastLength), 10)
.SetDisplay("Fast SMA", "Fast SMA period.", "Indicators");
_midLength = Param(nameof(MidLength), 50)
.SetDisplay("Mid SMA", "Medium SMA period.", "Indicators");
_slowLength = Param(nameof(SlowLength), 200)
.SetDisplay("Slow SMA", "Slow SMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period for volatility filter.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public int MidLength
{
get => _midLength.Value;
set => _midLength.Value = value;
}
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevMid = 0;
_prevSlow = 0;
_prevAtr = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevMid = 0;
_prevSlow = 0;
_prevAtr = 0;
_entryPrice = 0;
var fast = new SimpleMovingAverage { Length = FastLength };
var mid = new SimpleMovingAverage { Length = MidLength };
var slow = new SimpleMovingAverage { Length = SlowLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, mid, slow, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, mid);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal midVal, decimal slowVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevMid == 0 || _prevSlow == 0)
{
_prevFast = fastVal;
_prevMid = midVal;
_prevSlow = slowVal;
_prevAtr = atrVal;
return;
}
var close = candle.ClosePrice;
var bullishAligned = fastVal > midVal && midVal > slowVal;
var bearishAligned = fastVal < midVal && midVal < slowVal;
var atrRising = atrVal > _prevAtr;
// Exit on alignment lost
if (Position > 0 && !bullishAligned)
{
SellMarket();
}
else if (Position < 0 && !bearishAligned)
{
BuyMarket();
}
// Entry on alignment + rising ATR
if (Position == 0)
{
if (bullishAligned && atrRising && close > fastVal)
{
_entryPrice = close;
BuyMarket();
}
else if (bearishAligned && atrRising && close < fastVal)
{
_entryPrice = close;
SellMarket();
}
}
_prevFast = fastVal;
_prevMid = midVal;
_prevSlow = slowVal;
_prevAtr = atrVal;
}
}
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 SimpleMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class true_sort_1001_strategy(Strategy):
"""Trend-following: strict SMA alignment (fast>mid>slow) + rising ATR for entries."""
def __init__(self):
super(true_sort_1001_strategy, self).__init__()
self._fast_len = self.Param("FastLength", 10).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._mid_len = self.Param("MidLength", 50).SetDisplay("Mid SMA", "Medium SMA period", "Indicators")
self._slow_len = self.Param("SlowLength", 200).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._atr_len = self.Param("AtrLength", 14).SetDisplay("ATR Length", "ATR period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(true_sort_1001_strategy, self).OnReseted()
self._prev_fast = 0
self._prev_mid = 0
self._prev_slow = 0
self._prev_atr = 0
def OnStarted2(self, time):
super(true_sort_1001_strategy, self).OnStarted2(time)
self._prev_fast = 0
self._prev_mid = 0
self._prev_slow = 0
self._prev_atr = 0
fast = SimpleMovingAverage()
fast.Length = self._fast_len.Value
mid = SimpleMovingAverage()
mid.Length = self._mid_len.Value
slow = SimpleMovingAverage()
slow.Length = self._slow_len.Value
atr = AverageTrueRange()
atr.Length = self._atr_len.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(fast, mid, slow, atr, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, mid)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast_val, mid_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
fast = float(fast_val)
mid = float(mid_val)
slow = float(slow_val)
atr = float(atr_val)
close = float(candle.ClosePrice)
if self._prev_fast == 0 or self._prev_mid == 0 or self._prev_slow == 0:
self._prev_fast = fast
self._prev_mid = mid
self._prev_slow = slow
self._prev_atr = atr
return
bullish = fast > mid and mid > slow
bearish = fast < mid and mid < slow
atr_rising = atr > self._prev_atr
# Exit on alignment lost
if self.Position > 0 and not bullish:
self.SellMarket()
elif self.Position < 0 and not bearish:
self.BuyMarket()
# Entry
if self.Position == 0:
if bullish and atr_rising and close > fast:
self.BuyMarket()
elif bearish and atr_rising and close < fast:
self.SellMarket()
self._prev_fast = fast
self._prev_mid = mid
self._prev_slow = slow
self._prev_atr = atr
def CreateClone(self):
return true_sort_1001_strategy()