Eugene Bright
Eugene Bright личный блог
18 августа 2025, 14:56

Коллбэки своими руками. Личный опыт.


              Не знаю, может, я такой бестолковый или возраст наложил свою замшелую лапу на мозг, но какое-то время назад (что-то около 2018 года) пропало желание экспериментировать с коллбэками (типа, OnTransReply, OnOrders  и прочие) в QUIK’е. Наверное, это — полезные инструменты, но у меня как-то не сложились отношения с ними. То не приходят, то задваиваются, то приходят не вовремя и пачками за все пропущенные периоды. Как-то ненадежно, в общем.

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

              В общем, в том далеком уже году бросил я это занятие и решил заменить терминальные коллбэки своими собственными суррогатами. Время показало, что эти «суррогаты» неплохо себя зарекомендовали, а бот нормально их переваривает.

              В конце поста приложу логическую блок-схему «суррогата», которая может показаться излишне сложной для неподготовленного ума, но, прошу поверить, что дело того стоит:

  • Нет задваивания заявок,
  • Абсолютно стало «побоку» на действия брокера, когда у вас внезапно, «в самый интересный и ответственный момент», отваливается терминал («удаленный хост разорвал соединение…» или «вы уже работаете в системе…»), а бот продолжает генерить команды по работе с ордерами (выдача новых или перемещение неисполненных),
  • Даже в случае продолжительного дисконнекта и фактической потери ботом части рынка, после восстановления коннекта бот сразу встает в нужную позицию. Да, потери и убытки возможны, но зато не теряется смысл стратегии.
  • Исключение ситуаций, когда «вы не можете снять заявку…» или «вы не можете выставить заявку…».

 

Идея такова:

  1. Разбить «жизнь» заявки на этапы,
  2. Ввести процедуры верификации каждого этапа (собственно, это и есть «суррогаты» коллбэков»),
  3. Задать критерии начала и окончания каждого этапа с передачей заявки или состояния бота последовательно от начала её «жизни» до логического завершения (реализации), а также возврат бота в состояние готовности «0», т.е. на отработку самой стратегии.
  4. Завести регистры учета параметров и состояний ордеров, однозначно позволяющие управлять (регистрировать, разрешать реализацию этапа, блокировать этап или активность бота в части выдачи новых заявок).
  5. Создание механизма СИНХРОНИЗАЦИИ действий бота с информационным потоком терминала, построенный по принципу «ПО СОБЫТИЯМ», т.е. бот выполняет каждое последующее действие ТОЛЬКО ПОСЛЕ ПОСТУПЛЕНИЯ ОЧЕРЕДНОЙ ЗАКОНОМЕРНОЙ порции информации.

 

 

Для целей реализации создан инструмент ТРИГГЕРОВ, переключающих последовательно СТАДИИ РЕАЛИЗАЦИИ ордеров. Таких этапов – 4:

ОСНОВНОЙ РЕЖИМ – генерация системных ордеров по стратегии (выдача заявки, проверка её состояния с помощью test.bit-операции), 

РЕЖИМ ЗАВИСШИХ ОРДЕРОВ – реализация перемещаемых ордеров в случае, если заявка не реализована и «висит» в стакане дольше, чем время реакции ТС, назначенное параметром Sleep (по умолчанию, 10 секунд).

РЕЖИМ ОТЛОЖЕННЫХ ОРДЕРОВ – реализация заявок, не прошедших контроль терминала (ошибки, сбои и т.д.) в первый раз.

РЕЖИМ ВЫРАВНИВАНИЯ ПОЗИЦИЙ – процедура выравнивания позиции в терминале с РАСЧЕТНОЙ ПОЗИЦИЕЙ, хранящейся в системе Управленческого Учета бота в соответствии со стратегией.

 

Алгоритм (кратко):

В начале цикла расчетов бота, а также на каждой стадии «жизни» заявки, проверяются состояния триггеров, записанные в реестрах. Так определяется этап «жизни» заявки, её параметры и наличие блокировок по ней.

Эти состояния сверяются с параметрами из соответствующих QUIK-таблиц: Таблица лимитов, Таблица Заявок, Таблица Сделок. Эти сверки производятся с помощью bit.test-функции (ссылка на google-диске: простенький калькулятор bit-значений в виде excel-файла приложен).

Когда состояние заявки соответствует целевому, регистр триггера разблокируется.

 

Блок-схема «суррогата» (в коде занимает около 200 строк):

 Коллбэки своими руками. Личный опыт.
(ссылка на ЯДиск, если не читается)

Может, это избыточная доработка, но я другого выхода из ситуаций, вытекающих из нечеткостей работы QUIK’а и из произвола брокера, не нашел.

Возможны другие варианты? Пишите, обменивайтесь решениями. Полагаю, будет всем полезно.

 

На вопросы по теме отвечаю. Попытки потроллить пресекаю.

8 Комментариев
  • nicknh
    18 августа 2025, 15:58

    Очень давно, почти сразу перестал использовать колбеки. Подход как для чтения данных с датчиков как в системах реального времени — самое надежное решение. Опять же мы же про деньги говорим, а не про картинки с котиками.

     

    Это Вы, наверно, еще не ловили искажение индексов таблицы ордеров после вызова колбека OnCleanUp, который брокер вызывает после принудительного разрыва соединения. Писал про это forum.quik.ru/forum10/topic9201/

  • Synthetic
    18 августа 2025, 17:38
    Идея такова:

    Поздравляю!
    Вы заново изобрели такую важную и полезную штуку как «транзакция».
  • Synthetic
    18 августа 2025, 19:04
    боты «крутят» циклы «по времени», а я предложил — «по событиям»

    Извините. Вы просто выражаетесь своеобразно. Мы то вот так привыкли…
    event-driven programming — парадигма программирования, в которой выполнение программы определяется событиями.
  • Prophetic
    19 августа 2025, 10:04
    Каждый выбирает свою дорогу. Я тоже отказался от событийной модели достаточно быстро, и перешел на «циклы». Но везде есть свои плюсы и минусы. Когда у вас на одном ноуте одновременно работает пол сотни задач (задача = алгоритм + инструмент), то встает вопрос оптимизации ресурсов. И цикличная модель, в этом плане, мне нравится больше. Первые версии системы сжирали более 95% ресурсов CPU, и начинали тормозить всюд систему. Дальнейшие доработки занчительно снизили нагрузку, и ноут, кторому уже больше 10-ти лет, спокойно справляется с задачей торговой станции. Но я не занимаюсь HFT, и у меня достаточно ресурсоемкие алгоритмы, в части проводимых расчетов. Так что мне такой подход подходит, но он может оказаться не применим для некоторых других видов торговли.
    Данные о транзакциях и заявках храню в файлах. Это защищает от сбоев, и позволяет легко восстанавливать работу после «перезагрузки».
    Пример файла (под одну «задачу»):

    <?xml version=«1.0»?>
    <DealParam xmlns:xsi=«www.w3.org/2001/XMLSchema-instance» xmlns:xsd=«www.w3.org/2001/XMLSchema»>
    <startTime>2025-08-18T18:37:14.5925157+03:00</startTime>
    <lifeTimeDeal />
    <posOperation>Open</posOperation>
    <operation>Buy</operation>
    <status>Closed</status>
    <orderNumbers>
    <long>69592992656</long>
    </orderNumbers>
    <securityCode>GAZP</securityCode>
    <mailTo>v.hohlov@hotmail.com</mailTo>
    <robotMode>work</robotMode>
    <code_ts>InvestPortfolio.work</code_ts>
    <signal>Portfolio.Buy.Buy.137,17</signal>
    <positionID>InvestmentGAZPInvest.Bokovik.Long</positionID>
    <targetQty>1</targetQty>
    <limitMaxOrderQty>0</limitMaxOrderQty>
    <qtytrades>1</qtytrades>
    <old_toolqty>1180</old_toolqty>
    <toolqty>1190</toolqty>
    <transactionID>0</transactionID>
    <targetPrice>137.18</targetPrice>
    <limitPriceDeviation>0.2</limitPriceDeviation>
    <price_trades>137.17</price_trades>
    <price_entrance>132.32</price_entrance>
    <stoploss>0</stoploss>
    <takeprofit>0</takeprofit>
    <takeprofit2>0</takeprofit2>
    </DealParam>

    В конечном итоге, я считаю, что важно не слишком усложнять процессы. Чем проще все реализовано, тем стабильнее и быстрее работает. Возникающие в процессе эксплуатации ошибки/сбои и т.п. конечно же ведут к доработкам, которые обычно усложняют процессы. И тут важно не переборщить

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

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