Изображение блога
OS_Engine_team
OS_Engine_team Блог компании OsEngine
Вчера в 18:09

Механика внешних стопов в OsEngine

В статье рассматривается механика внешних (серверных) стоп-ордеров в OsEngine: как поддержка включается в коннекторе, какие коннекторы её имеют, как устроен жизненный цикл внешнего стопа и как он хранится внутри позиции.

До этого момента все стопы внутри платформы были внутренние. Теперь у нас появился механизм для выставления внешних. Пока в тестовом режиме и не для всех коннекторов. После бета-тестирования и как устоится – данный вид стопов будет проброшен по большинству популярных коннекторов в OsEngine.

Механика внешних стопов в OsEngine

 

1) Что такое внешний стоп?

Внутренний стоп-приказ хранится внутри OsEngine: движок сам отслеживает цену последней сделки и отправляет ордер на рынок только после достижения цены активации.

Внешний стоп-приказ сразу отправляется на биржу и хранится там. За ценой активации следит биржа и сама порождает заявку при касании уровня. Основные следствия:

стоп срабатывает, даже когда OsEngine выключен или потерял связь с сервером;

исключается задержка между касанием уровня и выставлением заявки — активацию выполняет биржа;

стоп виден в терминале брокера как обычный стоп-ордер.

 

2) Как поддержка включается в коннекторе?

Каждый коннектор в OsEngine декларирует свои возможности через интерфейс IServerPermission. За внешние стопы отвечает флаг StopOrdersIsSupport:

public bool StopOrdersIsSupport

{

    get { return true; } // коннектор поддерживает внешние стопы

}

Если флаг включён, коннектор маршрутизирует ордера с типом StopLimit и StopMarket не в обычный торговый поток, а в специализированный API стоп-ордеров биржи. Если флаг выключен, все методы выставления внешних стопов автоматически откатываются на внутренние — код робота при этом не меняется.

На уровне ядра признаком внешнего стопа являются два значения перечисления OrderPriceType — StopLimit и StopMarket — в сочетании с полем StopPrice (цена активации) у ордера.

 

3) Какие коннекторы поддерживают внешние стопы?

Внешние стоп-ордера, на момент выхода поста, поддерживает коннектор Т-Инвестиции. Реализация построена на gRPC-сервисе StopOrdersService Tinkoff Invest API:

PostStopOrder — выставление стоп-ордера (stop-limit и stop-market);
CancelStopOrder — отзыв стоп-ордера;
GetStopOrders — запрос активных стопов и истории (используется при восстановлении после переподключения);
OrderStateStream — поток событий: статусы стоп-ордеров и порождённых ими заявок приходят в коннектор в реальном времени.

На остальных коннекторах флаг StopOrdersIsSupport выключен, и внешние стопы прозрачно работают как внутренние. Архитектура открыта: чтобы подключить внешние стопы на новом коннекторе, достаточно включить флаг и обработать типы StopLimit / StopMarket при отправке, отзыве и приёме статусов ордеров.

 

4) Общая механика работы

Жизненный цикл внешнего стопа:

1) Робот или пользователь выставляет стоп-ордер (из кода — методы *OnServer, из интерфейса — чекбокс «Серверный стоп ордер» в окнах открытия, закрытия и доливки позиции).

2) Ордер уходит на биржу и переходит в статус Active. Он хранится на бирже, OsEngine следит за его статусом через поток событий.

3) Цена касается уровня активации — биржа активирует стоп и порождает дочернюю заявку: Limit для stop-limit, Market для stop-market.

4) Сам стоп-ордер завершает жизнь и приходит в робота со статусом Cancel — это штатное поведение, а не отмена пользователем.

5) Исполнение приходит на дочерней заявке: сделки (MyTrade) привязываются к ней.

 

Дополнительные свойства механики:

  • Цена выставленного стопа не редактируется: изменение уровня выполняется парой операций «отмена + новый ордер».
  • После перезапуска или переподключения активные стопы автоматически запрашиваются с сервера и восстанавливаются в журнале.
  • Когда позиция полностью закрыта, оставшиеся активные стопы на её закрытие снимаются автоматически.

 

5) Архитектура внутри позиции

Позиция в OsEngine хранит два списка ордеров: OpenOrders (ордера открытия и доливки) и CloseOrders (ордера закрытия). Внешний стоп — обычный объект Order в одном из этих списков, с характерным набором полей:

  • TypeOrder — StopLimit или StopMarket: признак внешнего стопа;
  • StopPrice — цена активации (триггер);
  • Price — лимитная цена дочерней заявки (только для stop-limit);
  • IsStopOrProfit — ордер создан для закрытия по стопу или профиту;
  • ChildOrderNumberMarket — биржевой номер дочерней заявки, порождённой при активации;
  • ParentOrderNumberMarket — у дочерней заявки: биржевой номер стопа-родителя.

Ордера в списках лежат в хронологическом порядке: сначала стоп, после активации в конец списка дописывается дочерняя заявка. Типичное состояние позиции после срабатывания стопа на вход и выставления стопа на выход:

Типичное состояние позиции после срабатывания стопа на вход и выставления стопа на выход выглядит так. В списке OpenOrders лежат два ордера: первым идёт стоп-лимит на вход в статусе Cancel — биржа активировала его и погасила; следом — исполненная дочерняя лимитная заявка в статусе Done. Дочерняя заявка ссылается на стоп через поле ParentOrderNumberMarket, а стоп — на дочернюю заявку через поле ChildOrderNumberMarket. В списке CloseOrders в этот момент находится один активный стоп-лимит на закрытие позиции.

Связывание выполняет ядро журнала (PositionController): когда от сервера приходит ордер с заполненным ParentOrderNumberMarket, ядро находит стоп-родителя в позициях и прикрепляет дочерний ордер к той же позиции. Поэтому открытие и закрытие позиции внешними стопами корректно отражается в журнале, на графике и в расчёте прибыли без участия робота.

Поля StopPrice, ParentOrderNumberMarket и ChildOrderNumberMarket сериализуются вместе с ордером, поэтому связи «стоп — дочерняя заявка» переживают перезапуск приложения.

Механика внешних стопов в OsEngine

 

6) Программный интерфейс

Все методы относятся к торговой вкладке робота BotTabSimple.

Открытие позиции:

  • BuyAtStopOnServer(decimal volume, decimal priceLimit, decimal priceActivation) и SellAtStopOnServer(...) — внешний стоп-лимит;
  • BuyAtStopMarketOnServer(decimal volume, decimal priceActivation) и SellAtStopMarketOnServer(...) — внешний стоп-маркет.


Доливка к открытой позиции:

  • BuyAtStopOnServerToPosition(Position position, decimal volume, decimal priceLimit, decimal priceActivation) и SellAtStopOnServerToPosition(...) — внешний стоп-лимит;
  • BuyAtStopMarketOnServerToPosition(Position position, decimal volume, decimal priceActivation) и SellAtStopMarketOnServerToPosition(...) — внешний стоп-маркет.


Закрытие позиции:

  • CloseAtStopOnServer(Position position, decimal priceActivation, decimal priceOrder) — внешний стоп-лимит на закрытие (есть перегрузки с объёмом и именем сигнала);
  • CloseAtStopMarketOnServer(Position position, decimal priceActivation) — внешний стоп-маркет на закрытие.


Отмена ордеров:

  • CloseAtStopOnServerCancel(Position position) — отзыв внешних стопов конкретной позиции;
  • CloseAtStopOnServerCancel() — отзыв внешних стопов всех открытых позиций вкладки;
  • CloseOrder(Order order) — отзыв произвольного ордера, включая внешний стоп.


На серверах без поддержки и в тестере все эти методы автоматически откатываются на внутренние стопы, поэтому один и тот же робот работает везде без изменений кода. Проверить поддержку можно свойством вкладки ServerIsSupportStopOrders.

Готовый пример — робот ServerStopOrdersSample (папка Robots/TechSamples): выставляет внешний стоп-лимит на покупку, ожидает активации заданное число свечей, перевыставляет ордер по актуальной цене и после открытия позиции сопровождает её внешним стопом на закрытие.

 

 

Удачных алгоритмов!

Комментарии открыты для друзей!

Механика внешних стопов в OsEngine
https://smart-lab.ru/company/os_engine/blog/1024149.php

Скачать OsEngine: https://github.com/AlexWan/OsEngine

Официальная поддержка OsEngine в MAX: https://max

Канал Научный трейдинг в MAX: https://max.ru/

 

Поддержка OsEngine в Телеграм: https://t.me/osengine_official_support 

Канал Научный трейдинг (Bad Quant) в Телеграм: https://t.me/bad_quant

Механика внешних стопов в OsEngine
https://www.tbank.ru/invest/

Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
0 Комментариев

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн