Auf GitHub ansehen

Strategie Expert ADC PL Stoch Strategy

Überblick

Die Expert ADC PL Stoch Strategy ist eine Candlestick-Muster-Strategie, die vom ursprünglichen MQL5 Expert Advisor Expert_ADC_PL_Stoch umgewandelt wurde. Es sucht nach bullischen Piercing Line- und bärischen Dark Cloud Cover-Formationen auf fertigen Kerzen und bestätigt die Signale mit der %D-Linie eines Stochastic-Oszillators. The method is trend-following when the market retraces into an established move and requires the oscillator to be in extreme zones before opening positions. Positionsausstiege basieren auf Stochastic-Übergängen aus extremen Bereichen und spiegeln die abstimmungsbasierte Ausstiegslogik des Quellsystems wider.

Handelslogik

  1. Subscribe to a configurable candle type (default: 1-hour time frame).
  2. Behalten Sie für jede fertige Kerze die letzten Kerzen bei, die für die Auswertung des Candlestick-Musters benötigt werden, und die aktuellen Stochastic %D-Werte.
  3. Long Entry
    • The previous candle pair must form a Piercing Line pattern:
      • Die Kerze am Balken t-1 ist bullisch mit einem Körper, der größer als die durchschnittliche Körpergröße ist.
      • Die Kerze am Balken t-2 ist bärisch mit einem Körper, der über dem Durchschnitt liegt.
      • Die zinsbullische Kerze klafft unterhalb des bärischen Tiefs und schließt wieder innerhalb des bärischen Körpers, während der Gesamttrend gemäß dem Schlussdurchschnitt abwärtsgerichtet ist.
    • Der Stochastic %D-Wert auf Balken t-1 muss unter dem Schwellenwert für den langen Einstieg liegen (Standard 30).
  4. Short Entry
    • Das vorherige Kerzenpaar muss ein Dark Cloud Cover-Muster bilden:
      • Die Kerze am Balken t-2 ist bullisch mit einem großen Körper.
      • Die Kerze bei Balken t-1 öffnet über dem vorherigen Hoch und schließt wieder innerhalb des bullischen Körpers.
      • Der mittlere Preis der rückläufigen Kerze liegt über dem gleitenden Durchschnitt der Schlusskurse, was einen Aufwärtstrend vor der Umkehr signalisiert.
    • Der Stochastic %D auf Balken t-1 muss über dem Short-Entry-Schwellenwert liegen (Standard 70).
  5. Exit Conditions
    • Long positions are closed when the Stochastic %D on bar t-1 crosses below either the upper (80) or lower (20) thresholds compared with bar t-2.
    • Short-Positionen werden geschlossen, wenn der Stochastic %D auf Balken t-1 entweder den unteren (20) oder oberen (80) Schwellenwert im Vergleich zu Balken t-2 überschreitet.
  6. Alle Berechnungen werden an fertigen Kerzen durchgeführt; Es wird keine Intrabar-Verarbeitung verwendet.

Parameter

Name Beschreibung Standard
CandleType Zeitrahmen der zur Mustererkennung verwendeten Kerzen. 1 Stunde
StochasticLength Basislänge für den Stochastic-Oszillator. 47
StochasticKPeriod Glättungslänge für die %K-Linie. 9
StochasticDPeriod Glättungslänge für die %D-Linie. 13
StochasticSlow Zusätzlicher Verlangsamungsfaktor, der auf den Oszillator angewendet wird. 3
AverageBodyPeriod Number of candles used to measure the reference body size and close average. 5
LongEntryThreshold Maximal zulässiger %D-Wert vor dem Einstieg in Long-Trades. 30
ShortEntryThreshold Vor dem Eingehen von Short-Trades ist ein Mindestwert von %D erforderlich. 70
ExitLowerThreshold Untere Grenze, die für Ausgangskreuzungen verwendet wird. 20
ExitUpperThreshold Upper boundary used for exit crossovers. 80

Risikomanagement

  • Die Strategie sendet Marktaufträge unter Verwendung des Basisstrategievolumens (Standard 1 Kontrakt/Lot).
  • No automatic protective orders are configured; external risk management or StartProtection can be added if needed.
  • Es wird jeweils nur eine Position verwaltet; Gegensignale schließen die aktive Position, bevor sie eine neue eröffnen.

Notizen

  • Durchschnittliche Kerzenkörper und Schlussdurchschnitte werden aus historischen Kerzen berechnet, um die MQL5-Abstimmungslogik genau nachzubilden.
  • Stochastic-Werte werden pro fertigem Balken gespeichert, um die gleichen Offsets auszuwerten, die im ursprünglichen Expert Advisor verwendet wurden.
  • Trades werden erst dann eröffnet und geschlossen, wenn die Strategie vollständig ausgearbeitet ist und der Handel durch die Basisklassenprüfungen zulässig ist.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Expert ADC PL Stoch strategy: Dark Cloud Cover and Piercing Line patterns
/// with Stochastic oscillator confirmation for entries and exits.
/// </summary>
public class ExpertAdcPlStochStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _stochPeriod;
	private readonly StrategyParam<decimal> _longThreshold;
	private readonly StrategyParam<decimal> _shortThreshold;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevSignal;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int StochPeriod { get => _stochPeriod.Value; set => _stochPeriod.Value = value; }
	public decimal LongThreshold { get => _longThreshold.Value; set => _longThreshold.Value = value; }
	public decimal ShortThreshold { get => _shortThreshold.Value; set => _shortThreshold.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public ExpertAdcPlStochStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_stochPeriod = Param(nameof(StochPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Stoch Period", "Stochastic period", "Indicators");
		_longThreshold = Param(nameof(LongThreshold), 30m)
			.SetDisplay("Long Threshold", "Stochastic below this for long", "Signals");
		_shortThreshold = Param(nameof(ShortThreshold), 70m)
			.SetDisplay("Short Threshold", "Stochastic above this for short", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevSignal = 0m;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_candlesSinceTrade = SignalCooldownCandles;
		var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(stoch, ProcessCandle).Start();

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var stochTyped = stochValue as StochasticOscillatorValue;
		if (stochTyped?.K is not decimal kValue) return;

		_candles.Add(candle);
		if (_candles.Count > 10)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			// Piercing Line: bearish prev + bullish curr that closes above prev midpoint
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover: bullish prev + bearish curr that closes below prev midpoint
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && kValue < LongThreshold && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && kValue > ShortThreshold && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevSignal = kValue;
	}
}