Die Wajdyss MA Expert Strategy ist eine C#-Portierung des MetaTrader 4 Expert Advisors „wajdyss MA expert v3“. Es vergleicht zwei gleitende Durchschnitte, die mit unabhängigen Zeiträumen, Berechnungsmodi, Verschiebungen und angewendeten Preisen konfiguriert sind. Ein bullischer Crossover des schnellen Durchschnitts über den langsamen Durchschnitt eröffnet ein Long-Engagement, während ein bärischer Crossover ein Short-Engagement eröffnet. Die Konvertierung reproduziert die ursprünglichen Money-Management-Regeln, optionale automatische Schließung gegensätzlicher Geschäfte und Liquidationsfilter am Ende des Tages/am Ende der Woche.
Handelslogik
Abonnieren Sie die ausgewählten CandleType (standardmäßig 15-Minuten-Kerzen) und berechnen Sie die schnellen und langsamen gleitenden Durchschnitte mithilfe der ausgewählten MovingAverageMethod- und PriceSource-Einstellungen für jedes Bein.
Speichern Sie die Indikatorwerte für fertige Kerzen. Bewerten Sie ein bullisches Signal, wenn der schnelle Durchschnitt (mit seiner konfigurierten Verschiebung) über dem langsamen Durchschnitt des letzten geschlossenen Balkens liegt, während er vor zwei Balken unter diesem lag. Bewerten Sie ein bärisches Signal mit der umgekehrten Bedingung.
Erzwingen Sie eine Abklingzeit zwischen neuen Einträgen in die gleiche Richtung. Die Strategie muss nach dem letzten Trade dieser Seite mindestens eine volle Kerze des abonnierten Zeitrahmens warten und spiegelt damit den globalen Variablen-Timing-Guard der MT4-Version wider.
Wenn AutoCloseOpposite aktiviert ist, stornieren Sie Arbeitsaufträge und kehren Sie das Engagement in einer einzigen Marktorder um: Das neue Auftragsvolumen umfasst alle ausstehenden Positionen in die entgegengesetzte Richtung, sodass das Konto sofort umgedreht wird.
Wenden Sie Tages- und Freitagsabschlussfilter an. Nach dem konfigurierten DailyCloseHour/DailyCloseMinute oder FridayCloseHour/FridayCloseMinute werden alle Positionen abgeflacht und neue Trades bis zur nächsten Sitzung blockiert.
Risiko- und Geldmanagement
TakeProfitPips, StopLossPips und TrailingStopPips werden in ganzen Pips interpretiert. Die Implementierung wandelt sie unter Verwendung der Sicherheitsmetadaten in Preisschritte um und steuert die StartProtection-Engine von StockSharp mit Marktausgängen für Parität mit der ursprünglichen Trailing-Logik.
UseMoneyManagement emuliert die MT4-Lotberechnung: volume = (account_balance / BalanceReference) * InitialVolume. Umtauschgrenzen werden durch Volumenschritt-, Mindest- und Höchstprüfungen eingehalten.
Wenn die Geldverwaltung deaktiviert ist, verwenden Bestellungen direkt InitialVolume.
Parameter
Parameter
Typ
Standard
Beschreibung
FastPeriod
int
10
Periode des schnellen gleitenden Durchschnitts.
FastShift
int
0
Balken zum Verschieben des schnellen Durchschnitts vor dem Vergleich der Crossover-Werte.
FastMethod
MovingAverageMethod
Ema
Gleitender Durchschnittsmodus für die schnelle Linie (Sma, Ema, Smma, Lwma).
FastPriceType
PriceSource
Close
Der Kerzenpreis floss in den sich schnell bewegenden Durchschnitt ein (Close, Open, High, Low, Median, Typical, Weighted).
SlowPeriod
int
20
Periode des langsamen gleitenden Durchschnitts.
SlowShift
int
0
Balken zur Verschiebung des langsamen Durchschnitts vor dem Vergleich.
SlowMethod
MovingAverageMethod
Ema
Moving-Average-Modus für die langsame Linie.
SlowPriceType
PriceSource
Close
Der Kerzenpreis trug zum langsamen Durchschnitt bei.
TakeProfitPips
decimal
100
Abstand zum Gewinnziel in Pips (zum Deaktivieren auf 0 setzen).
StopLossPips
decimal
50
Abstand zum Schutzstopp in Pips (zum Deaktivieren auf 0 einstellen).
TrailingStopPips
decimal
0
Trailing-Stop-Distanz in Pips (zum Deaktivieren auf 0 setzen).
AutoCloseOpposite
bool
true
Schließen Sie das gegnerische Engagement, bevor Sie einen neuen Trade in die andere Richtung eröffnen.
InitialVolume
decimal
0.1
Bestimmen Sie das Handelsvolumen, bevor Sie das Money-Management anwenden.
UseMoneyManagement
bool
true
Aktivieren Sie die ausgleichsbasierte Positionsgrößenbestimmung.
BalanceReference
decimal
1000
Divisor, der beim Skalieren des Volumens mit dem Kontostand verwendet wird.
DailyCloseHour
int
23
Stunde (0-23), nach der tägliche Positionen geschlossen werden.
DailyCloseMinute
int
45
Minutenkomponente des täglichen Abschlussfilters.
FridayCloseHour
int
22
Stunde (0-23), nach der der Freitagshandel endet.
FridayCloseMinute
int
45
Minutenkomponente des Freitagsschlussfilters.
CandleType
DataType
15m Zeitrahmen
Kerzenserien, die für Berechnungen und Abklingzeiten verwendet werden.
Notizen
Die Strategie basiert ausschließlich auf dem übergeordneten StockSharp API: Kerzen werden über SubscribeCandles verarbeitet, Indikatorbindungen versorgen gleitende Durchschnitte und StartProtection verwaltet Stops/Take-Profit/Trailing-Orders.
Beim Positionsflattening werden Marktaufträge verwendet, um die unmittelbaren Schließungen entgegengesetzter Tickets durch den MT4-Experten widerzuspiegeln.
In diesem Ordner ist keine Python-Übersetzung enthalten; Es wird nur die C#-Implementierung bereitgestellt.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Wajdyss MA Expert: Fast/slow EMA crossover with ATR stops.
/// </summary>
public class WajdyssMaExpertStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public WajdyssMaExpertStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastLength = Param(nameof(FastLength), 10)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowLength = Param(nameof(SlowLength), 20)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.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;
_prevSlow = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, atr, 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, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
// Exit
if (Position > 0)
{
if (close <= _entryPrice - atrVal * 2m || close >= _entryPrice + atrVal * 3m || fastVal < slowVal)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close >= _entryPrice + atrVal * 2m || close <= _entryPrice - atrVal * 3m || fastVal > slowVal)
{
BuyMarket();
_entryPrice = 0;
}
}
// Entry: EMA crossover
if (Position == 0)
{
if (_prevFast <= _prevSlow && fastVal > slowVal)
{
_entryPrice = close;
BuyMarket();
}
else if (_prevFast >= _prevSlow && fastVal < slowVal)
{
_entryPrice = close;
SellMarket();
}
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class wajdyss_ma_expert_strategy(Strategy):
def __init__(self):
super(wajdyss_ma_expert_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_length = self.Param("FastLength", 10) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_length = self.Param("SlowLength", 20) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastLength(self):
return self._fast_length.Value
@property
def SlowLength(self):
return self._slow_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(wajdyss_ma_expert_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._fast = ExponentialMovingAverage()
self._fast.Length = self.FastLength
self._slow = ExponentialMovingAverage()
self._slow.Length = self.SlowLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast, self._slow, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
av = float(atr_val)
if self._prev_fast == 0 or self._prev_slow == 0 or av <= 0:
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
# Exit
if self.Position > 0:
if close <= self._entry_price - av * 2.0 or close >= self._entry_price + av * 3.0 or fv < sv:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close >= self._entry_price + av * 2.0 or close <= self._entry_price - av * 3.0 or fv > sv:
self.BuyMarket()
self._entry_price = 0.0
# Entry: EMA crossover
if self.Position == 0:
if self._prev_fast <= self._prev_slow and fv > sv:
self._entry_price = close
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(wajdyss_ma_expert_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return wajdyss_ma_expert_strategy()