VPM написал: "В последнее время несколько раз наблюдал такое: приходит OnTrade, в котором trans_id=0. Я знаю, что это промежуточная версия, поэтому в мой алгоритм вписано игнорировать такие вызовы, ожидая более полных. И почти всегда они приходят. Но в среднем 1-2 раза за день случается так, что полный OnTrade с ненулевым trans_id так и не приходит. В чём может быть причина?" Ответ очевиден может.
Ситуация, которую вы описываете, связана не с багом в вашем коде, а с особенностями того, как QUIK и брокерский шлюз доставляют информацию о сделках. Подобную ошибку в событийной модели допускают даже грамотные, опытные разработчики на QUIK. Используя "умную заявку" (один trans_id=const на весь жизненный цикл инструмента, для 3 таблиц) в своих подходах, отлавливал такую же проблему.
Почему полный OnTrade может не прийти? То, что за день теряется 1-2 полных события, — это тревожный, но, к сожалению, не уникальный случай для распределенных систем.
Вот наиболее вероятные причины:
* Потеря пакетов на сетевом уровне: Система QUIK и брокерский шлюз обмениваются большим количеством данных. В условиях нестабильной сети или высокой нагрузки пакет со вторым, полным, событием мог быть просто потерян.
* Сбои в очередях событий QUIK: В самом терминале или на стороне брокерского шлюза есть очереди событий. При переполнении или внутреннем сбое часть событий может быть отброшена, не доходя до вашего скрипта.
* Особенности логики брокерского шлюза: Хотя это менее вероятно, существует возможность, что в редких случаях логика шлюза, отправляющего два события (служебное и полное), дает сбой, и второе событие не генерируется.
Наверняка список можно расширить.
Ну у меня trans_id не const, а как раз уникальный для каждой заявки. А в остальном - ок, в целом я и сам догадывался, что причина либо в потерянных пакетах (хотя если используется протокол TCP, они должны были быть отправлены повторно), либо во внутренних сбоях quik. Видимо ничего здесь не сделать, придётся учитывать вероятность такой ошибки в коде.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
13.02.2026 10:11:48
Цитата
VPM написал: , Скажите на русском читаете, если нет, то какие слова Вам не понятны
Цитата
Более-менее все слова понятны, только непонятно, как они связаны с моим вопросом.
написал: Таким образом, до начала проверок и основного кода, ВСЕ trd сохраняются в текстовый файл.
1. Всю обработку вы делаете в служебном потоке коллбека (отличным от потока main). Этот поток в QUIK один и он обслуживает все запущенные скрипты QUIK. Когда он занят вашей обработкой он перестает выполнять свои служебные функции, в том числе, обработку вновь возникающих данных по сделкам. Если нет служебной очереди внутри QUIK, то возможны потери возникающих данных. В вашем варианте желательно как можно быстрее выполнять коллбек, например, записывая trd в очередь между коллбеком и потоком main (со sleep(50) ), в котором выполнять остальную обработку таблицы trd. Вариант реализации очереди выложен мной в соседней ветке пользователя VPM. 2. Если вам нужны данные по сделкам, то их можно получать готовыми из таблицы QUIK trade с помощью функции getItem. Зачем вы отрабатываете "сырые" коллбеки OnTrade?
Я наблюдал, что даже в тех случаях, если коллбек содержал прямую задержку (я в качестве эксперимента ставил 500 мс), это не приводило к потере данных. Т.е. если даже десять транзакций в секунду выполняются, да, обработка функций от них растягивается на 5 сек, но в итоге они все обработаны. В тех случаях, когда наблюдались потерянные данные, таких сверхбыстрых вызовов не было, т.е. кажется, причина в другом. Но на всякий случай сейчас я все дополнительные задержки в коллбеках убрал, и они реально выполняются мгновенно. Посмотрим, будет ли ошибка повторяться.
Предложенная вами очередь событий сильно усложнит код, поэтому без слишком явной необходимости мне не хотелось бы так делать. Такая очередь наверное нужна, если код использует тяжёлые вычисления типа машинного обучения и т.д. У меня ничего такого нет.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
12.02.2026 17:42:37
Цитата
Йцукен написал: , по каким классам инструментов наблюдается? В самой таблице сделок trans_id есть?
Я использую только класс TQBR, стандартную торговлю акциями, если вы об этом спрашивали. В таблице сделок да, trans_id есть. Но возможно именно у тех сделок, о которых речь, не было. Не проверял, в следующий раз как случится - посмотрю.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
09.02.2026 20:37:27
Замечу также, что ошибка возникает крайне редко. Я выше писал - 1-2 раза в день, но это было преувеличение. На самом деле вот сегодня она случилась трижды, а до этого в последний раз была 1-го февраля. При том что мой код работает ежедневно и выполняет сотни транзакций в день. Если бы бяка была в моём коде, она бы вылезала чаще.
Не видя вашего кода, сложно что-то сказать, но попробуйте сделать sleep(50) и посмотрите что будет. С задержкой 585000 ваш код в main практически отключен. Это так вами задумано?
В main выполняется очень маленькая и незначительная часть кода: обновление таблиц и проверка согласованности количества акций. Т.е. я держу текущее количество акций в отдельной переменной, и после каждой OnTrade обновляю эту переменную. Раз в 10 минут из main проверяю, что значение переменной равно текущему количеству акций, полученному напрямую. Таким образом и отлавливаю потерянные OnTrade. Весь остальной код, как здесь уже упоминали, выполняется прямо в колбэк-функциях.
Sleep(50) при таком подходе никак не поможет и ни на что не повлияет.
И вообще здесь ошибка от моего кода ну вообще никак не зависит. Код функции OnTrade в общих чертах выглядит так:
function OnTrade(trd) всю таблицу trd записать в текстовый файл проверить поле brokerref, если там не то, что мне нужно - return проверить завершённость OnTrade (trans_id!=0, наличие комиссии и т.д.), если незавершённый - return выполнение основных действий end
Таким образом, до начала проверок и основного кода, ВСЕ trd сохраняются в текстовый файл. И если возникает подозрение об ошибке, я захожу в этот текстовый файл и нахожу все trd с данным trd_num. И вот по ним я вижу, что полная версия таблицы с trans_id !=0 не приходила.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
09.02.2026 19:40:13
Сегодня опять случилась эта бяка. За секунду произошли четыре транзакции, по трём из них полная версия OnTrade (с ненулевым trans_id) не пришла. Видимо придётся убрать из скрипта эту дополнительную проверку. Но вообще факт неприятный.
написал: , Два вопроса, которые могут дать ответ. 1) С какой задержкой у вас Sleep в main? 2) есть ли у Вас очередь событий?
1) 585 секунд. 2) Не знаю. А что это?
(Предыдущее сообщение отправилось по ошибке, не ту клавишу нажал).
Тогда вероятнее всего Вы просто теряете сообщения, когда по заявке совершаются несколько сделок относительно быстро.
Непонятно. Насколько я знаю, все функции OnTrade приходят в одном потоке, т.е. даже если две сделки совершились строго одновременно, функции по ним вызовутся последовательно, и их невозможно потерять.
Кроме того, в приведённом примере интервал между сделками несколько секунд. Это не быстро. Быстро - это когда десятки сделок в секунду. Я такое видел, и мой скрипт их успешно обрабатывает.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
05.02.2026 01:35:11
Цитата
nikolz написал: , Два вопроса, которые могут дать ответ. 1) С какой задержкой у вас Sleep в main? 2) есть ли у Вас очередь событий?
1) 585 секунд. 2) Не знаю. А что это?
(Предыдущее сообщение отправилось по ошибке, не ту клавишу нажал).
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
05.02.2026 01:33:09
Цитата
nikolz написал: , Два вопроса, которые могут дать ответ. 1) С какой задержкой у вас Sleep в main?
Уточните, пожалуйста, версию Рабочего места QUIK, которую Вы в данный момент используете? Используется свой скрипт или какие-то готовые библиотеки? По каким именно сделкам не приходят trans_id, можете привести пример? Заполнен ли при этом параметр в Таблице Сделок в Рабочем месте?
Версия quik 12.6.0.53. Полностью свой скрипт. Например сделка на покупку одной акции SOFL. Последний раз ошибка была 1-го февраля. За короткий промежуток были совершены три абсолютно идентичные сделки по близкой цене: в 17:01:54, в 17:04:15, и в 17:05:29. Все три на покупку одной акции SOFL. По первой и третьей сделкам пришли три функции OnTrade. По второй сделке только одна. Замечу также, что по первой и третьей сделкам вместе с функциями OnTrade приходили также две функции OnOrder, по второй сделке функция OnOrder пришла только одна. Но в эти функции я не заглядывал, не могу сказать, в чём отличие (если это важно - могу заглянуть, всё сохранено). Каких-либо особых событий, предшествовавших этой ошибке, типа разрыва соединения и т.д., не наблюдалось.
написал: В последнее время несколько раз наблюдал такое: приходит OnTrade, в котором trans_id=0. Я знаю, что это промежуточная версия, поэтому в мой алгоритм вписано игнорировать такие вызовы, ожидая более полных. И почти всегда они приходят. Но в среднем 1-2 раза за день случается так, что полный OnTrade с ненулевым trans_id так и не приходит. В чём может быть причина? Я мог бы убрать эту дополнительную проверку из своего кода и обрабатывать такие вызовы, в принципе trans_id мне ни для чего не нужен, достаточно brokerref. Но ведь может не прийти что-то более важное. Например бывает, что приходит OnTrade с нулевой комиссией, и сразу после него ещё один OnTrade с заполненной комиссией. Здесь сбоев не было ни разу, но что если он тоже не придёт?
А зачем Вам trans_id в сделке?
Конкретно trans_id мне не нужен. Но если по протоколу он должен прийти, и не приходит, значит что-то пошло не так. В другой раз не прийти может что-то более серьёзное, например комиссия. Или это другое? Вопрос отчасти пересекается с моим предыдущим вопросом про повторные OnTrade ( ). Т.е. по trans_id=0 я пытался фильтровать OnTrade, которые заведомо не последние.
Не приходит полная версия OnTrade
Пользователь
Сообщений: Регистрация: 26.11.2025
01.02.2026 14:42:49
В последнее время несколько раз наблюдал такое: приходит OnTrade, в котором trans_id=0. Я знаю, что это промежуточная версия, поэтому в мой алгоритм вписано игнорировать такие вызовы, ожидая более полных. И почти всегда они приходят. Но в среднем 1-2 раза за день случается так, что полный OnTrade с ненулевым trans_id так и не приходит. В чём может быть причина? Я мог бы убрать эту дополнительную проверку из своего кода и обрабатывать такие вызовы, в принципе trans_id мне ни для чего не нужен, достаточно brokerref. Но ведь может не прийти что-то более важное. Например бывает, что приходит OnTrade с нулевой комиссией, и сразу после него ещё один OnTrade с заполненной комиссией. Здесь сбоев не было ни разу, но что если он тоже не придёт?
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
написал: Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Кстати раз уж вы выложили код, есть вопрос по вот этой строке. Сейчас проверил в тех сделках, которые у себя отлавливал: там есть поле broker_comission, которое я воспринимал как итоговую сумму всех комиссий. И оно больше, чем написанная вами сумма. Например для одного лота MOEX: tech_center_comission = 0 clearing_comission = 0.22 exchange_comission = 0.3 broker_comission = 1.57
Проверка по остатку на счёте показывает, что 1.57 - точное значение итоговой комиссии, т.е. уже включает в себя всё остальное (и ещё что-то).
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
написал: Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Код
Спасибо. Принцип такого костыля понятен, но очень надеялся, что можно как-то проще. Видимо нельзя.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 26.11.2025
09.01.2026 13:21:00
Цитата
Nikolay написал: Например, если поля broker_comission и broker_comission_currency не важны, то этот второй вызов бесполезен, а если важны, то уже нет.
Речь о том, как проигнорировать бесполезный вызов и не посчитать дважды то, что нужно? Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают (спрашивал об этом вот здесь: ). Значит нужно вводить отдельную переменную - количество акций, и при каждом OnTrade обновлять. Но тогда при повторном OnTrade происходит повторное обновление, и пожалуйста - ошибка.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 26.11.2025
09.01.2026 12:24:50
Опять отловил два повторных OnTrade, на этот раз совпадали все поля кроме broker_comission и broker_comission_currency (в первом они были 0 и пусто, во втором правильные). Можно ли как-то конкретно определить полный набор полей, которые я должен проверить, чтобы уверенно знать, что данный вызов OnTrade является последним по данной заявке? Речь только про заявки из скрипта qlua, строго на один лот.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 26.11.2025
06.01.2026 22:52:46
Создаю заявку из lua-скрипта на покупку ровно одной акции. Т.е. никаких финтов с частичным исполнением не может быть. При исполнении происходят два вызова функции OnTrade. Сделал полную распечатку всей таблицы от обоих вызовов. Отличие только в трёх полях: uid, on_behalf_of_uid, trans_id. При первом вызове все три нулевые, при втором все три - ненулевые.
Вопросы следующие: 1. Гарантируется ли, что вызов OnTrade, в котором эти поля нулевые, является не последним, т.е. я могу его игнорировать, т.к. после него будет следующий? 2. Гарантируется ли, что вызов, в котором эти поля ненулевые, является последним? 3. Являются ли эти три поля синхронными всегда? (Т.е. либо все три равны 0, либо все три не равны 0?) Т.е. можно ли проверять только одно из них, а не все три вместе?
Подскажите, пожалуйста, вы в терминале QUIK вы подключаетесь к серверу демо-доступа с нашего сайта или к серверу брокера?
Я не знаю, что такое демо-доступ. Вроде бы у меня не демо, а полноценный доступ. Подключаюсь к серверу брокера (сбербанк).
в таблице текущих торгов некоторые цены нулевые
Пользователь
Сообщений: Регистрация: 26.11.2025
28.12.2025 15:32:14
На скриншоте текущее состояние моей таблицы текущих торгов. Видно, что по акциям T, TUCH, X5 что-то странное, как будто торги не идут. Но функция getParamEx возвращает правильную цену, и в приложении сбер инвестиций тоже всё ок. Т.е. это ошибка в таблице квик. В чём может быть причина?
Я эту акцию добавлял сам, при изначальной установке квика её по умолчанию почему-то не было.
OnTrade отображает неверное количество акций, Изменения в состоянии счёта отображаются не мгновенно
Пользователь
Сообщений: Регистрация: 26.11.2025
27.12.2025 00:36:40
Предположим была заявка на покупку акции. В момент исполнения заявки вызывается OnTrade. Если из этой функции OnTrade напечатать текущий размер позиции с помощью getDepoEx, только что исполненная заявка там не будет учтена, т.е. напечатается неверное количество (которое было до исполнения заявки). Почему так происходит и как это исправить? Спустя несколько миллисекунд количество становится правильным, уже в следующих функциях. Но мне нужно в функции OnTrade использовать текущее количество акций. Как я могу его надёжно получить?
Разрыв соединения quik по ночам, Приходится каждое утро переподключаться
В Рабочем месте QUIK есть возможность настроить автоматическое восстановление связи с сервером в определенный период времени. Находится она в Система/Соединения. Вам нужно установить галочки напротив пунктов "Восстанавливать связь автоматически через" и "При восстановлении использовать только параметры последнего соединения".
В первой настройке нужно настроить временной промежуток, в которой Рабочее место будет подключаться к серверу автоматически. В вашем случае это с 07:00 до 03:00. Вторая настройка использует данные последнего подключения сервера. Важно, чтобы вы списке доступных вам серверов первым стоял тот, к которому вы хотите подключиться.
Не помогло. В указанное время приходит смс с паролем, и если его не ввести, соединение не устанавливается.
У каких брокеров нет смс-аутентификации?
Разрыв соединения quik по ночам, Приходится каждое утро переподключаться
Пользователь
Сообщений: Регистрация: 26.11.2025
18.12.2025 12:48:01
Здравствуйте. Пользуюсь системой quik версии 12.6.0.53 через брокера сбербанк. Каждую ночь ровно в 3 часа ночи происходит автоматический разрыв соединения, и в течение ночи подключение невозможно. Утром подключение становится возможным, но не автоматически, т.е. приходится вручную вводить пароль. В техподдержке сбера сказали, что да, они на ночь отключаются из-за тех. работ, никаких способов устранить это нет. Но проблема в том, что невозможно ставить скрипт на автоматическую работу по расписанию с утра, т.к. всё равно пока я сам не проснулся и не подключился, ничего работать не будет. В той же техподдержке сказали, что и это исправить нельзя, т.е. да, надо каждый день переподключаться заново, все, кто пользуется квиком, так делают. Соответственно все, кто хотят торговать в утреннюю сессию, исправно просыпаются в 7 утра.
Хотелось бы уточнить, насколько это правда.
Функции обратного вызова не вызываются одновременно?, Т.е. отследить изнутри OnTrade выполнение другого OnOrder невозможно?
Пользователь
Сообщений: Регистрация: 26.11.2025
14.12.2025 19:48:43
Допустим у меня есть заявка. Я хочу сразу, как только она сработает, прямо из функции OnTrade создать новую заявку. Чтобы убедиться, что заявка принята успешно, я дожидаюсь выполнения функции OnOrder, которая должна присвоить значение глобальной переменной. Т.е. схематично код выглядит так:
OnTrade(trd) somevariable = false ord = .... sendTransaction(ord) repeat sleep(100) until somevariable=true
OnOrder(ord) somevarialbe = true
Этот код не работает, т.к. функция OnTrade виснет в ожидании OnOrder, а OnOrder не вызывается, пока не завершится OnTrade (проверял, если в OnTrade поставить return после нескольких итераций цикла, OnOrder сразу вызывается)
Т.е. отследить изнутри OnTrade успешное выполнение новой заявки невозможно?
Поле trans_id для закрытия заявки: в чём смысл?, Есть ли примеры, где оно может быть использовано?
Пользователь
Сообщений: Регистрация: 26.11.2025
13.12.2025 23:58:46
Предположим я создал заявку, присвоив ей trans_id=1. При создании срабатывает OnOrder(ord), где ord.trans_id=1, ord.order_num = номер новой заявки. Теперь я хочу отменить эту заявку. Для этого я создаю новую транзакцию, в которой пишу trans_id=2, action = kill_order. Но при срабатывании OnOrder(ord) я опять вижу, что ord.trans_id=1, ord.order_num = номер удаляемой заявки. Т.е. новая транзакция, у которой trans_id=2, не вернулась в OnOrder, и даже не отобразилась в общем списке заявок. Это в целом понятно и логично, но непонятно, для чего тогда указывать trans_id=2? Т.е. если я не заполню поле trans_id=2, будет ошибка, но по факту это значение 2 дальше нигде не будет использовано. Или есть какие-то случаи, когда оно может пригодиться?
Не получается запустить два скрипта одновременно, При запуске второго первый останавливается
Пользователь
Сообщений: Регистрация: 26.11.2025
11.12.2025 16:01:18
Кажется я понял, в чём дело. Первый скрипт останавливается, если второй запускается из другой папки. Если файл второго скрипта скопировать в папку с первым и оттуда запустить, всё работает. Интересно, это только у меня, или встроенная бяка квика?
P.S. Вчера не смог отправить ни одного сообщения, все блокировались. Админы, мне кажется, слишком перестарались. Они так не с ботами борются, а с живыми людьми. Нет мотивации дальше сюда что-то писать.
Не получается запустить два скрипта одновременно, При запуске второго первый останавливается
Я проверил, если запускать два простейших скрипта, типа message(...) sleep, то работают. Но если мой мониторинг цены запараллелить с простейшим - останавливается. Возможно какая-то конкретная функция есть, которая не хочет делить ресурсы.
Более того, останавливается даже в момент загрузки второго скрипта. Т.е. нажимаю кнопку "добавить", выбираю файл скрипта (но не запускаю) - и первый останавливается.
P.S. Тут по правилам форума новичку можно писать только одно сообщение в сутки. Так что если я молчу - не значит, что всё ок или я забил.
Не получается запустить два скрипта одновременно, При запуске второго первый останавливается
Пользователь
Сообщений: Регистрация: 26.11.2025
08.12.2025 14:33:06
Есть скрипт, который включен на постоянную работу, мониторит цены некоторых акций. Хочу не прекращая его, запустить второй учебный скрипт. При запуске второго примерно через 10 секунд первый останавливается. Так и должно быть?
getBuySellInfo в QuikPy, Правильно ли я понимаю, что эта функция не реализована?
Мне нужно не передать данные, а получить данные. Т.е. находясь в питоновском скрипте, нужно узнать, сколько сейчас акций в портфеле. Например рублевый счёт в портфеле я научился узнавать через функцию QuikPy().GetPortfolioInfo. Вопрос о том, если аналогичный способ для количества акций.
getBuySellInfo в QuikPy, Правильно ли я понимаю, что эта функция не реализована?
Пользователь
Сообщений: Регистрация: 26.11.2025
26.11.2025 01:44:45
В модуле QukPy нет функции getBuySellInfoEx. Есть закомментированная строка с этой функцией, т.е. я как понял, в планах на реализацию. Попробовал сделать вот так: