Diese Strategie portiert den MetaTrader-Expertenberater Exp_Open_Oscillator_Cloud_MMRec auf die StockSharp High-Level-API. Das System handelt den Kreuzungspunkt des Open Oscillator Cloud-Indikators, der den aktuellen Eröffnungskurs mit den Eröffnungskursen der höchsten und niedrigsten Balken innerhalb eines gleitenden Fensters vergleicht und das Ergebnis mit einem konfigurierbaren gleitenden Durchschnitt glättet.
Strategie-Logik
Indikator-Konstruktion
Ein Rückblickfenster (Oscillator Period, Standard 20 Balken) abgeschlossener Kerzen vom gewählten Zeitrahmen wird erstellt.
Der Balken mit dem höchsten Hoch wird gefunden und sein Eröffnungskurs gespeichert; der Balken mit dem niedrigsten Tief wird gefunden und sein Eröffnungskurs gespeichert.
Zwei Rohwerte für die aktuelle Kerze werden berechnet:
Oberes Band = aktuelle Eröffnung − Eröffnungskurs beim höchsten Hoch.
Unteres Band = Eröffnungskurs beim niedrigsten Tief − aktuelle Eröffnung.
Beide Serien werden mit dem gewählten gleitenden Durchschnitt geglättet (Smoothing Method, Smoothing Length). Unterstützte Typen sind Einfache, Exponentielle, Geglättete und Gewichtete gleitende Durchschnitte.
Die geglättete Historie wird gespeichert und das Signal um Signal Bar vollständig geschlossene Kerzen (Standard 1) verzögert, um die ursprüngliche EA-Logik nachzuahmen, die auf dem vorherigen Balken agiert.
Einstiegskriterien
Long-Einstieg: Das obere Band des vorherigen Balkens lag über dem unteren Band, und der letzte verzögerte Wert kreuzt nach unten (upper ≤ lower). Kann über Enable Long Entries deaktiviert werden.
Short-Einstieg: Das obere Band des vorherigen Balkens lag unter dem unteren Band, und der letzte verzögerte Wert kreuzt nach oben (upper ≥ lower). Kann über Enable Short Entries deaktiviert werden.
Ausstiegskriterien
Long-Ausstieg: Das obere Band des vorherigen Balkens lag unter dem unteren Band, was ein bearishes Regime signalisiert. Gesteuert durch Enable Long Exits.
Short-Ausstieg: Das obere Band des vorherigen Balkens lag über dem unteren Band, was ein bullishes Regime signalisiert. Gesteuert durch Enable Short Exits.
Risikomanagement: Wenn Stop Loss Points oder Take Profit Points größer als null sind, schließt die Strategie die Position automatisch, sobald der Preis diese Abstände (gemessen in Instrument-Preisschritten) vom Einstieg erreicht.
Order-Handling
Es werden nur Marktorders verwendet. Vor dem Öffnen einer neuen Position wird die entgegengesetzte Seite geglättet, um mit dem Einzelpositions-Verhalten des MetaTrader-Roboters ausgerichtet zu bleiben.
Der Parameter Trade Volume legt die Basis-Positionsgröße für jeden Einstieg fest.
Parameter
Candle Type – Zeitrahmen der für den Oszillator verwendeten Kerzen (Standard 1 Stunde).
Oscillator Period – Anzahl der Kerzen im gleitenden Fenster (Standard 20).
Smoothing Method – Auf die Eröffnungslücken angewandter gleitender Durchschnitt (Simple, Exponential, Smoothed, Weighted).
Smoothing Length – Länge des glättenden gleitenden Durchschnitts (Standard 10).
Signal Bar – Anzahl vollständig geschlossener Balken zur Verzögerung der Signalauswertung (Standard 1).
Enable Long Entries / Enable Short Entries – Erlaubt oder blockiert das Öffnen von Trades in jede Richtung.
Enable Long Exits / Enable Short Exits – Erlaubt oder blockiert automatische Ausstiege für die jeweilige Richtung.
Stop Loss Points – Schützender Stop-Abstand in Preisschritten (0 deaktiviert den Stop, Standard 1000).
Take Profit Points – Gewinnziel-Abstand in Preisschritten (0 deaktiviert das Ziel, Standard 2000).
Implementierungshinweise
Die Glättungsmethoden entsprechen den gängigsten Optionen des ursprünglichen EA. Exotische Modi wie JJMA, T3, VIDYA oder AMA werden nicht portiert, da StockSharp bereits reichhaltige Alternativen für Optimierung und Robustheit bietet.
Signale werden nur bei CandleStates.Finished-Ereignissen ausgewertet, um nicht auf unvollständige Daten zu reagieren.
Die Strategie hält eine interne Historie geglätteter Werte, anstatt Indikator-Puffer abzufragen, was dem empfohlenen High-Level-StockSharp-Workflow entspricht.
Schutzlevels werden automatisch gelöscht, wenn die Position flach wird, um zu verhindern, dass veraltete Stops Trades wieder eröffnen.
Standardverhalten
Trendfolge in beide Richtungen mit verzögerter Bestätigung zur Rauschreduzierung.
Verwendet festes Money-Management (konstantes Trade Volume) unter Einhaltung von Stop-Loss- und Take-Profit-Abständen ähnlich der MetaTrader-Version.
Geeignet als Vorlage zum Experimentieren mit verschiedenen Glättungstypen oder zur Kombination des Oszillators mit zusätzlichen Filtern.
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>
/// Open oscillator cloud strategy using EMA crossover as trend proxy.
/// </summary>
public class OpenOscillatorCloudMmrecStrategy : 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 OpenOscillatorCloudMmrecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "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 fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fast;
_prevSlow = slow;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast;
_prevSlow = slow;
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 open_oscillator_cloud_mmrec_strategy(Strategy):
def __init__(self):
super(open_oscillator_cloud_mmrec_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", 10) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.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(open_oscillator_cloud_mmrec_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(open_oscillator_cloud_mmrec_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
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 open_oscillator_cloud_mmrec_strategy()