Auf GitHub ansehen

Strategie zum Ausbruch aus dem Seitwärtsbereich

Diese Strategie erkennt ruhige Marktphasen, in denen drei gleitende Durchschnitte innerhalb eines engen Bandes konvergieren. Wenn der Preis schließlich über oder unter diesen Bereich ausbricht, tritt die Strategie in Richtung des Ausbruchs ein und zielt darauf ab, den entstehenden Trend zu erfassen.

Das System beobachtet die Spanne zwischen dem schnellen, mittleren und langsamen SMA. Wenn der maximale Unterschied zwischen diesen Durchschnitten für eine bestimmte Anzahl von Bars unterhalb des konfigurierten Schwellenwerts bleibt, wird der Markt als "seitwärtsgebunden" angesehen. Das höchste Hoch und das niedrigste Tief dieses Zeitraums definieren die Ausbruchsniveaus.

Trades werden eröffnet, wenn der Preis jenseits dieser Extremwerte schließt. Positionen werden durch umgekehrte Bedingungen geschützt: Wenn der Preis in den Bereich zurückkehrt oder ein Vielfaches der Bereichsbreite als Gewinn erreicht, wird die Position geschlossen.

Details

  • Einstiegskriterien:
    • Long: Nach einem Bereich von RangeLength Bars, in dem die SMA-Spanne unter ShakeThreshold liegt, einsteigen wenn der Preis über das höchste Hoch des Bereichs schließt.
    • Short: Unter denselben Bereichsbedingungen einsteigen, wenn der Preis unter das niedrigste Tief des Bereichs schließt.
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien:
    • Long: Schließen wenn der Preis unter das Bereichstief zurückkehrt oder der Gewinn 4 * (Bereichshoch - Bereichstief) übersteigt.
    • Short: Schließen wenn der Preis über das Bereichshoch zurückkehrt oder der Gewinn 4 * (Bereichshoch - Bereichstief) übersteigt.
  • Stops: Implizite Ausstiege basierend auf Bereichsgrenzen und Gewinnmultiplikator.
  • Standardwerte:
    • FastSma = 38
    • MidSma = 140
    • SlowSma = 210
    • ShakeThreshold = 250
    • RangeLength = 200
    • CandleType = TimeSpan.FromMinutes(1)
  • Filter:
    • Kategorie: Ausbruch
    • Richtung: Beide
    • Indikatoren: SMA, Highest, Lowest
    • Stops: Ja
    • Komplexität: Grundlegend
    • Zeitrahmen: Intraday
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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;

/// <summary>
/// Breakout strategy that waits for converging SMAs and trades on breakout.
/// </summary>
public class BreakTheRangeBoundStrategy : Strategy
{
	private readonly StrategyParam<int> _fastSma;
	private readonly StrategyParam<int> _slowSma;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _prevClose;
	private bool _hasPrev;

	public int FastSma { get => _fastSma.Value; set => _fastSma.Value = value; }
	public int SlowSma { get => _slowSma.Value; set => _slowSma.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BreakTheRangeBoundStrategy()
	{
		_fastSma = Param(nameof(FastSma), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast moving average period", "Parameters");

		_slowSma = Param(nameof(SlowSma), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow moving average period", "Parameters");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_prevClose = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastSma };
		var slow = new ExponentialMovingAverage { Length = SlowSma };

		SubscribeCandles(CandleType).Bind(fast, slow, ProcessCandle).Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			_prevClose = close;
			_hasPrev = true;
			return;
		}

		// Cross above slow SMA => buy breakout
		if (_prevClose <= _prevSlow && close > slowValue && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		// Cross below slow SMA => sell breakout
		else if (_prevClose >= _prevSlow && close < slowValue && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
		_prevClose = close;
	}
}