Auf GitHub ansehen

Hoop Master-Strategie

Übersicht

Die Hoop Master-Strategie ist ein ausstehendes Ausbruch-System, das kontinuierlich zwei Stop-Orders um den aktuellen Preis hält. Der ursprüngliche MetaTrader 5 Expert Advisor platziert einen Buy-Stop oberhalb des Marktes und einen Sell-Stop unterhalb. Wenn eine Seite auslöst, wird die entgegengesetzte Order storniert und beide Seiten werden mit einem größeren Volumen neu erstellt. Der StockSharp-Port folgt derselben Idee, indem er Stop-Orders und optionale Martingal-Größenbestimmung innerhalb einer einzigen Strategieklasse verwaltet.

Die Strategie kann auch schützende Stop-Loss- und Take-Profit-Orders an jede offene Position anhängen. Ein Trailing-Stop-Modul bewegt den schützenden Stop schrittweise, wenn der Markt in Tradingrichtung voranschreitet.

Handelslogik

  1. Bei jeder abgeschlossenen Kerze berechnet die Strategie die Platzierungsniveaus für die Ausbruch-Stops neu.
  2. Wenn keine Position offen ist, werden sowohl ein Buy-Stop als auch ein Sell-Stop bei einem konfigurierbaren Pip-Abstand vom aktuellen Bid/Ask registriert.
  3. Wenn einer der ausstehenden Stops gefüllt wird, wird der entgegengesetzte Stop entfernt. Neue Ausbruch-Stops werden sofort mit dem doppelten Basisvolumen gesendet.
  4. Nachdem ein Trade eröffnet wird, erstellt die Strategie unabhängige Stop-Loss- und Take-Profit-Orders. Eine Trailing-Engine kann den Stop zum Preis bewegen sobald die Bewegung groß genug ist.
  5. Wenn die Position geschlossen wird, werden alle Schutzorders storniert und die Ausbruch-Orders beim nächsten Signal mit dem Basisvolumen neu initialisiert.

Parameter

Parameter Beschreibung
Candle Type Kerzendatentyp für die Kerzen-für-Kerzen-Logik.
Order Volume Basisvolumen für jede Ausbruch-Order. Der Martingal-Schritt verwendet das Doppelte davon.
Stop Loss (pips) Abstand in Pips zwischen Einstiegspreis und schutzender Stop-Order. Auf 0 setzen zum Deaktivieren.
Take Profit (pips) Abstand in Pips zwischen Einstiegspreis und schützender Ziel-Order. Auf 0 setzen zum Deaktivieren.
Trailing Stop (pips) Abstand beim Bewegen des Trailing Stops. Auf 0 setzen um Trailing zu deaktivieren.
Trailing Step (pips) Minimale Preisverbesserung (in Pips) erforderlich bevor der Trailing Stop aktualisiert wird.
Indent (pips) Offset, in Pips gemessen, oberhalb des Ask und unterhalb des Bid beim Platzieren von Ausbruch-Stops.

Order-Verwaltungsdetails

  • Die Strategie verfolgt kontinuierlich die besten Bid/Ask-Kurse. Wenn Kurse nicht verfügbar sind, fällt sie auf den letzten Handelspreis oder Kerzenschlusskurs zurück.
  • Alle Orders werden am Kursschritt des Instruments ausgerichtet um ungültige Preise zu vermeiden.
  • Schützende Stop- und Take-Profit-Orders werden ersetzt wann immer eine neue Position erscheint.
  • Trailing funktioniert nur wenn sowohl der Trailing-Abstand als auch die Schritt-Parameter über null liegen. Der Stop wird in Tradingrichtung bewegt wenn die gewünschte Verbesserung groß genug ist.

Hinweise

  • Stelle sicher dass der verbundene Broker oder Simulator Stop- und Limit-Orders für das gewählte Instrument unterstützt.
  • Der Martingal-Schritt kann das Engagement schnell erhöhen. Passe das Basisvolumen an um innerhalb akzeptabler Risikolimits zu bleiben.
  • Die Strategie erwartet Level1-Daten (Bid/Ask) zusammen mit Kerzendaten zu erhalten damit Ausbruchpreise genau berechnet werden können.
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 HoopMasterStrategy : 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 HoopMasterStrategy()
	{
		_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;
	}
}