Высокоуровневые подписки
Обзор
Класс Strategy предоставляет набор высокоуровневых методов подписки на рыночные данные: SubscribeCandles, SubscribeTicks, SubscribeLevel1 и SubscribeOrderBook. Эти методы возвращают объект ISubscriptionHandler<T>, который позволяет привязывать обработчики данных и индикаторы в удобном fluent-стиле.
В отличие от ручного создания объекта Subscription и вызова Subscribe(), высокоуровневые методы:
- Автоматически создают подписку с правильными параметрами
- Предоставляют типизированный
ISubscriptionHandler<T>для привязки обработчиков - Интегрируются с системой индикаторов через методы
Bind - Поддерживают автоматическую отрисовку на графике
- Корректно управляют жизненным циклом подписки
Методы подписки
SubscribeCandles
Подписка на свечи. Принимает таймфрейм или DataType:
// Подписка по таймфрейму
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
TimeSpan tf,
bool isFinishedOnly = true,
Security security = default);
// Подписка по DataType (поддерживает все типы свечей)
ISubscriptionHandler<ICandleMessage> SubscribeCandles(
DataType dt,
bool isFinishedOnly = true,
Security security = default);
// Подписка с готовым объектом Subscription
ISubscriptionHandler<ICandleMessage> SubscribeCandles(Subscription subscription);
Параметр isFinishedOnly по умолчанию true -- обработчик получает только завершенные свечи.
SubscribeTicks
Подписка на тиковые сделки:
ISubscriptionHandler<ITickTradeMessage> SubscribeTicks(Security security = null);
ISubscriptionHandler<ITickTradeMessage> SubscribeTicks(Subscription subscription);
SubscribeLevel1
Подписка на данные Level1 (лучшие цены bid/ask, последняя сделка и другие поля):
ISubscriptionHandler<Level1ChangeMessage> SubscribeLevel1(Security security = null);
ISubscriptionHandler<Level1ChangeMessage> SubscribeLevel1(Subscription subscription);
SubscribeOrderBook
Подписка на стакан котировок:
ISubscriptionHandler<IOrderBookMessage> SubscribeOrderBook(Security security = null);
ISubscriptionHandler<IOrderBookMessage> SubscribeOrderBook(Subscription subscription);
Если параметр security не указан, используется Security стратегии.
Интерфейс ISubscriptionHandler
Объект ISubscriptionHandler<T> предоставляет следующие методы:
Start / Stop
Запуск и остановка подписки:
handler.Start(); // вызывает Subscribe
handler.Stop(); // вызывает UnSubscribe
Bind (без индикаторов)
Привязка простого обработчика данных:
handler.Bind(Action<T> callback);
Bind (с индикаторами)
Привязка обработчика с одним или несколькими индикаторами. Индикатор автоматически обрабатывает входящие данные, и обработчик получает уже рассчитанное значение:
// Один индикатор -- значение типа decimal
handler.Bind(IIndicator indicator, Action<T, decimal> callback);
// Два индикатора
handler.Bind(IIndicator ind1, IIndicator ind2, Action<T, decimal, decimal> callback);
// До восьми индикаторов
handler.Bind(ind1, ind2, ind3, ..., callback);
// Массив индикаторов
handler.Bind(IIndicator[] indicators, Action<T, decimal[]> callback);
Обработчик с Bind вызывается только тогда, когда все индикаторы вернули непустое значение.
BindWithEmpty
Аналогичен Bind, но обработчик вызывается даже если индикатор вернул пустое значение. Значения представлены как decimal?:
handler.BindWithEmpty(IIndicator indicator, Action<T, decimal?> callback);
BindEx
Предоставляет доступ к полному объекту IIndicatorValue вместо извлеченного decimal:
handler.BindEx(IIndicator indicator, Action<T, IIndicatorValue> callback, bool allowEmpty = false);
Пример: стратегия с индикаторами
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);
// Привязка двух индикаторов -- обработчик вызывается,
// когда оба индикатора сформированы
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();
// Настройка графика
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, shortSma);
DrawIndicator(area, longSma);
DrawOwnTrades(area);
}
}
}
Пример: подписка на тики
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeTicks()
.Bind(tick =>
{
if (!IsFormedAndOnlineAndAllowTrading())
return;
this.AddInfoLog("Тик: цена={0}, объем={1}", tick.Price, tick.Volume);
})
.Start();
}
Пример: подписка на стакан
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("Спред: {0}", spread);
}
})
.Start();
}
Отличия от ручного создания подписки
| Аспект | Ручная подписка | Высокоуровневый метод |
|---|---|---|
| Создание | new Subscription(DataType, Security) |
SubscribeCandles(tf) |
| Обработка данных | Подписка на события коннектора | Bind(callback) |
| Индикаторы | Ручной вызов indicator.Process() |
Автоматически через Bind(indicator, callback) |
| Регистрация индикаторов | Ручное добавление в Indicators |
Автоматически при Bind |
| Отрисовка на графике | Ручная интеграция с IChart |
DrawCandles, DrawIndicator |
Высокоуровневые методы рекомендуется использовать в большинстве стратегий, так как они значительно сокращают объем кода и уменьшают вероятность ошибок.