Die No-Nonsense-Tester-Strategie ist eine StockSharp-Portierung des MQL4-Expertenberaters „NoNonsenseTester“. Die Implementierung konzentriert sich auf den Kern-NNFX-Workflow, der eine Trendbasislinie validiert, auf zwei Bestätigungsindikatoren wartet, die Volatilität mithilfe von ATR überprüft und Trades mit strenger Exit-Logik überwacht. Die Strategie ist für das Experimentieren mit mehreren Parametern konzipiert und stellt daher alle wichtigen Schwellenwerte über StrategyParam-Objekte bereit, sodass sie innerhalb von StockSharp optimiert werden können.
Handelslogik
Basislinienfilter – ein EMA mit konfigurierbarer Länge definiert die primäre Trendrichtung. Einträge werden nur berücksichtigt, wenn der Preis über der Basislinie schließt.
Bestätigung Nr. 1 – ein RSI muss auf der bullischen (über dem Schwellenwert) oder bärischen (unter dem komplementären Schwellenwert) Seite liegen, um den Grundliniendurchbruch zu bestätigen.
Bestätigung #2 – ein CCI muss mit dem Trend übereinstimmen und die konfigurierte absolute Größe überschreiten, um schwache Signale zu blockieren.
Volatilitätsfilter – ATR muss größer als der Wert AtrMinimum sein, um sicherzustellen, dass Trades nur dann getätigt werden, wenn der Markt eine ausreichende Spanne aufweist.
Einstieg – wenn die Basislinie kreuzt, die beiden Bestätigungen und der Volatilitätsfilter übereinstimmen, eröffnet die Strategie eine Position in der Richtung der Bewegung. Die Positionsgröße kann optional mit ATR über den Parameter AtrEntryMultiplier skaliert werden.
Stopp und Ziel – unmittelbar nach dem Einstieg berechnet die Strategie ATR-basierte Stop-Loss- und Take-Profit-Level. Das optionale ATR-Trailing aktualisiert den Schutzstopp ständig, während sich der Handel positiv entwickelt.
Exit-Overlay – ein zusätzlicher RSI mit kürzerer Periode überwacht offene Trades. Wenn es bei Long-Positionen das untere Band oder bei Short-Positionen das obere Band überschreitet, wird die Position geschlossen, auch wenn der Preis die Schutzniveaus nicht erreicht hat.
Parameter
Parameter
Beschreibung
BaselineLength
Zeitraum der EMA-Basislinie.
ConfirmationRsiLength
Länge des Bestätigungsindikators RSI.
ConfirmationRsiThreshold
RSI-Level, das bullische und bärische Bestätigungen trennt.
ConfirmationCciLength
Länge des Bestätigungsindikators CCI.
ConfirmationCciThreshold
Minimale absolute CCI-Größe, um ein Signal zu akzeptieren.
AtrPeriod
ATR Lookback-Zeitraum.
AtrEntryMultiplier
Optionaler ATR-Multiplikator, der das gehandelte Volumen skaliert.
AtrTakeProfitMultiplier
ATR Multiplikator für das Take-Profit-Level.
AtrStopLossMultiplier
ATR Multiplikator für das Stop-Loss-Level.
AtrTrailingMultiplier
ATR-Multiplikator, der für dynamisches Trailing verwendet wird. Zum Deaktivieren auf 0 setzen.
AtrMinimum
Vor der Eröffnung von Trades ist ein Mindestwert von ATR erforderlich.
ExitRsiLength
Länge des Exit-Overlays RSI.
ExitRsiUpperLevel
RSI-Level, das kurze Exits erzwingt.
ExitRsiLowerLevel
RSI-Level, das lange Exits erzwingt.
CandleType
Für die Berechnungen verwendeter Kerzentyp (Zeitrahmen).
Diagrammobjekte
Die Strategie zeichnet automatisch:
Quellkerzen.
EMA Grundlinie.
Markierungen für ausgeführte Trades.
Optimierungshinweise
Jedes in der Logik verwendete StrategyParam stellt Optimierungsbereiche bereit, die die Flexibilität des ursprünglichen Testers widerspiegeln. Verwenden Sie die Optimierungstools von StockSharp, um Basislinienlängen, Bestätigungsschwellenwerte und Risikoeinstellungen zu durchsuchen und die von der Version MQL bereitgestellten Parameterrastertests zu reproduzieren.
Nutzungstipps
Kombinieren Sie die Strategie mit NNFX-Indikatorvoreinstellungen, indem Sie die Schwellenwerte an Ihre benutzerdefinierten Tools anpassen.
Behalten Sie den Filter ATR im Auge. Ein AtrMinimum ungleich Null verhindert Trades während Sitzungen mit geringer Volatilität.
Stellen Sie beim Testen von Continuation Trades AtrTrailingMultiplier größer als Null ein, um profitable Positionen atmen zu lassen und gleichzeitig Gewinne zu sichern.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// No Nonsense Tester strategy: EMA baseline + RSI confirmation + CCI confirmation.
/// Buys when price above EMA, RSI above 50, CCI above 0.
/// Sells when price below EMA, RSI below 50, CCI below 0.
/// </summary>
public class NoNonsenseTesterStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cciPeriod;
private bool _wasBullish;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public NoNonsenseTesterStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 25)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA baseline period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI confirmation period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI confirmation period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullish = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrevSignal = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, rsi, cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema, decimal rsi, decimal cci)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var isBullish = close > ema && rsi > 50 && cci > 0;
if (_hasPrevSignal && isBullish != _wasBullish)
{
if (isBullish && Position <= 0)
BuyMarket();
else if (!isBullish && close < ema && rsi < 50 && cci < 0 && Position >= 0)
SellMarket();
}
_wasBullish = isBullish;
_hasPrevSignal = true;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class no_nonsense_tester_strategy(Strategy):
def __init__(self):
super(no_nonsense_tester_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 25) \
.SetDisplay("EMA Period", "EMA baseline period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI confirmation period", "Indicators")
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI confirmation period", "Indicators")
self._ema = None
self._rsi = None
self._cci = None
self._was_bullish = False
self._has_prev_signal = False
@property
def ema_period(self):
return self._ema_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def cci_period(self):
return self._cci_period.Value
def OnReseted(self):
super(no_nonsense_tester_strategy, self).OnReseted()
self._ema = None
self._rsi = None
self._cci = None
self._was_bullish = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(no_nonsense_tester_strategy, self).OnStarted2(time)
self._ema = ExponentialMovingAverage()
self._ema.Length = self.ema_period
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
self._cci = CommodityChannelIndex()
self._cci.Length = self.cci_period
self._has_prev_signal = False
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(15)))
subscription.Bind(self._ema, self._rsi, self._cci, self._process_candle)
subscription.Start()
def _process_candle(self, candle, ema_value, rsi_value, cci_value):
if candle.State != CandleStates.Finished:
return
if not self._ema.IsFormed or not self._rsi.IsFormed or not self._cci.IsFormed:
return
close = float(candle.ClosePrice)
ema_val = float(ema_value)
rsi_val = float(rsi_value)
cci_val = float(cci_value)
is_bullish = close > ema_val and rsi_val > 50.0 and cci_val > 0.0
if self._has_prev_signal and is_bullish != self._was_bullish:
if is_bullish and self.Position <= 0:
self.BuyMarket()
elif not is_bullish and close < ema_val and rsi_val < 50.0 and cci_val < 0.0 and self.Position >= 0:
self.SellMarket()
self._was_bullish = is_bullish
self._has_prev_signal = True
def CreateClone(self):
return no_nonsense_tester_strategy()