Auf GitHub ansehen

Cronex RSI-Strategie

Die Cronex RSI-Strategie bildet den Exp_CronexRSI.mq5 Experten-Advisor auf der StockSharp High-Level-API nach. Der Indikatorstack kombiniert einen klassischen Relative Strength Index (RSI) mit zwei sequentiellen gleitenden Durchschnitten zur Rauschreduzierung. Handelsentscheidungen basieren auf Crossovern zwischen den schnellen und langsamen geglätteten RSI-Kurven, mit konfigurierbaren Ein-/Ausstiegsberechtigungen, die den ursprünglichen MQL5-Parametern entsprechen.

Handelslogik

  1. Den RSI aus dem ausgewählten angewandten Preis und dem Rückblickzeitraum aufbauen.
  2. Den RSI-Wert mit einem schnellen gleitenden Durchschnitt glätten, dann das Ergebnis mit einem langsamen gleitenden Durchschnitt glätten.
  3. Crossover mit einem konfigurierbaren Bestätigungs-Shift auswerten:
    • Wenn die schnelle Kurve eine Bar früher über der langsamen Kurve lag und auf der bestätigten Bar darunter fällt, schließt die Strategie Short-Positionen und öffnet, wenn aktiviert, eine Long-Position.
    • Wenn die schnelle Kurve unter der langsamen Kurve lag und auf der bestätigten Bar darüber kreuzt, schließt die Strategie Longs und kann Short-Trades eingehen.
  4. Volumen sind in beiden Richtungen symmetrisch. Wenn ein neues Signal die Position umkehrt, deckt die Strategie zunächst die bestehende Exposition ab und öffnet dann die neue Seite mit dem konfigurierten Basisvolumen.

Standardmäßig wartet die Strategie auf eine vollständig geschlossene Kerze, bevor sie auf ein Signal reagiert, und reproduziert das SignalBar = 1-Verhalten von Exp_CronexRSI. Den Shift auf null setzen verarbeitet den Crossover sofort auf der Schlusskursbalk.

Parameter

Name Beschreibung
RsiPeriod RSI-Rückblickzeitraum.
FastPeriod Länge des schnellen Glättungs-Durchschnitts.
SlowPeriod Länge des zweiten Glättungs-Durchschnitts.
SignalShift Anzahl abgeschlossener Balken zur Bestätigung (0 reagiert sofort).
SmoothingMethod Gleitender-Durchschnitt-Typ während beider Glättungsstufen (einfach, exponentiell, geglättet, linear gewichtet, volumengewichtet).
AppliedPrice Preiskomponente, die an den RSI übergeben wird (Schlusskurs, Eröffnung, Hoch, Tief, Median, typisch, gewichtet).
CandleType Kerzenserie, die von der Strategie verarbeitet wird.
TradeVolume Basis-Ordergröße für neue Einstiege.
EnableLongEntry / EnableShortEntry Öffnen von Long-/Short-Positionen erlauben.
EnableLongExit / EnableShortExit Schließen von Positionen als Reaktion auf entgegengesetzte Signale erlauben.

Implementierungshinweise

  • Die Glättungsmethode verwendet StockSharp-Klassen für gleitende Durchschnitte. Die Option VolumeWeighted deckt auch die VIDYA/AMA-Stile von MQL5 ab, indem ein pragmatischer volumengewichteter Ersatz angewendet wird.
  • Die Auswahl des angewandten Preises entspricht den Cronex-Indikatoreinstellungen und spiegelt den Helfer wider, der im ursprünglichen Experten-Advisor verwendet wird.
  • Alle Indikatorwerte werden durch DecimalIndicatorValue-Instanzen verarbeitet, um mit der Indikator-Pipeline von StockSharp kompatibel zu bleiben und direktes Wert-Polling zu vermeiden.
  • Die Strategie skaliert ihren internen Verlauf automatisch, wenn sich der Bestätigungs-Shift ändert, und stellt sicher, dass die Crossover-Logik die genaue Rückblickstruktur der MQL5-Version beibehält.

Verwendung

  1. Die Strategie einem Portfolio und Wertpapier im StockSharp-Designer oder per Code zuordnen.
  2. Zeitrahmen, Glättungsstil und Handelsberechtigungen konfigurieren, um dem bevorzugten Cronex RSI-Setup zu entsprechen.
  3. Die Strategie starten. Sie abonniert die ausgewählte Kerzenserie, aktualisiert die RSI/MA-Kombination und sendet Market-Orders bei bestätigten Crossovern.
  4. Die integrierten Diagramm-Helfer verwenden, um Indikator-Kurven und ausgeführte Trades zur weiteren Validierung zu visualisieren.
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;

public class CronexRsiStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public CronexRsiStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}