Auf GitHub ansehen

CCIT3 Zero Cross-Strategie

Überblick

Die CCIT3 Zero Cross-Strategie ist eine StockSharp-Portierung des MetaTrader 5-Expertenberaters, der Nulllinienumkehrungen des CCIT3-Oszillators handelt. Der Indikator wird durch Anwendung der Tillson T3-Glättungskette auf einen Commodity Channel Index (CCI) erstellt. Immer wenn der geglättete Oszillator das Vorzeichen wechselt, öffnet die Strategie entweder eine neue Position in der Umkehrrichtung oder schließt, sofern konfiguriert, die aktuelle Position und kehrt sie um.

Handelslogik

  • Berechnen Sie den CCI anhand des ausgewählten angewendeten Preises und Zeitraums.
  • Glätten Sie den Oszillator mit einer Tillson T3-Pipeline. Es stehen zwei Berechnungsmodi zur Verfügung:
    • Einfach – dauerhafte sechsstufige Glättung, die sich wie der ursprüngliche neu berechnende MetaTrader-Indikator verhält.
    • NoRecalc – wertet das T3-Polynom nur für den aktuellsten Balken aus und erstellt die vereinfachte Version „ohne Neuberechnung“ aus dem Quellcode neu.
  • Wenn der CCIT3-Wert von positiv auf negativ übergeht, eröffnen Sie eine Long-Position (oder kehren Sie eine Short-Position um, wenn Trade Overturn aktiviert ist).
  • Wenn der CCIT3-Wert von negativ auf positiv übergeht, eröffnen Sie eine Short-Position (oder kehren Sie eine Long-Position um, wenn Trade Overturn aktiviert ist).
  • Optionale Take-Profit-, Stop-Loss- und Trailing-Stop-Levels werden über den StartProtection-Helper von StockSharp verwaltet.

Indikatoren und Berechnungen

  • Commodity Channel Index (CCI) – läuft auf dem konfigurierbaren angewandten Preis (Schluss, Eröffnung, Hoch, Tief, Median, typisch, gewichtet) und Zeitraum.
  • Tillson T3-Glättung – genau wie im MQL5-Indikator mit dem Volumenfaktor B implementiert. Der einfache Modus behält zustandsbehaftete EMA-Ketten über Balken hinweg bei, während NoRecalc das Polynom aus dem letzten rohen CCI-Wert neu berechnet.
  • Nulldurchgangserkennung – Trades werden ausschließlich bei abgeschlossenen Kerzen ausgelöst und spiegeln die ursprünglichen Überprüfungen neuer Balken im Expert Advisor wider.

Risiko- und Positionsmanagement

  • Take Profit (pts) und Stop Loss (pts) werden mithilfe des PriceStep des Instruments in absolute Preisabstände umgewandelt.
  • Trailing Stop (pts) aktiviert die nachlaufende Engine von StockSharp mit demselben Punktabstand.
  • Max Drawdown Target skaliert das Basisauftragsvolumen anhand des aktuellen oder anfänglichen Portfoliowerts (volume = OrderVolume * balance / target) neu. Lassen Sie den Parameter auf Null, um eine feste Losgröße beizubehalten.
  • Trade Overturn ermöglicht eine vollständige Umkehrung – zuerst wird die aktuelle Position geschlossen und dann eine neue in die entgegengesetzte Richtung eröffnet.

Parameter

Name Standard Beschreibung
Volume 1 Basis-Ordervolumen vor etwaiger Drawdown-Skalierung.
Take Profit (pts) 1750 Take-Profit-Distanz in Punkten.
Stop Loss (pts) 0 Stop-Loss-Distanz in Punkten.
Trailing Stop (pts) 0 Trailing-Stop-Distanz in Punkten (0 deaktiviert das Trailing).
Trade Overturn falsch Kehren Sie die Position bei entgegengesetzten CCIT3-Signalen um.
CCI Period 285 Lookback-Zeitraum für den Indikator CCI.
CCI Price Typisch Angewendeter Preis für die Fütterung von CCI.
T3 Period 60 Tillson T3 Glättungslänge.
T3 Volume Factor 0,618 Tillson T3 B-Koeffizient.
Mode Einfach CCIT3-Berechnungsmodus (Simple oder NoRecalc).
Candle Type Zeitrahmen 1 Stunde Für Kerzenabonnements verwendeter Zeitrahmen.
Max Drawdown Target 0 Balance-Divisor für die adaptive Volumengröße (0 deaktiviert die Skalierung).

Hinweise zur Implementierung

  • Die Strategie abonniert eine durch Candle Type angegebene einzelne Kerzenquelle und verarbeitet nur abgeschlossene Kerzen.
  • Alle Volumenwerte sind an der Volumenstufe des Wertpapiers ausgerichtet und durch VolumeMin/VolumeMax begrenzt.
  • Die Standardparameter replizieren die veröffentlichte MT5-Konfiguration: CCIT3-Einfachmodus mit einem 285-Perioden-CCI, einer T3-Länge von 60 und einem Volumenfaktor von 0,618.
  • Durch den Wechsel zu NoRecalc bleibt das Verhalten des ursprünglichen Indikators erhalten, der sofort auf das rohe CCI-Zeichen reagiert und gleichzeitig weiterhin positive/negative Signale erzeugt.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// CCIT3 Zero Cross: EMA crossover with RSI filter and ATR stops.
/// </summary>
public class Ccit3ZeroCrossStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

	public Ccit3ZeroCrossStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 9)
			.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 21)
			.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
	public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
		var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, rsi, atr, 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 fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevFast = fastVal; _prevSlow = slowVal;
	}
}