Auf GitHub ansehen

Charles Ausbruch-Strategie

Ausbruchsstrategie basierend auf täglichen Hoch- und Tiefniveaus. Sie sucht nach Preisbewegungen jenseits der Tagesspanne des Vortages mit einem RSI- und EMA-Trendfilter. Die Strategie berechnet das tägliche Hoch und Tief, verschiebt sie um ein konfigurierbares Delta und geht long oberhalb des oberen Niveaus oder short unterhalb des unteren Niveaus, wenn Trendbedingungen bestätigt werden.

Details

  • Einstiegskriterien:
    • Long: Close > DailyHigh + Delta und RSI > 55 und FastEMA > SlowEMA
    • Short: Close < DailyLow - Delta und RSI < 45 und FastEMA < SlowEMA
  • Long/Short: Beide
  • Ausstiegskriterien: Entgegengesetztes Signal oder Schutz
  • Stops: Konfigurierbarer Take-Profit und Stop-Loss in Prozent
  • Standardwerte:
    • Delta = 0.0002m
    • FastPeriod = 18
    • SlowPeriod = 60
    • RsiPeriod = 14
    • TakeProfit = 1m
    • StopLoss = 0.5m
    • CandleType = TimeSpan.FromHours(1).TimeFrame()
  • Filter:
    • Kategorie: Ausbruch
    • Richtung: Beide
    • Indikatoren: EMA, RSI
    • Stops: Ja
    • Komplexität: Mittel
    • 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 based on EMA crossover with RSI trend filter.
/// </summary>
public class CharlesBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<DataType> _candleType;

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

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CharlesBreakoutStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 18)
			.SetDisplay("Fast EMA Period", "Fast EMA length", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 60)
			.SetDisplay("Slow EMA Period", "Slow EMA length", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI length", "Indicators");

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

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

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

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

		var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		SubscribeCandles(CandleType).Bind(fastEma, slowEma, rsi, ProcessCandle).Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fastEma;
			_prevSlow = slowEma;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastEma > slowEma;
		var crossDown = _prevFast >= _prevSlow && fastEma < slowEma;

		if (crossUp && rsi > 50 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && rsi < 50 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastEma;
		_prevSlow = slowEma;
	}
}