Блог им. HOME
Не знаю, может, я такой бестолковый или возраст наложил свою замшелую лапу на мозг, но какое-то время назад (что-то около 2018 года) пропало желание экспериментировать с коллбэками (типа, OnTransReply, OnOrders и прочие) в QUIK’е. Наверное, это — полезные инструменты, но у меня как-то не сложились отношения с ними. То не приходят, то задваиваются, то приходят не вовремя и пачками за все пропущенные периоды. Как-то ненадежно, в общем.
Периодически отслеживаю на форуме ARQA, но время идет, а проблема, похоже не решается, т.к. много вопросов задаются пользователями, а действенных советов не прибавляется.
В общем, в том далеком уже году бросил я это занятие и решил заменить терминальные коллбэки своими собственными суррогатами. Время показало, что эти «суррогаты» неплохо себя зарекомендовали, а бот нормально их переваривает.
В конце поста приложу логическую блок-схему «суррогата», которая может показаться излишне сложной для неподготовленного ума, но, прошу поверить, что дело того стоит:
Идея такова:
Для целей реализации создан инструмент ТРИГГЕРОВ, переключающих последовательно СТАДИИ РЕАЛИЗАЦИИ ордеров. Таких этапов – 4:
ОСНОВНОЙ РЕЖИМ – генерация системных ордеров по стратегии (выдача заявки, проверка её состояния с помощью test.bit-операции),
РЕЖИМ ЗАВИСШИХ ОРДЕРОВ – реализация перемещаемых ордеров в случае, если заявка не реализована и «висит» в стакане дольше, чем время реакции ТС, назначенное параметром Sleep (по умолчанию, 10 секунд).
РЕЖИМ ОТЛОЖЕННЫХ ОРДЕРОВ – реализация заявок, не прошедших контроль терминала (ошибки, сбои и т.д.) в первый раз.
РЕЖИМ ВЫРАВНИВАНИЯ ПОЗИЦИЙ – процедура выравнивания позиции в терминале с РАСЧЕТНОЙ ПОЗИЦИЕЙ, хранящейся в системе Управленческого Учета бота в соответствии со стратегией.
Алгоритм (кратко):
В начале цикла расчетов бота, а также на каждой стадии «жизни» заявки, проверяются состояния триггеров, записанные в реестрах. Так определяется этап «жизни» заявки, её параметры и наличие блокировок по ней.
Эти состояния сверяются с параметрами из соответствующих QUIK-таблиц: Таблица лимитов, Таблица Заявок, Таблица Сделок. Эти сверки производятся с помощью bit.test-функции (ссылка на google-диске: простенький калькулятор bit-значений в виде excel-файла приложен).
Когда состояние заявки соответствует целевому, регистр триггера разблокируется.
Блок-схема «суррогата» (в коде занимает около 200 строк):

(ссылка на ЯДиск, если не читается)
Может, это избыточная доработка, но я другого выхода из ситуаций, вытекающих из нечеткостей работы QUIK’а и из произвола брокера, не нашел.
Возможны другие варианты? Пишите, обменивайтесь решениями. Полагаю, будет всем полезно.
На вопросы по теме отвечаю. Попытки потроллить пресекаю.
Очень давно, почти сразу перестал использовать колбеки. Подход как для чтения данных с датчиков как в системах реального времени — самое надежное решение. Опять же мы же про деньги говорим, а не про картинки с котиками.
Это Вы, наверно, еще не ловили искажение индексов таблицы ордеров после вызова колбека OnCleanUp, который брокер вызывает после принудительного разрыва соединения. Писал про это forum.quik.ru/forum10/topic9201/
Но мне не нужно проверять поле на наличие ВСЕХ граблей. Мне достаточно наступить на пару-другую, коими и оказались приведенные в тексте коллбеки.
Но я предполагал, что возможны и такие «подарки», что привели Вы.
Я уже не первый пост упоминаю о Системе Управленческого (внутреннего) Учета в моем боте. Он ведет все параметры торгов автономно, периодически сравнивая с QUIK'ом, но имея при этом приоритет.
Бот только транслирует данные УУ в терминал.
ЗЫ: в смысле «считывания показателей датчиков» мы с Вами, в принципе, соратники.
Поздравляю!
Вы заново изобрели такую важную и полезную штуку как «транзакция».
Дело не в названии.
Дело в том, что боты «крутят» циклы «по времени», а я предложил — «по событиям». Разница, конечно, не очевидна… Но до тех пор, пока событие происходит в пределах времени «прокрутки» бота. Как только событие «опоздает», возникнет некий эксцесс непонимания ботом ситуации.
Извините. Вы просто выражаетесь своеобразно. Мы то вот так привыкли…
Да, я не являюсь профессиональным программистом и потому не знаю соответствующего сленга.
Данные о транзакциях и заявках храню в файлах. Это защищает от сбоев, и позволяет легко восстанавливать работу после «перезагрузки».
Пример файла (под одну «задачу»):
<?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>
В конечном итоге, я считаю, что важно не слишком усложнять процессы. Чем проще все реализовано, тем стабильнее и быстрее работает. Возникающие в процессе эксплуатации ошибки/сбои и т.п. конечно же ведут к доработкам, которые обычно усложняют процессы. И тут важно не переборщить