High-Level-Abonnements

Überblick

Die Klasse Strategy stellt eine Reihe von High-Level-Methoden für Marktdatenabonnements bereit: SubscribeCandles, SubscribeTicks, SubscribeLevel1 und SubscribeOrderBook. Diese Methoden geben ein Objekt ISubscriptionHandler<T> zurück, mit dem Datenhandler und Indikatoren bequem im Fluent-Stil gebunden werden können.

Im Unterschied zum manuellen Erstellen eines Subscription-Objekts und zum Aufruf von Subscribe() erledigen die High-Level-Methoden Folgendes:

  • Sie erstellen automatisch ein Abonnement mit den richtigen Parametern.
  • Sie stellen einen typisierten ISubscriptionHandler<T> zum Binden von Handlern bereit.
  • Sie integrieren sich über Bind-Methoden in das Indikatorsystem.
  • Sie unterstützen automatische Chart-Darstellung.
  • Sie verwalten den Abonnement-Lebenszyklus korrekt.

Abonnementmethoden

SubscribeCandles

Abonniert Candles. Akzeptiert einen Zeitrahmen oder DataType:

// Nach Zeitrahmen abonnieren
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
    TimeSpan tf,
    bool isFinishedOnly = true,
    Security security = default);

// Nach DataType abonnieren (unterstützt alle Candle-Typen)
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
    DataType dt,
    bool isFinishedOnly = true,
    Security security = default);

// Mit einem vorbereiteten Subscription-Objekt abonnieren
ISubscriptionHandler<ICandleMessage> SubscribeCandles(Subscription subscription);

Der Parameter isFinishedOnly ist standardmäßig true - der Handler empfängt nur abgeschlossene Candles.

SubscribeTicks

Abonniert Tick-Trades:

ISubscriptionHandler<ITickTradeMessage> SubscribeTicks(Security security = null);
ISubscriptionHandler<ITickTradeMessage> SubscribeTicks(Subscription subscription);

SubscribeLevel1

Abonniert Level1-Daten (beste Bid-/Ask-Preise, letzter Trade und weitere Felder):

ISubscriptionHandler<Level1ChangeMessage> SubscribeLevel1(Security security = null);
ISubscriptionHandler<Level1ChangeMessage> SubscribeLevel1(Subscription subscription);

SubscribeOrderBook

Abonniert das Orderbuch:

ISubscriptionHandler<IOrderBookMessage> SubscribeOrderBook(Security security = null);
ISubscriptionHandler<IOrderBookMessage> SubscribeOrderBook(Subscription subscription);

Wenn der Parameter security nicht angegeben ist, wird Security der Strategie verwendet.

ISubscriptionHandler-Interface

Das Objekt ISubscriptionHandler<T> stellt die folgenden Methoden bereit:

Start / Stop

Starten und Stoppen des Abonnements:

handler.Start();   // ruft Subscribe auf
handler.Stop();    // ruft UnSubscribe auf

Bind (ohne Indikatoren)

Binden eines einfachen Datenhandlers:

handler.Bind(Action<T> callback);

Bind (mit Indikatoren)

Binden eines Handlers mit einem oder mehreren Indikatoren. Der Indikator verarbeitet eingehende Daten automatisch, und der Handler erhält den bereits berechneten Wert:

// Ein Indikator - decimal-Wert
handler.Bind(IIndicator indicator, Action<T, decimal> callback);

// Zwei Indikatoren
handler.Bind(IIndicator ind1, IIndicator ind2, Action<T, decimal, decimal> callback);

// Bis zu acht Indikatoren
handler.Bind(ind1, ind2, ind3, ..., callback);

// Array von Indikatoren
handler.Bind(IIndicator[] indicators, Action<T, decimal[]> callback);

Der Handler mit Bind wird nur aufgerufen, wenn alle Indikatoren einen nicht leeren Wert zurückgegeben haben.

BindWithEmpty

Ähnlich wie Bind, aber der Handler wird auch aufgerufen, wenn der Indikator einen leeren Wert zurückgegeben hat. Werte werden als decimal? dargestellt:

handler.BindWithEmpty(IIndicator indicator, Action<T, decimal?> callback);

BindEx

Stellt Zugriff auf das vollständige Objekt IIndicatorValue bereit, anstatt den extrahierten decimal-Wert zu liefern:

handler.BindEx(IIndicator indicator, Action<T, IIndicatorValue> callback, bool allowEmpty = false);

Beispiel: Strategie mit Indikatoren

public class SmaStrategy : Strategy
{
    private readonly StrategyParam<int> _shortPeriod;
    private readonly StrategyParam<int> _longPeriod;
    private readonly StrategyParam<DataType> _candleType;

    public int ShortPeriod
    {
        get => _shortPeriod.Value;
        set => _shortPeriod.Value = value;
    }

    public int LongPeriod
    {
        get => _longPeriod.Value;
        set => _longPeriod.Value = value;
    }

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

    public SmaStrategy()
    {
        _shortPeriod = Param(nameof(ShortPeriod), 10);
        _longPeriod = Param(nameof(LongPeriod), 20);
        _candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
    }

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

        var shortSma = new SimpleMovingAverage { Length = ShortPeriod };
        var longSma = new SimpleMovingAverage { Length = LongPeriod };

        var subscription = SubscribeCandles(CandleType);

        // Zwei Indikatoren binden - der Handler wird aufgerufen,
        // wenn beide Indikatoren gebildet sind
        subscription
            .Bind(shortSma, longSma, (candle, shortValue, longValue) =>
            {
                if (!IsFormedAndOnlineAndAllowTrading())
                    return;

                if (shortValue > longValue && Position <= 0)
                    BuyMarket(Volume + Math.Abs(Position));
                else if (shortValue < longValue && Position >= 0)
                    SellMarket(Volume + Math.Abs(Position));
            })
            .Start();

        // Chart einrichten
        var area = CreateChartArea();
        if (area != null)
        {
            DrawCandles(area, subscription);
            DrawIndicator(area, shortSma);
            DrawIndicator(area, longSma);
            DrawOwnTrades(area);
        }
    }
}

Beispiel: Tick-Abonnement

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

    SubscribeTicks()
        .Bind(tick =>
        {
            if (!IsFormedAndOnlineAndAllowTrading())
                return;

            this.AddInfoLog("Tick: Preis={0}, Volumen={1}", tick.Price, tick.Volume);
        })
        .Start();
}

Beispiel: Orderbuch-Abonnement

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

    SubscribeOrderBook()
        .Bind(book =>
        {
            var bestBid = book.GetBestBid();
            var bestAsk = book.GetBestAsk();

            if (bestBid != null && bestAsk != null)
            {
                var spread = bestAsk.Price - bestBid.Price;
                this.AddInfoLog("Spread: {0}", spread);
            }
        })
        .Start();
}

Unterschiede zur manuellen Abonnementerstellung

Aspekt Manuelles Abonnement High-Level-Methode
Erstellung new Subscription(DataType, Security) SubscribeCandles(tf)
Datenverarbeitung Abonnieren von Connector-Ereignissen Bind(callback)
Indikatoren Manueller Aufruf von indicator.Process() Automatisch über Bind(indicator, callback)
Indikatorregistrierung Manuelles Hinzufügen zu Indicators Automatisch bei Bind
Chart-Darstellung Manuelle Integration mit IChart DrawCandles, DrawIndicator

High-Level-Methoden werden für die meisten Strategien empfohlen, da sie den Codeumfang deutlich reduzieren und die Fehlerwahrscheinlichkeit senken.