Auf GitHub ansehen

Sitzungs-Breakout-Strategie

Überblick

Die Session Breakout-Strategie repliziert den Expertenberater „Session Breakout“ von MetaTrader. Es beobachtet die europäische Morgensitzung auf und misst seine Preisspanne. Wenn diese Spanne ausreichend eng ist, bereitet sich die Strategie auf den Handel mit Ausbrüchen während des US-Zeitraums vor. Nachmittagssitzung mit StockSharps High-Level-API. Die Implementierung erzwingt höchstens einen Long- und einen Short-Eintrag pro Tag a Und fügt jeder Position automatisch Schutzaufträge (Stop-Loss und Take-Profit) hinzu.

Handelslogik

  • Setzen Sie den Status zu Beginn jedes Handelstages zurück und überspringen Sie Wochenenden. Montags sind optional und werden durch einen Parameter gesteuert.
  • Verfolgen Sie fertige Kerzen während der europäischen Sitzung (Standard 06:00–12:00 Uhr) und zeichnen Sie das höchste Hoch und das niedrigste Tief auf.
  • Zu Beginn der US-Sitzung wird der erfasste Bereich als „klein“ klassifiziert, wenn seine Breite kleiner als „SmallSessionThreshol“ ist dPips`.
  • Wenn die Spanne klein ist, beobachten Sie die US-Sitzungskerzen (Standard 12:00–16:00) und warten Sie, bis mindestens ein US-Balken geschlossen hat („Eu RopeSessionStartHour + 5toEuropeSessionStartHour + 10`).
  • Ein langer Ausbruch wird ausgelöst, wenn die gesamte Kerze über dem europäischen Hoch zuzüglich eines konfigurierbaren Puffers („BreakoutBuffer“) bleibt Pips`). Für einen kurzen Ausbruch muss die Kerze unter dem europäischen Tief abzüglich des Puffers bleiben.
  • Nach dem Eingehen einer Position fügt die Strategie Stop-Loss- und Take-Profit-Levels hinzu, die in Pips ausgedrückt werden, und verhindert ein zusätzliches En versucht den Rest des Tages in die gleiche Richtung.

Parameter

Parameter Beschreibung
Volume Das Ordervolumen wird sowohl für Long- als auch für Short-Breakouts verwendet.
EuropeSessionStartHour Stunde, in der die europäische Reichweitenverfolgung beginnt.
EuropeSessionEndHour Stunde, in der die europäische Reichweitenverfolgung stoppt.
UsSessionStartHour Stunde, die den Beginn des US-Sitzungsfensters markiert.
UsSessionEndHour Stunde, die das Ende des US-Sitzungsfensters markiert.
SmallSessionThresholdPips Maximale Breite (in Pips), damit der europäische Bereich als Squeeze gilt.
BreakoutBufferPips Zusätzlicher Puffer oberhalb/unterhalb der Spanne hinzugefügt, bevor Ausbrüche ausgelöst werden.
TradeOnMonday Ermöglicht den Handel montags. Wochenenden werden immer ausgelassen.
TakeProfitPips Abstand zwischen Einstiegspreis und Take-Profit-Niveau.
StopLossPips Abstand zwischen dem Einstiegspreis und dem Stop-Loss-Level.
CandleType Für alle Berechnungen verwendete Kerzenserie (standardmäßig 15-Minuten-Kerzen).

Notizen

  • Die Pip-Größe wird vom Instrument PriceStep abgeleitet. Passen Sie die Pip-basierten Parameter an die Vertragsspezifikation an s des ausgewählten Wertpapiers.
  • Da Aufträge generiert werden, wenn eine qualifizierte Kerze schließt, erfolgt die Ausführung bei Backtests zum Schlusskurs dieser Kerze. Liv Die Füllungen können je nach Marktbedingungen variieren.
  • Pro Tag kann nur ein Long- und ein Short-Trade eröffnet werden. Die Logik spiegelt das ursprüngliche Verhalten des Expert Advisors bei der Verwendung von S wider tockSharps positionsbasierte Risikomanagement-Helfer.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Session breakout strategy that tracks a range during first hours and trades breakouts later.
/// Accumulates high/low during range hours (0-8), then trades breakouts during active hours (8-20).
/// </summary>
public class SessionBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _rangeStartHour;
	private readonly StrategyParam<int> _rangeEndHour;
	private readonly StrategyParam<int> _tradeEndHour;
	private readonly StrategyParam<DataType> _candleType;

	private DateTime _currentDate;
	private decimal? _rangeHigh;
	private decimal? _rangeLow;
	private bool _rangeComplete;
	private bool _tradedToday;

	public int RangeStartHour { get => _rangeStartHour.Value; set => _rangeStartHour.Value = value; }
	public int RangeEndHour { get => _rangeEndHour.Value; set => _rangeEndHour.Value = value; }
	public int TradeEndHour { get => _tradeEndHour.Value; set => _tradeEndHour.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SessionBreakoutStrategy()
	{
		_rangeStartHour = Param(nameof(RangeStartHour), 0)
			.SetDisplay("Range Start", "Hour to start tracking range", "Sessions");

		_rangeEndHour = Param(nameof(RangeEndHour), 8)
			.SetDisplay("Range End", "Hour to stop tracking range", "Sessions");

		_tradeEndHour = Param(nameof(TradeEndHour), 20)
			.SetDisplay("Trade End", "Hour to stop trading", "Sessions");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_currentDate = default;
		_rangeHigh = null;
		_rangeLow = null;
		_rangeComplete = false;
		_tradedToday = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_currentDate = default;
		_rangeHigh = null;
		_rangeLow = null;
		_rangeComplete = false;
		_tradedToday = false;

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

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

		var candleDate = candle.OpenTime.Date;
		var hour = candle.OpenTime.Hour;

		// Reset on new day
		if (candleDate != _currentDate)
		{
			_currentDate = candleDate;
			_rangeHigh = null;
			_rangeLow = null;
			_rangeComplete = false;
			_tradedToday = false;
		}

		// Build range during accumulation hours
		if (hour >= RangeStartHour && hour < RangeEndHour)
		{
			if (_rangeHigh == null || candle.HighPrice > _rangeHigh)
				_rangeHigh = candle.HighPrice;
			if (_rangeLow == null || candle.LowPrice < _rangeLow)
				_rangeLow = candle.LowPrice;
			return;
		}

		// Mark range as complete
		if (!_rangeComplete && hour >= RangeEndHour && _rangeHigh != null && _rangeLow != null)
			_rangeComplete = true;

		if (!_rangeComplete || _rangeHigh == null || _rangeLow == null)
			return;

		// Trade during active hours
		if (hour >= RangeEndHour && hour < TradeEndHour)
		{
			// Breakout above range high - buy
			if (Position <= 0 && candle.ClosePrice > _rangeHigh.Value && !_tradedToday)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
				_tradedToday = true;
			}
			// Breakout below range low - sell
			else if (Position >= 0 && candle.ClosePrice < _rangeLow.Value && !_tradedToday)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
				_tradedToday = true;
			}
		}

		// Close at end of day
		if (hour >= TradeEndHour && Position != 0)
		{
			if (Position > 0)
				SellMarket();
			else
				BuyMarket();
		}
	}
}