Рекомендуем в начале настроить ежедневную выгрузку скриптом export_alltrades.lua После этого включить ODBC драйвер. Комбинация обоих механизмов позволяет практически исключить пробелы в истории сделок.
Практическое применение - backtesting, оптимизация алгоритов в части выставления заявок.
Использование СУБД бесплатное. Будем признательны за обратную связь. На хорошие вопросы постараюсь отвечать в течение дня.
При этом несоответствие наблюдается для отдельных инструментов и разброс в отдельных случаях весьма существенный. С дататипами переменных и округлением не связано.
Как оказалось, waprice акций который раньше воспринимался как тот же дневной vwap данного класса, оказался гораздо хитрее. А именно, выяснилось, что при расчете waprice биржа "cмешивает" сделки не только из класса TQBR но и из других классов, в частности из РПС (с ЦК и без) и неполные лоты. Объем в режиме неполных лотов малый, до 500 тысяч рублей в день, а РПС - это 2 млрд рублей в день, что достаточно для точечного вредительства алгоритмам.
Подробности в расследовании по ссылке, но краткий вывод такой - используйте valtoday/voltoday.
waprice лежит в основе marketprice2, marketpricetoday, prevwaprice, priceminusprevwa - соответственно эти параметры также затронуты.
В каком параметре транслируется ожидаемый объем в ходе аукциона (фаза сбора заявок, открытие)? Согласно документации, это должен быть VOLUME, но он постоянно nil. При этом AUCTPRICE возвращает корректное значение.
После окончания фазы сбора заявок (случайно в 09:59:30+) на аукционе открытия наблюдаю, что TRADINGSTATUS остается на 3 (открыта) и при этом ENDTIME (время окончания фазы) иногда проставлено иногда нет.Существует ли надежный способ узнать, можно ли выставлять заявку во время аукциона открытия?
Есть ли возможность отправить на биржу транзакцию, которая произведет замену заявки (изменение цены)? Сейчас использую NEW_ORDER и KILL_ORDER в sendTransaction для замены.
Из документа биржи:
Код
Сообщение Order Cancel/Replace Request (G) используется для изменения параметров заявки. Обработка приказа Order Cancel/Replace Request (G) – атомарная операция, то есть другие приказы не могут обрабатываться между снятием исходной заявки и регистрацией новой. Время обработки сообщения (время ожидания ответа) Order Cancel Replace превышает время ожидания ответа при регистрации новой заявки, но меньше суммарного времени обработки пары приказов Order Cancel Request + New order single. Среднее время доставки приказа Order Cancel Replace от клиента во входную очередь ядра торговой системы не отличается от времени доставки приказов других типов (New Order Single или Order Cancel Request).
Обработка лимитной заявки с типом "По одной цене" предполагает несколько сценариев. Один из таких сценариев - это дефицит количества во встречных заявках по наилучшей цене.
Допустим, что есть встречные заявки на продажу:
- 261.10 x 10 - 260.00 x 5
Отправляем заявку на покупку "По одной цене": + 262.00 x 20
Данная заявка на покупку приведет к сделке на 5 бумаг по 260.00, при этом остаток будет поставлен в очередь в книге заявок по цене первой сделки 260.00. Состояние книги после частичного исполнения:
- 261.10 x 10 + 260.00 x 15
После отправки транзакции с этим признаком
Код
transaction['Тип по цене'] = 'По одной цене'
transaction['Цена'] = '262.0'
в терминал Квик приходит событие OnOrder, в котором цена указана 260.00, при этом заявка является частично исполненной. 1) Сохраняется ли в таблице Order информация об исходной лимитной цене (262), или эта информация утрачивается? 2) В какой момент (сервер Quik, терминал Quik, биржа) происходит данное "уточнение" цены заявки. 3) Для каких стратегий может быть полезен данный тип заявки?
В скрипте используются имена полей на английском языке. Терминал на русском языке. При выводе в tri вижу следующее:
Код
TRANS_ID=1;CLASSCODE=TQBR;ACTION=Ввод айсберг заявки;Торговый счет=NNNN;К/П=Купля;Тип=Лимитная;
Тип по цене=По разным ценам;Тип по остатку=Поставить в очередь;Тип ввода значения цены=По цене;Назначение заявки=По умолчанию;
Тип события активации заявки=Обычная заявка;Режим=TQBR;Инструмент=AFLT;Цена=99.90;Лоты=110;Примечание=;Объем заявки=0.00;
Код внешнего пользователя=;Время активации=;Доп. инфо=;Фирма торгового счета=;Видимое количество=100;
Коллеги, есть ли возможность в параметрах инструмента увидеть это значение? По умолчанию это 100 лотов, но в таблице А-5 приведены исключения: https://fs.moex.com/files/5877/32604Из интерфейса Квик мне непонятно - проводится ли проверка на клиенте или на сервере биржи?
Функция getParamEx уже предоставляет доступ к информации о последней сделке, а именно о ее цене, количестве и времени. Однако при высокочастной торговле, когда почти одновременно происходит большое количество сделок, эти параметры не дают однозначной идентификации сделки. Предлагаю добавить поле lasttrade, которое будет содержать trade_num сделки. Также рассмотреть вопрос об увеличении точности времени последней сделки до долей секунды. Речь идет о поле time.
Эта информация (микросекунды) уже транслируется в таблице alltrades.
Используя разных брокеров (Сбер и Финам) обнаружил, что разница между полями date_time и gate_reply_time зависит от брокера. В одном случае gate_reply_time всегда больше date_time, в другом случае наоборот. Что же все-таки означает это поле? В документации указано, что это "Дата и время получения шлюзом ответа на транзакцию". Тогда не совсем понятно почему оно предшествует date_time, да и само поле date_time требует уточнения. Является ли это поле временем получения транзакции Quik сервером у брокера? В целом планирую использовать дельту между gate_reply_time и date_time для целей мониторинга и выбора оптимального Квик сервера в зависимости от стратегии.
Для мониторинга ключевых показателей использую выделенный скрипт. Торговые стратегии реализованы в отдельных скриптах.
Есть определенные пороги, при превышении которых небходимо остановить исполнение всех lua скриптов, кроме контрольного. Также необходимо при определенных условиях отсоединить терминал.
Контекст: для тех кто не сталкивался с доп. вознаграждением биржи за гиперактивные торговые алгоримты, советую ознакомиться и поставить на мониторинг!
Из сервисных функций есть isConnected. Функции disconnect() похоже нет. Сейчас вызывается os.exit(), но это брутально. Есть ли еще варианты, которые следует изучить?
Я пользуюсь нижеприведенным вариантом для получения подвыборки строк из таблицы, в данном примере из таблицы orders.
Код
function find_active_orders(class_code, sec_code)
function matchItem(_flags, _class_code, _sec_code)
return bit.band(_flags, 0x1) ~= 0
and _class_code == class_code
and _sec_code == sec_code
end
local indexes = SearchItems("orders", 0, getNumberOf("orders")-1, matchItem, "flags,class_code,sec_code")
if indexes == nil then return {} end
local res = {}
for i=1, #indexes do
local item = getItem("orders", indexes[i])
if matchItem(item.flags, item.class_code, item.sec_code) then
res[#res+1] = item
end
end
return res
end
В строке if matchItem(item.flags, item.class_code, item.sec_code) then я дополнительно проверяю, что полученная заявка соответствует изначальному фильтру на случай, если таблица orders будет изменена и в нее будут добавлены новые заявки в произвольном порядке.
Два вопроса:
1) Необходима ли повторная проверка или можно полагаться, что а) строки не удаляются, б) новые заявки помещаются в конец таблицы и в) порядок строк не меняется в течение торгового дня? Если так, применима ли такая модель ко всем таблицам в Quik (строки никогда не удаляются, новые добавляются в конец, порядок строк зафиксирован).
2) По ходу биржевого дня количество строк в таблице постоянно увеличивается и доходит до 20000, в результате постоянного изменения лимитных заявок по цене (снять старую, выставить новую по другой цене). При этом активных заявок только несколько сотен. При каком размере таблицы имеет смысл задуматься о производительности функции find_active_orders и как ее можно было ускорить для случая когда практически все заявки неактивные?