Diese Strategie reproduziert die Logik des originalen MetaTrader-Expertenberaters "Exp_2XMA_Ichimoku_Oscillator", indem zwei Ichimoku-artige Preisenveloppen kombiniert werden, die mit konfigurierbaren gleitenden Durchschnitten geglättet werden. Die StockSharp-Implementierung verwendet die High-Level-Strategie-API und konzentriert sich auf kerzenbasierte Signalerzeugung, während die Positionsverwaltungsregeln des Quellalgorithmus beibehalten werden.
Kernidee
Zwei Donchian-artige Mittelpunkte werden auf dem ausgewählten Zeitrahmen berechnet:
Der schnelle Mittelpunkt mittelt das höchste Hoch und tiefste Tief über UpPeriod1 und DownPeriod1 Balken.
Der langsame Mittelpunkt führt dieselbe Operation mit UpPeriod2 und DownPeriod2 Balken durch.
Jeder Mittelpunkt wird durch einen gleitenden Durchschnitt (Method1, Method2) mit den Längen XLength1 und XLength2 geglättet. Die verfügbaren Glättungsmethoden sind Einfach, Exponentiell, Geglättet und Linear Gewichtet.
Der Oszillatorwert ist die Differenz zwischen den beiden geglätteten Mittelpunkten. Vier Farbzustände beschreiben sein Verhalten:
PositiveRising (0): Oszillator liegt über null und steigt.
PositiveFalling (1): Oszillator liegt über null und verliert Dynamik.
NegativeRising (3): Oszillator liegt unter null, steigt aber in Richtung null.
NegativeFalling (4): Oszillator liegt unter null und fällt weiter.
Neutral (2) wird während der Aufwärmphase zugewiesen.
Signale werden anhand der Farben der Balken bei SignalBar und dem unmittelbar vorherigen Balken (SignalBar + 1) ausgewertet, was die Pufferverschiebung in der MQL-Version widerspiegelt.
Handelslogik
Long-Einstieg: erlaubt, wenn EnableBuyOpen wahr ist. Wenn die Farbe des älteren Balkens (SignalBar + 1) aufsteigend war (0 oder 3) und der neuere Balken (SignalBar) zu einer fallenden Farbe (1 oder 4) wechselte, schließt die Strategie jede Short-Position (EnableSellClose) und öffnet/erweitert eine Long-Position mit Volume + |Position| Einheiten.
Short-Einstieg: erlaubt, wenn EnableSellOpen wahr ist. Wenn die Farbe des älteren Balkens fallend war (1 oder 4) und der neuere Balken zu einer aufsteigenden Farbe (0 oder 3) wechselte, schließt die Strategie bestehende Longs (EnableBuyClose) und öffnet/erweitert eine Short-Position mit Volume + |Position| Einheiten.
Alle Ausführungen erfolgen beim Schließen der Kerze, die den Auslöser erzeugt. Aufträge sind immer Marktaufträge und die Strategie wendet keine zusätzlichen Stop-Loss- oder Take-Profit-Niveaus an; sie verlässt sich ausschließlich auf Farbübergänge für Ausstiege.
StartProtection() wird beim Start aktiviert, um die integrierten Sicherheitsprüfungen des Frameworks für unerwartete Positionen zu nutzen.
Parameter
Name
Beschreibung
Standard
CandleType
Zeitrahmen für Indikatorberechnungen.
4-Stunden-Kerzen
UpPeriod1, DownPeriod1
Rückblickfenster für den schnellen Mittelpunkt.
6, 6
UpPeriod2, DownPeriod2
Rückblickfenster für den langsamen Mittelpunkt.
9, 9
XLength1, XLength2
Glättungslängen für die zwei gleitenden Durchschnitte.
Historische Balkenverschiebung zum Lesen der Oszillatorfarben.
1
EnableBuyOpen, EnableSellOpen
Long/Short-Einstiege umschalten.
true
EnableBuyClose, EnableSellClose
Long/Short-Ausstiege umschalten.
true
Volume
Basis-Handelsgröße; bestehende Positionen werden bei Umkehr zu diesem Wert addiert.
1
Verwendungshinweise
Die Typen gleitender Durchschnitte decken die häufigsten Glättungsverhalten des ursprünglichen Experten ab. Erweiterte Optionen wie benutzerdefinierte XMA-Phasenanpassungen sind in StockSharp nicht verfügbar und wurden durch Standardindikatoren ersetzt.
Da der Oszillator auf geschlossenen Kerzen berechnet wird, erscheinen Signale mit der gleichen Einbalken-Verzögerung, die die MQL-Implementierung verwendete (SignalBar = 1). Erhöhen Sie SignalBar, wenn Sie zusätzliche Bestätigungsbalken benötigen.
Erwägen Sie, die Strategie mit externem Risikomanagement (Portfolio-Manager, Schutz-Stops) zu kombinieren, wenn Sie auf Live-Märkten handeln, da Ausstiege ausschließlich von Oszillatorfarbumkehrungen abhängen.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Exp 2XMA Ichimoku Oscillator strategy (simplified).
/// Uses two SMAs of different periods as a crossover oscillator.
/// Buys when fast SMA crosses above slow SMA, sells when fast crosses below.
/// </summary>
public class Exp2XmaIchimokuOscillatorStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
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 Exp2XmaIchimokuOscillatorStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Source candles", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast moving average length", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow moving average length", "Indicators");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastMa = new ExponentialMovingAverage { Length = FastPeriod };
var slowMa = new ExponentialMovingAverage { Length = SlowPeriod };
decimal prevFast = 0, prevSlow = 0;
bool prevInitialized = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastValue;
prevSlow = slowValue;
prevInitialized = true;
return;
}
if (!prevInitialized)
{
prevFast = fastValue;
prevSlow = slowValue;
prevInitialized = true;
return;
}
// Buy on bullish crossover
if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
{
BuyMarket();
}
// Sell on bearish crossover
else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
{
SellMarket();
}
prevFast = fastValue;
prevSlow = slowValue;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
}
}
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 exp2_xma_ichimoku_oscillator_strategy(Strategy):
def __init__(self):
super(exp2_xma_ichimoku_oscillator_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Source candles", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast Period", "Fast moving average length", "Indicators")
self._slow_period = self.Param("SlowPeriod", 20) \
.SetDisplay("Slow Period", "Slow moving average length", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._prev_initialized = False
@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(exp2_xma_ichimoku_oscillator_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._prev_initialized = False
def OnStarted2(self, time):
super(exp2_xma_ichimoku_oscillator_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._prev_initialized = False
fast_ma = ExponentialMovingAverage()
fast_ma.Length = self.FastPeriod
slow_ma = ExponentialMovingAverage()
slow_ma.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(fast_ma, slow_ma, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, slow_ma)
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 not self.IsFormedAndOnlineAndAllowTrading():
self._prev_fast = fv
self._prev_slow = sv
self._prev_initialized = True
return
if not self._prev_initialized:
self._prev_fast = fv
self._prev_slow = sv
self._prev_initialized = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return exp2_xma_ichimoku_oscillator_strategy()