Auf GitHub ansehen

Close-Agent-Strategie

Überblick

Close Agent Strategy ist ein Risikomanagement-Assistent, der den CloseAgent-Expertenberater MQL widerspiegelt. Die Strategie eröffnet keine neuen Trades. Stattdessen überwacht es bestehende Positionen und schließt sie, wenn der Preis über die Bollinger-Bänder hinausgeht, während der Relative-Stärke-Index (RSI) extreme Zonen erreicht. Das Tool kann nach manuell oder durch andere automatisierte Strategien erstellten Positionen Ausschau halten und optional alles auflösen, sobald ein globales Gewinnziel erreicht ist.

Indikatoren und Daten

  • Kerzen: konfigurierbarer Zeitrahmen (Standard: 5 Minuten), der zur Berechnung von Indikatoren verwendet wird.
  • Bollinger Bänder (Länge 21, Breite 2): erkennt Preisausschläge über das obere Band oder unter das untere Band.
  • Relative Strength Index (Länge 13): bestätigt, ob der Markt überkauft (>70) oder überverkauft (<30) ist.
  • Level1-Daten: erfasst die neuesten Geld- und Briefkurse, um die Ausstiegsbedingungen so genau wie möglich zu bewerten.

Parameter

  • Schließmodus (CloseMode): wählt aus, welche Positionen zum Schließen berechtigt sind.
    • Manual – nur Positionen ohne diese Strategiekennung (manuelle Trades oder andere Bots).
    • Auto – nur von dieser Strategieinstanz eröffnete Positionen.
    • Both – Überwachen Sie jede Position auf dem Strategiesymbol.
  • Kerzentyp (CandleType): Zeitrahmen, der zur Berechnung der Bollinger-Bänder und RSI verwendet wird.
  • Betriebsmodus (OperationMode):
    • LiveBar – die zuletzt entstehende Kerze verwenden; reagiert schneller, verwendet jedoch möglicherweise unfertige Daten.
    • NewBar – wartet auf das Schließen einer Kerze, bevor ein Signal generiert wird (sicherer, aber langsamer).
  • Alle Ziele schließen (CloseAllTarget): Wenn der variable Gewinn (PnL) diesen absoluten Wert erreicht, wird jede überwachte Position sofort geschlossen.
  • Benachrichtigungen aktivieren (EnableAlerts): Wenn der Wert „true“ ist, wird jedes Mal eine Nachricht protokolliert, wenn ein Exit ausgelöst wird, einschließlich der Schätzung des realisierten Gewinns.

Handelslogik

  1. Abonniert Level1-Kurse und die konfigurierte Kerzenserie. Bollinger-Bänder und RSI werden für jede eingehende Kerze aktualisiert.
  2. Behält einen kompakten Verlaufspuffer bei, damit die Strategie auf die zuletzt geschlossene Kerze verweisen kann, wenn OperationMode auf NewBar gesetzt ist.
  3. Überprüft, ob das globale Gewinnziel erreicht wird. Wenn CloseAllTarget > 0 und PnL den Schwellenwert überschreitet, werden alle zulässigen Positionen zu Marktpreisen reduziert.
  4. Für jede überwachte Position auf dem Strategiesymbol:
    • Long-Positionen: geschlossen, wenn das beste Gebot über dem oberen Bollinger-Band liegt, RSI über 70 liegt und der Preis über dem Einstiegsdurchschnittspreis bleibt.
    • Short-Positionen: geschlossen, wenn der beste Brief unter dem unteren Bollinger-Band liegt, RSI unter 30 liegt und der Preis unter dem Einstiegsdurchschnittspreis bleibt.
  5. Verwendet Geld-/Briefkurse, sofern verfügbar; Andernfalls wird auf den zuletzt verarbeiteten Kerzenschluss zurückgegriffen, um verpasste Ausgänge zu vermeiden.

Nutzungshinweise

  • Die Strategie ist als Schutzschicht konzipiert und geht davon aus, dass Positionen möglicherweise extern eröffnet werden.
  • Da die Logik nur bei Marktaustritten wirkt, sollte die Strategie parallel zu anderen Handelssystemen laufen, um das Risikorisiko zu steuern.
  • Benachrichtigungen werden im Designer-Protokoll angezeigt, wenn EnableAlerts aktiv ist und mit den ursprünglichen MQL-Benachrichtigungen übereinstimmt.
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>
/// Closes open positions when price stretches beyond Bollinger Bands and RSI reaches extreme values.
/// Adds SMA crossover entries for backtesting.
/// </summary>
public class CloseAgentStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _bollingerLength;
	private readonly StrategyParam<decimal> _rsiOverbought;
	private readonly StrategyParam<decimal> _rsiOversold;

	/// <summary>
	/// Candle type used to calculate indicators.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Length of the RSI indicator.
	/// </summary>
	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	/// <summary>
	/// Length of the Bollinger Bands indicator.
	/// </summary>
	public int BollingerLength
	{
		get => _bollingerLength.Value;
		set => _bollingerLength.Value = value;
	}

	/// <summary>
	/// RSI threshold for overbought.
	/// </summary>
	public decimal RsiOverbought
	{
		get => _rsiOverbought.Value;
		set => _rsiOverbought.Value = value;
	}

	/// <summary>
	/// RSI threshold for oversold.
	/// </summary>
	public decimal RsiOversold
	{
		get => _rsiOversold.Value;
		set => _rsiOversold.Value = value;
	}

	/// <summary>
	/// Initializes parameters.
	/// </summary>
	public CloseAgentStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for indicators", "General");

		_rsiLength = Param(nameof(RsiLength), 13)
			.SetGreaterThanZero()
			.SetDisplay("RSI Length", "RSI period", "Indicators");

		_bollingerLength = Param(nameof(BollingerLength), 21)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Length", "Bollinger Bands period", "Indicators");

		_rsiOverbought = Param(nameof(RsiOverbought), 70m)
			.SetRange(0m, 100m)
			.SetDisplay("RSI Overbought", "Overbought threshold", "Signals");

		_rsiOversold = Param(nameof(RsiOversold), 30m)
			.SetRange(0m, 100m)
			.SetDisplay("RSI Oversold", "Oversold threshold", "Signals");
	}

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

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0m;
		_prevSlow = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var smaFast = new SimpleMovingAverage { Length = 10 };
		var smaSlow = new SimpleMovingAverage { Length = 30 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(smaFast, smaSlow, ProcessCandle)
			.Start();

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

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

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

		_prevFast = fast;
		_prevSlow = slow;
	}
}