Auf GitHub ansehen

EA-Stochastic-Strategie

High-Level-StockSharp-Port des MetaTrader-Expertenberaters "EA Stochastic". Die Strategie abonniert eine Kerzenserie, liest stochastische Oszillatorwerte und hält höchstens eine Nettoposition. Einstiege erfolgen, wenn die stochastische Hauptlinie über eine konfigurierbare Anzahl von Balken auf der gleichen Seite der konfigurierten Schwellenwerte geblieben ist. Schutzausstiege und ein Trailing Stop spiegeln die ursprüngliche MQL-Implementierung mit pip-basierten Abständen wider.

Strategie-Überblick

  • Indikator: klassischer stochastischer Oszillator (%K- und %D-Komponenten mit konfigurierbarer Glättung)
  • Richtung: Long und Short
  • Positionierung: jeweils nur eine Position (neue Trades werden ignoriert, solange eine Exit-Order aussteht)
  • Ordertyp: Marktorders mit festem Volumen
  • Daten: eine einzelne benutzerdefinierte Kerzentype (Standard: 15-Minuten-Kerzen)

Einstiegslogik

  1. Der stochastische Hauptwert wird bei jeder abgeschlossenen Kerze gespeichert.
  2. Nachdem mindestens ComparedBar Werte zwischengespeichert wurden, wird der aktuelle kValue mit dem Wert vor ComparedBar - 1 Kerzen verglichen.
  3. Long gehen, wenn beide Werte unter UpperLevel liegen. Dies entspricht dem ursprünglichen EA, der nur kauft, wenn der Oszillator für die konfigurierte Lookback-Länge unter der oberen Schwelle geblieben ist.
  4. Short gehen, wenn beide Werte über LowerLevel liegen. Der ursprüngliche EA erlaubte Shorts, wenn der Stochastik über der unteren Grenze blieb.
  5. Neue Einstiege werden übersprungen, wenn eine Position existiert oder wenn bereits ein Schutzausstieg für die aktuelle Position angefordert wurde.

Ausstieg und Risikomanagement

  • Stop-Loss: optionaler fester Pip-Abstand vom Einstandspreis. Stops werden gegen Kerzentiefs (für Longs) oder -hochs (für Shorts) bewertet.
  • Take-Profit: optionales festes Pip-Ziel. Hoch/Tief-Prüfungen emulieren das MetaTrader-orderbasierte Take-Profit-Verhalten.
  • Trailing Stop: wird aktiviert, wenn der offene Trade mehr als (TrailingStopPips + TrailingStepPips) Pips gewinnt. Der Stop wird dann TrailingStopPips hinter dem letzten Extremum platziert, wobei der Trailing-Schritt-Abstand wie beim ursprünglichen EA eingehalten wird.
  • Exit-Orders: Schließungen werden mit Marktorders ausgeführt (SellMarket / BuyMarket). Ein Schutz-Flag verhindert wiederholte Exit-Orders, bis OnPositionChanged den Flat-Zustand bestätigt.

Parameter

  • StopLossPips (Standard 50): Pip-Abstand für den anfänglichen Schutz-Stop. Auf null setzen, um zu deaktivieren.
  • TakeProfitPips (Standard 150): Pip-Abstand zur Gewinnmitnahme. Auf null setzen, um zu deaktivieren.
  • TrailingStopPips (Standard 15): Trailing-Abstand in Pips. Muss größer als null sein, wenn Trailing aktiviert ist.
  • TrailingStepPips (Standard 5): mindestens erforderlicher Pip-Fortschritt, bevor der Trailing Stop aktualisiert wird. Trailing wird abgelehnt, wenn dieser Wert null ist.
  • Volume (Standard 1): Marktorder-Volumen für Long- und Short-Trades.
  • KPeriod (Standard 5): Lookback-Länge für die stochastische %K-Linie.
  • DPeriod (Standard 3): Glättungslänge für die %D-Linie.
  • Slowing (Standard 3): abschließende Glättung auf die %K-Berechnung.
  • UpperLevel (Standard 80): Schwellenwert zur Validierung von Long-Setups.
  • LowerLevel (Standard 20): Schwellenwert zur Validierung von Short-Setups.
  • ComparedBar (Standard 3): Anzahl der zurückzublickenden Balken bei der Validierung stochastischer Niveaus (Minimum 1).
  • CandleType (Standard 15-Minuten-Kerzen): von der Strategie abonnierte Kerzenserie.

Implementierungshinweise

  • Die Pip-Größe wird aus Security.PriceStep approximiert. Für Instrumente mit Bruchteil-Pips (typische FX-Paare) werden Schritte kleiner als 0.001 automatisch mit 10 multipliziert, was die MetaTrader-digits_adjust-Logik reproduziert.
  • Die Trailing-Stop-Konfiguration wird beim Start validiert, um den ursprünglichen EA-Fehlerfall zu vermeiden (TrailingStop > 0 mit null Trailing Schritt).
  • Der StockSharp-Stochastik-Oszillator verwendet Standard-Glättungs- und Preismodi (Schlusskurs/Hoch/Tief), was den EA-Einstellungen von einfachem gleitenden Durchschnitt über Hoch/Tief-Bereichen entspricht.
  • Der ursprüngliche EA bot sowohl feste Lot- als auch Risikoprozent-Positionsgröße. Dieser Port behält den festen Volume-Parameter bei und kann erweitert werden, wenn prozentbasierte Größenbestimmung erforderlich ist.
  • Die Chartausgabe rendert die verarbeiteten Kerzen, den Stochastik-Indikator und die ausgeführten Trades für einfacheres Debugging.

Empfehlungen zur Verwendung

  • Funktioniert auf Intraday- oder höheren Zeitrahmen; CandleType und stochastische Perioden an das Instrument anpassen.
  • UpperLevel, LowerLevel und ComparedBar für verschiedene Marktregimes (Range vs. Trend) anpassen.
  • In der Live-Trading-Kombination mit broker-seitigen Risikokontrollen verwenden, da Ausstiege durch Marktorders nach Kerzenbestätigung simuliert werden.
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>
/// EA Stochastic strategy (simplified). Uses RSI as oscillator proxy.
/// </summary>
public class EaStochasticStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<decimal> _upperLevel;
	private readonly StrategyParam<decimal> _lowerLevel;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public decimal UpperLevel
	{
		get => _upperLevel.Value;
		set => _upperLevel.Value = value;
	}

	public decimal LowerLevel
	{
		get => _lowerLevel.Value;
		set => _lowerLevel.Value = value;
	}

	public EaStochasticStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Length", "RSI period", "Indicators");

		_upperLevel = Param(nameof(UpperLevel), 70m)
			.SetDisplay("Upper Level", "Overbought level", "Levels");

		_lowerLevel = Param(nameof(LowerLevel), 30m)
			.SetDisplay("Lower Level", "Oversold level", "Levels");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		decimal prevRsi = 50;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, (ICandleMessage candle, decimal rsiValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevRsi = rsiValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevRsi = rsiValue;
					return;
				}

				// Cross up from oversold
				if (prevRsi < LowerLevel && rsiValue >= LowerLevel && Position <= 0)
				{
					BuyMarket();
				}
				// Cross down from overbought
				else if (prevRsi > UpperLevel && rsiValue <= UpperLevel && Position >= 0)
				{
					SellMarket();
				}

				prevRsi = rsiValue;
			})
			.Start();

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