Auf GitHub ansehen

Holen Sie sich die trendige Stochastic-Strategie

Die Strategie ist eine StockSharp High-Level-Portierung des MetaTrader 4 Expert Advisors Get trend.mq4. Es wertet das M15-Diagramm aus Einträge, validiert den breiteren Trend im ersten Halbjahr und stützt sich auf zwei geglättete gleitende Durchschnitte zusammen mit einem Paar stochastischer Werte Oszillatoren zur Erkennung von Mean-Reversion-Ausbrüchen in der Nähe des längerfristigen Trends. Die Implementierung behält die ursprüngliche Geldverwaltung bei Regeln, die auf festen Take-Profit-, Stop-Loss- und Trailing-Stop-Abständen basieren, ausgedrückt in Preispunkten.

Handelslogik

  1. Indikatoren und Daten
    • M15-Kerzen speisen einen geglätteten gleitenden Durchschnitt (SMMA, Medianpreis) mit der Periode M15MaPeriod und zwei stochastischen Oszillatoren.
    • H1-Kerzen versorgen einen weiteren SMMA (Medianpreis) mit der Periode H1MaPeriod.
    • Die schnelle Stochastik (FastStochasticPeriod, 3, 3) liefert die %K-Linie und ihren vorherigen Wert. Die langsame Stochastik (SlowStochasticPeriod, 3, 3) liefert die %D-Signalleitung.
  2. Lange Einrichtung
    • Der aktuelle M15-Schlusskurs liegt unter seinem SMMA und der H1-Schlusskurs liegt unter seinem eigenen SMMA.
    • Der Abstand zwischen dem M15 SMMA und dem Schlusskurs liegt innerhalb von ThresholdPoints Preisschritten.
    • Beide stochastischen Linien liegen unter 20. Die schnelle Linie kreuzt während der letzten Kerze die langsame Linie (fast > slow, während der vorherige schnelle Wert unter slow lag).
    • Wenn eine Short-Position besteht, kauft die Strategie zunächst genug Volumen, um diese zu glätten, und eröffnet dann eine neue Long-Position mit TradeVolume.
  3. Kurzer Aufbau spiegelt die lange Logik wider:
    • Beide Schlusskurse liegen über ihren SMMAs, der Abstand liegt innerhalb von ThresholdPoints, die stochastischen Werte liegen über 80 und der schnelle Linie kreuzt unterhalb der langsamen Linie. Die Strategie verkauft und schließt bei Bedarf eine bestehende Long-Position.
  4. Risikomanagement
    • Nach jeder Eingabe werden Schutzaufträge zu StopLossPoints und TakeProfitPoints (umgerechnet in einen absoluten Preis) platziert Entfernungen anhand der Preisstufe des Instruments).
    • Ein Trailing Stop richtet die Stop-Loss-Order neu aus, sobald der Trade mindestens TrailingStopPoints Punkte erreicht. Die neue Haltestelle ist positioniert am aktuellen Schlusskurs minus/plus der Nachlaufdistanz für Longs/Shorts.
    • Wenn die Position wieder flach ist, werden alle Schutzaufträge storniert.

Unterschiede zum Original EA

  • Der SMMA von MetaTrader verwendet eine Indikatorverschiebung von acht Balken; StockSharp-Indikatoren machen keine direkte Verschiebungseinstellung verfügbar. Der Hafen wertet stattdessen den aktuellsten Endwert aus. Dadurch wird das Crossover-Timing beibehalten und gleichzeitig zusätzliche benutzerdefinierte Puffer vermieden.
  • Der ursprüngliche EA verwendete die Bid/Ask-Kurse von MQL für den Schluss. Der Port verwendet den abgeschlossenen Kerzenschluss, der das Trailing ausgelöst hat Update, das dem nächsten verfügbaren Analogon im High-Level API entspricht.
  • Die Geldverwaltung stützt sich stattdessen auf die Auftragsregistrierungshilfen von StockSharp (BuyMarket, SellMarket, SellStop usw.). OrderSend und OrderModify.

Parameter

Gruppe Name Beschreibung Standard
Daten M15 Candle Type Kerzentyp/Zeitrahmen, der für die Hauptberechnungen verwendet wird. Zeitrahmen M15
Daten H1 Candle Type Kerzentyp/Zeitrahmen, der zur Bestätigung verwendet wird. H1-Zeitrahmen
Indikatoren M15 SMMA Period Länge des geglätteten gleitenden Durchschnitts der M15-Serie. 200
Indikatoren H1 SMMA Period Länge des geglätteten gleitenden Durchschnitts der H1-Serie. 200
Indikatoren Slow Stochastic Period %K-Länge für den langsamen stochastischen Oszillator, der die %D-Linie bereitstellt. 14
Indikatoren Fast Stochastic Period %K-Länge für den schnellen stochastischen Oszillator, der die %K-Hauptleitung bereitstellt. 14
Signale Threshold (points) Maximaler Abstand zwischen dem M15 SMMA und dem aktuellen Nahbereich, um Eingaben zu ermöglichen. 50
Risiko Take Profit (points) Take-Profit-Distanz, ausgedrückt in Preisschritten. 570
Risiko Stop Loss (points) Stop-Loss-Distanz ausgedrückt in Preisschritten. 30
Risiko Trailing Stop (points) Trailing-Stop-Distanz, ausgedrückt in Preisschritten. 200
Handel Trade Volume Mit jeder Marktorder gesendetes Volumen. 0,1

Hinweise zur Nutzung

  • Stellen Sie sicher, dass das gehandelte Wertpapier PriceStep offenlegt; Andernfalls fallen die punktbasierten Abstände auf 1 zurück, was zu großen Entfernungen führen kann Schutzanordnungen für Instrumente, die in Bruchteilen notiert sind.
  • Die Strategie storniert Stop-Orders und erstellt sie neu, sobald ein besseres Trailing-Level erkannt wird. Makler, die häufiges verbieten Änderungen erfordern möglicherweise eine Drosselung.
  • Da der Port nur mit fertigen Kerzen arbeitet, ist das System für Backtests und die Ausführung am Ende des Balkens konzipiert. Läuft weiter Live-Tick-Daten erfordern den Abgleich der Kerzenaufbaueinstellungen zwischen dem Terminal und StockSharp.
using System;

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

namespace StockSharp.Samples.Strategies;

public class GetTrendStochasticStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GetTrendStochasticStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetDisplay("RSI Period", "RSI lookback", "Indicators");
		_emaPeriod = Param(nameof(EmaPeriod), 20).SetDisplay("EMA Period", "EMA filter", "Indicators");
		_oversold = Param(nameof(Oversold), 35m).SetDisplay("Oversold", "RSI oversold level", "Levels");
		_overbought = Param(nameof(Overbought), 65m).SetDisplay("Overbought", "RSI overbought level", "Levels");
		_cooldownCandles = Param(nameof(CooldownCandles), 30).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal ema)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (!_hasPrev) { _prevRsi = rsi; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevRsi = rsi;
			return;
		}

		if (_prevRsi <= Oversold && rsi > Oversold && close > ema && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevRsi >= Overbought && rsi < Overbought && close < ema && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevRsi = rsi;
	}
}