Auf GitHub ansehen

Lucky Jump-Strategie

Die Lucky Jump-Strategie ist ein kurzfristiges Mean-Reversion-System, das auf plötzliche Preissprünge beim besten Bid und Ask reagiert. Wenn der Ask-Preis gegenüber der vorherigen Notierung um eine bestimmte Anzahl von Punkten nach oben springt, eröffnet die Strategie eine Short-Position in Erwartung eines Rückschlags. Umgekehrt geht sie long, wenn der Bid-Preis um denselben Betrag fällt. Positionen werden entweder beim ersten günstigen Tick oder wenn der Verlust einen vordefinierten Grenzwert überschreitet, geschlossen.

Dieser Ansatz versucht, schnelle Korrekturen nach aggressiven Marktbewegungen zu erfassen. Er arbeitet ausschließlich mit Level1-Kursdaten und ist nicht auf Kerzen oder Indikatoren angewiesen.

Details

  • Einstiegskriterien:
    • Short: Ask(t) - Ask(t-1) >= Shift * PriceStep.
    • Long: Bid(t-1) - Bid(t) >= Shift * PriceStep.
  • Ausstiegskriterien:
    • Position schließen, sobald sie profitabel wird.
    • Schließen, wenn der Verlust Limit * PriceStep überschreitet.
  • Stops: impliziter Stop basierend auf dem Limit-Parameter.
  • Standardwerte:
    • Shift = 30 Punkte.
    • Limit = 180 Punkte.
    • Volume = 1.
  • Filter:
    • Kategorie: Mean Reversion
    • Richtung: Beide
    • Indikatoren: Keine
    • Stops: Ja
    • Komplexität: Einfach
    • Zeitrahmen: Ultra-kurzfristig
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Hoch
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>
/// Price jump reversal strategy using EMA crossover.
/// </summary>
public class LuckyJumpStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	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 DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public LuckyJumpStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Trading");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Trading");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "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 fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

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

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

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

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

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}