Auf GitHub ansehen

S4 IBS Mean-Reversion-Strategie mit 3-Kerzen-Ausstieg

Die Strategie kauft, wenn die interne Balkenstärke (IBS) der vorherigen Kerze unter einem Schwellenwert liegt, und erwartet eine Mean Reversion. Sie steigt aus, wenn der Kurs über den Einstiegspreis schließt oder nach drei Kerzen, falls der Trade noch im Verlust liegt.

Details

  • Einstiegskriterien: vorheriger IBS <= Schwellenwert
  • Long/Short: Nur Long
  • Ausstiegskriterien: Schluss über dem Einstiegspreis oder nach 3 Kerzen, falls noch unter dem Einstieg; erzwungener Ausstieg nach Endzeitpunkt
  • Stops: Nein
  • Standardwerte:
    • IbsThreshold = 0.25
    • StartTime = 2024-01-01 05:00:00 UTC
    • EndTime = 2024-12-31 00:00:00 UTC
  • Filter:
    • Kategorie: Mean Reversion
    • Richtung: Long
    • Indikatoren: Keine
    • Stops: Nein
    • Komplexität: Grundlegend
    • Zeitrahmen: Täglich
    • Saisonalität: Ja
    • 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>
/// S4 IBS mean rev 3 candle exit strategy using EMA crossover.
/// </summary>
public class S4IBSMeanRev3candleExitStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public S4IBSMeanRev3candleExitStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}