Auf GitHub ansehen

Back Kick-Strategie

Die Back Kick-Strategie ist ein gehedgtes Ausbruchssystem, das vom MetaTrader 5-Expertenberater Back kick.mq5 konvertiert wurde. Sie hält kontinuierlich ein zweiseitiges Exposure aufrecht, indem sie beim Schließen jeder Bar sowohl eine Long- als auch eine Short-Marktposition eröffnet. Jedes Bein ist mit symmetrischen Stop-Loss- und Take-Profit-Distanzen in Pips geschützt. Der StockSharp-Port hält die gepaartePositionen unabhängig, indem er deren Zustand manuell verfolgt, anstatt sich auf die aggregierte Nettoposition zu stützen.

Trading-Logik

  1. Den konfigurierten Zeitrahmen-Kerzen abonnieren. Wenn eine Kerze schließt und keine aktiven gehedgten Beine vorhanden sind, ein neues Eintrittspaar anfordern.
  2. Sofort eine Market-Buy- und eine Market-Sell-Order mit demselben Volumen einreichen. Jedes Bein behält seine eigenen Stop-Loss- und Take-Profit-Abstände bei, die aus Pip-Distanzen konvertiert wurden.
  3. Die besten Geld/Brief-Preise aus Level-1-Daten überwachen. Wenn ein Bein seinen Schutzpreis erreicht, wird es mit einer Market-Order geschlossen, während das gegenüberliegende Bein aktiv bleibt, bis sein eigener Ausstieg ausgelöst wird.
  4. Nachdem beide Beine flat sind, wartet die Strategie auf die nächste abgeschlossene Kerze, bevor die Hedge neu erstellt wird.

Dieses Verhalten spiegelt den ursprünglichen Experten wider, der ständig in beide Richtungen wieder einsteigt, um abrupte Preis-"Kicks" zu erfassen.

Parameter

Name Beschreibung Standard Hinweise
OrderVolume Volumen für jedes Hedge-Bein. 0.1 Auf den VolumeStep des Instruments normalisiert, muss MinVolume/MaxVolume einhalten.
StopLossPips Stop-Loss-Distanz in Pips. 50 Auf 0 setzen, um den Schutz-Stop für beide Beine zu deaktivieren.
TakeProfitPips Take-Profit-Distanz in Pips. 140 Auf 0 setzen, um den Schutz-Take-Profit zu deaktivieren.
CandleType Zeitrahmen, der neue gehedgte Paare auslöst. 15m Akzeptiert jeden TimeFrame, der vom ausgewählten Wertpapier unterstützt wird.
LogDiagnostics Aktiviert ausführliche Protokollierung über Einstiege und Ausstiege. false Nützlich zum Debuggen von Fill-Sequenzen.

Implementierungshinweise

  • Pip-Konvertierung – Der ursprüngliche EA passt die Pip-Größe für 3/5-Stellen-Symbole an. Der StockSharp-Port repliziert dies, indem er den Preisschritt bei Bedarf mit 10 multipliziert.
  • Manuelles Hedging-Modell – StockSharp verwendet Netto-Positionen, daher hält die Strategie einen Zustand pro Bein (PositionState) und sendet explizite Market-Orders für Ausstiege. Dies ermöglicht ein Verhalten ähnlich dem MT5-Hedged-Account-Modus.
  • Risikomanagement – Stop-Loss- und Take-Profit-Niveaus sind optional. Wenn eines deaktiviert ist, wird dieses Bein nur geschlossen, wenn das gegenüberliegende Schutzniveau erreicht wird oder durch externe Verwaltung.
  • SchutzdienstStartProtection() wird weiterhin aufgerufen, damit das Framework unerwartete Verbindungsabbrüche überwachen kann, obwohl benutzerdefinierte Ausstiegslogik implementiert ist.

Verwendung

  1. Strategie an ein Wertpapier mit zuverlässigen Level-1-Daten (Geld/Brief) und den gewünschten Zeitrahmen-Kerzen anhängen.
  2. Pip-Abstände und Handelsvolumen entsprechend dem Risikoprofil konfigurieren.
  3. Strategie starten; sie wartet auf den nächsten Kerzenschluss, bevor das gehedgte Paar eingereicht wird.
  4. Protokolle oder Chart überwachen, um zu beobachten, wie jedes Bein unabhängig aussteigt.

Unterschiede zur MT5-Version

  • Geldmanagement basierend auf Risikoprozentsatz wird nicht übertragen; verwenden Sie OrderVolume zur Steuerung der Handelsgröße.
  • Da StockSharp Portfolio-Positionen aggregiert, emuliert die Strategie Hedging durch interne Buchhaltung. Dies gewährleistet ein dem ursprünglichen Experten nahes Verhalten, während es mit Brokern kompatibel bleibt, die Positionen netzen.
  • Broker-spezifische Freeze/Stop-Level-Prüfungen werden weggelassen. Stattdessen wirft die Volumen-Normalisierungsroutine beschreibende Ausnahmen, wenn Exchange-Limits verletzt werden.

Dateien

  • CS/BackKickStrategy.cs – Strategieimplementierung mit der High-Level-StockSharp-API.
  • README.md – Englische Dokumentation (diese Datei).
  • README_ru.md – Russische Dokumentation.
  • README_zh.md – Chinesische Dokumentation.
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 BackKickStrategy : 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 BackKickStrategy()
	{
		_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;
	}
}