Take-Profit und Stop-Loss respektieren den konfigurierten Punktabstand multipliziert mit Security.PriceStep (oder werden direkt verwendet, wenn der Schritt unbekannt ist).
Der Trailing-Stop sperrt Gewinne, sobald der Preis um mehr als TrailingStopPoints ansteigt, und folgt dem nach dem Einstieg erreichten Extremwert.
Ausfallsicherer Ausstieg, wenn die gleitenden Durchschnitte in die entgegengesetzte Reihenfolge wechseln, was die ursprüngliche OrderClose-Logik widerspiegelt.
Positionsgrößen
Das Standardvolumen beträgt BaseVolume (0,1 Lot), wenn keine Portfoliokennzahlen verfügbar sind.
Wenn Portfolio.CurrentValue vorhanden ist, multipliziert die Strategie es mit RiskFraction (Standard 0.00002, äquivalent zur MQL-Formel FreeMargin * 0.02 / 1000).
Nach mehr als einem verlorenen Ausgang wird die Lautstärke um volume * losses / 3 reduziert, genau wie bei der LotsOptimized-Routine.
Das Volumen wird auf Security.VolumeStep abgerundet und auf Null gesenkt, wenn es Security.MinVolume nicht erfüllen kann.
Parameter
Parameter
Standard
Beschreibung
FastPeriod
24
Länge des am schnellsten verschobenen SMA.
MediumPeriod
60
Länge des um SMA verschobenen Mediums.
SlowPeriod
120
Länge des langsam verschobenen SMA.
TakeProfitPoints
150
Abstand in Preispunkten zwischen dem Einstiegspreis und dem Take-Profit.
StopLossPoints
100
Abstand in Preispunkten zwischen dem Einstiegspreis und dem Stop-Loss.
TrailingStopPoints
100
Optionaler Trailing-Stop-Abstand in Punkten (zum Deaktivieren auf 0 setzen).
BaseVolume
0,1
Fallback-Handelsgröße und Mindestvolumen nach Reduzierungen.
RiskFraction
0,00002
Bruchteil des Portfoliowerts, der zur Berechnung des dynamischen Volumens verwendet wird.
CandleType
Zeitrahmen 1 Stunde
Kerzenserie zur Versorgung von Indikatoren.
Konvertierungshinweise
Die Strategie verwendet die übergeordnete API (SubscribeCandles + Bind) und vermeidet manuelle Verlaufspuffer.
Indikatorwerte werden zwischen Aufrufen gespeichert, um den Parameter shift ohne direkten Indexzugriff nachzuahmen.
Schutzexits werden mit Marktbefehlen auf dem erkannten Preisniveau ausgeführt, um mit der StockSharp-Abstraktion kompatibel zu bleiben.
Alle Inline-Kommentare sind in englischer Sprache verfasst und entsprechen den Projektrichtlinien.
Nutzung
Hängen Sie die Strategie in StockSharp Designer oder Code an ein Wertpapier und Portfolio an.
Wählen Sie eine Kerzenserie (CandleType) aus, die Ihrem MT4-Zeitrahmen (standardmäßig H1) entspricht.
Überprüfen Sie die punktbasierten Risikoparameter, um sie an die Tick-Größe des Instruments anzupassen (z. B. 0,0001 für die meisten Forex-Paare).
Setzen Sie TrailingStopPoints auf Null, wenn kein Trailing erforderlich ist.
Überwachen Sie Protokolle auf Meldungen wie „Enter long“ und „Exit short“, die die MQL-Diagnose widerspiegeln.
Der Handel ist mit erheblichen Risiken verbunden. Die Strategie wird zu Bildungszwecken bereitgestellt und muss vor dem Live-Handel anhand historischer und simulierter Daten validiert werden.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Up3x1ShiftedSmaStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Up3x1ShiftedSmaStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8).SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 24).SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 2;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 2;
}
_prevFast = fast; _prevSlow = slow;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class up_3x1_shifted_sma_strategy(Strategy):
"""Simple SMA crossover (fast/slow) with cooldown between trades."""
def __init__(self):
super(up_3x1_shifted_sma_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 8).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 24).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(up_3x1_shifted_sma_strategy, self).OnReseted()
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
self._cooldown = 0
def OnStarted2(self, time):
super(up_3x1_shifted_sma_strategy, self).OnStarted2(time)
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
self._cooldown = 0
fast = SimpleMovingAverage()
fast.Length = self._fast_period.Value
slow = SimpleMovingAverage()
slow.Length = self._slow_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(fast, slow, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fv = float(fast_val)
sv = float(slow_val)
if not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fv
self._prev_slow = sv
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
volume = self.Volume + abs(self.Position)
self.BuyMarket(volume)
self._cooldown = 2
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
volume = self.Volume + abs(self.Position)
self.SellMarket(volume)
self._cooldown = 2
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return up_3x1_shifted_sma_strategy()