Auf GitHub ansehen

Auto KD Crossover-Strategie

Überblick

Die Auto KD Crossover-Strategie repliziert das ursprüngliche MQL5-Beispiel autoKD_EA.
Sie verwendet den StochasticOscillator-Indikator, um Kauf- und Verkaufssignale basierend auf Kreuzungen der %K- und %D-Linien zu generieren.

Die Basisberechnung verwendet die RSV-Formel: RSV = (Close - LowestLow) / (HighestHigh - LowestLow) * 100 wobei das höchste Hoch und das niedrigste Tief über KDPeriod Balken berechnet werden.
Die %K-Linie ist ein gleitender Durchschnitt des RSV mit Länge KPeriod; %D ist ein gleitender Durchschnitt von %K mit Länge DPeriod.

Parameter

Name Beschreibung Standard
KDPeriod Anzahl der Balken für die RSV-Basisperiode. 30
KPeriod Glättungsperiode für die %K-Linie. 3
DPeriod Glättungsperiode für die %D-Linie. 6
CandleType Typ und Zeitrahmen der für Berechnungen verwendeten Kerzen. 5-Minuten-Zeitrahmen
Volume Von Strategy vererbtes Order-Volumen. Strategy.Volume

Alle Parameter sind für die Optimierung verfügbar.

Handelslogik

  1. Abonnieren der ausgewählten Kerzenserie und Berechnen des Stochastik-Oszillators.
  2. Wenn der vorherige Wert von %K unter %D lag und der aktuelle %K über %D kreuzt, wird eine Long-Position eröffnet.
  3. Wenn der vorherige Wert von %K über %D lag und der aktuelle %K unter %D kreuzt, wird eine Short-Position eröffnet.
  4. Die Strategie hält jeweils nur eine Position. Kreuzungen in der entgegengesetzten Richtung schließen die Position und öffnen die entgegengesetzte Seite.
  5. StartProtection() aktiviert die von StockSharp bereitgestellten Standard-Verlust-/Gewinnschutzmechanismen.

Visualisierung

Die Strategie zeigt automatisch Kerzen, den Stochastik-Indikator und ausgeführte Trades im Chart an.

Hinweise

  • Funktioniert mit jedem Instrument und Zeitrahmen.
  • Parameter sollten an die Volatilität des ausgewählten Marktes angepasst werden.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on %K and %D crossover from the Stochastic oscillator.
/// </summary>
public class AutoKdStrategy : Strategy
{
	private readonly StrategyParam<int> _kdPeriod;
	private readonly StrategyParam<int> _kPeriod;
	private readonly StrategyParam<int> _dPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevK;
	private decimal? _prevD;

	/// <summary>
	/// Lookback period for RSV calculation.
	/// </summary>
	public int KdPeriod
	{
		get => _kdPeriod.Value;
		set => _kdPeriod.Value = value;
	}

	/// <summary>
	/// Smoothing period for %K.
	/// </summary>
	public int KPeriod
	{
		get => _kPeriod.Value;
		set => _kPeriod.Value = value;
	}

	/// <summary>
	/// Smoothing period for %D.
	/// </summary>
	public int DPeriod
	{
		get => _dPeriod.Value;
		set => _dPeriod.Value = value;
	}

	/// <summary>
	/// Type of candles used by the strategy.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="AutoKdStrategy"/>.
	/// </summary>
	public AutoKdStrategy()
	{
		_kdPeriod = Param(nameof(KdPeriod), 30)
		.SetGreaterThanZero()
		.SetDisplay("KD Period", "Base period for RSV", "Parameters")
		
		.SetOptimize(10, 60, 5);

		_kPeriod = Param(nameof(KPeriod), 3)
		.SetGreaterThanZero()
		.SetDisplay("K Period", "%K smoothing", "Parameters")
		
		.SetOptimize(1, 10, 1);

		_dPeriod = Param(nameof(DPeriod), 6)
		.SetGreaterThanZero()
		.SetDisplay("D Period", "%D smoothing", "Parameters")
		
		.SetOptimize(1, 10, 1);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
		.SetDisplay("Candle Type", "Timeframe for analysis", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevK = null;
		_prevD = null;
	}

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

		var stochastic = new StochasticOscillator();
		stochastic.K.Length = KdPeriod;
		stochastic.D.Length = DPeriod;

		var subscription = SubscribeCandles(CandleType);
		subscription
		.BindEx(stochastic, ProcessCandle)
		.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		return;

		var stoch = (StochasticOscillatorValue)stochValue;
		if (stoch.K is not decimal k || stoch.D is not decimal d)
			return;

		if (_prevK is decimal prevK && _prevD is decimal prevD)
		{
			if (prevK < prevD && k > d && Math.Min(prevK, k) < 30m && Position <= 0)
				BuyMarket(Volume + Math.Abs(Position));
			else if (prevK > prevD && k < d && Math.Max(prevK, k) > 70m && Position >= 0)
				SellMarket(Volume + Math.Abs(Position));
		}

		_prevK = k;
		_prevD = d;
	}
}