Auf GitHub ansehen

Ichimoku Kumo-Ausbruch

Strategie basierend auf dem Ichimoku-Kumo (Wolken)-Ausbruch.

Tests zeigen eine durchschnittliche jährliche Rendite von etwa 70%. Die Strategie funktioniert am besten im Aktienmarkt.

Dieser Ansatz stützt sich auf Ichimoku-Wolkensignale. Ein Preisausbruch über die Wolke mit Tenkan-sen, das Kijun-sen kreuzt, löst einen Kauf aus, während der entgegengesetzte Ausbruch unter die Wolke einen Short startet. Positionen werden gehalten, bis der Preis durch die Wolke zurückkehrt.

Die Wolke skizziert wichtige Unterstützungs- und Widerstandsniveaus, daher wartet das System auf entscheidende Schlusskurse über sie hinaus. Durch die Kombination mehrerer Ichimoku-Komponenten vermeidet die Strategie Trades mit geringerer Wahrscheinlichkeit während seitwärts laufender Märkte.

Details

  • Einstiegskriterien: Signale basierend auf Ichimoku.
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien: Gegensätzliches Signal.
  • Stops: Nein.
  • Standardwerte:
    • TenkanPeriod = 9
    • KijunPeriod = 26
    • SenkouSpanPeriod = 52
    • CandleType = TimeSpan.FromMinutes(15)
  • Filter:
    • Kategorie: Ausbruch
    • Richtung: Beide
    • Indikatoren: Ichimoku
    • Stops: Nein
    • Komplexität: Grundlegend
    • Zeitrahmen: Intraday (15m)
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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;

/// <summary>
/// Strategy based on Ichimoku Kumo (cloud) breakout.
/// Trades on Tenkan/Kijun crosses with cloud confirmation.
/// </summary>
public class IchimokuKumoBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _tenkanPeriod;
	private readonly StrategyParam<int> _kijunPeriod;
	private readonly StrategyParam<int> _senkouSpanPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private bool _prevTenkanAboveKijun;
	private bool _hasPrevValues;
	private int _candlesSinceLastTrade;

	/// <summary>
	/// Period for Tenkan-sen line.
	/// </summary>
	public int TenkanPeriod
	{
		get => _tenkanPeriod.Value;
		set => _tenkanPeriod.Value = value;
	}

	/// <summary>
	/// Period for Kijun-sen line.
	/// </summary>
	public int KijunPeriod
	{
		get => _kijunPeriod.Value;
		set => _kijunPeriod.Value = value;
	}

	/// <summary>
	/// Period for Senkou Span B.
	/// </summary>
	public int SenkouSpanPeriod
	{
		get => _senkouSpanPeriod.Value;
		set => _senkouSpanPeriod.Value = value;
	}

	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initialize the Ichimoku Kumo Breakout strategy.
	/// </summary>
	public IchimokuKumoBreakoutStrategy()
	{
		_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
			.SetDisplay("Tenkan-sen Period", "Period for Tenkan-sen line", "Indicators")
			.SetOptimize(7, 13, 2);

		_kijunPeriod = Param(nameof(KijunPeriod), 26)
			.SetDisplay("Kijun-sen Period", "Period for Kijun-sen line", "Indicators")
			.SetOptimize(20, 30, 2);

		_senkouSpanPeriod = Param(nameof(SenkouSpanPeriod), 52)
			.SetDisplay("Senkou Span B Period", "Period for Senkou Span B", "Indicators")
			.SetOptimize(40, 60, 4);

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevTenkanAboveKijun = default;
		_hasPrevValues = default;
		_candlesSinceLastTrade = default;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var tenkan = new Highest { Length = TenkanPeriod };
		var tenkanLow = new Lowest { Length = TenkanPeriod };
		var kijun = new Highest { Length = KijunPeriod };
		var kijunLow = new Lowest { Length = KijunPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(tenkan, tenkanLow, kijun, kijunLow, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal tenkanHigh, decimal tenkanLow, decimal kijunHigh, decimal kijunLow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var tenkan = (tenkanHigh + tenkanLow) / 2m;
		var kijun = (kijunHigh + kijunLow) / 2m;

		if (tenkan == 0 || kijun == 0)
			return;

		var tenkanAboveKijun = tenkan > kijun;

		_candlesSinceLastTrade++;

		if (!_hasPrevValues)
		{
			_hasPrevValues = true;
			_prevTenkanAboveKijun = tenkanAboveKijun;
			return;
		}

		// Detect cross
		var isCross = tenkanAboveKijun != _prevTenkanAboveKijun;
		_prevTenkanAboveKijun = tenkanAboveKijun;

		if (!isCross)
			return;

		// Cooldown to avoid too many trades
		if (_candlesSinceLastTrade < 4)
			return;

		if (tenkanAboveKijun && Position <= 0)
		{
			BuyMarket();
			_candlesSinceLastTrade = 0;
		}
		else if (!tenkanAboveKijun && Position >= 0)
		{
			SellMarket();
			_candlesSinceLastTrade = 0;
		}
	}
}