После перезапуска Quik в созданный файл quik_odbc.log ничего не записывается. Саму проблему воспроизвел скриншотами, всё отправил по указанному адресу эл. почты.
Да, конечно, отображаются. Настраивается их вывод по ODBC как обычно, вместе с другими параметрами. Другие параметры передаются, а в указанных параметрах - NULL. Причем проверял на этот глюк Quik от двух брокеров - разницы нет.
Quik позволяет настроить экспорт по ODBC "Таблицу транзакций", при этом поля таблицы "Время", "Время мкс.", "Время шлюза", "Время шлюза мкс." предлагается выводить в поля ODBC-таблицы типа "varchar" (экспорт производится в таблицу MySql). Поля "Время шлюза", "Время шлюза мкс." хотя и настраиваются для вывода по ODBC, но реально не выводятся (в принимающей таблице всегда NULL). В то же время поля "Время", "Время мкс.", как и другие поля (например, ID транзакции - "integer") выводятся без проблем. Похоже на "баг" Quik-а.
Проблема решена. И trans2quik, к чести разработчиков, здесь ни при чем. Проблема состояла в упаковке данных для сообщения. Дельфийские Msg1.WParamHi, Lo, LParamHi, Lo по ходу работают только на чтение. Приведу работающий код: asm mov EAX, nBalance mov word ptr Msg1.WParam, AX mov EAX, qty mov word ptr Msg1.WParam + 2, AX mov EAX, nStatus mov word ptr Msg1.LParam, AX mov EAX, dwTransID mov word ptr Msg1.LParam + 2, AX end; SendMessage(MainHandle, My_Mes, Msg1.WParam, Msg1.LParam);
Это Ваше: Функция TRANS2QUIK_ORDER_STATUS_CALLBACK Функция обратного вызова для получения информации о параметрах заявки. void TRANS2QUIK_ORDER_STATUS_CALLBACK (long nMode, DWORD dwTransID, double dNumber, LPSTR lpstrClassCode, LPSTR lpstrSecCode, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor)
Параметр
Описание
nMode
Тип: Long. Признак того, идет ли начальное получение заявок или нет, возможные значения: «0» – новая заявка, «1» - идет начальное получение заявок, «2» – получена последняя заявка из начальной рассылки
dwTransID
Тип: Long. TransID транзакции, породившей заявку. Имеет значение «0», если заявка не была порождена транзакцией из файла, либо если TransID неизвестен
dNumber
Тип: Double. Номер заявки
lpstrClassCode
Тип: указатель на переменную типа Строка. Код класса
lpstrSecCode
Тип: указатель на переменную типа Строка. Код бумаги
dPrice
Тип: Double. Цена заявки
nBalance
Тип: Long. Неисполненный остаток заявки
dValue
Тип: Double. Объем заявки
nIsSell
Тип: Long. Направление заявки: «0» еcли «Покупка», иначе «Продажа»
nStatus
Тип: Long. Состояние исполнения заявки: Значение «1» соответствует состоянию «Активна», «2» - «Снята», иначе «Исполнена»
nOrderDescriptor Тип: Long. Дескриптор заявки, может использоваться для следующих специальных функций в теле функции обратного вызова: и т.д.
Какой параметр Вы мне советуете объявить типом double (занимает 8 байт)? Я, кстати, ранее уже пробовал объявлять nBalance типом int64 (занимает 8 байт), и nOrderDescriptor типом intptr_t. По сути это один тип данных - LongLong. Так вот возникла ошибка - Quik не передает в стек параметры такого размера для trans2quik версии 1.2, что ожидаемо. Хотелось бы узнать, воспроизводится ли у Вас моя проблема?
Попробовал. Это не имеет значения. Integer - 32-x битное целое число. Его можно объявить как long, longInt и хоть как угодно - от этого ничего не изменится.
var Msg1: TMessage; qty: integer; begin if nMode = 0 then begin qty:= QUIK_ORDER_QTY(nOrderDescriptor); Msg1.WParamLo:= nBalance; Msg1.WParamHi:= qty; Msg1.LParamLo:= nStatus; Msg1.LParamHi:= dwTransID; SendMessage(MainHandle, My_Mes, Msg1.WParam, Msg1.LParam); end; end; Подразумевается, что qty, nBalance, dwTransID не больше чем максимальное значение word. PChar = PAnsiChar. Обработчик сообщения My_Mes выводит информацию пользователю.
Добавлю: Процессор 32 бит. То есть trans2quik.dll версии 1.3 в принципе не встанет. Кстати вопрос: зачем было писать 32-х разрядную библиотеку trans2quik.dll (а она именно 32-х разрядная) для 32-х разрядного Quik, только для 64-х разрядного процессора? В PE заголовке библиотеки указано: IMAGE_FILE_MACHINE_AMD64
где: CodeOfClass = 'SPBFUT'; SECCODE = 'SiM7'; OPERATION = 'B'; QUANTITY = '1'; PRICE = '55571'; TransID = 17; BaseContract = 'Si'; Далее посылаем асинхронную транзакцию. В общем, параметры не так важны, так ка транзакция встает. Версия Quik 7.9.1.1 На версии 7.2.2.3 поведение такое же. На более ранних версиях 6.17.3.6 и ранее такого поведения не было, то есть всё было корректно.
В связи с выходом библиотеки trans2quik.dll версии 1.3 объявлена поддержка старой версии 1.2. Однако это не так. Выявлено следующее: в QUIK_ORDER_STATUS_CALLBACK функция QUIK_ORDER_QTY работает неправильно, параметр nBalance передается некорректно. Пример: ставим заявку с TransID=17. В QUIK_ORDER_STATUS_CALLBACK получаем три события с nStatus=1: 1) dwTransID=0, при этом QUIK_ORDER_QTY работает корректно и nBalance правильный, только вот dwTransID некорректен; 2) dwTransID=17, при этом QUIK_ORDER_QTY выдает 48562515, nBalance тоже неправильный. 3) то же самое что и 2)
Проблема распознана и решена. Я считаю, что это баг торговой системы либо сервера. В функции QUIK_ORDER_STATUS_CALLBACK параметр dwTransID - уникальный идентификатор транзакции "породившей" заявку. Так вот до начала торгов при первоначальном получении заявок (nMode = 1, 2) по каждой заявке выдается dwTransID = 0. То есть за ночь этот параметр "теряется". Если использовать для снятия заявки полученный ноль в TransID, то QUIK_TRANSACTION_REPLY_CALLBACK выдаст сообщение об ошибке, что указан неправильный идентификатор транзакции. Я решил проблему так: если первоначально полученный TransID заявки равен нулю, то при формировании строки транзакции на её снятие меняем его на "не ноль" TRANS_ID=1 например. Тогда все работает, заявки снимаются. Но надо учитывать, что QUIK_ORDER_STATUS_CALLBACK при снятии заявки пришлет "сообщение" с nStatus = 2 и параметром dwTransID = 0.
Хорошо, так и сделаю. Завтра проверю все еще раз, запущу программу в Debug mode, контролируя все параметры, дополнительно с выдачей сообщений обо всех параметрах. Если что не так, отпишу Вам как сказали. Дополнительно могу сказать, что QUIK_ORDER_STATUS_CALLBACK при nMode = 0 и nStatus = 2 запрашивает результат функции QUIK_ORDER_DATE_TIME(nOrderDescriptor, ORDER_WITHDRAW_QUIKTIME); Если результат равен нулю (а такое бывает), то QUIK_ORDER_STATUS_CALLBACK пропускает такие "сообщения".
Проверка Result при выполнении TRANS2QUIK_SEND_ASYNC_TRANSACTION есть. Если бы Result не был равен TRANS2QUIK_SUCCESS, то выдавалось бы сообщение. Параметры pnExtendedErrorCode и lpstrErrorMessage программа не контролировала. Сейчас чуть допишу код, а завтра тогда перед началом торгов проконтролирую эти параметры. Но я так понимаю, что при Result = TRANS2QUIK_SUCCESS эти параметры не важны.
Никаких ошибок не возникает. Вообще не приходит никакого ответа. В Торговля-Таблица транзакций отображены только успешно снятые вручную заявки. Также успешно через API перед началом торгов были сняты все заявки с параметром транзакции KILL_ALL_FUTURES_ORDERS, это тоже есть в Торговля-Таблица транзакций. Установлена функция обратного вызова QUIK_ORDER_STATUS_CALLBACK. Туда при попытке снять отдельную заявку перед началом торгов также ничего не приходит. При снятии всех заявок пришло nStatus = 2 по каждой, то есть сработало. Полные параметры каждой отдельной активной заявки для снятия были получены через QUIK_ORDER_STATUS_CALLBACK при nMode = 1 и 2 (последняя заявка из очереди).
Вообщем, если идут торги, все прекрасно работает, заявка снимается. Необходимо снять выставленную с вечера предыдущего дня заявку перед началом торгов. И вот тут такая посылаемая транзакция на выполняется, хотя вручную из Quik заявку можно нормально снять. Подскажите, пожалуйста, может я какой параметр пропустил или что не так?