Ingrit ist eine Konvertierung des MetaTrader 5 Expert Advisors Ingrit.mq5. Die Strategie überwacht Fünf-Minuten-Kerzen und reagiert, wenn auf eine starke gegenläufige Kerze ein breiter Ausbruch folgt, der gegen einen Swing von vierzehn Bars zuvor gemessen wird. Orders werden zum Marktpreis platziert, mit konfigurierbaren Stop-Loss-, Take-Profit- und Trailing-Stop-Abständen in Pips. Signale können optional umgekehrt oder dazu gebracht werden, die entgegengesetzte Exposition zu schließen, bevor ein neuer Trade eingegangen wird.
Strategie-Logik
Ausbrucherkennung
Die Strategie verarbeitet nur abgeschlossene Kerzen des ausgewählten Zeitrahmens (Standard: 5 Minuten).
Für ein Long-Setup muss die vorherige Kerze bärisch schließen und der Abstand zwischen dem Hoch der Kerze 14 Bars zurück und dem Tief der vorherigen Kerze muss StepPips überschreiten (nach Konvertierung von Pips in Preiseinheiten).
Für ein Short-Setup muss die vorherige Kerze bullisch schließen und der Abstand zwischen dem Hoch der vorherigen Kerze und dem Tief der Kerze 14 Bars zurück muss StepPips überschreiten.
Das Aktivieren von ReverseSignals tauscht die Long- und Short-Bedingungen aus und reproduziert den optionalen Umkehrmodus des ursprünglichen Roboters.
Trade-Verwaltung
Marktorders werden mit dem Volume der Strategie gesendet. Wenn CloseOppositePositions aktiviert ist, wird die angeforderte Größe um den absoluten Wert der aktuellen Position erhöht, sodass Umkehrungen die bestehende Exposition im selben Trade schließen.
Ein fester Stop-Loss und Take-Profit (falls größer als null) werden unmittelbar nach dem Einstieg angehängt. Beide Abstände werden aus Pips unter Verwendung des Preisschritts des Instruments konvertiert und passen sich automatisch an drei- und fünfstellige FX-Kurse an.
Der Trailing-Stop wird aktiv, sobald der nicht realisierte Gewinn TrailingStopPips + TrailingStepPips übersteigt. Bei Long-Positionen folgt der Stop unterhalb des Schlusskurses, bei Short-Positionen oberhalb. Jede Aktualisierung hält den Stop mindestens TrailingStepPips vom vorherigen Trailing-Niveau entfernt, um schnelle Modifikationen zu vermeiden.
Zusätzliches Verhalten
Das Trailing kann durch Setzen von TrailingStopPips auf null deaktiviert werden. Wenn Trailing aktiv ist, muss der Schritt positiv bleiben (die Strategie führt dieselbe Validierung wie die MQL-Version durch).
Alle Berechnungen laufen auf abgeschlossenen Kerzen; keine Intrabar-Verarbeitung ist in StockSharp erforderlich.
Die Strategie erstellt keine ausstehenden Orders – jedes Signal wird mit einer Marktorder ausgeführt und die Schutzebenen werden intern simuliert.
Parameter
Parameter
Beschreibung
CandleType
Zeitrahmen für den Kerzenaufbau der Ausbruchslogik. Standard: 5-Minuten-Zeitrahmen.
StopLossPips
Stop-Loss-Abstand in Pips. Ein Wert von 0 deaktiviert den festen Stop.
TakeProfitPips
Take-Profit-Abstand in Pips. Ein Wert von 0 deaktiviert das feste Ziel.
TrailingStopPips
Basis-Trailing-Stop-Abstand in Pips. Auf 0 setzen, um Trailing zu deaktivieren.
TrailingStepPips
Zusätzlicher Pip-Abstand, der gewonnen werden muss, bevor sich der Trailing-Stop wieder bewegt. Muss positiv sein, wenn Trailing aktiviert ist.
StepPips
Minimaler Swing-Abstand in Pips zwischen der Referenzkerze und der letzten Kerze, bevor ein Signal ausgelöst wird.
ReverseSignals
Bei true werden Long- und Short-Bedingungen getauscht (Umkehrmodus).
CloseOppositePositions
Bei true wird die Marktorder erweitert, um jede entgegengesetzte Exposition zu schließen, bevor die neue Position eröffnet wird.
Volume
Strategie-Eigenschaft, die die Basis-Ordergröße definiert. Mit CloseOppositePositions kombinieren, um das Umkehrverhalten zu steuern.
Hinweise
Pip-Werte werden aus dem Preisschritt des Instruments abgeleitet. Wenn das Instrument drei oder fünf Dezimalstellen verwendet, multipliziert die Strategie den Schritt mit zehn, sodass ein Pip der Standard-FX-Definition entspricht.
Es gibt keine Python-Version dieser Strategie im Repository.
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;
public class IngritStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public IngritStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class ingrit_strategy(Strategy):
def __init__(self):
super(ingrit_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(ingrit_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(ingrit_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return ingrit_strategy()