Auf GitHub ansehen

Range-Filter-Strategie

Range-Filter-Strategie mit realistischer Berechnung der Bandbreite und festen Risiko-/Renditeniveaus.

Es wird eine geglättete Bandbreite verwendet, um dynamische Bänder um den Preis zu erstellen. Trades werden eröffnet, wenn der Preis diese Bänder nach oben oder unten durchbricht. Das Risikomanagement verwendet feste Stop-Loss- und Take-Profit-Abstände.

Details

  • Einstiegskriterien: Preis bricht die Range-Filter-Bänder.
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien: Stop Loss oder Take Profit.
  • Stops: Ja.
  • Standardwerte:
    • SamplingPeriod = 100
    • RangeMultiplier = 3
    • RiskPoints = 50
    • RewardPoints = 100
    • MaxTradesPerDay = 5
    • CandleType = TimeSpan.FromMinutes(5)
  • Filter:
    • Kategorie: Trend
    • Richtung: Beide
    • Indikatoren: Range filter
    • Stops: Ja
    • Komplexität: Mittel
    • Zeitrahmen: Intraday (5m)
    • 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>
/// Range filter strategy using EMA crossover.
/// </summary>
public class RangeFilterStrategy : 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 RangeFilterStrategy()
	{
		_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");
	}

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

	/// <inheritdoc />
	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);
		}
	}
}