Auf GitHub ansehen

AIS3-Handelsroboter-Vorlage

Überblick

Die AIS3 Trading Robot-Vorlage ist ein MetaTrader-Breakout-System, das auf zwei koordinierten Zeitrahmen basiert. Der primäre Zeitrahmen erfasst die Struktur der vorherigen Kerze, während ein sekundärer Zeitrahmen die aktuelle Volatilität misst, um nachfolgende Aktualisierungen zu kontrollieren. Dieser StockSharp-Port reproduziert originalgetreu die ursprüngliche Auftragsgröße, Eingabeprüfungen und abschließende Logik, ist jedoch implementiert oben auf der übergeordneten Strategie API, sodass es in Designer, Shell oder einem beliebigen benutzerdefinierten StockSharp-Host ausgeführt werden kann.

Handelsablauf

  • Marktdatenabonnements: Die Strategie abonniert zwei Kerzenserien. Die primäre Serie (Standard 15 Minuten) bietet das vorherige Kerzenhoch, -tief, -schluss, -mittelpunkt und -bereich. Die sekundäre Serie (Standard 1 Minute) misst den verwendeten schnellen Bereich für Trailing Stops. Ein Live-Orderbuch-Feed hält die aktuell besten Geld-/Briefkurse mit den ursprünglichen MQL MarketInfo synchronisiert. Anfragen.
  • Breakout-Validierung:
    • Ein Long-Setup wird ausgelöst, wenn der vorherige Schlusskurs über dem Mittelpunkt liegt und der aktuelle Briefkurs über den vorherigen ausbricht hoch plus die gemessene Spanne. Der Einstiegspreis ist der aktuelle Briefkurs.
    • Ein Short-Setup erfordert, dass der vorherige Schlusskurs unter dem Mittelpunkt bleibt und der Geldkurs das vorherige Tief durchbricht. Der Eintrittspreis ist das aktuelle Gebot.
    • Beide Richtungen übernehmen die Broker-Sicherheitsüberprüfungen aus der Vorlage: den Abstand zwischen der Einfahrt und dem geplanten Stopp/Ziel muss den konfigurierten Stop-Puffer überschreiten und der Stop muss auch nach Addition auf der richtigen Seite des Einstiegspreises bleiben verbreiten.
  • Schutzanordnungen:
    • Die Stop-Loss-Distanz beträgt primaryRange × StopMultiplier und ist oberhalb (für Long-Positionen) bzw. unterhalb (für Short-Positionen) verankert Breakout-Kerze, wie im Integrationshandbuch beschrieben.
    • Die Take-Profit-Distanz beträgt primaryRange × TakeMultiplier und wird vom Einstiegspreis in Handelsrichtung platziert.
  • Handelsmanagement:
    • Wenn eine Position offen ist, definiert der sekundäre Zeitrahmenbereich multipliziert mit TrailMultiplier die Nachlaufdistanz.
    • Der Trailing-Stop wird nur aktualisiert, wenn der Handel profitabel ist und das neue Niveau weiter entfernt ist als der konfigurierte Freeze- und Stop-Wert Puffern und die Entfernung zwischen der aktuellen und der geplanten Haltestelle überschreitet TrailStepMultiplier × spread. Dies spiegelt die wider Die Vorlage erfordert, dass der Preis um mindestens einen Trail-Schritt steigen muss, bevor der Stop geändert wird.
    • Positionen werden mit Marktaufträgen geschlossen, wenn der Geld-/Briefkurs die gespeicherten Stop-Loss- oder Take-Profit-Werte berührt.

Risikomanagement

  • Kontoreserve: AccountReserve hält einen Bruchteil des Portfolio-Eigenkapitals gesperrt. Die Strategie weigert sich, neue Positionen zu eröffnen wenn das reservierte Kapital das beantragte Auftragsbudget unterschreiten würde. Dies entspricht dem Verhalten der Vorlage, bei dem das Risiko besteht Die Rücklage schützt das Konto vor kaskadierenden Verlusten.
  • Orderreserve: OrderReserve steuert den Teil des verbleibenden Kapitals, der pro Trade riskiert werden darf. Die Positionsgröße wird als riskBudget / |entry - stop| berechnet und dann an den Sicherheitsvolumenschritt angepasst. Wenn keine Portfoliokennzahlen vorhanden sind verfügbar, wird stattdessen der Fallback-Parameter BaseVolume verwendet.
  • Puffer stoppen und einfrieren: StopBufferTicks und FreezeBufferTicks übersetzen Broker-Stoppbeschränkungen (z. B. MODE_STOPLEVEL und MODE_FREEZELEVEL von MetaTrader) mithilfe der Wertpapierpreisstufe in Preiseinheiten umwandeln. Sie verhindern, dass die Strategie umgesetzt wird Aufträge, die gegen Wechselkursbeschränkungen verstoßen oder den Trailing Stop zu aggressiv verschieben würden.
  • Multiplikator für nachfolgende Schritte: TrailStepMultiplier spiegelt die Konstante acd.TrailStepping aus der MQ4-Vorlage wider. Es sorgt dafür dass nachlaufende Aktualisierungen nur dann erfolgen, wenn der neue Stopp mindestens ein Spread-Vielfaches vom vorherigen Wert entfernt ist.

Parameter

Parameter Beschreibung
AccountReserve Als Sicherheitsreserve gehaltener Anteil des Eigenkapitals (0–0,95).
OrderReserve Anteil des handelbaren Eigenkapitals, der dem Risikobudget pro Trade zugewiesen wird (standardmäßig 0–0,5).
PrimaryCandleType Arbeitszeitrahmen für die Ausbruchserkennung (standardmäßig 15-Minuten-Kerzen).
SecondaryCandleType Schnellerer Zeitrahmen, der die Nachlaufdistanz steuert (standardmäßige 1-Minuten-Kerzen).
TakeMultiplier Multiplikator des primären Bereichs, der zum Platzieren der Take-Profit-Order verwendet wird.
StopMultiplier Multiplikator des primären Bereichs, der zur Berechnung des Schutzstopps verwendet wird.
TrailMultiplier Multiplikator des sekundären Bereichs, der die Nachlaufdistanz definiert.
BaseVolume Größe der Ersatzposition, wenn Portfoliokennzahlen nicht verfügbar sind.
StopBufferTicks Zusätzlicher Abstand in Preisticks, der zwischen Einstiegs- und Stop-/Zielniveau bleiben muss.
FreezeBufferTicks Zusätzlicher Puffer, der verhindert, dass Stoppaktualisierungen zu nahe am Einfrierniveau des Brokers liegen.
TrailStepMultiplier Spread-Multiplikator, der das minimale Inkrement zwischen nachfolgenden Anpassungen definiert.

Nutzungshinweise

  • Füttern Sie die Strategie mit beiden Kerzenserien und einem Level-1- oder Orderbuch-Stream, damit die besten Geld-/Briefkurse verfügbar sind. Laufen Wenn nur die Daten des letzten Handels berücksichtigt werden, ändern sich die Ausbruchsprüfungen, da sie auf dem Spread basieren.
  • Die Standardparameterwerte replizieren das MQ4-Vorlagenbeispiel (TakeMultiplier = 1, StopMultiplier = 2, TrailMultiplier = 3). Passen Sie sie an die Vermögenswerte an, mit denen Sie handeln, oder experimentieren Sie mit der Ausbruchsintensität.
  • Der Trailing Stop ist virtuell – Aufträge werden an der Börse nicht geändert. Wenn die Nachstellbedingung erfüllt ist, ist die Strategie einfach gibt einen Marktausstieg aus, der die Art und Weise widerspiegelt, wie der ursprüngliche Fachberater die Stopps intern verwaltet hat.
  • Kombinieren Sie die Strategie mit dem integrierten Schutzmodul von StockSharp (bereits im Konstruktor aktiviert), um den Notfall aufrechtzuerhalten Stop-Loss-Handhabung, auch wenn die Strategie vorübergehend unterbrochen ist.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// AIS3 Trading Robot: breakout strategy with ATR-based stops and trailing.
/// Enters on breakout above/below previous candle range with EMA filter.
/// </summary>
public class Ais3TradingRobotTemplateStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<decimal> _takeMultiplier;
	private readonly StrategyParam<decimal> _stopMultiplier;

	private decimal _prevHigh;
	private decimal _prevLow;
	private decimal _entryPrice;
	private decimal _stopPrice;

	public Ais3TradingRobotTemplateStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "EMA period for trend filter.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");

		_takeMultiplier = Param(nameof(TakeMultiplier), 2.0m)
			.SetDisplay("Take Multiplier", "ATR multiplier for TP.", "Risk");

		_stopMultiplier = Param(nameof(StopMultiplier), 1.5m)
			.SetDisplay("Stop Multiplier", "ATR multiplier for SL.", "Risk");
	}

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

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

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public decimal TakeMultiplier
	{
		get => _takeMultiplier.Value;
		set => _takeMultiplier.Value = value;
	}

	public decimal StopMultiplier
	{
		get => _stopMultiplier.Value;
		set => _stopMultiplier.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevHigh = 0;
		_prevLow = 0;
		_entryPrice = 0;
		_stopPrice = 0;
	}

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

		_prevHigh = 0;
		_prevLow = 0;
		_entryPrice = 0;
		_stopPrice = 0;

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

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

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

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

		if (_prevHigh == 0 || atrVal <= 0)
		{
			_prevHigh = candle.HighPrice;
			_prevLow = candle.LowPrice;
			return;
		}

		var close = candle.ClosePrice;
		var takeDistance = atrVal * TakeMultiplier;
		var stopDistance = atrVal * StopMultiplier;

		// Manage position
		if (Position > 0)
		{
			if (close - _entryPrice >= takeDistance)
			{
				SellMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else if (_stopPrice > 0 && close <= _stopPrice)
			{
				SellMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else
			{
				var trail = close - stopDistance;
				if (trail > _stopPrice) _stopPrice = trail;
			}
		}
		else if (Position < 0)
		{
			if (_entryPrice - close >= takeDistance)
			{
				BuyMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else if (_stopPrice > 0 && close >= _stopPrice)
			{
				BuyMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else
			{
				var trail = close + stopDistance;
				if (trail < _stopPrice || _stopPrice == 0) _stopPrice = trail;
			}
		}

		// Entry on breakout + EMA filter
		if (Position == 0)
		{
			if (close > _prevHigh && close > emaVal)
			{
				_entryPrice = close;
				_stopPrice = close - stopDistance;
				BuyMarket();
			}
			else if (close < _prevLow && close < emaVal)
			{
				_entryPrice = close;
				_stopPrice = close + stopDistance;
				SellMarket();
			}
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
	}
}