本页面尚未提供您的语言版本,显示其他语言版本。

High-Level Subscriptions

Overview

The Strategy class provides a set of high-level market data subscription methods: SubscribeCandles, SubscribeTicks, SubscribeLevel1, and SubscribeOrderBook. These methods return an ISubscriptionHandler<T> object that allows binding data handlers and indicators in a convenient fluent style.

Unlike manually creating a Subscription object and calling Subscribe(), the high-level methods:

  • Automatically create a subscription with the correct parameters
  • Provide a typed ISubscriptionHandler<T> for binding handlers
  • Integrate with the indicator system via Bind methods
  • Support automatic chart rendering
  • Properly manage the subscription lifecycle

Subscription Methods

SubscribeCandles

Subscribes to candles. Accepts a timeframe or DataType:

// Subscribe by timeframe
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
    TimeSpan tf,
    bool isFinishedOnly = true,
    Security security = default);

// Subscribe by DataType (supports all candle types)
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
    DataType dt,
    bool isFinishedOnly = true,
    Security security = default);

// Subscribe with a ready-made Subscription object
ISubscriptionHandler<ICandleMessage> SubscribeCandles(Subscription subscription);

The isFinishedOnly parameter is true by default -- the handler receives only completed candles.

SubscribeTicks

Subscribes to tick trades:

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

SubscribeLevel1

Subscribes to Level1 data (best bid/ask prices, last trade, and other fields):

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

SubscribeOrderBook

Subscribes to the order book:

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

If the security parameter is not specified, the strategy's Security is used.

ISubscriptionHandler Interface

The ISubscriptionHandler<T> object provides the following methods:

Start / Stop

Starting and stopping the subscription:

handler.Start();   // calls Subscribe
handler.Stop();    // calls UnSubscribe

Bind (without indicators)

Binding a simple data handler:

handler.Bind(Action<T> callback);

Bind (with indicators)

Binding a handler with one or more indicators. The indicator automatically processes incoming data, and the handler receives the already-calculated value:

// One indicator -- decimal value
handler.Bind(IIndicator indicator, Action<T, decimal> callback);

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

// Up to eight indicators
handler.Bind(ind1, ind2, ind3, ..., callback);

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

The handler with Bind is called only when all indicators have returned a non-empty value.

BindWithEmpty

Similar to Bind, but the handler is called even if the indicator returned an empty value. Values are represented as decimal?:

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

BindEx

Provides access to the full IIndicatorValue object instead of the extracted decimal:

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

Example: Strategy with Indicators

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);

        // Binding two indicators -- handler is called
        // when both indicators are formed
        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 setup
        var area = CreateChartArea();
        if (area != null)
        {
            DrawCandles(area, subscription);
            DrawIndicator(area, shortSma);
            DrawIndicator(area, longSma);
            DrawOwnTrades(area);
        }
    }
}

Example: Tick Subscription

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

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

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

Example: Order Book Subscription

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();
}

Differences from Manual Subscription Creation

Aspect Manual subscription High-level method
Creation new Subscription(DataType, Security) SubscribeCandles(tf)
Data handling Subscribing to connector events Bind(callback)
Indicators Manual indicator.Process() call Automatically via Bind(indicator, callback)
Indicator registration Manual addition to Indicators Automatically on Bind
Chart rendering Manual integration with IChart DrawCandles, DrawIndicator

High-level methods are recommended for use in most strategies, as they significantly reduce the amount of code and decrease the likelihood of errors.