Die Forex Fraus M1-Strategie repliziert den MetaTrader 5-Expert-Advisor "Forex Fraus M1" im StockSharp-Framework. Es ist ein konträres System, das einen Williams %R-Oszillator mit langem Rückblick (Periode 360) auf Ein-Minuten-Kerzen überwacht. Immer wenn der Oszillator extreme Werte berührt, versucht die Strategie, die Bewegung zu verblassen, mit dem Ziel einer schnellen Reversion zum Mittelpunkt des jüngsten Bereichs. Die Implementierung behält das ursprüngliche Money-Management des Experten bei, einschließlich optionaler Handelszeiten, statischer Stop-Loss- und Take-Profit-Levels in Pips und einem pip-basierten Trailing Stop.
Handelslogik
Indikator: Williams %R mit einem 360-Perioden-Rückblick.
Kaufsignal: Wenn Williams %R unter -99.9 fällt, gilt der Markt als extrem überverkauft. Die Strategie sendet eine Market-Kauforder, wenn keine Long-Position vorhanden ist. Wenn CloseOppositePositions aktiviert ist, wird jedes Short-Engagement in derselben Orderanforderung geschlossen.
Verkaufssignal: Wenn Williams %R über -0.1 steigt, ist der Markt extrem überkauft. Die Strategie gibt eine Market-Verkaufsorder aus und schließt optional zuerst jedes offene Long-Engagement.
Zeitfilter: Wenn UseTimeControl aktiviert ist, wertet die Strategie Signale nur zwischen StartHour (inklusiv) und EndHour (exklusiv) aus. Wenn die Sitzung Mitternacht überspannt (StartHour > EndHour), ist der Handel von StartHour bis 23 und von 0 bis EndHour - 1 erlaubt.
Risikomanagement
Stop-Loss: Berechnet als StopLossPips * PipSize unterhalb (für Longs) oder oberhalb (für Shorts) des Einstiegspreises. Wenn das Kerzentief das Stop-Level berührt, wird die Position zum Markt geschlossen.
Take-Profit: Berechnet als TakeProfitPips * PipSize oberhalb (für Longs) oder unterhalb (für Shorts) des Einstiegspreises. Wenn das Kerzenhoch/-tief dieses Level erreicht, wird die Position zur Gewinnsicherung geschlossen.
Trailing Stop: Wenn sowohl TrailingStopPips als auch TrailingStepPips positiv sind, wird der Stop gestrafft, sobald der Preis sich mindestens TrailingStopPips + TrailingStepPips Pips zugunsten des Trades bewegt. Für Longs folgt der Stop dem Schluss minus TrailingStopPips; für Shorts folgt er dem Schluss plus TrailingStopPips.
Pip-Größe: PipSize definiert den monetären Wert eines Pips. Für fünfstellige Forex-Symbole setzen Sie PipSize auf 0.0001, für dreistellige JPY-Paare verwenden Sie 0.01 usw.
Die Strategie überprüft Stop-Loss- und Take-Profit-Bedingungen anhand von Kerzenhochs/-tiefs. Wenn beide innerhalb derselben Kerze berührt werden, hat der Schutz-Stop Vorrang, was das konservative Verhalten des ursprünglichen Experten widerspiegelt.
Parameter
Name
Standard
Beschreibung
OrderVolume
0.1
Handelsvolumen für neue Positionen.
StopLossPips
50
Stop-Loss-Abstand in Pips vom Einstiegspreis. Auf null setzen zum Deaktivieren.
TakeProfitPips
150
Take-Profit-Abstand in Pips vom Einstiegspreis. Auf null setzen zum Deaktivieren.
TrailingStopPips
1
Basis-Trailing-Stop-Abstand in Pips. Auf null setzen zum Deaktivieren des Trailings.
TrailingStepPips
1
Mindest-Pip-Gewinn vor Bewegung des Trailing Stops.
UseTimeControl
true
Aktiviert den Intraday-Sitzungsfilter.
StartHour
7
Startstunde für die Handelssitzung (0-23).
EndHour
17
Endstunde für die Handelssitzung (1-24, exklusiv).
CloseOppositePositions
true
Bei Aktivierung werden bestehende Positionen in einer einzigen Order umgekehrt.
WilliamsPeriod
360
Rückblickperiode für den Williams %R-Indikator.
CandleType
1 minute
Kerzentyp zur Bewertung von Williams %R und Handelsregeln.
PipSize
0.0001
Wert eines einzelnen Pips in Preiseinheiten.
Zusätzliche Hinweise
Die Strategie verwendet StockSharps High-Level-Kerzen-Abonnement-API und Indikator-Bindung für präzise Logik ohne manuelle Buffer-Verwaltung.
Stop-Loss-, Take-Profit- und Trailing-Berechnungen erfolgen auf abgeschlossenen Kerzen, um nicht auf unvollständige Preisdaten zu reagieren.
Die Implementierung ruft StartProtection() einmalig beim Start auf, um den Projektrichtlinien zu entsprechen, während das eigentliche Risiko-Management innerhalb der Strategielogik verwaltet wird.
Passen Sie den PipSize-Parameter an das gehandelte Instrument an, damit Pip-basierte Abstände korrekt auf Preisbewegungen abgebildet werden.
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>
/// Forex Fraus M1 strategy using fast EMA crossover on short timeframes.
/// </summary>
public class ForexFrausM1Strategy : 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 ForexFrausM1Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA", "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)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
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 forex_fraus_m1_strategy(Strategy):
def __init__(self):
super(forex_fraus_m1_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", 5) \
.SetDisplay("Fast Period", "Fast EMA", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow Period", "Slow EMA", "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(forex_fraus_m1_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(forex_fraus_m1_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 forex_fraus_m1_strategy()