Auf GitHub ansehen

Reversal Trap Sniper-Strategie

Reversal Trap Sniper sucht nach RSI-Fallen, bei denen der Momentum zurückgeht, der Preis sich aber weiter bewegt. Er kauft nach einer überkauften Umkehrung, die dennoch höher schließt, und verkauft nach einer überverkauften Umkehrung, die dennoch tiefer schließt.

Details

  • Einstiegskriterien: RSI war vor drei Bars überkauft/überverkauft, aktueller RSI kreuzt zurück und Preis setzt sich in gleicher Richtung fort
  • Long/Short: Beide
  • Ausstiegskriterien: ATR-Stop, Ziel oder maximale Anzahl Bars
  • Stops: ATR-basiert
  • Standardwerte:
    • RsiLength = 14
    • RsiOverbought = 70
    • RsiOversold = 30
    • RiskReward = 2
    • MaxBars = 30
    • AtrLength = 14
  • Filter:
    • Kategorie: Umkehr
    • Richtung: Beide
    • Indikatoren: RSI, ATR
    • 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>
/// Reversal trap sniper strategy using EMA crossover.
/// </summary>
public class ReversalTrapSniperStrategy : 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 ReversalTrapSniperStrategy()
	{
		_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); }
	}
}