Die Symbol-Swap-Panel-Strategie ist eine StockSharp-Konvertierung des MQL-Panels „Symbol-Swap-Panel“. Der ursprüngliche Experte fungierte als Diagramm-Widget, das es Händlern ermöglichte, ein Symbol einzugeben, das aktive Diagramm auf dieses Symbol umzustellen und Marktinformationen wie OHLC-Werte, Tick-Volumen und Spread in Echtzeit zu überwachen. Die konvertierte Strategie erstellt denselben Workflow in der StockSharp-Umgebung neu. Es kann auf jedem Wertpapier gestartet werden und ermöglicht einen manuellen Wechsel zu einem anderen Instrument, während gleichzeitig die relevantesten Marktkennzahlen kontinuierlich protokolliert werden.
Kernverhalten
Abonniert Kerzendaten und Level-1-Kurse für das aktive Wertpapier.
Protokolliert jede abgeschlossene Kerze mit Eröffnung, Höchst-, Tiefst- und Schlusskurs, Gesamtvolumen und dem zuletzt berechneten Spread.
Speichert Bid/Ask-Kurse und leitet eine aktuelle Spanne ab, die die Anzeige im MQL-Panel widerspiegelt.
Reagiert auf manuelle Swap-Anfragen und ersetzt die überwachte Sicherheit durch die gewählte Kennung, ohne dass die Strategie neu gestartet werden muss.
Behält die zuvor ausgewählte Sicherheit bei, sodass redundante Swaps ignoriert werden und versehentliche Doppelaktivierungen die Abonnements nicht unterbrechen.
Parameter
Name
Typ
Beschreibung
TargetSecurityId
string
Sicherheitskennung, die aktiviert werden soll, wenn die Swap-Anfrage ausgelöst wird. Leere Zeichenfolgen werden mit einer Warnung ignoriert.
CandleType
DataType
Kerzenaggregation für regelmäßige Aktualisierungen (standardmäßig 1-Stunden-Kerzen, repliziert den Panel-Zeitrahmen MQL).
SwapRequested
bool
Manuelle Markierung, die einen sofortigen Wechsel zu TargetSecurityId anfordert. Es wird auf false zurückgesetzt, nachdem der Austauschversuch verarbeitet wurde.
Datenabonnements
Candle-Abonnement erstellt mit CandleType für das aktuell aktive Wertpapier.
Abonnement der ersten Stufe, das zur Verfolgung von Geld-/Briefkursen und zur Berechnung eines Live-Spread-Werts verwendet wird.
Abonnements werden bei jeder Sicherheitsänderung sicher neu gestartet, um sicherzustellen, dass veraltete Datenströme nicht weiter ausgeführt werden.
Arbeitsablauf
Wenn die Strategie startet, löst sie die anfängliche Sicherheit von Strategy.Security oder, falls sie fehlt, von TargetSecurityId auf.
Für dieses Instrument werden Candle- und Level-One-Abonnements eröffnet.
Jede abgeschlossene Kerze löst eine detaillierte Protokollmeldung aus, die den in den Original-Panel-Beschriftungen angezeigten Text widerspiegelt.
Eingehende Aktualisierungen der Ebene 1 aktualisieren die zwischengespeicherten Geld-/Briefwerte.
Wenn Sie SwapRequested auf true setzen und ein gültiges TargetSecurityId angeben, wird die überwachte Sicherheit sofort umgeschaltet und die Abonnements neu gestartet.
Nutzungshinweise
Die Strategie ist auf manuelle Überwachung ausgelegt und erteilt keine Aufträge.
Der Spread wird nur gemeldet, wenn sowohl Geld- als auch Briefwerte vorhanden und positiv sind.
Wenn ein ungültiges oder unbekanntes Symbol angegeben wird, wird eine Warnung protokolliert und die Anfrage verworfen, ohne dass die laufenden Abonnements unterbrochen werden.
Da das ursprüngliche Tool die Benutzeroberfläche einmal pro Sekunde aktualisierte, können Sie den Kerzenzeitraum verkürzen, wenn Sie häufigere Protokollaktualisierungen benötigen.
Ursprüngliche MQL-Funktionen bleiben erhalten
Manuelle Symbolumschaltung über eine Textkennung.
Echtzeitanzeige von OHLC-Werten, Volumen und Spread für das ausgewählte Symbol.
Schützt vor leeren Eingaben und fehlgeschlagenen Market Watch-Ergänzungen (übersetzt in StockSharp-Warnungen).
Unterschiede zur MQL-Implementierung
Die StockSharp-Strategie verwendet Protokollmeldungen anstelle von Beschriftungen auf dem Bildschirm. Dies entspricht dem typischen Workflow in StockSharp und stellt dennoch dieselben Informationen bereit.
Der Kartenwechsel wird durch Neuzuweisung der Strategiesicherheit und Neuerstellung von Abonnements implementiert, anstatt ein Terminal-Kartenfenster zu ändern.
Die zeitgesteuerte Aktualisierungslogik wird durch Kerzenabschlussereignisse ersetzt, um mit den StockSharp-APIs auf hoher Ebene in Einklang zu bleiben.
Anforderungen
StockSharp Connector mit Zugriff auf die gewünschten Wertpapiere.
Datenfeed der ersten Ebene, um Geld-/Briefkurse für die Spread-Berechnung zu erhalten.
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>
/// Price monitoring strategy that logs OHLC metrics and trades on candle patterns.
/// Simplified from the "Symbol Swap Panel" MQL display widget.
/// </summary>
public class SymbolSwapPanelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private SimpleMovingAverage _sma;
private decimal _entryPrice;
private decimal _prevClose;
/// <summary>
/// Candle type for monitoring.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Moving average period for trend signals.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Initializes strategy parameters.
/// </summary>
public SymbolSwapPanelStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle series for monitoring and signals", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period for entry signals", "Indicators");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_sma = null;
_entryPrice = 0m;
_prevClose = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_sma = new SimpleMovingAverage { Length = MaPeriod };
SubscribeCandles(CandleType)
.Bind(_sma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
var price = candle.ClosePrice;
var high = candle.HighPrice;
var low = candle.LowPrice;
// Log price info
LogInfo(
$"Time: {candle.CloseTime:O}, O: {candle.OpenPrice}, H: {high}, L: {low}, C: {price}, " +
$"Vol: {candle.TotalVolume}, SMA: {smaValue:F5}");
// Exit: reversal or profit target
if (Position != 0 && _entryPrice > 0m)
{
var pnl = Position > 0
? price - _entryPrice
: _entryPrice - price;
// Exit on trend reversal
if ((Position > 0 && price < smaValue) ||
(Position < 0 && price > smaValue))
{
if (Position > 0)
SellMarket(Math.Abs(Position));
else
BuyMarket(Math.Abs(Position));
_entryPrice = 0m;
_prevClose = price;
return;
}
}
// Entry: follow MA trend with momentum confirmation
if (Position == 0 && _prevClose > 0m)
{
if (price > smaValue && _prevClose <= smaValue)
{
BuyMarket();
_entryPrice = price;
}
else if (price < smaValue && _prevClose >= smaValue)
{
SellMarket();
_entryPrice = price;
}
}
_prevClose = 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_panel_strategy(Strategy):
def __init__(self):
super(symbol_swap_panel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle series for monitoring and signals", "General")
self._ma_period = self.Param("MaPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("MA Period", "Moving average period for entry signals", "Indicators")
self._entry_price = 0.0
self._prev_close = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
def OnReseted(self):
super(symbol_swap_panel_strategy, self).OnReseted()
self._entry_price = 0.0
self._prev_close = 0.0
def OnStarted2(self, time):
super(symbol_swap_panel_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.MaPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(sma, self._process_candle) \
.Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
sma_v = float(sma_value)
# Exit: reversal against trend
if self.Position != 0 and self._entry_price > 0:
if (self.Position > 0 and price < sma_v) or \
(self.Position < 0 and price > sma_v):
if self.Position > 0:
self.SellMarket(abs(self.Position))
else:
self.BuyMarket(abs(self.Position))
self._entry_price = 0.0
self._prev_close = price
return
# Entry: follow MA trend with momentum confirmation
if self.Position == 0 and self._prev_close > 0:
if price > sma_v and self._prev_close <= sma_v:
self.BuyMarket()
self._entry_price = price
elif price < sma_v and self._prev_close >= sma_v:
self.SellMarket()
self._entry_price = price
self._prev_close = price
def CreateClone(self):
return symbol_swap_panel_strategy()