Auf GitHub ansehen

Exp HLRSign-Strategie

Diese Strategie implementiert die HLRSign-Indikatorlogik in StockSharp. Sie öffnet und schließt Positionen, wenn das High-Low Ratio (HLR) vordefinierte Niveaus kreuzt.

Funktionsweise

  • Berechnet Donchian-Kanal-Werte über einen konfigurierbaren Bereich.
  • Berechnet den HLR-Wert als prozentuale Position des Mittelkurses innerhalb des Kanals.
  • Erzeugt Kauf- oder Verkaufssignale, wenn das HLR die oberen oder unteren Schwellenwerte kreuzt, abhängig vom ausgewählten Modus:
    • ModeIn – kaufen beim Kreuzen über das obere Niveau und verkaufen beim Kreuzen unter das untere Niveau.
    • ModeOut – verkaufen beim Kreuzen unter das obere Niveau und kaufen beim Kreuzen über das untere Niveau.
  • Ermöglicht das separate Aktivieren oder Deaktivieren des Öffnens und Schließens von Long- und Short-Positionen.

Parameter

Name Beschreibung
Mode Indikator-Betriebsmodus (ModeIn oder ModeOut).
Range Rückblickzeitraum für höchste und niedrigste Preise.
UpLevel Oberer Schwellenwert in Prozent für HLR.
DnLevel Unterer Schwellenwert in Prozent für HLR.
CandleType Zeitrahmen der für Berechnungen verwendeten Kerzen.
BuyOpen Öffnen von Long-Positionen erlauben.
SellOpen Öffnen von Short-Positionen erlauben.
BuyClose Schließen von Long-Positionen erlauben.
SellClose Schließen von Short-Positionen erlauben.

Hinweise

  • Die Strategie verwendet die High-Level-API mit dem DonchianChannels-Indikator.
  • Es werden nur abgeschlossene Kerzen verarbeitet und Positionsberechtigungen vor dem Handel geprüft.
  • Es sind keine Stop-Loss- oder Take-Profit-Niveaus definiert; der Positionsschutz kann manuell hinzugefügt werden.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;


/// <summary>
/// HLRSign based strategy.
/// Opens and closes positions based on HLR level crossings.
/// </summary>
public class ExpHlrSignStrategy : Strategy
{
	public enum AlgMethods
	{
		ModeIn,
		ModeOut,
	}

	private readonly StrategyParam<AlgMethods> _mode;
	private readonly StrategyParam<int> _range;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _dnLevel;
	private readonly StrategyParam<int> _cooldownBars;
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<bool> _buyOpen;
	private readonly StrategyParam<bool> _sellOpen;
	private readonly StrategyParam<bool> _buyClose;
	private readonly StrategyParam<bool> _sellClose;

	private decimal _previousHlr;
	private bool _isFirst = true;
	private int _barsSinceTrade;

	/// <summary>
	/// Indicator mode.
	/// </summary>
	public AlgMethods Mode
	{
		get => _mode.Value;
		set => _mode.Value = value;
	}

	/// <summary>
	/// Lookback range for highest and lowest values.
	/// </summary>
	public int Range
	{
		get => _range.Value;
		set => _range.Value = value;
	}

	/// <summary>
	/// Upper level in percent for HLR crossing.
	/// </summary>
	public decimal UpLevel
	{
		get => _upLevel.Value;
		set => _upLevel.Value = value;
	}

	/// <summary>
	/// Lower level in percent for HLR crossing.
	/// </summary>
	public decimal DnLevel
	{
		get => _dnLevel.Value;
		set => _dnLevel.Value = value;
	}

	/// <summary>
	/// Bars to wait after a completed trade.
	/// </summary>
	public int CooldownBars
	{
		get => _cooldownBars.Value;
		set => _cooldownBars.Value = value;
	}

	/// <summary>
	/// Type of candles to use.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Allow opening long positions.
	/// </summary>
	public bool BuyOpen
	{
		get => _buyOpen.Value;
		set => _buyOpen.Value = value;
	}

	/// <summary>
	/// Allow opening short positions.
	/// </summary>
	public bool SellOpen
	{
		get => _sellOpen.Value;
		set => _sellOpen.Value = value;
	}

	/// <summary>
	/// Allow closing long positions on sell signal.
	/// </summary>
	public bool BuyClose
	{
		get => _buyClose.Value;
		set => _buyClose.Value = value;
	}

	/// <summary>
	/// Allow closing short positions on buy signal.
	/// </summary>
	public bool SellClose
	{
		get => _sellClose.Value;
		set => _sellClose.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="ExpHlrSignStrategy"/>.
	/// </summary>
	public ExpHlrSignStrategy()
	{
		_mode = Param(nameof(Mode), AlgMethods.ModeIn)
			.SetDisplay("Mode", "Indicator operation mode", "General");

		_range = Param(nameof(Range), 40)
			.SetDisplay("Range", "Lookback period for HLR", "Indicator")
			.SetOptimize(20, 80, 10)
			;

		_upLevel = Param(nameof(UpLevel), 80m)
			.SetDisplay("Up Level", "Upper level for HLR", "Indicator")
			.SetOptimize(60m, 90m, 5m)
			;

		_dnLevel = Param(nameof(DnLevel), 20m)
			.SetDisplay("Down Level", "Lower level for HLR", "Indicator")
			.SetOptimize(10m, 40m, 5m)
			;

		_cooldownBars = Param(nameof(CooldownBars), 1)
			.SetDisplay("Cooldown Bars", "Bars to wait after a completed trade", "Trading");

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

		_buyOpen = Param(nameof(BuyOpen), true)
			.SetDisplay("Buy Open", "Allow opening long positions", "Trading");

		_sellOpen = Param(nameof(SellOpen), true)
			.SetDisplay("Sell Open", "Allow opening short positions", "Trading");

		_buyClose = Param(nameof(BuyClose), true)
			.SetDisplay("Buy Close", "Allow closing long positions", "Trading");

		_sellClose = Param(nameof(SellClose), true)
			.SetDisplay("Sell Close", "Allow closing short positions", "Trading");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_previousHlr = 0;
		_isFirst = true;
		_barsSinceTrade = CooldownBars;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var donchian = new DonchianChannels { Length = Range };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(donchian, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, donchian);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue value)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (_barsSinceTrade < CooldownBars)
			_barsSinceTrade++;

		var donchian = (DonchianChannelsValue)value;
		var upper = donchian.UpperBand;
		var lower = donchian.LowerBand;

		if (upper == null || lower == null)
			return;

		var mid = (candle.HighPrice + candle.LowPrice) / 2m;
		var range = (decimal)(upper - lower);
		var hlr = range != 0m ? 100m * (mid - lower.Value) / range : 0m;

		bool buySignal = false;
		bool sellSignal = false;

		if (_isFirst)
		{
			_previousHlr = hlr;
			_isFirst = false;
			return;
		}

		if (Mode == AlgMethods.ModeIn)
		{
			if (hlr > UpLevel && _previousHlr <= UpLevel)
				buySignal = true;
			if (hlr < DnLevel && _previousHlr >= DnLevel)
				sellSignal = true;
		}
		else
		{
			if (hlr < UpLevel && _previousHlr >= UpLevel)
				sellSignal = true;
			if (hlr > DnLevel && _previousHlr <= DnLevel)
				buySignal = true;
		}

		if (_barsSinceTrade >= CooldownBars && buySignal)
		{
			if (BuyOpen && Position <= 0)
			{
				BuyMarket(Volume + Math.Abs(Position));
				_barsSinceTrade = 0;
			}
		}

		if (_barsSinceTrade >= CooldownBars && sellSignal)
		{
			if (SellOpen && Position >= 0)
			{
				SellMarket(Volume + Math.Abs(Position));
				_barsSinceTrade = 0;
			}
		}

		_previousHlr = hlr;
	}
}