Die NNFX Auto Trade Strategy repliziert den Risikodimensionierungs- und Management-Workflow des ursprünglichen NNFX MetaTrader 4-Panels innerhalb von StockSharp. Anstelle einer grafischen Oberfläche stellt die Strategie manuelle Befehle über Parameter bereit. Händler können Long- oder Short-Einträge anfordern, das Engagement sofort abflachen oder Breakeven- und Trailing-Logik anwenden, die den Expertenberater widerspiegelt.
Hauptmerkmale:
ATR-gesteuerte Volatilitätsgrößenbestimmung mit einer optionalen Überschreibung für manuelle Stop- und Take-Profit-Distanzen.
Positionseinträge sind in zwei Teile aufgeteilt: einen mit einem prognostizierten Ziel und einen Läufer, der für die diskretionäre Verwaltung offen bleibt.
Breakeven- und Trailing-Befehle werden bei Bedarf ausgeführt und aktualisieren die gespeicherten Stop-Level, ohne automatisch bei jedem Balken ausgelöst zu werden.
Bei der Berechnung des monetären Risikos kann zusätzliches Kapital einbezogen werden, das dem Verhalten des MQL-Skripts entspricht.
Handelslogik
ATR-Sammlung – Die Strategie abonniert den konfigurierten Kerzentyp und verarbeitet einen Average True Range-Indikator. Wenn UsePreviousDailyAtr aktiviert ist, kopiert es den ATR-Wert des Vortages während der ersten 12 Stunden des neuen Handelstages und imitiert so das ursprüngliche Skript.
Risikobasierte Dimensionierung – Bei einem manuellen Buy- oder Sell-Befehl berechnet die Engine das monetäre Risiko pro Einheit anhand der Schutzstoppdistanz und wandelt den gewünschten Risikoprozentsatz in ein ausführbares Volumen um.
Positionssplit – Das Einstiegsvolumen wird in zwei Hälften geteilt. Die erste Hälfte wird automatisch liquidiert, wenn das projizierte Ziel erreicht wird, während die zweite Hälfte so lange verbleibt, bis der Händler weitere Befehle erteilt.
Stopp-Handhabung – Die anfänglichen Stopps werden intern gespeichert und bei jeder fertigen Kerze ausgewertet. Manuelle Befehle können den Stopp auf die Gewinnschwelle bringen oder ihn gemäß der NNFX-Trailing-Formel erhöhen.
Ausstiegskontrollen – CloseAll glättet das Buch sofort, während Stop-Verletzungen oder Teilziele Marktausstiege auslösen, die die berechneten Volumina respektieren.
Parameter
Parameter
Standard
Beschreibung
RiskPercent
2.0
Prozentsatz des Kontokapitals (plus AdditionalCapital), das pro Trade riskiert wird.
AdditionalCapital
0
Bei der Größenbestimmung von Positionen wird der Eigenkapitalbasis zusätzliches Kapital hinzugefügt.
UseAdvancedTargets
false
Ändert die Risikoentfernungen von ATR-Vielfachen auf manuelle Pip-Werte.
AdvancedStopPips
0
Stoppdistanz in Pips, wenn der erweiterte Modus aktiv ist.
AdvancedTakeProfitPips
0
Zielentfernung in Pips für den teilweisen Ausgang, wenn der erweiterte Modus aktiv ist.
UsePreviousDailyAtr
true
Kopiert den vorherigen Tageswert ATR während der ersten 12 Stunden eines neuen Tages.
AtrPeriod
14
ATR Lookback-Länge.
AtrStopMultiplier
1.5
Bei der Berechnung der Stoppentfernung wird ein Multiplikator auf ATR angewendet.
AtrTakeProfitMultiplier
1.0
Bei der Berechnung der Take-Profit-Distanz wird ein Multiplikator auf ATR angewendet.
CandleType
1 Minute
Kerzentyp, der für ATR und die Preisüberwachung verwendet wird.
BuyCommand
false
Manuelles Flag – auf true gesetzt, um einen langen Eintrag anzufordern. Wird automatisch zurückgesetzt.
SellCommand
false
Manuelles Flag – auf true gesetzt, um einen kurzen Eintrag anzufordern. Wird automatisch zurückgesetzt.
BreakevenCommand
false
Manuelle Flagge – Bewegen Sie den Schutzstopp auf den Einstiegspreis. Wird automatisch zurückgesetzt.
TrailingCommand
false
Manuelle Markierung – wenden Sie die NNFX-Nachlaufformel einmal an. Wird automatisch zurückgesetzt.
CloseAllCommand
false
Manuelle Markierung – alle offenen Positionen sofort schließen. Wird automatisch zurückgesetzt.
Nutzungshinweise
Die Strategie erfordert ein verbundenes Portfolio und Sicherheit mit gültigen Step-, StepPrice- und VolumeStep-Metadaten für genaue Risikoberechnungen.
Befehle werden für fertige Kerzen ausgewertet, daher muss nach dem Umschalten eines manuellen Parameters ein neuer Balken (oder eine Kerzenaktualisierung) empfangen werden.
Wenn Sie erweiterte Entfernungen verwenden, stellen Sie sicher, dass sowohl AdvancedStopPips als auch AdvancedTakeProfitPips ausgefüllt sind. andernfalls bleiben die ATR-basierten Standardeinstellungen in Kraft.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// NNFX Auto Trade strategy: ATR-based trend following with EMA filter.
/// Enters on EMA direction with ATR-based trailing stop management.
/// </summary>
public class NnfxAutoTradeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrMultiplier;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _entryPrice;
private decimal _bestPrice;
private bool _wasBullish;
private bool _hasPrevSignal;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal AtrMultiplier { get => _atrMultiplier.Value; set => _atrMultiplier.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public NnfxAutoTradeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(120).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 100)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR period", "Indicators");
_atrMultiplier = Param(nameof(AtrMultiplier), 2.5m)
.SetDisplay("ATR Multiplier", "ATR multiplier for stop", "Risk");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 12)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_bestPrice = 0m;
_wasBullish = false;
_hasPrevSignal = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_bestPrice = 0;
_hasPrevSignal = false;
_candlesSinceTrade = SignalCooldownCandles;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, atr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var stopDist = atrValue * AtrMultiplier;
var isBullish = close > emaValue;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
// Trailing stop check
if (Position > 0)
{
if (close > _bestPrice) _bestPrice = close;
if (_bestPrice - close > stopDist)
{
SellMarket();
_entryPrice = 0;
_bestPrice = 0;
_candlesSinceTrade = 0;
return;
}
}
else if (Position < 0)
{
if (close < _bestPrice) _bestPrice = close;
if (close - _bestPrice > stopDist)
{
BuyMarket();
_entryPrice = 0;
_bestPrice = 0;
_candlesSinceTrade = 0;
return;
}
}
// Entry signals
if (_hasPrevSignal && isBullish != _wasBullish && _candlesSinceTrade >= SignalCooldownCandles)
{
if (isBullish && Position <= 0)
{
BuyMarket();
_entryPrice = close;
_bestPrice = close;
_candlesSinceTrade = 0;
}
else if (!isBullish && Position >= 0)
{
SellMarket();
_entryPrice = close;
_bestPrice = close;
_candlesSinceTrade = 0;
}
}
_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, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class nnfx_auto_trade_strategy(Strategy):
def __init__(self):
super(nnfx_auto_trade_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(120)))
self._ema_period = self.Param("EmaPeriod", 100)
self._atr_period = self.Param("AtrPeriod", 14)
self._atr_multiplier = self.Param("AtrMultiplier", 2.5)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 12)
self._entry_price = 0.0
self._best_price = 0.0
self._was_bullish = False
self._has_prev_signal = False
self._candles_since_trade = 12
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@AtrPeriod.setter
def AtrPeriod(self, value):
self._atr_period.Value = value
@property
def AtrMultiplier(self):
return self._atr_multiplier.Value
@AtrMultiplier.setter
def AtrMultiplier(self, value):
self._atr_multiplier.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(nnfx_auto_trade_strategy, self).OnReseted()
self._entry_price = 0.0
self._best_price = 0.0
self._was_bullish = False
self._has_prev_signal = False
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(nnfx_auto_trade_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._best_price = 0.0
self._has_prev_signal = False
self._candles_since_trade = self.SignalCooldownCandles
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
atr = AverageTrueRange()
atr.Length = self.AtrPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, atr, self._process_candle).Start()
def _process_candle(self, candle, ema_value, atr_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
stop_dist = float(atr_value) * float(self.AtrMultiplier)
is_bullish = close > float(ema_value)
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
# Trailing stop check
if self.Position > 0:
if close > self._best_price:
self._best_price = close
if self._best_price - close > stop_dist:
self.SellMarket()
self._entry_price = 0.0
self._best_price = 0.0
self._candles_since_trade = 0
return
elif self.Position < 0:
if close < self._best_price:
self._best_price = close
if close - self._best_price > stop_dist:
self.BuyMarket()
self._entry_price = 0.0
self._best_price = 0.0
self._candles_since_trade = 0
return
# Entry signals
if self._has_prev_signal and is_bullish != self._was_bullish and self._candles_since_trade >= self.SignalCooldownCandles:
if is_bullish and self.Position <= 0:
self.BuyMarket()
self._entry_price = close
self._best_price = close
self._candles_since_trade = 0
elif not is_bullish and self.Position >= 0:
self.SellMarket()
self._entry_price = close
self._best_price = close
self._candles_since_trade = 0
self._was_bullish = is_bullish
self._has_prev_signal = True
def CreateClone(self):
return nnfx_auto_trade_strategy()