Михаил, добрый день. Обращаюсь по привычке к Вам, так как не в курсе, поддерживает ли S# еще кто либо. Если я ошибаюсь, поправьте меня.
Михаил, прошу помочь разобраться в следующем. Ситуация:
- Проверяю состояние заявки.
- Если состояние заявки Active, отменяю асинхронно заявку.
- Дожидаюсь события OrdersChanged, когда заявка станет Done.
- Проверяю Balance, он равен Volume.
- Проверяю в Квике состояние заявки, заявка оказывается полностью удовлетворена. То-есть Balance должен был быть равен нулю в пункте 4.
Если между пунктом 3 и 4 сделать пауза в 1 секунду, то Balance будет равен нулю.
Из этого я могу предположить, что Balance может изменится после того, как заявка приобрела статус Done. Хотя в мануале написано: «Done - заявка более не активна на бирже, и по ней не может прийти ни одно изменение.»
Так ли это? Сталкивались ли Вы с этим?
Комментарии (41)
Вход или Создать аккаунт, Войдите или зарегистрируйтесь, чтобы оставить комментарий
Можете это выразить небольшим кодом для теста?
Добавляем две синхронизации:
В обработчик события Global.Quik.NewOrders добавляем строку waitActiveOrFailed.Set() А в обработчик события Global.Quik.OrdersChanged добавляем строку waitDone.Set();
После соединения с квиком и подпиской на событие, запускаем код:
Получаем результат:
private ManualResetEventSlim waitDone = new ManualResetEventSlim(false); private ManualResetEventSlim waitActiveOrFailed = new ManualResetEventSlim(false);
qt.OrdersChanged += orders => { foreach (var order in orders) { Debug.WriteLine("Id {0} State {1} Balance {2}".Put(order.Id, order.State, order.Balance)); } };
Первоначально в обработчике OrdersChanged просто был один метод: waitDone.Set()
Я это и имел ввиду, кода писал:
Теперь обработчик выгладит так:
Обновленный результат вывода привожу ниже. Состояние «State Done» и «Balance 100» в выводе есть. Что говорит о том, что что-то не так.
Забыл упомянуть, этот сценарий наблюдается на тестовом Квике. Если это имеет значение. На реальном пока не тестировал.
А если убрать все блокировки и просто выводить в лог? Код слишком сложным получился с теми, так с ходу не разобраться, где ошибка.
А как без использования блокировщика отменять заявку?
Если не дождаться когда заявка станет Active — отменять ее нельзя. Как без блокировщика понять, что заявка перешла в статус Active и ее можно отменить?
Немного подумал и попробовал сделать все без блокировщиков. В результатах все так же есть вариант с «State Done Balance 100».
Вариант тестового кода
Результат:
Тоже поймал такую ситуацию. С воспроизведением проблема. В начале стабильно приходил Done с балансом 100. Теперь стабильно Done с балансом 0. Видимо еще ситуация со стаканом значение имеет.
Ошибку добавил в список багов так как она подтвердилась. Пока не буду ее искать, так как сейчас занимаюсь релизом 3.0. Выпущу на след. неделе. После этого начну анализировать код. + к вам просьба небольшая. Так сказать отвергнуть предположения о неправильных данных в ДДЕ. Можете подписаться на событие PreProcessDdeData, и посмотреть, идет ли там совместно ненулевой баланс вместе с состоянием matched. Если в этом виноват сам Квик, то это будет уже сложнее поправить.
Состояние matched не обнаружил. Везде где наблюдался случай «State Done Balance 100» была ситуация, которая описана ниже.
Сначала было событие OrdersChanged с «Balance 100». После этого событие PreProcessDdeData с «FILLED». После этого событие OrdersChanged с«Balance 0».
Этого достаточно или надо еще что либо проверить?
Михаил, добрый день.
Рассматривали ли Вы более подробно данную проблему? Есть ли какой либо прогресс?
Понимаю, что Вы придерживаетесь своего плана. Но все же считаю ошибку достаточно весомой, что бы задать эти вопросы.
Без решения этой ошибки я не могу продолжить работать и использовать робота.
Как временно обойти данную ситуацию придумать не могу. Как понять, что заявка уже отработана и по ней не будет никаких изменений?
Надеюсь на понимание. Спасибо.
Да, я нашел закономерность. Выложу 3.0.1 в конце недели.
Михаил, вечер добрый.
К сожалению сообщаю, что данная ошибка не устранена окончательно. В процессе торгов появляются случаи, когда заявка имеет статус Done, но значение разницы Volume - Balance больше нуля, но меньше, чем реальный объем сделок прошедших в Квике по этой заявке.
С данной ситуацией я уже столкнулся в третий раз.
К сожалению не удается произвести данную ошибку на тестовом Квике. Возможно связано с тем, что поведение тестового Квика и реального отличаются.
Прошу Вас обратить внимание на данную ошибку и еще раз проанализировать Ваш код. Немного удручает, что программа продает или покупает не то количество бумаг, которое необходимо. Со своей стороны постараюсь добиться повторяемости ошибки в тестовом Квике.
Добрый день, Михаил. Я обнаружил при работе (в боевом режиме с боевым квиком) аналогичную проблему. Зарегистрировался и нашел этот топик.
Ситуация такая (используется версия библиотеки 2.6.2 и асинхронный режим):
В реальности алгоритмом выставляются подряд 2 ордера (по 2 разным инстументам) и при этом по второму ордеру этой "ошибки" нет - уже на втором шаге Balance = 0, но при этом после выставления заявки не приходит начальное сообщение NewOrders (сразу OrdersChanged - хотя здесь я не до конца уверен, м.б. это какая-то ошибка в моем коде).
Проблема очень критична, поскольку между пунктами 2 и 3 алгоритм успевает учесть этот ордер, т.к. уже не ждет по нему сделок. Нужен какой-то work-around.
С уважением, Алексей.
В 3.0.1 частично эта проблема была решена. Рекомендую обновить библиотеку, хоть проблема и не решена окончательно.
Боюсь обновлятся, т.к. объем работы для перетестирования всего очень большой. Если других шансов нет, то конечно придется.
Но, как вы пишите, проблема в не была окончательно решена, поэтому я решил узнать, есть ли возможности обхода. К.м.к, если есть возможность как-то получить точную информацию о том есть ли по ордеру в статусе Done еще не пришедшие сделки (или, например, окончательное общее число сделок на бирже) - то я смогу скорректировать приходящий статус ордера в своем алгоритме, анализируя количество еще непришедших сделок.
Давайте проинспектируем проблему:
Добрый день, Михаил.
Чтобы можно было потом логи понять.
Я новичек в этой теме (stock#), прошу простить. поскольку я не знаю что именно в этих логах нужно выводить, можно дать конкретный пример кода?
Номер заявки, транзакции, объем, баланс, состояние... Может еще что-то попутно понадобиться, так сложно сказать. Вы начните, там и видно будет.
Безрезультатно пытаюсь повторить эту ошибку в тестовом Квике. Михаил, а может эта ошибка быть вызвана некоректным поведением брокерского сервера?
Первая заявка:
Вторая заявка:
1)Михаил, а в каком свойстве класса Order находится информация из столбца «Состояние» Квика?
2)Заметил следующее. При отмене заявки в Квике заполняется столбик «Снята(время)». Но на момент, когда состояние заявки становится Order.State == Done, свойство Order.CancelTime остается неопределенным. Это происходит не всегда. Из 16 отмененных заявок в 4 заявках свойство Order.CancelTime все же определилось. Из этого могу предположить, что все таки после того, как Order.State стал Done, заявки изменяются.
Order.State
Нужны логи из ДДЕ.
Но зная Order.State нельзя определить, была ли отменена заявка, правильно? Получается, что единственный признак того, что заявка была отменена, это наличие Order.CancelTime? Или я ошибаюсь?
В файле можно найти данные из OrdersChanged и PreProcessDdeData: эксель
Данные из NewOrders
В этих данных можно посмотреть на заявки 44300176 и 44300177. После того, как Order.State поменялся на Done, в заявке 44300176 свойство Order.Time было «2011-04-26 12:20:31.0000000». Тогда как, в заявке 44300177 свойство Order.Time было «0001-01-01 00:00:00.0000000».
Просмотрев DDE данные, заметил, что в первом случае данные PreProcessDdeData приходят перед тем, как появится событие OrdersChanged. Во втором случае перед первым OrdersChanged данные из PreProcessDdeData не приходят.
В файле можно найти данные из OrdersChanged и PreProcessDdeData: эксель
Данные из NewOrders:
В этих данных можно посмотреть на заявки 44300189 и 44300190. После того, как Order.State поменялся на Done, в заявке 44300189 свойство Order.CancelTime было «2011-04-26 12:21:34.0000000». Тогда как, в заявке 44300190 свойство Order.CancelTime было пустым.
В данных DDE можно увидеть, что событие первое событие OrdersChanged , когда Order.State поменялся на Done, происходит самопроизвольно, без поступления данных из DDE. Это мое предположение, могу и ошибаться.
У меня файлы не скачиваются.
Можно скачать по номерам: 5286502 и 5286555 http://www.webfile.ru/
Ок, по данным все ок. По выводу в сообщении тоже все нормально. Я пропустил проблему? Если да, куда смотреть?
Maxim, вы могли бы выложить свой проект для детального разбора?
Немного исправил код, который упоминал выше. При помощи этого кода на тестовом Квике получилось добиться двух ошибок описанных выше:
Не совсем понял, что подразумевается под «свой проект»? Что конкретно не хватает для повторения ошибки? Вопрос касается снятия и выставления заявок. Ничего необычного в моей программе не используется. Выше в этом посту я уже приводил пример куска кода. Правда в этот раз я его не использовал для получения ошибок, но уверен, что этот код даст такие же результаты.
Кстати, насчет первого вопроса есть отдельный пост. http://stocksharp.com/forum/878/Order-Time-vozvrashchaiet-00-00-00-0001-ghoda/
Я выше писал. Но наверно нить диалога потерялась и запуталась. Напишу суть еще разок.
Глобальная проблема Глобальная проблема заключается в том, что при покупке моя программа покупает или продает больше лотов, чем это необходимо. Делает это она не всегда. На глаз могу сказать, что одна заявка из пяти выполняется некорректно. Причина этого — заявка получила статус Done, программа учла сколько было реализовано в заявке бумаг, а после этого пришли дополнительные сделки. То есть, косяк в том, что заявка изменяется после того, как она получила статус Done. В частности это можно наблюдать в логах OrdersChanged, которые я приводил в этом комментарии: http://stocksharp.com/posts/m/7659/ Собрать полноценный лог (с данными по DDE) по этой ошибке в рабочем Квике пока не получается. Над этим работаю.
Повторить эту ошибку на тестовом Квике у меня не получается. Возможно зависит от того, что тестовый Квик и рабочий ведут себя по разному.
В процессе анализа проблемы на тестовом Квике я заметил две ошибки, которые возможно связаны с глобальной проблемой. И решив эти ошибки решится и глобальная. А может и нет.
Промежуточная ошибка номер Раз — неверное время Order.Time «0001-01-01 00:00:00.0000000» В экселе «44300176 and 44300177.xls» можно посмотреть данные по заявке 44300177. В первой записи , в которой Order.State поменялся на Done, Order.Time равно «0001-01-01 00:00:00.0000000».
В файлике свойства Order.Time не видно. Но это точно так, потому что как только заявка становится Done, она у меня логируется в SQL. И в SQL Order.Time для этой заявки равно «0001-01-01 00:00:00.0000000».
Позже я исправил это упущение и в коде, который я привел раньше, Order.Time логируется в Debug. Но, к сожалению, на момент создания эксель файликов этого изменения еще не было.
Итак, основная мысль, что на момент, когда заявка становится Done время заявки Order.Time некорректно. Эта же ошибка уже встречалась здесь: http://stocksharp.com/forum/878/Order-Time-vozvrashchaiet-00-00-00-0001-ghoda/
Заявка 44300176 в экселике имеет корректное свойство Order.Time. Сравнивая DDE данные для заявок 44300177 и 44300176 я обнаружил, что перед первым событием OrdersChanged когда статус становиться равным Done для заявки 44300176 данные по DDE пришли, а для 44300177 нет. То есть заявка 44300177 произвольно поменяла значение статуса на Done. Это мои предположения, возможно они не верны.
Элемент данных DDE для 44300177, когда статус стал Done, а соответствующих данных DDE нет:
Элемент данных DDE для 44300176, когда статус стал Done, но соответствующие данные DDE есть:
Промежуточная ошибка номер Два — время Order.CancelTime отсутствует, а должно быть. В экселе «44300189 and 44300190.xls» можно посмотреть данные по заявке 44300190. Когда пришло первое событие OrdersChanged для этой заявки с статусом Done, свойство Order.CancelTime было пустым. В следующем событии это время уже не пустое.
Аналогично предыдущему случаю, если посмотреть данные DDE то перед третьим событием OrdersChanged данные DDE для заявки не приходят. Из чего я делаю вывод, что заявка меняет статус на Done самопроизвольно:
Итог В этих двух локальных ошибках, на мой взгляд, есть общая черта — заявка изменяется после того, как статус стал Done. Возможно эти ошибки связаны с глобальной ошибкой, а возможно нет.
Ок, я кажется понял в чем проблема. Буду фиксить.
Но есть ряд моментов, которые нужно прояснить. Order.Time не всегда сразу инициализируется. В асинхронном режиме это чаще всего, потому что callback приходит раньше, чем ответ через ДДЕ. При это callback не несет информацию о времени регистрации.
Что касается записи:
то судя по логу, ДДЕ не присылал время снятия. Единственно, что тут неправильно - это выставление Done преждевременно. Ошибка, как я понял, в слишком раннем выставлении Done для заявки. По сути это можно трактовать как и правильно поведение (ведь заявка реально была снята). Но неправильность начинается как раз в том случае, если после снятия заявки начинают приходить по ней сделки. И тогда баланс начинает уменьшаться для уже Done заявки. Это я исправлю. Но всегда остается тот вариант, когда Квик пришлет уведомление по ДДЕ для уже Done заявки (например, в Квик добавлена колонки, которые тикают для уже исполненных заявок). Баланс уменьшаться не будет, но OrdersChanged все равно вызовется.
Наверно надо тогда внести пояснение в документацию, о том что в некоторых случаях заявка все таки может изменяться после изменения статуса на Done. Или реализовать так, что бы до появления Order.Time заявка не становилась Done. Или ввести опцию, которая позволяла выбирать из двух вариантов поведения один определенный.
То что придет событие OrdersChanged не страшно на мой взгляд. Главное, что бы поведение заявки совпадало с документацией. Это я о не изменении после Done. В противном случае рассчитываешь на одно, а в реалии получается другое.
Михаил, не ответили на вопрос. Он не критичен, но для общего развития не помешает узнать ответ.
Повторюсь, что все второстепенные ошибки лично для меня пока не критичны. Возможно в будущем и придется с ними столкнутся , если они останутся, но на данные момент они не мешают.
Основная проблема, которая мешает — это в изменении баланса, после того заявка стала Done.
Михаил, так и не ответили. Спрошу еще раз, что бы закрыть вопрос.
Зная Order.State, нельзя определить, была ли отменена заявка, правильно? Получается, что единственный признак того, что заявка была отменена, это наличие Order.CancelTime? Или я ошибаюсь?
Да, можно по Order.CancelTime.
Михаил, есть ошибка.
При выставлении и быстром снятии заявки статус остается Active.
Кусочек логов. Записи идут в хронологическом порядке (забыл время добавить в лог). Это последние данные по этой заявке.
Случаем не это http://stocksharp.com/posts/m/7845/
Ситуация вроде похожа. Вроде бы тоже проблема в том, что после отмены заявка не становится Done.
Скачал последнюю версию, запустил. Ситуация не изменилась. Все так же отмененные заявки не становятся Done. Возможно связано стем, что Trader.IsAsyncMode у меня true? В приведенном Вами случае у пользователя Garry был случай с false.
При QuikTrader.CancelOrderInstantly = true все работает нормально.
Отдельный вопрос. А зачем свойство QuikTrader.CancelOrderInstantly ? Если заявка отменилась, то почему сразу не переводить ее в Done? Зачем ждать данных из DDE?
Сегодня скачали? Может нужно пересобрать проект? Вдруг старые dll закэшировались.
Теперь Done будет выставляться только тогда, когда пришел поток ДДЕ с признаком KILLED. Что у вас и происходит по логу.😒
Чтобы не было вашей ситуации, когда баланс начинает чудесным образом обновляться после отмены.
Спасибо, Михаил, за ответы и за работу. Чо то я совсем заработался. Надо делать выходные. На последние вопросы и сам смог бы ответить, если бы подумал.
Все работает.