Auf GitHub ansehen

Hpcs Inter7-Strategie

Überblick

Die Hpcs Inter7-Strategie ist ein Bollinger-Band-Breakout-System, das aus dem MetaTrader 4-Expertenberater _HPCS_Inter7_MT4_EA_V01_We.mq4 umgewandelt wurde. Der Algorithmus überwacht Standard-Bollinger-Bänder, die für die ausgewählte Kerzenserie berechnet wurden. Wenn der Preis die Bänder überschreitet, interpretiert er dies als Momentum-Ausbruch und eröffnet eine Position in Richtung des Ausbruchs. Bei jedem neuen Einstieg platziert die Strategie sofort sowohl Stop-Loss- als auch Take-Profit-Ziele in einem festen Abstand zum Einstiegspreis, um das ursprüngliche Verhalten des Expert Advisors nachzubilden.

Handelslogik

  • Short-Einstieg: Wenn die vorherige Kerze oberhalb des unteren Bandes schloss und die zuletzt geschlossene Kerze unterhalb des unteren Bandes endete, eröffnet die Strategie einen Marktverkauf. Dadurch wird der ursprüngliche Zustand Close[0] < LowerBand[0] && Close[1] > LowerBand[1] wiederhergestellt.
  • Long-Einstieg: Wenn die vorherige Kerze unterhalb des oberen Bandes schloss und die letzte geschlossene Kerze oberhalb des oberen Bandes endete, eröffnet die Strategie einen Marktkauf. Dadurch wird Close[0] > UpperBand[0] && Close[1] < UpperBand[1] aus der MQL-Implementierung repliziert.
  • Einzelhandel pro Kerze: Der Algorithmus merkt sich die Öffnungszeit der Kerze, die den letzten Auftrag generiert hat. Ein neues Signal auf derselben Kerze wird ignoriert, um doppelte Trades zu vermeiden, was die Guard-Variable gdt_Candle von MQL4 widerspiegelt.
  • Schutzanordnungen: Unmittelbar nachdem eine neue Position eröffnet wurde, ruft die Strategie SetStopLoss und SetTakeProfit unter Verwendung der konfigurierten Distanz auf. Beide sind symmetrisch um den Einstiegspreis platziert, sodass die Position immer vordefinierte Risiko- und Ertragsziele aufweist.

Parameter

Name Beschreibung Standard Optimierbar
BollingerLength Anzahl der Kerzen, die zum Aufbau der Bollinger-Bänder verwendet werden. 20 Ja
BollingerDeviation Standardabweichungsmultiplikator für die Bandbreite Bollinger. 2 Ja
CandleType Für Berechnungen verwendete Kerzenserie (standardmäßig 1 Minute Zeitrahmen). 1-Minuten-Kerzen Nein
ProtectionDistancePoints Stop-Loss- und Take-Profit-Distanz, ausgedrückt in Preisschritten. 10 Ja

Zusätzliche Hinweise

  • Die Strategie verwendet die StockSharp-Hochebene API (SubscribeCandles().Bind(...)) und speichert keine benutzerdefinierten Verlaufsarrays.
  • StartProtection() wird beim Start aktiviert, sodass die Plattform automatisch Schutzanordnungen verwaltet, die von SetStopLoss und SetTakeProfit aufgegeben wurden.
  • Die Positionsgröße wird durch die Basiseigenschaft Strategy.Volume gesteuert, genau wie beim ursprünglichen Expert Advisor, der ein festes Volumen von einem Lot handelte.
  • Die Strategie wurde für FX-Instrumente entwickelt, bei denen der ursprüngliche EA eingesetzt wurde, sie kann jedoch auf jedes Wertpapier angewendet werden, das aussagekräftige Bollinger-Bandsignale und einen gültigen PriceStep-Wert liefert.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy converted from _HPCS_Inter7_MT4_EA_V01_We.mq4.
/// Sells when price crosses below the lower Bollinger band and buys when price crosses above the upper band.
/// </summary>
public class HpcsInter7Strategy : Strategy
{
	private readonly StrategyParam<int> _bollingerLength;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<decimal> _bandPercent;

	private decimal? _prevClose;
	private decimal? _prevLower;
	private decimal? _prevUpper;

	/// <summary>
	/// Initializes a new instance of the <see cref="HpcsInter7Strategy"/> class.
	/// </summary>
	public HpcsInter7Strategy()
	{
		_bollingerLength = Param(nameof(BollingerLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Length", "Number of candles included in the Bollinger Bands calculation", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Deviation", "Standard deviation multiplier for the Bollinger Bands", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Time frame used for Bollinger Bands", "General");

		_bandPercent = Param(nameof(BandPercent), 0.01m)
			.SetGreaterThanZero()
			.SetDisplay("Band Percent", "MA percentage band width", "Indicators");
	}

	/// <summary>
	/// Bollinger Bands length.
	/// </summary>
	public int BollingerLength
	{
		get => _bollingerLength.Value;
		set => _bollingerLength.Value = value;
	}

	/// <summary>
	/// Bollinger Bands deviation multiplier.
	/// </summary>
	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

	/// <summary>
	/// Candle type used for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public decimal BandPercent
	{
		get => _bandPercent.Value;
		set => _bandPercent.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = null;
		_prevLower = null;
		_prevUpper = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = null;
		_prevLower = null;
		_prevUpper = null;

		var bollinger = new ExponentialMovingAverage { Length = BollingerLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(bollinger, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, bollinger);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal middle)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var upper = middle * (1 + BandPercent);
		var lower = middle * (1 - BandPercent);

		if (_prevClose.HasValue && _prevLower.HasValue && _prevUpper.HasValue)
		{
			// Downward cross through the lower band - open short
			if (_prevClose.Value > _prevLower.Value && candle.ClosePrice < lower && Position >= 0)
			{
				SellMarket();
			}
			// Upward cross through the upper band - open long
			else if (_prevClose.Value < _prevUpper.Value && candle.ClosePrice > upper && Position <= 0)
			{
				BuyMarket();
			}
		}

		_prevClose = candle.ClosePrice;
		_prevLower = lower;
		_prevUpper = upper;
	}
}