Auf GitHub ansehen

Strategie zum Schließen von Orders

Diese Hilfsstrategie schließt sofort bestehende Positionen und storniert ausstehende Orders gemäß benutzerdefinierten Filtern. Sie kann entweder nur auf das angehängte Instrument oder auf alle Portfolio-Instrumente angewendet werden. Optionale Zeitfenster- und Preisbereichsbeschränkungen ermöglichen eine präzise Kontrolle darüber, welche Orders betroffen sind.

Details

  • Zweck: Risikomanagement und manuelle Liquidation.
  • Betrieb:
    • Beim Start prüft die Strategie das optionale Zeitfenster.
    • Falls erlaubt, schließt sie Positionen und storniert Orders, die den Filtern entsprechen.
    • Nach der Verarbeitung stoppt die Strategie automatisch.
  • Filter:
    • CloseAllSecurities – alle Portfolio-Instrumente statt nur des angehängten Instruments einbeziehen.
    • CloseOpenLongOrders / CloseOpenShortOrders – bestehende Long- oder Short-Positionen schließen.
    • ClosePendingLongOrders / ClosePendingShortOrders – ausstehende Kauf- oder Verkaufsorders stornieren.
    • SpecificOrderId – nur Orders mit der angegebenen Transaktions-ID berühren, wenn ungleich null.
    • CloseOrdersWithinRange, CloseRangeHigh, CloseRangeLow – nach Einstiegspreisbereich begrenzen.
    • EnableTimeControl, StartCloseTime, StopCloseTime – nur während eines bestimmten Zeitfensters anwenden.
  • Standardwerte:
    • Alle Schließoptionen aktiviert.
    • SpecificOrderId = 0.
    • CloseOrdersWithinRange = false.
    • CloseRangeHigh = 0.
    • CloseRangeLow = 0.
    • EnableTimeControl = false.
    • StartCloseTime = 02:00.
    • StopCloseTime = 02:30.
  • Hinweise:
    • Die Strategie eröffnet keine neuen Positionen.
    • Preisbereichsfilter werden ignoriert, wenn die Grenzen null oder negativ sind.
    • Bei aktiviertem CloseAllSecurities werden Positionen im gesamten Portfolio verarbeitet.
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>
/// Strategy that closes positions based on time-of-day and EMA conditions.
/// Opens positions during trend and closes them at specific time.
/// </summary>
public class CloseOrdersStrategy : Strategy
{
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma;
	private bool _hasPrev;

	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CloseOrdersStrategy()
	{
		_emaLength = Param(nameof(EmaLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("EMA Length", "EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevEma = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var ema = new ExponentialMovingAverage { Length = EmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevEma = emaVal;
			_hasPrev = true;
			return;
		}

		var close = candle.ClosePrice;

		// EMA rising -> buy
		if (emaVal > _prevEma && close > emaVal && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// EMA falling -> sell
		else if (emaVal < _prevEma && close < emaVal && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevEma = emaVal;
	}
}