Die Ultra MFI MMRec Strategie ist ein direkter Port des MetaTrader 5 Expert Advisors Exp_UltraMFI_MMRec. Sie kombiniert einen mehrfach geglätteten Money Flow Index (MFI) Oszillator mit reihungsbasiertem Geldmanagement. Zwei interne Zähler akkumulieren, wie viele Glättungsschichten nach oben oder unten zeigen. Kreuzungen zwischen diesen Zählern generieren Handelssignale, während jüngste Handelsergebnisse bestimmen, ob die nächste Position die normale oder reduzierte Positionsgröße verwendet.
Handelslogik
Basisindikator – ein Money Flow Index mit konfigurierbarer Länge wird auf dem ausgewählten Kerzentyp berechnet.
Stufenglättung – der MFI-Wert wird durch eine Leiter von gleitenden Durchschnitten geleitet. Jeder Schritt erhöht die Glättungslänge um einen festen Zuwachs. Unterstützte Glättungsmethoden sind Simple, Exponential, Smoothed, Linear Weighted und Jurik Moving Averages (andere MT5-spezifische Modi sind in StockSharp nicht verfügbar).
Richtungszähler – für jeden Balken vergleicht die Strategie den aktuellen und vorherigen Ausgang jedes Glättungsschritts. Wenn der Schritt steigt, erhöht sich der bullische Zähler, andernfalls der bärische. Beide Zähler werden nochmals durch einen abschließenden gleitenden Durchschnitt geglättet.
Signalverschiebung – Handelsregeln operieren auf fertigen Balken. Ein konfigurierbarer SignalShift teilt der Strategie mit, wie viele geschlossene Kerzen beim Vergleich der Zähler zurückgeschaut werden sollen, was das MT5-Verhalten mit SignalBar=1 nachahmt.
Einstiege und Ausstiege –
Wenn der vorherige Balken stärkere Bullen zeigte (bulls > bears) und der neueste Balken einen Kreuzung zu bulls < bears zeigt, öffnet die Strategie eine Long-Position. Dieselbe Bedingung schließt auch jede offene Short-Position.
Wenn der vorherige Balken stärkere Bären zeigte und der neueste Balken auf bulls > bears wechselt, öffnet die Strategie eine Short-Position und schließt jede offene Long-Position.
Optionaler Stop-Loss und Take-Profit (prozentbasiert) können über StartProtection verwaltet werden.
Geldmanagement – die nächste Ordergröße hängt von den jüngsten Handelsergebnissen pro Richtung ab. Nach dem Schließen jeder Position wird der realisierte PnL inspiziert:
Die Strategie speichert die jüngsten BuyTotalTrigger Kauftrades und zählt, wie viele Verluste waren. Wenn die Anzahl BuyLossTrigger erreicht, verwendet die nächste Kauforder ReducedVolume, andernfalls NormalVolume.
Dieselbe Logik wird unabhängig für Verkaufstrades mit SellTotalTrigger und SellLossTrigger angewendet.
Parameter
CandleType – Instrument-Datentyp (Zeitrahmen) für die Signalerzeugung.
MfiPeriod – Länge des Money Flow Index Oszillators.
StepSmoothing / FinalSmoothing – Moving-Average-Typ für die Stufenschritte und die abschließenden Zähler.
StartLength / StepSize / StepsTotal – Geometrie der Glättungsleiter (erste Länge, Zuwachs, Anzahl der Schritte).
FinalSmoothingLength – Länge der Zähler-Glättungsphase.
SignalShift – Anzahl abgeschlossener Balken, die beim Auswerten von Signalen zurückgeschaut werden.
NormalVolume / ReducedVolume – Handelsgröße für normale Bedingungen und nach einer Verluststrähne.
BuyTotalTrigger / BuyLossTrigger – Verlaufstiefe und Verlustschwelle zum Umschalten des nächsten Long-Trades auf reduzierte Größe.
SellTotalTrigger / SellLossTrigger – analoge Einstellungen für Short-Trades.
AllowLongEntries / AllowShortEntries / AllowLongExits / AllowShortExits – Einstiege und Ausstiege für jede Richtung aktivieren oder deaktivieren.
Die Stufenglättung erfordert genügend historische Kerzen, um jeden gleitenden Durchschnitt zu füllen. Warten Sie, bis die Strategie vollständig ausgebildet ist, bevor Sie den Signalen vertrauen.
Da StockSharp keine MT5-spezifischen Glätter wie JurX, Parabolic, VIDYA oder AMA bereitstellt, werden die nächstliegenden unterstützten Alternativen verwendet. Jurik-Glättung ist ein guter Standard, der das ursprüngliche Gefühl des UltraMFI-Indikators reproduziert.
Das Geldmanagement basiert auf realisiertem PnL. Stellen Sie sicher, dass Ihre Backtests die Orderausführung beinhalten, damit der realisierte PnL nach jedem Positionsschluss aktualisiert wird.
Dieser Port hält das Verhalten bei, neue Positionen nur einzugehen, wenn die aktuelle Position flach ist. Wenn ein Umkehrsignal erscheint, während die entgegengesetzte Position gehalten wird, verlässt die Strategie zuerst den bestehenden Trade und wird beim nächsten geeigneten Balken einsteigen, sobald sie flach ist.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Ultra MFI MMRec strategy. Uses EMA crossover as signal generator.
/// </summary>
public class UltraMfiMmRecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public UltraMfiMmRecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (prevAbove && !currAbove && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
}
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 ultra_mfi_mm_rec_strategy(Strategy):
def __init__(self):
super(ultra_mfi_mm_rec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 8) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(ultra_mfi_mm_rec_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(ultra_mfi_mm_rec_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return ultra_mfi_mm_rec_strategy()