Система таймеров
Обзор
Стратегии в StockSharp поддерживают встроенную систему таймеров, позволяющую выполнять действия через определенные интервалы времени. Таймеры работают на основе механизма WhenIntervalElapsed коннектора и корректно функционируют как в реальной торговле, так и при бэктестинге (используя виртуальное время эмулятора).
Таймеры удобны для:
- Периодической проверки условий рынка
- Ребалансировки портфеля через фиксированные интервалы
- Закрытия позиций по времени
- Мониторинга состояния стратегии
Интерфейс ITimerHandler
Таймер управляется через интерфейс ITimerHandler, который предоставляет следующие члены:
| Член | Описание |
|---|---|
Start() |
Запускает таймер. Возвращает ITimerHandler для цепочки вызовов |
Stop() |
Останавливает таймер. Возвращает ITimerHandler для цепочки вызовов |
Interval |
Интервал срабатывания таймера (чтение и запись) |
IsStarted |
Признак того, что таймер запущен |
Dispose() |
Освобождает ресурсы и останавливает таймер |
Методы создания таймеров
CreateTimer
Создает таймер, но не запускает его. Запуск производится отдельным вызовом Start():
ITimerHandler CreateTimer(TimeSpan interval, Action callback);
StartTimer
Создает и сразу запускает таймер. Эквивалентно CreateTimer(...).Start():
ITimerHandler StartTimer(TimeSpan interval, Action callback);
Интервал должен быть положительным значением (> TimeSpan.Zero), иначе будет выброшено исключение.
Управление таймером
Таймер можно останавливать и запускать повторно:
var timer = CreateTimer(TimeSpan.FromMinutes(1), MyCallback);
// Запустить
timer.Start();
// Остановить
timer.Stop();
// Изменить интервал
timer.Interval = TimeSpan.FromMinutes(5);
// Запустить снова
timer.Start();
// Освободить ресурсы
timer.Dispose();
Пример использования
public class TimerStrategy : Strategy
{
private ITimerHandler _checkTimer;
private ITimerHandler _closeTimer;
private readonly StrategyParam<TimeSpan> _checkInterval;
private readonly StrategyParam<TimeSpan> _maxHoldTime;
public TimeSpan CheckInterval
{
get => _checkInterval.Value;
set => _checkInterval.Value = value;
}
public TimeSpan MaxHoldTime
{
get => _maxHoldTime.Value;
set => _maxHoldTime.Value = value;
}
public TimerStrategy()
{
_checkInterval = Param(nameof(CheckInterval), TimeSpan.FromMinutes(1));
_maxHoldTime = Param(nameof(MaxHoldTime), TimeSpan.FromHours(4));
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Таймер для периодической проверки условий рынка
_checkTimer = StartTimer(CheckInterval, OnCheckTimer);
// Таймер для принудительного закрытия позиции (создаем, но не запускаем)
_closeTimer = CreateTimer(MaxHoldTime, OnCloseTimer);
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5));
subscription
.Bind(ProcessCandle)
.Start();
}
private void OnCheckTimer()
{
if (!IsFormedAndOnlineAndAllowTrading())
return;
this.AddInfoLog("Проверка условий рынка в {0}", CurrentTime);
// Периодическая проверка состояния позиции
if (Position != 0)
{
this.AddInfoLog("Текущая позиция: {0}", Position);
}
}
private void OnCloseTimer()
{
if (Position != 0)
{
this.AddInfoLog("Время удержания позиции истекло, закрытие");
ClosePosition();
// Остановить таймер закрытия после срабатывания
_closeTimer.Stop();
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (candle.OpenPrice < candle.ClosePrice && Position == 0)
{
BuyMarket();
// Запустить таймер принудительного закрытия
_closeTimer.Start();
}
}
}
В этом примере используются два таймера: один для периодической проверки состояния (StartTimer -- создан и сразу запущен), второй для ограничения времени удержания позиции (CreateTimer -- создан, но запускается только при входе в позицию).