Auf GitHub ansehen

Symbol-Swap-Strategie

Die Symbol-Swap-Strategie ist der StockSharp-Port des MetaTrader 5-Dienstprogramms „Symbol Swap“. Das ursprüngliche MQL5-Programm öffnet ein Panel, in dem ein Händler einen beliebigen Ticker eingeben, das aktuelle Diagramm sofort auf dieses Symbol umstellen und ein kompaktes Datenfenster mit der neuesten Zeit, OHLC-Preisen, Tick-Volumen und Spread überwachen kann. Diese C#-Konvertierung behält die gleichen Verantwortlichkeiten bei, verlässt sich jedoch ausschließlich auf das High-Level-Abonnement API von StockSharp.

Verhalten

  1. Beim Start löst die Strategie das zu beobachtende Instrument auf. Es versucht zuerst WatchedSecurityId; Wenn das Feld leer ist, wird auf Strategy.Security zurückgegriffen, das im Launcher konfiguriert ist.
  2. Kerzendaten des ausgewählten CandleType werden über SubscribeCandles(...) gestreamt. Fertige Balken liefern die Eröffnungs-, Höchst-, Tiefst-, Schluss- und Tick-Volumen, die das Panel füllen.
  3. Die besten Geld-/Briefwerte in Echtzeit kommen über SubscribeLevel1(...) an. Der Spread wird bei jeder Kursaktualisierung neu berechnet, um das Datenfenster MQL widerzuspiegeln.
  4. Der formatierte Block wird entweder in das Strategieprotokoll (OutputMode = Log) geschrieben oder mit DrawText(...) in einem Diagramm (OutputMode = Chart) gerendert, wodurch das schwebende Panel aus MetaTrader neu erstellt wird.
  5. Durch den Aufruf von SwapSecurity("TICKER") während der Ausführung wird das neue Wertpapier über SecurityProvider.LookupById aufgelöst und sowohl die Candle- als auch die Level-1-Feeds nahtlos erneut für das angeforderte Instrument abonniert.

Die Strategie dient nur der Information; Es werden keine Bestellungen aufgegeben. Es kann eigenständig als Markt-Dashboard oder zusammen mit anderen Trading-Bots ausgeführt werden.

Parameter

Name Beschreibung Standard
CandleType Zeitrahmen, der das Kerzenabonnement definiert, das zum Erstellen von OHLC- und Tick-Volumendaten verwendet wird. TimeFrame(1 minute)
WatchedSecurityId Optionale Gerätekennung. Leer lassen, um Strategy.Security zu verwenden. leer
OutputMode Rendering-Ziel des Informationsblocks. Wählen Sie zwischen Chart (Overlay in der Nähe des Preises) oder Log (Strategieprotokoll). Chart

Öffentliche Methoden

Methode Beschreibung
SwapSecurity(string securityId) Löst den bereitgestellten Ticker über das aktive SecurityProvider auf und schaltet das Panel sofort auf dieses Symbol um. Die Methode kann mehrfach aufgerufen werden; Bei jedem Aufruf werden vorherige Candle-/Level-1-Abonnements gelöscht, bevor die neuen Feeds hinzugefügt werden.

Nutzungshinweise

  • Stellen Sie sicher, dass der Connector die angeforderte Kennung offenlegt. andernfalls löst SecurityProvider.LookupById eine Ausnahme aus.
  • Bei OutputMode = Chart erstellt die Strategie automatisch einen Diagrammbereich, zeichnet die abonnierten Kerzen und überlagert den Statusblock. Im Protokollmodus werden nur die Textaktualisierungen erstellt.
  • Das Tick-Volumen entspricht dem TotalVolume der Kerze. Auf diese Weise meldet MetaTrader die Tick-Anzahl pro Balken.
  • Der Spread wird nur angezeigt, wenn sowohl der beste Geldkurs als auch der beste Briefkurs verfügbar sind. Andernfalls zeigt das Feld n/a an.

Konvertierungsdetails

  • Die MetaTrader-Timerschleife wird durch StockSharp-Abonnements ersetzt. Kerzen werden einmal pro fertigem Balken ausgelöst und Kurse der Stufe 1 aktualisieren den Spread in Echtzeit.
  • Die Panel-Beschriftungen MQL werden durch einen einzelnen mehrzeiligen Textblock dargestellt. Der Text verwendet die genaue Reihenfolge des Originaltools: Zeit, Periode, Symbol, Schluss, Eröffnung, Hoch, Tief, Tick-Volumen, Spread.
  • Für den Austausch von Laufzeitsymbolen ist kein manuelles Market Watch-Management mehr erforderlich – die Strategie löst Instrumente direkt über den Sicherheitsanbieter StockSharp auf.
  • Es werden nur API-Aufrufe auf hoher Ebene verwendet (SubscribeCandles, SubscribeLevel1, DrawText, AddInfo). Es gibt keine manuellen Indikatorberechnungen oder direkten Connector-Manipulationen, wodurch die Kodierungsregeln des Repositorys erfüllt werden.
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>
/// Market monitoring strategy that tracks price metrics and trades on significant
/// spread changes. Simplified from the MetaTrader "Symbol Swap" display panel.
/// </summary>
public class SymbolSwapStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<decimal> _spreadThreshold;

	private SimpleMovingAverage _sma;
	private decimal _entryPrice;

	/// <summary>
	/// Candle type for monitoring.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// SMA period for trend detection.
	/// </summary>
	public int SmaPeriod
	{
		get => _smaPeriod.Value;
		set => _smaPeriod.Value = value;
	}

	/// <summary>
	/// Price deviation threshold for entry signals.
	/// </summary>
	public decimal SpreadThreshold
	{
		get => _spreadThreshold.Value;
		set => _spreadThreshold.Value = value;
	}

	/// <summary>
	/// Initializes strategy parameters.
	/// </summary>
	public SymbolSwapStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle series for signals", "General");

		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "Moving average period", "Indicators");

		_spreadThreshold = Param(nameof(SpreadThreshold), 3m)
			.SetGreaterThanZero()
			.SetDisplay("Spread Threshold", "Price deviation from SMA to trigger entry", "Signals");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_sma = null;
		_entryPrice = 0m;
	}

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

		_sma = new SimpleMovingAverage { Length = SmaPeriod };

		SubscribeCandles(CandleType)
			.Bind(_sma, ProcessCandle)
			.Start();
	}

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

		if (!IsFormed)
			return;

		var price = candle.ClosePrice;

		// Exit on mean reversion
		if (Position != 0 && _entryPrice > 0m)
		{
			var pnl = Position > 0
				? price - _entryPrice
				: _entryPrice - price;

			// Exit on profit or loss threshold
			if (pnl >= SpreadThreshold || pnl <= -SpreadThreshold * 2m)
			{
				if (Position > 0)
					SellMarket(Math.Abs(Position));
				else
					BuyMarket(Math.Abs(Position));

				_entryPrice = 0m;
				return;
			}
		}

		// Entry on deviation
		if (Position == 0)
		{
			var deviation = price - smaValue;

			if (deviation > SpreadThreshold)
			{
				SellMarket();
				_entryPrice = price;
			}
			else if (deviation < -SpreadThreshold)
			{
				BuyMarket();
				_entryPrice = price;
			}
		}
	}
}