В этой статье расскажу о некоторых интересных проблемах, с которыми встретился в процессе написания торгового робота облигациями.
Для контекста — схема робота была приведена в
этой статье.
Отправка тысяч заявок — это долго
В виду того, что на Мосбирже на рынке облигаций (и не только) заявки не переносятся через ночь, каждое утро надо выставлять в стакан на продажу то, что напокупал ранее.
Когда речь идёт о выставлении тысяч заявок через Quik, невольно сталкиваешься с тем, что это:
— долго;
— возможно дорого (чревато платежами за большой напор заявок).
В самом начале я отправлял заявки синхронной функцией TRANS2QUIK_SEND_SYNC_TRANSACTION. Этого было вполне достаточно на малых объёмах. Но на большем объёме стало туговато.
Синхронная отправка:

Все заявки выставляются за 6.5 минут, более половины времени аукциона открытия. А можно быстрее?
Решение простое — переключаемся на асинхронную отправку функцией TRANS2QUIK_SEND_ASYNC_TRANSACTION. Но тут есть другие проблемы:
— коллбэк асинхронной отправки не содержит пользовательский transaction_id;
— следовательно, коллбэк я не жду, и между асинхронной отправкой заявки и появлением её в таблице заявок (в любом статусе) может пройти много времени, и тогда робот может отправить эту заявку более одного раза.
Хорошо, в таком случае будем кешировать отправленные transaction_id в память на какое-то короткое время, чтобы не отправлять лишний раз.
Асинхронная отправка:
45 секунд. Всё круто, да? Нет, т.к. в логах Quik видно: «Превышено максимальное количество транзакций 50 в интервале 1 сек».
Пу-пу-пуууу, а на некоторых тарифах такое превышение конвертируется в заработок брокера.
Ясно. Введём рейтлимит отправки.
Асинхронная отправка с рейтлимитом:

2 минуты. Есть пространство для роста.
Наверное, можно предположить, что, имея прямое подключение до серверов биржи, можно было бы не выполнять все эти приседания. Но, учитывая свои объёмы и доходность, платить за такой доступ смысла не вижу.
ask, который я покупаю — мой же ордер на продажу
Допустим, алгоритм настроен так, что свободные средства тратятся на покупку инструмента с наибольшим потенциалом доходности на данный момент.
Для этого сканируются все стаканы и выбирается самый доходный ask. И бывает так, что самый доходный ask — это моя жа заявка:
Помимо тщетных попыток купить самого себя, навскидку есть следующие варианты:
— Ждать. Т.е., беря приведённый выше пример, ждать удовлетворения всех моих завок до 98.38 (если эта цена к тому моменту тоже будет лучшей среди всех стаканов) либо ждать чей-то более доходный ask (в этом или другом стакане). Для простоты опустим случай, когда на лучшей цене находится моя заявка вместе с чьей-то ещё, и я не знаю, кто в голове очереди (на одной цене заявки выстроены в очередь, в хронологическом порядке их поступления на биржу).
— Пропускать этот инструмент и переходить к другому стакану в соответствии с доходностью ask-ов. Но тут есть другая проблема — тогда я упускаю лучшую в моменте доходность.
— Перемещать выше в стакане этот свой лучший ask. Но тут есть другая проблема — перемещение в стакане не является атомарным с т.з. всей моей системы (либо я ещё не придумал, как сделать это атомарным), т.е. в процессе может, например, оборваться связь и, как следствие, в БД и в стакане будут разные состояния (и синхронизировать их — значит сильно усложнять вещи, а где тонко, там и рвётся).
Есть ещё варианты, но для простоты опущу их. Пока я выбрал первый вариант — ждать.
Робот иногда начинает сливать
Эта проблема относится не к Quik, а сугубо к кривизне рук, но всё равно поведаю о ней, т.к. забавно.
Покупай дешевле, продавай дороже — что может пойти не так?
На скриншоте видно, как робот покупает выше, продаёт ниже — это гайзенбаг, возникает раз в несколько месяцев, и его я пока ещё не исправил (а может и исправил, но не подозреваю об этом). Кстати, в поисках проблемного места мне не помогли даже железные друзья.
Уход в минус по деньгам
Источником истины по деньгам является Quik (его таблица depo_limits), и обновления по ней могут доезжать не сразу, что иногда приводит к перерасходу свободных средств и уходу в небольшой минус.
Наивное решение — получать состояние счёта в самом начале торгового дня, увеличивать/уменьшать при торговле на своей стороне и опираться на то, что получается в итоге. Но это решение не подходит, т.к. тут надо как-то учитывать поступления купонов, амортизаций, пополнения счёта и т.п., а это большая сложнота. Надо как можно проще.
На данный момент эта проблема пока не решена, а точнее — когда ушёл в минус (а это бывает редко и на чуть-чуть), подкидываю денег или продаю парочку лотов руками.
Медленная работа робота в целом
Это стало ощущаться ещё до проблем с долгой отправкой заявок на премаркете (описал выше).
Если в одном инстансе Quik открыть кучу инструментов (стаканы, таблицы), то всё в нём работает ооочень меееедленно, в т.ч. медленно работают потоки робота.
Решение простое — вынести робота на отдельный инстанс Quik, где открыть максимум окошко с запущенными скриптами.
Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
— Есть фронтраннеры, как бы смешно это не звучало для рынка облигаций.
— Это усложнение алгоритма и ведения позиции (в контексте моей системы).
Но опять же, любое решение — это компромисс. И я даже соглашусь с Вами, что робот странный в контексте и понимании другого человека.
Один из вариантов набора позиции (его и описал в данной статье) — робот всегда старается купить самый доходный на данный момент инструмент. И может такое произойти, что в стакане этого инструмента самая доходная лимитка на продажу — моя же. Хоть это и не одно и то же, но другие трейдеры писали о кросс-сделках в своих алгоритмах на срочном рынке.Есть розетки с таймером. Выключаем розетку, заведя таймер на достаточное кол-во времени для выключения ноутбука.
Да, это крайнее решение.
Понятнее не стало, но опять же — дело хозяйское.
А для ноутбука лучше купить умный нажиматель кнопок, чем умную розетку. Ну если кнопка у ноута достаточно удобно для нажимателя расположена.
Как бы Вы вели позицию при условии обязательной продажи всех лотов до даты погашения/оферты? Не воспримите как пассивную агрессию. Мне действительно интересно.Вы не поверите! О нажимателе кнопок хотел написать где-то в следующих статьях.
Между делом — нынешний нажиматель не захотел управляться через хаб удалённо. Но да, замечание ценное, спасибо!
Если не секрет, почему не смотрели в сторону openapi/gRPC от брокеров?
Смотря про какой алготрейдинг мы говорим. Для HFT — на 100% согласен с Вами. Для моего «автоматизированного инвестирования» с горем пополам сгодится. Но да, в целом Quik сомнителен как для алготрейдинга, так и для всего остального.Переподключение есть, и оно работает. Но да, чтобы сделать автологин (после загрузки ОС, например), надо подставить костылик (простой, работает).У моего брокера нет API. Уходить от этого пока не хочу, но новые идеи, скорее всего, буду реализовывать у других брокеров (если подойдут по условиям).
Несколько раз сталкивался с таким на сильных движениях рынка, такое ощущение, что специально так читерили. Брокер ВТБ, если что.
Еще как-то был глюк, когда quik врал со свечами, показывал заниженные значения для индексов. В идеале маркет дату надо брать с разных брокеров и сверять на отклонения.
Да, на сильных движениях проявляются разные проблемы, одна из которых у меня — задержка в поступлении данных (состояния счёта, сделок). Приходится сооружать костыли.Да, тоже такое наблюдал. Тут помогает удаление директории archive. Вероятно, такое происходит из-за внутренних гонок или из-за кривоватого I/O в терминале.