Распределенность обработки вызовов OnOrder

Страницы: 1
RSS
Распределенность обработки вызовов OnOrder
 
Вопрос к разработчикам.

Столкнулся с очень странным эффектом при работе callback-функции OnOrder().
Картина следующая. Работает скрипт, выставляется заявка, отрабатывает. Далее следуют два вызова OnOrder() в ситуации, когда оба раза флаги показывают, что заявка снята. Но двойной вызов OnOrder() на СНЯТОЙ заявке - это еще ладно, проблема в другом.

Суть проблемы.
В скрипте создан массив, куда заносятся номера выставленных заявок. После того, как заявка снята, соответствующий элемент с order_num снятой заявки из массива исключается. СУЩЕСТВЕННО: обе операции - и включение в массив заявки , и исключение ее из этого массива происходят именно в OnOrder(), а не где-либо еще в скрипте.
Трассируя функцию OnOrder(), обнаружил, что почти мгновенно происходят ДВА ее вызова при снятии заявки ( lags показывает, что заявка снята), но при этом оба вызова, проходя через тело OnOrder(), отрабатывают, как если бы в первом вызове не было указано, что заявка на биржевом сервере уже снята, и она с ее order_num не была бы исключена из массива.

Я могу понять такую ситуацию, если допустить что два эти вызова OnOrder() происходят из РАЗНЫХ потоков. Тогда - да, возможна ситуация, что VM LUA еще не успела полностью отработать код OnOrder(), вызванный первым потоком, тогда как сразу же запустилось исполнение экземпляра OnOrder(), созданного для второго потока.
Но разработчики QUIK все время говорят, что ВСЕ вызовы callback-функций со стороны терминала происходят исключительно в главном (т.е. одном и том же) потоке терминала. В этом случае описанного мною эффекта достичь не получится, так как обработка второго вызова OnOrder() для уже снятой заявки произойдет только после полного завершения отработки первого вызова OnOrder(), который априори исключит  данную заявку по ее order_num из массива.

На мой взгляд возможны два варианта:
а) вызовы callback-функций, в том числе и OnOrder(), ДЕЙСТВИТЕЛЬНО происходят из разных потоков терминала, а не только из одного единственного  - главного; при этом очередность вызовов не предустановлена, и тогда руководство по QLUA и комментарии на форуме от разработчиков вводят нас в явное заблуждение.
б) разработчики не знают, какой конкретно поток внутри терминала может в конкретный момент времени - помимо ОСНОВНОГО потока рабочего места QUIK - вклиниться в цепочку вызовов callback-функций. И имеют в виду, что?, к примеру, вызов OnOrder() происходит не строго, а ПРЕИМУЩЕСТВЕННО в главном потоке терминала, что допускает такие вызовы и другими потоками терминала, в том числе и с неуловимой для VM QLUA задержкой по времени вызова.

Прошу разработчиков прокомментировать изложенное, и - либо подтвердить один из вариантов, либо опровергнуть.
Вопрос очень существенный.
 
Причем тут потоки не понятно.
А Вы не думали что например сервер мог прислать два колбека?
 
для колбеков поток один - это точно.
но возможно, что Вы работаете с таблицами в main. Тогда будет два потока.
-----------------------------------------
проблема может быть в Вашем алгоритме обработки.
Чтобы ответить точно, надо видеть как (вернее где)  Вы обрабатываете сигналы заявки.
 
Николай Камынин,

казус произошел именно при выполнении OnOrder(). Массив, в который вносятся и из которого исключаются заявки по order_num, объявлен локальным для всего скрипта, но затрагивается только в OnOrder(). Поток функции main() с этим массивом не работает.
Попробую тестировать еще, так как ранее подобных случаев не наблюдал.
 
Sergey Gorokhov,

Такой вариант я анализировал.
Даже если брать в расчет ситуацию прихода двух вызовов: первый - "сырой" (с отсутствующими uid и trans_id), второй - нормальный (с проставленными uid и trans_id), то в моем скрипте на обработку в теле OnOrder() будет допущен лишь второй вызов, так как первый, ввиду отсутствия uid и trans_id, будет отбракован. То есть, обработка в любом случае будет происходить один раз. До сегодняшнего дня все было нормально: трассировка показывала однократное исполнение OnOrder() в случае, когда flags в пришедшей записи указывает, что заявка снята. Это логично: если заявка снята, то биржа с ней ничего уже делать не будет, так как сама заявка уже отправлена в архив. Что может сделать сервер QUIK, стоящий у брокера, после получения от биржи записи о том, что заявка снята? Если я правильно понимаю, то только одну вещь: поместить заявку в архив как снятую и неактивную и выслать соответствующее уведомление на рабочее место QUIK. Пусть даже это уведомление и будет в виде двух вышеуказанных вызовов - "сырого" и нормального.
Но казус проявился в двукратном срабатывании кода OnOrder(), как если бы ее вызвали одновременно из двух разных потоков..
 
Чтобы уж точно не зависеть от того в одном потоке исполняются колбеки или в нескольких, я не обрабатываю в них информацию, а только фильтрую нужные и ставлю их в очередь. Обработкой же занимается исключительно поток main в той очередности, в какой были вызваны соответствующие колбеки (OnTransReply, OnOrder, OnTrade). При этом я не отбраковываю OnOrder с неизвестными trans_id и uid, т.к. к моменту их прихода зачастую уже известно соответствие order_num и trans_id из ранее пришедших OnTrade или OnTransReply.
Что касается редких парных (в единичных случаях тройных) вызовов OnOrder при снятии заявки, то по анализу моих логов выходит, что в первом (втором) из них всегда не достает какой-нибудь информации и лишь в последнем имеется все информация, а именно: uid, trans_id, flags - заявка неактивна-снята, "правильный" balance (соответствует ранее пришедшим OnTrade и OnTransReply на снятие заявки), withdraw_datetime, canceled_uid. Бывает, что приходит canceled_uid - заполнен, а withdraw_datetime - еще нет, хотя OnTransReply для транзакции на снятие заявки с успешным статусом уже пришел. Вот когда все эти поля заполнены - тогда мой алгоритм считает, что пришел последний OnOrder о снятии заявки.
 
 
поделюсь своим решением.
обрабатываю в колбеке.
В таблице пассивные заявки удаляю. в колбеке обрабатываю все приходы и мне безразлично сколько их.
-----------------
обрабатывал и в майн.
===================
Последний вариант - один колбек на все скрипты.
т е роботов много, но колбеков по одному для каждого вида (заявки, сделки, стаканы и т д)
Страницы: 1
Читают тему
Наверх