Indikatoren: Ichimoku (Tenkan/Kijun), Linear Weighted Moving Averages, Momentum, MACD.
Stops: Optionaler fester Take-Profit und Stop-Loss in Preispunkten über StartProtection.
Strategiebeschreibung
Diese Strategie rekreiert den Entscheidungsfluss des MetaTrader-Experten „Ichimoku" (Ordner MQL/23469). Sie bewertet die vorherige geschlossene Kerze und eröffnet neue Trades zu Beginn des nächsten Balkens, wenn alle vier Bestätigungen übereinstimmen:
Ichimoku-Ausrichtung – Tenkan (Konversionslinie) muss bei Long-Trades über Kijun (Basislinie) und bei Shorts darunter liegen.
LWMA-Trendfilter – Ein schneller linear gewichteter Moving Average muss für Longs über dem langsamen LWMA und für Shorts darunter bleiben. Beide Durchschnitte werden auf demselben Zeitrahmen wie die abonnierten Kerzen berechnet.
Momentum-Stärke – Die absolute Distanz des Momentum-Oszillators vom Neutralniveau 100 muss bei mindestens einer der letzten drei geschlossenen Kerzen größer als ein konfigurierbarer Schwellenwert sein.
MACD-Bestätigung – Das MACD-Histogramm muss mit der Richtung übereinstimmen (MACD-Linie über der Signallinie mit gleichem Vorzeichen positioniert).
Wenn alle vier Bedingungen bullisch ausgerichtet sind und die Strategie derzeit nicht Long ist, kauft sie das konfigurierte Volumen plus alle Einheiten, die zum Flatten einer bestehenden Short-Position erforderlich sind. Wenn die Bedingungen auf bärisch umschlagen, spiegelt sie den Prozess auf der Verkaufsseite. Entgegengesetzte Signale schließen immer offene Positionen und bieten einen deterministischen Ausstieg auch ohne Schutzorders.
Das Risikomanagement wird durch StockSharp's StartProtection gehandhabt, was feste Take-Profit- und Stop-Loss-Abstände in Instrument-Punkten ermöglicht. Das Setzen eines Parameters auf null deaktiviert das entsprechende Schutzbein.
Parameterübersicht
Parameter
Beschreibung
FastMaPeriod
Länge des schnellen linear gewichteten Moving Average für den Trendfilter.
SlowMaPeriod
Länge des langsamen linear gewichteten Moving Average.
MomentumPeriod
Lookback-Periode des Momentum-Oszillators.
MomentumThreshold
Mindestabstand von 100, den das Momentum bei mindestens einer der letzten drei Kerzen erreichen muss.
MacdFastPeriod
Schnelle EMA-Länge des MACD-Filters.
MacdSlowPeriod
Langsame EMA-Länge des MACD-Filters.
MacdSignalPeriod
Signal-EMA-Länge des MACD-Filters.
TenkanPeriod
Ichimoku Tenkan-sen-Länge.
KijunPeriod
Ichimoku Kijun-sen-Länge.
SenkouSpanBPeriod
Ichimoku Senkou Span B-Länge.
TakeProfitPoints
Optionaler Take-Profit-Abstand in Preispunkten (0 deaktiviert).
StopLossPoints
Optionaler Stop-Loss-Abstand in Preispunkten (0 deaktiviert).
CandleType
Zeitrahmen für alle Indikatorberechnungen.
Verwendungshinweise
Die Strategie liest nur abgeschlossene Kerzen und speichert die Indikatorwerte des vorherigen Balkens, was der shift=1-Logik des MetaTrader-EA entspricht.
MomentumThreshold anpassen, wenn zu Märkten mit anderer Momentum-Skalierung gewechselt wird (z.B. Krypto vs. Forex-Paare).
Schutzorders werden intern verwaltet; Exchange-Level-Bracket-Orders werden nicht gesendet.
Charts, wenn verfügbar, zeigen Preiskerzen, beide LWMAs, die Ichimoku-Wolke und ausgeführte Trades.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class IchimokuMomentumMacdStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public IchimokuMomentumMacdStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 ichimoku_momentum_macd_strategy(Strategy):
"""
EMA crossover with SL/TP in price steps and cooldown.
"""
def __init__(self):
super(ichimoku_momentum_macd_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_momentum_macd_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(ichimoku_momentum_macd_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self._fast_period.Value
slow = ExponentialMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self._process_candle).Start()
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
fast = float(fast_val)
slow = float(slow_val)
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast
self._prev_slow = slow
return
close = float(candle.ClosePrice)
step = 1.0
if self.Security is not None and self.Security.PriceStep is not None:
step = float(self.Security.PriceStep)
if step <= 0:
step = 1.0
sl = self._stop_loss_points.Value
tp = self._take_profit_points.Value
if self.Position > 0 and self._entry_price > 0:
if sl > 0 and close <= self._entry_price - sl * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast
self._prev_slow = slow
return
if tp > 0 and close >= self._entry_price + tp * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast
self._prev_slow = slow
return
elif self.Position < 0 and self._entry_price > 0:
if sl > 0 and close >= self._entry_price + sl * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast
self._prev_slow = slow
return
if tp > 0 and close <= self._entry_price - tp * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast
self._prev_slow = slow
return
if self._prev_fast <= self._prev_slow and fast > slow and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast < slow and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return ichimoku_momentum_macd_strategy()