Auf GitHub ansehen

SR-Breakout-Strategie

Zusammenfassung

SR Breakout Strategy überwacht die von Donchian-Kanälen abgeleiteten Unterstützungs- und Widerstandsniveaus in zwei Zeitrahmen (H1 und H4). Wenn eine abgeschlossene Kerze über dem Widerstand oder unter der Unterstützung schließt, schreibt die Strategie eine informative Protokollmeldung. Die Implementierung spiegelt die Alarmierungslogik des ursprünglichen MQL4-Experten wider, ohne dass Aufträge erteilt werden müssen.

Wie es funktioniert

  1. Es werden zwei Kerzenabonnements erstellt: eines für den 1-Stunden-Zeitraum und eines für den 4-Stunden-Zeitraum.
  2. Jedes Abonnement ist an seinen eigenen DonchianChannels-Indikator mit einer konfigurierbaren Lookback-Länge (Standard 26) gebunden.
  3. Sobald der Indikator gebildet ist, verfolgt die Strategie für jeden Zeitrahmen den vorherigen Kerzenschluss.
  4. Bei jeder fertigen Kerze wird der aktuelle Schlusskurs mit den oberen und unteren Bändern von Donchian verglichen:
    • Wenn sich der Schlusskurs von unterhalb nach oberhalb des oberen Bandes bewegt, wird eine Meldung „Über dem Widerstand kreuzen“ protokolliert.
    • Wenn sich der Schlusskurs von oben nach unten über das untere Band bewegt, wird die Meldung „Unterschreitung der Unterstützung“ protokolliert.
  5. Die Logik reproduziert das Benachrichtigungsverhalten des MQL4-Skripts, indem sie LogInfo-Einträge als Warnungen verwendet.

Parameter

Name Beschreibung Standard
LookbackLength Anzahl der Kerzen, die zur Berechnung von Donchian Unterstützung/Widerstand verwendet werden. 26
Hour1CandleType Kerzentyp für das einstündige Abonnement. TimeFrame(1h)
Hour4CandleType Kerzentyp für das Vier-Stunden-Abonnement. TimeFrame(4h)

Signale

  • H1-Ausbruch – wird protokolliert, wenn der einstündige Schlusskurs der Kerze den Widerstand oder die Unterstützung überschreitet.
  • H4-Ausbruch – wird protokolliert, wenn der 4-Stunden-Kerzenschluss den Widerstand oder die Unterstützung überschreitet.

Notizen

  • Die Strategie dient ausschließlich der Alarmierung; es führt keine Trades aus.
  • Damit der Indikator Donchian ordnungsgemäß funktioniert, müssen beide Kerzenabonnements Hoch- und Tiefstdaten liefern.
  • Passen Sie die Lookback-Länge oder Kerzentypen an, um sie an andere Handelssitzungen oder Instrumente anzupassen.
using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Support and resistance breakout strategy using Donchian channels.
/// Buys when price breaks above resistance (upper band), sells when breaks below support (lower band).
/// </summary>
public class SrBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _lookbackLength;
	private readonly StrategyParam<DataType> _candleType;

	private readonly Queue<decimal> _highHistory = new();
	private readonly Queue<decimal> _lowHistory = new();

	public int LookbackLength
	{
		get => _lookbackLength.Value;
		set => _lookbackLength.Value = value;
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public SrBreakoutStrategy()
	{
		_lookbackLength = Param(nameof(LookbackLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Lookback", "Number of candles for Donchian channel", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis", "General");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_highHistory.Clear();
		_lowHistory.Clear();

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

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

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

		if (_highHistory.Count < LookbackLength)
		{
			EnqueueCandle(candle);
			return;
		}

		var highs = _highHistory.ToArray();
		var lows = _lowHistory.ToArray();
		var upper = GetMax(highs);
		var lower = GetMin(lows);
		var close = candle.ClosePrice;
		var range = upper - lower;

		var volume = Volume;
		if (volume <= 0)
			volume = 1;
		var breakoutPadding = range * 0.05m;

		// Break above resistance
		if (close > upper + breakoutPadding)
		{
			if (Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		// Break below support
		else if (close < lower - breakoutPadding)
		{
			if (Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		EnqueueCandle(candle);
	}

	private void EnqueueCandle(ICandleMessage candle)
	{
		_highHistory.Enqueue(candle.HighPrice);
		_lowHistory.Enqueue(candle.LowPrice);

		if (_highHistory.Count > LookbackLength)
		{
			_highHistory.Dequeue();
			_lowHistory.Dequeue();
		}
	}

	private static decimal GetMax(IEnumerable<decimal> values)
	{
		var max = decimal.MinValue;

		foreach (var value in values)
		{
			if (value > max)
				max = value;
		}

		return max;
	}

	private static decimal GetMin(IEnumerable<decimal> values)
	{
		var min = decimal.MaxValue;

		foreach (var value in values)
		{
			if (value < min)
				min = value;
		}

		return min;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_highHistory.Clear();
		_lowHistory.Clear();

		base.OnReseted();
	}
}