Auf GitHub ansehen

Ichimoku Momentum MACD-Strategie

Zusammenfassung

  • Typ: Trendfolge mit Momentum-Bestätigung.
  • Zeitrahmen: Konfigurierbar (Standard 15-Minuten-Kerzen).
  • 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 re­kreiert 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:

  1. Ichimoku-Ausrichtung – Tenkan (Konversionslinie) muss bei Long-Trades über Kijun (Basislinie) und bei Shorts darunter liegen.
  2. 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.
  3. 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.
  4. 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;
	}
}