Auf GitHub ansehen

Hammer und hängender Mann mit CCI-Bestätigung

Diese Strategie implementiert den Experten MetaTrader „AH HM CCI“ in StockSharp erneut. Es achtet auf Hammer und hängenden Kerzenleuchter Muster und erfordert eine Bestätigung durch den Commodity Channel Index (CCI), bevor ein Handel abgeschlossen wird. Die zusätzlichen Bestätigungsfilter erkennt schwache Muster und hilft dabei, Einträge an der durch CCI signalisierten Momentumverschiebung auszurichten.

Die Logik läuft nur auf abgeschlossenen Kerzen und verwendet einen kurzen einfachen gleitenden Durchschnitt (SMA), um den vorherrschenden Trend zu definieren. Der Vorherige Kerze muss ein Hammer in einem Abwärtstrend mit überverkauftem CCI zum Kaufen oder ein hängender Mann in einem Aufwärtstrend mit überkauftem CCI zum Verkauf sein. Ausgänge werden verwaltet, wenn CCI konfigurierbare Auslöseschwellen überschreitet, wodurch die abstimmungsbasierte Exit-Logik des ursprünglichen Experten repliziert wird.

Handelslogik

  1. Trendfilter – Der Mittelpunkt der vorherigen Kerze muss unter (für Long-Positionen) oder über (für Short-Positionen) einem berechneten Wert von SMA liegen Schlusskurse. Dies ahmt die Trendprüfung des gleitenden Durchschnitts des ursprünglichen Assistenten nach.
  2. Mustererkennung – Die Strategie wertet den vorherigen Balken aus und prüft:
    • Körper vollständig im oberen Drittel des Kerzenbereichs.
    • Lücke zwischen dem Öffnen/Schließen der vorherigen Kerze und der Kerze davor.
    • Richtungskontext (Hammer für einen Abwärtstrend, hängender Mann für einen Aufwärtstrend).
  3. CCI-Bestätigung – Der CCI des vorherigen Balkens muss unter dem Long-Schwellenwert oder über dem Short-Schwellenwert liegen. Die Standardwerte entsprechen der Vorlage MetaTrader (40 für Long-Positionen und 60 für Short-Positionen).
  4. Positionsausstiege – Bestehende Positionen werden geschlossen, wenn CCI entweder die untere oder obere Ausstiegsschwelle überschreitet. Überquerung von unten schließt Longs; Überqueren von oben schließt Shorts.

Parameter

Name Beschreibung Standard
CandleType Kerzentyp und Zeitrahmen, die zur Mustererkennung verwendet werden. TimeSpan.FromMinutes(15)
CciPeriod Anzahl der vom Commodity Channel Index verwendeten Balken. 11
MaPeriod Anzahl der Balken im Trendfilter SMA. 5
LongConfirmationThreshold Maximal zulässiger CCI-Wert für ein Hammersignal. 40
ShortConfirmationThreshold Zulässiger Mindestwert CCI für ein Hängender-Mann-Signal. 60
ExitUpperThreshold CCI-Ebene, die nach einem Aufwärtsübergang Ausstiege auslöst. 70
ExitLowerThreshold Sekundäre Ausstiegsebene für Frühsignale. 30

Alle Parameter stehen zur Optimierung zur Verfügung. Die Schwellenwerte akzeptieren negative Werte, sodass Sie die Strategie an andere anpassen können Märkte oder Lärmpegel durch Anziehen oder Lösen der Filter anpassen.

Orderverwaltung

  • Bei Eingaben werden Marktaufträge mit einer Größe von Volume + |Position| verwendet, um sicherzustellen, dass Umkehrungen in einem einzigen Trade ausgeführt werden.
  • Ausgänge verlassen sich ausschließlich auf die CCI-Kreuze, um in der Nähe des MetaTrader-Experten zu bleiben. Fügen Sie bei Bedarf StartProtection Anrufe hinzu explizite Stop-Loss- oder Take-Profit-Level.

Nutzungstipps

  • Wenden Sie die Strategie auf liquide Instrumente an, bei denen Candlestick-Gaps und -Tails informativ sind.
  • Experimentieren Sie mit längeren CciPeriod- und MaPeriod-Werten, um Störungen beim Handel mit höheren Zeitrahmen auszugleichen.
  • Eine Senkung von LongConfirmationThreshold oder eine Erhöhung von ShortConfirmationThreshold verringert die Anzahl der Trades, verbessert sich jedoch Selektivität.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Hammer/Hanging Man + CCI strategy.
/// Buys on hammer with negative CCI, sells on hanging man with positive CCI.
/// </summary>
public class HammerHangingManCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _cciLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public HammerHangingManCciStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_cciLevel = Param(nameof(CciLevel), 100m)
			.SetDisplay("CCI Level", "CCI threshold", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candlesSinceTrade = SignalCooldownCandles;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal cciValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		var range = candle.HighPrice - candle.LowPrice;
		if (range <= 0 || body <= 0) return;

		var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
		var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;

		var isHammer = lowerShadow > body * 2.5m && upperShadow < body * 0.5m;
		var isHangingMan = upperShadow > body * 2.5m && lowerShadow < body * 0.5m;

		if (isHammer && cciValue < -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			BuyMarket();
			_candlesSinceTrade = 0;
		}
		else if (isHangingMan && cciValue > CciLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			SellMarket();
			_candlesSinceTrade = 0;
		}
	}
}