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
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.
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.
Die besten Geld-/Briefwerte in Echtzeit kommen über SubscribeLevel1(...) an. Der Spread wird bei jeder Kursaktualisierung neu berechnet, um das Datenfenster MQL widerzuspiegeln.
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.
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;
}
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class symbol_swap_strategy(Strategy):
def __init__(self):
super(symbol_swap_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle series for signals", "General")
self._sma_period = self.Param("SmaPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("SMA Period", "Moving average period", "Indicators")
self._spread_threshold = self.Param("SpreadThreshold", 3.0) \
.SetGreaterThanZero() \
.SetDisplay("Spread Threshold", "Price deviation from SMA to trigger entry", "Signals")
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def SmaPeriod(self):
return self._sma_period.Value
@SmaPeriod.setter
def SmaPeriod(self, value):
self._sma_period.Value = value
@property
def SpreadThreshold(self):
return self._spread_threshold.Value
@SpreadThreshold.setter
def SpreadThreshold(self, value):
self._spread_threshold.Value = value
def OnReseted(self):
super(symbol_swap_strategy, self).OnReseted()
self._entry_price = 0.0
def OnStarted2(self, time):
super(symbol_swap_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.SmaPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(sma, self._process_candle) \
.Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormed:
return
price = float(candle.ClosePrice)
sma_v = float(sma_value)
threshold = float(self.SpreadThreshold)
# Exit on mean reversion
if self.Position != 0 and self._entry_price > 0:
pnl = price - self._entry_price if self.Position > 0 else self._entry_price - price
if pnl >= threshold or pnl <= -threshold * 2:
if self.Position > 0:
self.SellMarket(abs(self.Position))
else:
self.BuyMarket(abs(self.Position))
self._entry_price = 0.0
return
# Entry on deviation
if self.Position == 0:
deviation = price - sma_v
if deviation > threshold:
self.SellMarket()
self._entry_price = price
elif deviation < -threshold:
self.BuyMarket()
self._entry_price = price
def CreateClone(self):
return symbol_swap_strategy()