Auf GitHub ansehen

Intelligente Forex-Systemstrategie

Überblick

Die Smart Forex System Strategy ist eine StockSharp-Portierung des MetaTrader Expertenberaters „Smart Forex System“. Der Roboter kombiniert einen Einzelkerzen-Impulsfilter mit einem Mittelungsgitter im Martingal-Stil. Der erste Trade wird eröffnet, wenn die vorherige Kerze einen starken Richtungsschluss zeigt und sich der aktuelle Preis ausreichend vom Referenzschluss entfernt hat. Zusätzliche Einträge werden in festen Pip-Intervallen in die entgegengesetzte Richtung hinzugefügt, wobei die Positionsgröße um einen konfigurierbaren Multiplikator zunimmt. Die Strategie verwaltet Ausstiege durch durchschnittliche Take-Profit-Niveaus und einen Sicherheits-Stop-Loss, der an die letzte Netzbestellung gekoppelt ist.

Handelslogik

  • Signalerzeugung
    • Bewerten Sie die letzte abgeschlossene Kerze im ausgewählten Zeitrahmen.
    • Berechnen Sie ein Impulsverhältnis: (current close - previous close) / previous close * 10,000.
    • Wenn die vorherige Kerze bärisch ist und das Momentum unter dem negativen Schwellenwert liegt, kann ein Long-Korb beginnen.
    • Wenn die vorherige Kerze bullisch ist und das Momentum den positiven Schwellenwert überschreitet, kann ein Short-Basket beginnen.
    • Der Handel kann über den Parameter Trading Mode auf Long-Only, Short-Only oder beide Richtungen beschränkt oder vollständig deaktiviert werden.
  • Netzausbau
    • Sobald ein Warenkorb vorhanden ist, werden neue Einträge immer dann hinzugefügt, wenn sich der Preis gegenüber der Position um mindestens Grid Step Pips gegenüber dem Preis der letzten Bestellung bewegt.
    • Jedes neue Bestellvolumen wird mit Lot Multiplier multipliziert. Die Volumina sind auf die Broker-Limits und den konfigurierten Max Volume beschränkt.
    • Der Warenkorb hört auf zu wachsen, wenn die Anzahl der Bestellungen Max Trades erreicht.
  • Exit-Management
    • Ein harter Stop-Loss wird Stop Loss Pips vom Preis der letzten Order entfernt platziert. Durch das Überschreiten dieser Distanz wird der gesamte Korb geschlossen.
    • Die Take-Profit-Höhe hängt von der Warenkorbgröße ab:
      • Für eine einzelne Bestellung werden First Take Profit Pips vom volumengewichteten durchschnittlichen Einstiegspreis verwendet.
      • Bei mehreren Orders werden Grid Take Profit Pips vom gleichen durchschnittlichen Einstiegspreis verwendet, um kleinere Rebounds zu erzielen.
    • Exits werden an fertigen Kerzen verarbeitet, um sicherzustellen, dass die Indikatoren endgültige Werte haben.

Hinweise zum Risikomanagement

  • Die Martingal-ähnliche Positionsgröße erhöht das Risiko bei ungünstigen Trends dramatisch. Verwenden Sie konservative Multiplikatoren und Korbgrößen bei stark volatilen Instrumenten.
  • Der Standard-Stop-Loss (400 Pips) ist absichtlich breit, um den ursprünglichen EA widerzuspiegeln. Erwägen Sie eine Ausrichtung auf den ATR des Instruments, wenn geringere Verluste erforderlich sind.
  • Der Grid-Handel verbraucht schnell Marge. Stellen Sie sicher, dass die Kontohebelwirkung, die Vertragsgröße und die Start Volume-Parameter mit den Brokerspezifikationen übereinstimmen.

Parameter

Name Beschreibung Standard
Handelsmodus Zulässige Handelsrichtung (nur Long, nur Short, beides oder deaktiviert). Lang und kurz
Impulsschwelle Mindestimpuls in Pseudo-Pips, der zum Auslösen eines Signals erforderlich ist. 1
Lautstärke starten Volumen der allerersten Bestellung in einem neuen Warenkorb. 0,01
Maximale Lautstärke Eine feste Obergrenze gilt für jedes einzelne Bestellvolumen. 2
Lot-Multiplikator Multiplikator, der bei der Dimensionierung nachfolgender Rasteraufträge verwendet wird. 1.5
Rasterschritt Mindestabstand in Pips vor dem Hinzufügen der nächsten Bestellung. 26
Max Trades Maximal zulässige Anzahl von Bestellungen pro Richtung. 12
Nehmen Sie zuerst den Gewinn mit Take-Profit-Distanz in Pips, wenn nur eine Order offen ist. 30
Grid-Take-Profit Take-Profit-Distanz in Pips, sobald der Warenkorb mehrere Aufträge enthält. 7
Stop-Loss Stop-Distanz in Pips vom letzten Orderpreis. 400
Kerzentyp Zeitrahmen, der für die Signalauswertung verwendet wird. 1-Stunden-Kerzen

Empfohlene Verwendung

  1. Verknüpfen Sie die Strategie mit einem Forex-Symbol mit ausreichender Liquidität und vorhersehbarem Spread.
  2. Stellen Sie den Candle Type so ein, dass er mit dem Betriebszeitraum des ursprünglichen EA übereinstimmt (standardmäßig H1), oder passen Sie ihn an Ihren bevorzugten Horizont an.
  3. Optimieren Sie den Rasterabstand, den Multiplikator und den Impulsfilter für historische Daten vor der Live-Bereitstellung.
  4. Überwachen Sie die Margennutzung genau. Der Warenkorb kann schnell wachsen. Erwägen Sie daher die Kombination der Strategie mit einem kontoweiten Aktienschutz.
  5. Vermeiden Sie Überschneidungen mit anderen netzbasierten Systemen auf demselben Instrument, um das Risiko zunehmender Verluste zu verringern.

Unterschiede im Vergleich zur MetaTrader-Version

  • Der StockSharp-Port arbeitet mit fertigen Kerzen statt mit Tick-für-Tick-Aktualisierungen, was das Rauschen reduziert und die Logik deterministisch macht.
  • Das Auftragsvolumen wird mithilfe von StockSharp-Sicherheitsmetadaten (Min., Max. und Schritt) angepasst, um die Kompatibilität mit einer Vielzahl von Brokern sicherzustellen.
  • Take-Profit- und Stop-Loss-Prüfungen werden innerhalb der Strategielogik durchgeführt, anstatt individuelle Orderänderungen für jede Rasterebene einzureichen.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Smart Forex System strategy: Triple EMA alignment.
/// Enters when fast > mid > slow (buy) or fast < mid < slow (sell).
/// </summary>
public class SmartForexSystemStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _midPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private bool _wasBullishAlignment;
	private bool _hasPrevAlignment;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int MidPeriod { get => _midPeriod.Value; set => _midPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public SmartForexSystemStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_midPeriod = Param(nameof(MidPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Mid EMA", "Mid EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullishAlignment = false;
		_hasPrevAlignment = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_wasBullishAlignment = false;
		_hasPrevAlignment = false;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var mid = new ExponentialMovingAverage { Length = MidPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, mid, slow, ProcessCandle).Start();
	}

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

		var bullishAlignment = fastValue > midValue && midValue > slowValue;
		var bearishAlignment = fastValue < midValue && midValue < slowValue;
		var crossedUp = bullishAlignment && (!_hasPrevAlignment || !_wasBullishAlignment);
		var crossedDown = bearishAlignment && (!_hasPrevAlignment || _wasBullishAlignment);

		if (crossedUp && Position <= 0)
			BuyMarket();
		else if (crossedDown && Position >= 0)
			SellMarket();

		if (bullishAlignment || bearishAlignment)
		{
			_wasBullishAlignment = bullishAlignment;
			_hasPrevAlignment = true;
		}
	}
}