Auf GitHub ansehen

Swetten-Strategie

Überblick

Swetten ist eine durch ein neuronales Netzwerk gesteuerte Breakout-Strategie, die ursprünglich für MetaTrader 4 verbreitet wurde. Sie bewertet die Spanne zwischen einem langfristigen einfachen gleitenden Durchschnitt mit 233 Perioden und zehn schnelleren gleitenden Durchschnitten, die auf Ein-Minuten-Kerzen berechnet werden. Die Spreads werden in ein radiales Basisnetzwerk eingespeist, das ein bullisches oder bärisches Aktivierungsniveau erzeugt. Wenn die Aktivierung positiv ist, geht die Strategie in die Long-Position ein, ist sie negativ, geht sie in die Short-Position.

Markt und Zeitrahmen

  • Entwickelt für die wichtigsten FX-Paare (der ursprüngliche Code zielte auf EURUSD ab).
  • Bei der Analyse werden Ein-Minuten-Kerzen verwendet und Entscheidungen werden nur anhand abgeschlossener Kerzen getroffen.
  • Die Signalauswertung erfolgt alle zwei Stunden zur vollen Stunde (00:00, 02:00, …, 22:00 Uhr Wechselzeit). Samstags und sonntags sind keine Geschäfte geöffnet.

Indikatoren und Funktionen

  • Simple moving averages with periods: 233 (baseline), 144, 89, 55, 34, 21, 13, 8, 5, 3, 2.
  • Eingaben des neuronalen Netzwerks sind die Unterschiede zwischen dem 233-Perioden-Durchschnitt und jedem schnelleren Durchschnitt.
  • Vor der Übergabe an das Netzwerk werden die Eingaben auf trainierte Bereiche beschränkt, normalisiert und mit denselben Koeffizienten skaliert, die in der ursprünglichen DLL verwendet wurden.
  • Das radiale Basisnetzwerk wird exakt aus der exportierten EURUSDn-Funktion repliziert und besteht aus 38 Gaußschen Merkmalen, deren Ausgaben gemittelt werden, um die endgültige Aktivierung zu erhalten.

Handelsregeln

  1. Warten Sie auf den Schluss einer einminütigen Kerze, die zu einer geraden Stunde endet und auf einen Wochentag fällt.
  2. Berechnen Sie die Aktivierung des neuronalen Netzwerks anhand der Spreads des gleitenden Durchschnitts.
  3. Wenn die Aktivierung > 0 ist und die aktuelle Position nicht lang ist, senden Sie einen Marktkauf für TradeVolume + abs(current position) Lots.
  4. Wenn die Aktivierung < 0 ist und die aktuelle Position nicht leer ist, senden Sie einen Marktverkauf für TradeVolume + abs(current position) Lots.
  5. Positionen sind geschützt durch:
    • Ein fester Take-Profit, definiert in Preisschritten (TakeProfitPoints).
    • Ein fester Stop-Loss, definiert in Preisschritten (StopLossPoints).
    • Wenn eines der beiden Niveaus durch die Hoch-/Tief-Extremwerte der Kerze erreicht wird, wird die Position durch eine Marktorder geschlossen.

Parameter

Name Beschreibung Standard
CandleType Für Berechnungen verwendete Kerzenreihe. Zeitrahmen von 1 Minute
TradeVolume Basisauftragsvolumen in Losen. 0,1
SlowPeriod Periode des einfachen gleitenden Basisdurchschnitts. 233
TakeProfitPoints Gewinnzielentfernung in Preisschritten. 150
StopLossPoints Stop-Loss-Distanz in Preisschritten. 40

Konvertierungshinweise

  • Das DLL-basierte neuronale Netzwerk von MetaTrader wurde vollständig auf C# portiert, indem die exportierte Funktion in verwalteten Code übersetzt wurde.
  • Protective exits mimic the original OrderClose conditions by checking candle highs and lows against price step thresholds.
  • Die Eintrittsverwaltung verfolgt den letzten Füllpreis über OnNewMyTrade, um Ausstiege mit tatsächlichen Füllungen in Einklang zu bringen.
  • Alle Kommentare wurden in Englisch umgeschrieben und der Code verwendet High-Level-StockSharp-APIs (SubscribeCandles, Bind), wie in den Konvertierungsrichtlinien erforderlich.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Swetten strategy: multi-SMA spread crossover system.
/// Uses fast SMA (5) and slow SMA (50) to generate trend signals.
/// Buys when fast crosses above slow, sells when fast crosses below slow.
/// </summary>
public class SwettenStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _isReady;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public SwettenStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type for strategy", "General");

		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 34)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
	}

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

		_prevFast = 0;
		_prevSlow = 0;
		_isReady = false;
	}

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

		_prevFast = 0;
		_prevSlow = 0;
		_isReady = false;

		var fast = new SMA { Length = FastPeriod };
		var slow = new SMA { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, OnProcess)
			.Start();

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

	private void OnProcess(ICandleMessage candle, decimal fastVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_isReady)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_isReady = true;
			return;
		}

		// Fast crosses above slow = buy
		if (_prevFast <= _prevSlow && fastVal > slowVal)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Fast crosses below slow = sell
		else if (_prevFast >= _prevSlow && fastVal < slowVal)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}