finsight / QUIKSharp

QUIK# (QUIK Sharp) is the QUIK Lua interface ported to .NET.
Other
230 stars 134 forks source link

Обработка ошибок от quik #316

Closed serebrennikovvitaly closed 2 years ago

serebrennikovvitaly commented 2 years ago

Подскажите как обработать ошибку от quik? После любой команды: SendLimitOrder, SendMarketOrder, отправляемых заведомо с ошибкой (например, мало денег или биржа закрыта или другие) - процесс останавливается с ожиданием ответа.

При этом, quik сразу в сообщениях отдает ошибку, также ошибку вижу в TransReply, в том числе и текст ошибки. Но SendLimitOrder и SendMarketOrder зависают на неопереденный срок.

Это воспроизводится и в тестовом примере, трассировка не идет дальше команды SendLimitOrder. И не получаю ни сам ордер (так как он не создан) и исключения не возникает. Также TransID не известен, хотя в TransReply приходит.

Как решить этот вопрос?

image

Pr0phet1c commented 2 years ago

При сильном желании экспериментировать с передачей заведомо некорректных данных в терминал, лучше использовать базовый функционал QUIK, а не методы, являющиеся производными, которые созданы для облегчения/упрощения написания кода. Под "базовым" функционалом, я подразумеваю функцию "SendTransaction". Справку по ее использованию можете подсмотреть в справке по QLua.

serebrennikovvitaly commented 2 years ago

Попробовал все-таки штатно решить, прошел дебаггером в движок QuikSharp. Так вот, ошибка логическая в функции SendOrder!

После получения ошибки от квика, при попытке в строке 134 получить номер ордера через GetOrder_by_transID, order_result оказывается == null.

И далее, в строке 147 такого условия не находится и соответственно, set не становится = true и далее не выходит из бесконечного цикла в строке 128

Надо добавить такое условие в строку 147

image

Pr0phet1c commented 2 years ago

Если в 147 строке добавить установку set = true, при условии, что order_result == null, то мы выйдем из цикла, без ошибки, т.е. будем считать, что заявка успешно выставлена. Но суть проблемы я понял. Подумаю на досуге как лучше обыграть эту ситуацию.

serebrennikovvitaly commented 2 years ago

Решил примерно так:

  1. Добавил флаг в переменную класса image

  2. добавил в функцию GetOrder_by_transID выставление этого флага по окончанию выполнения image

  3. Добавил в функцию SendOrder условие выход из цикла по флагу и возврат order_result, а также до-кучи order_result.TransID = res; перед выводом из SendOrder image

Если нужно, то приложил файл To-Be OrderFunctions.zip

Версия 2.0.1

Pr0phet1c commented 2 years ago

Не самое удачное решение. Цикл появился из-за того, что после отправки транзакции, может пройти некоторое время, прежде чем в терминале появится информация по заявке. Если считать, что при отсутствии информации после первого же запроса заявки нет, то будем сталкиваться с выставлением заявок, думая, что их нет. Помню, как в какой-то момент это привело к выставлению нескольких десятков заявок на покупку какой-то бумаги, в течении буквально нескольких секунд. Адреналина мне тогда хватило по самые уши. Нужно другое решение, но пока у меня нет возможности заняться этим вопросом.

serebrennikovvitaly commented 2 years ago

Предлагаю тогда такой вариант. На тесте работает (и выставляет заявки и возвращает ошибки).

  1. Подписываемся на событие OnTransReply перед вызовом транзакции

image

  1. В обработчике OnTransReply: 2.1. Получаем транзакцию из словаря 2.2. Если пришла нужная транзакция, то загоняем ошибку квика в transaction.ErrorMessage если код ошибки от квика не 0 (если код 0, то текст содержит что-то типа "заявка создана успешно" 2.3. Записываем обратно в словарь, теперь в словаре содержится текст тразакции

image

  1. Проверяем, если в словаре транзакции содержится текст ошибки, то создаем пустой ордер с текстом ошибки image

  2. Перед выходом отписываемся от колбэка, чистим словарь, возвращаем TransID image

  3. в SendTransaction запись в словарь ставим перед вызовом транзакции image

OrderFunctions.zip

Pr0phet1c commented 2 years ago

Приведите, пожалуйста, пример параметров заявки, при которых у Вас функция гарантированно уходила в бесконечный цикл. Я не уверен в оптимальности Вашего решения. По хорошему, ошибку отправки транзакции необходимо отлавливать в методе "SendTransaction", и дальше работать с полученным результатом. Желательно, без дополнительных подписок на события (если это возможно).

serebrennikovvitaly commented 2 years ago

например при закрытии биржи в выходные. Квик отдает ошибку - инструмент не торгуется. Или например если баланс с учетом покупки будет отрицательным. Уходит в бесконечный цикл даже на тестовых примерах из quiksharp

Pr0phet1c commented 2 years ago

В общем, в SendTransaction обработать эту ошибку не удается, т.к. по сути команда отправки транзакции считается успешно выполненной. Нашел у себя старую реализацию контроля подобных ошибок, в чуть более простом варианте, чем у Вас. Предварительное тестирование показало успешный результат. После боевого тестирования (на реально работающем роботе, выставляющим не единичные заявки), выложу фикс.

FocusPo1nt commented 2 years ago

Тоже сталкивался, что иногда из-за некоректных данных от квика (неверное отображение позиции по инструменту или деньгам) после отправки заявки программа виснет. В терминале квика ошибки "превышена позиция по деньгам" и "запрет на операцию шорт". Буду благодарен, если выложите фикс

Pr0phet1c commented 2 years ago

Боевое тестирование в процессе. Скорее всего вечером будет фикс.

Pr0phet1c commented 2 years ago

Фикс выложил.

FocusPo1nt commented 2 years ago

Большое спасибо, буду тестировать

serebrennikovvitaly commented 2 years ago

Спасибо за патч, все работает! Можно закрывать тикет