Auf GitHub ansehen

Strategie Cronex AC

Die Cronex-AC-Strategie bildet den klassischen Cronex Acceleration/Deceleration (AC) Experten-Advisor mit der StockSharp High-Level-API nach. Sie glättet den Accelerator Oscillator mit zwei aufeinanderfolgenden gleitenden Durchschnitten und reagiert, wenn die schnelle Linie die langsame Linie kreuzt. Bullische Crossover öffnen Long-Positionen und schließen Shorts, während bärische Crossover Shorts öffnen und Longs schließen.

Handelslogik

  1. Accelerator Oscillator (AO-AC)-Werte aus der ausgewählten Kerzenserie aufbauen.
  2. Den AC zweimal mit dem gewählten gleitenden Durchschnittstyp glätten: Die erste Glättung erzeugt die "schnelle" Linie und die zweite Glättung erzeugt die "Signal"-Linie.
  3. Die zwei Linien auf dem durch den SignalBar-Parameter definierten Balken auswerten. Die Strategie schaut auch einen Balken weiter zurück, um einen Crossover zu bestätigen.
  4. Wenn die schnelle Linie über die Signallinie kreuzt, schließt die Strategie bestehende Short-Positionen (wenn aktiviert) und öffnet eine neue Long-Position (wenn aktiviert).
  5. Wenn die schnelle Linie unter die Signallinie kreuzt, schließt die Strategie bestehende Long-Positionen (wenn aktiviert) und öffnet eine neue Short-Position (wenn aktiviert).
  6. Die Positionsgröße entspricht dem konfigurierten Volume plus dem absoluten Wert der aktuellen Position, was Umkehrungen in einer einzigen Market-Order ermöglicht.

Die Logik spiegelt den MQL5-Experten wider, indem nur vollständig abgeschlossene Kerzen benutzt und Berechtigungen für Einstiege und Ausstiege in beiden Richtungen getrennt werden.

Parameter

Name Typ Standard Beschreibung
SmoothingType CronexMovingAverageType Simple Gleitender-Durchschnitt-Algorithmus für den Accelerator Oscillator. Optionen: Simple, Exponential, Smoothed, Weighted.
FastPeriod int 14 Rückblick der ersten Glättung (schnelle Linie).
SlowPeriod int 25 Rückblick der zweiten Glättung (Signallinie).
SignalBar int 1 Anzahl abgeschlossener Balken, die beim Lesen des Signals zurückgeblickt werden. Ein Wert von 1 repliziert das Standard-Cronex-Verhalten.
CandleType DataType TimeFrame(8h) Kerzenserie für Berechnungen.
EnableLongEntry bool true Long-Positionen nach einem bullischen Crossover öffnen erlauben.
EnableShortEntry bool true Short-Positionen nach einem bärischen Crossover öffnen erlauben.
EnableLongExit bool true Long-Positionen schließen erlauben, wenn die schnelle Linie unter die langsame Linie fällt.
EnableShortExit bool true Short-Positionen schließen erlauben, wenn die schnelle Linie über die langsame Linie steigt.
Volume decimal Strategie-Standard Ordergröße für Einstiege. Die Strategie fügt automatisch den absoluten Wert der offenen Position hinzu, um in einem Trade umzukehren.

Charting

Wenn ein Diagrammbereich verfügbar ist, zeichnet die Strategie:

  • Quellkerzen für den ausgewählten Zeitrahmen,
  • Accelerator Oscillator-Werte,
  • schnelle und Signal-gleitende Durchschnitte,
  • eigene Trades der Strategie zur visuellen Validierung.

Hinweise

  • Alle Berechnungen beruhen auf abgeschlossenen Kerzen (CandleStates.Finished), um Neuzeichnung zu vermeiden.
  • Die Glättungspuffer behalten genau genug historische Werte, um den angeforderten SignalBar-Shift auszuwerten, passend zum ursprünglichen MQL-Experten.
  • Geldmanagement-Funktionen der MQL-Version (Stop-Loss, Take-Profit, Abweichung) werden absichtlich weggelassen, damit das Positionsmanagement extern über die StockSharp-Risikokontrollen verwaltet werden kann.
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 CronexAcStrategy : 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 CronexAcStrategy()
	{
		_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;
	}
}