Как показывает практика, полноценно использовать CreateDataSource для подписки на таблицу обезличенных сделок не представляется возможным. Посему предлагаю добавить в qlua несколько новых функций.
1. Функция getAllTradeFilters
Код
STRING getAllTradeFilters(STRING class_code)
Возвращает строку в формате, аналогичном возвращаемому getClassSecurities(class_code), содержащую список бумаг указанного класса, для которых включен заказ всех сделок (попросту строку из INFO.ini для данного класса). Если для класса нет выбранных инструментов (эквивалентно отсутствию класса в INFO.ini или же там записано class_code=), возвращает пустую строку. Если для класса выбраны все инструменты (эквивалентно class_code=ALL в INFO.ini), возвращает то же самое, что и getClassSecurities(). В случае ошибки возвращает nil.
Устанавливает список бумаг, для которых включен заказ всех сделок, для указанного класса. Если security_code_list является пустой строкой, отключает заказ всех сделок для всего класса (эквивалентно class_code= в INFO.ini). Если security_code_list содержит ту же строку, что вернула бы getClassSecurities(class_code), включает заказ всех инструментов класса (эквивалентно class_code=ALL в INFO.ini). Возвращает true, если фильтры были изменены, false в случае ошибки (и гарантирует, что во втором случае имевшиеся до вызова фильтры остались неизменными). Определенная сложность видится при наличии открытых в терминале ТОС, что делать, если данный вызов пытается отменить заказ данных для используемых таблицами инструментов?
Выполняет подписку на ТОС по указанному классу и списку инструментов, как если бы пользователь открыл ТОС с аналогичными фильтрами в терминале, но, в отличие от таблицы, не изменяет глобальные фильтры заказа данных, даже если установлена автонастройка фильтров по открытым таблицам. Возвращает таблицу, одним из полей которой является функция close() для последующей отписки, и, возможно, в таблице имеются поля с кодом класса и списком инструментов, прошедших глобальные фильтры, т.е. по которым действительно произошел заказ данных. Возвращает nil в случае ошибки.
Квик должен гарантировать, что при любом (нормальном/принудительном) завершении скрипта, выполнившего подписки на ТОС, все эти подписки будут автоматически отменены, что легко достижимо установкой метаметода __gc для возвращенной из SubscribeAllTrades таблицы на ее же метод close().
Anton написал: Как показывает практика, полноценно использовать CreateDataSource для подписки на таблицу обезличенных сделок не представляется возможным
Из переписки совершенно не следует сказанное. Трудности да есть, но "не возможным" использование функции CreateDataSource не делает.
1) Уберите в коде функцию split, она совершенно лишняя. getClassesList и getClassSecurities прекрасно обрабатываются через string.gmatch, без всяких лишних манипуляций с циклами А лишние циклы в борьбе за скорость, это великое зло. Пример кода: for vv in string.gmatch(getClassSecurities(v), "([^,]+)") do -- end
2) в ОС Windows есть свой собственный таймер процессора, который по умолчанию равен 15.625 мс Если вы про него не знали, почитайте про него в интернете В результате на каждую итерацию цикла, кроме обработки самой итерации, вносится указанная задержка. Крайне рекомендуем прочитать текст статьи прежде чем комментировать, это сразу избавит от лишних вопросов.
3) Вам уже говорили что нужно перенести функцию из OnInit в main.
4) зачем делать отдельный цикл для SetEmptyCallback, совершенно не понятно, хотя вопрос не в этом.
5) И последнее, куда важнее с какой скоростью данные поступают и обрабатываются нежели с какой скоростью происходит заказ.
Sergey Gorokhov, благодарю за фидбек. Несколько обескураживает ваш ответ, если честно, особенно часть про таймер, особенно после ознакомления со статьей по ссылке. Таймер тут при чем? Равно как и сплит тут мало на что влияет, он выполняется один раз на класс, коих в тестовом случае всего 19. Перенос в мейн тоже ничего не меняет, интерфейс висеть не будет, но сам процесс подписки идет с той же скоростью. В общем, про таймер как раз добавило лишних вопросов. А так-то я больше 20 лет под винды пишу, краем уха слышал, как там внутри все устроено, даже, если поднапрячься, вспомню, на какое прерывание этот "таймер процессора" заведен.
Категорически не согласен с пунктом 5. Пример. Юзер в 23:45 запустил квик, чтобы скачать данные за день, запустил скрипт. В 0:15 брокер вырубил сервер. И вдруг внезапно оказывается, что наш скрипт за это время (когда вся ТВС уже приехала бы сто раз) не то чтобы не сохранил данные, а даже еще и не подписался на них. То есть сессия пропала (нет подписки -> нет данныех даже в alltrade.dat), завтра утром на сервере ее уже не будет. Нормальный такой скрипт, удобный. Зато уж компом рычит как зверь по три часа кряду, сразу видно, что важным делом занят.
Таки да, мне в соседней ветке говорили про мейн и между делом намекнули на "другой подход", не знаю вот, стоит ли тут публично контору палить. Этим (или не этим) "другим способом" я подписался на все за пару секунд, но там другой вопрос возникает, такой способ сработает только когда глобальные фильтры уже установлены все на ALL, а при отписке (и закрытой ТВС) квик их сбрасывает. Тогда вопросы другие - а если я в info.ini их из скрипта запишу? Квик это увидит? А если квик со скриптом пересечется на доступе к info.ini, будет ждать анлока или упадет? А если через версию квика вы решите в другом месте фильтры хранить?
Как же, он добавляет задержку на каждую итерацию каждого цикла.
Цитата
Anton написал: Равно как и сплит тут мало на что влияет, он выполняется один раз на класс, коих в тестовом случае всего 19.
да он тут не причем, это просто один из примеров оптимизации
Цитата
Anton написал: Тогда вопросы другие - а если я в info.ini их из скрипта запишу? Квик это увидит? А если квик со скриптом пересечется на доступе к info.ini, будет ждать анлока или упадет? А если через версию квика вы решите в другом месте фильтры хранить?
Правка info.ini в данном месте саппортом не обслуживается, т.к. не является документированным функционалом.
К слову, тема еще не закрыта. Прежде чем регистрировать пожелание мы должны выяснить а действительно ли оно нужно. Так например на нашем боевом контуре, Ваш код по классу EQOB показал время ~20 сек Это само по себе уже является основанием перейти к разбору проблемы а не регистрации пожеланий.
Anton написал: Категорически не согласен с пунктом 5. Пример. Юзер в 23:45 запустил квик, чтобы скачать данные за день, запустил скрипт. В 0:15 брокер вырубил сервер. И вдруг внезапно оказывается, что наш скрипт за это время (когда вся ТВС уже приехала бы сто раз) не то чтобы не сохранил данные, а даже еще и не подписался на них. То есть сессия пропала (нет подписки -> нет данныех даже в alltrade.dat), завтра утром на сервере ее уже не будет. Нормальный такой скрипт, удобный. Зато уж компом рычит как зверь по три часа кряду, сразу видно, что важным делом занят.
По этому пункту, дело конечно Ваше, стартовать в конце гонки или в начале. Обычно люди стартуют в начале.
Так вот я и не понял, где у меня в скрипте таймер что-то добавляет. Там нет слип(0), где действительно бы отдавался остаток таймслота до следующего тика, тиккаунт же поток не снимает, да и тот выполняется всего 20 раз за скрипт, на каждом классе, а не на каждом инструменте. Там запись в лог больше лопает.
Любопытно, что подписка на дневки в том же самом цикле происходит практически мгновенно, хотя квику приходится несколько тысяч файлов создать в архиве (почистил предварительно). А вот если добавить ds:SetUpdateCallback(), приходится подождать секунд 10 (опять же на все). К сожалению, на ТВС это не влияет, фильтры не устанавливаются и все сделки не едут, а то был бы вариант.
Вот по разнице во времени выполнения уже интереснее. Заметил, между прочим, что и открытие ТВС тоже как-то не то чтобы быстро происходит после обновления на восьмую версию, хоть и не часы конечно, но "раньше было лучше". Попробую у себя почистить все для начала и повторить эксперименты.
Где стартовать, дело даже не мое, а того, кто этим будет пользоваться. По опыту юзеры выдумывают такие юзкейсы, которые мне и в голову не могли прийти, и через икс времени переписывать весь код "по гарантии", сиречь даром, не очень улыбается. Это же относится и к недокументированным всяким возможностям, так что гипотетический вариант с хачением info.ini всерьез и не рассматривал. Вариант с info.ini кстати не работает, если вдруг кто еще возжелает попробовать. Чтобы квик увидел написанное, надо диалог фильтров "продернуть", а зачем тогда в файл писать, можно в диалоге кнопки подавить, раз уж его открывать все равно. В любом случае это все не вариант, одно "неудачное" обновление квика и попал на субботник.
Anton написал: Любопытно, что подписка на дневки в том же самом цикле происходит практически мгновенно, хотя квику приходится несколько тысяч файлов создать в архиве (почистил предварительно). А вот если добавить ds:SetUpdateCallback(), приходится подождать секунд 10 (опять же на все). К сожалению, на ТВС это не влияет, фильтры не устанавливаются и все сделки не едут, а то был бы вариант.
ТОС (он же тики) и интервальные графики едут по разным технологиям. Интервалы генерирует сервер и хранит их у себя в хранилище, в связи с чем на терминал Вы уже получаете все готовое. Тики же едут в сыром виде, как пришли с биржи. Естественно объемы не соизмеримые.
Как уже было сказано, Ваши ~500 сек никуда не идут в сравнении с нашими ~20сек. И как уже было сказано, надо разобраться в начале с этим, а потом уже принимать решение о регистрации пожеланий. Попробуйте собрать больше информации, например провести тестирование на другом компьютере и канале связи. Кроме того, попробуйте провести тест в разное время, утром до торгов, утром при старте торгов, в обед и вечером. Сравните данные и сообщите нам.
Sergey Gorokhov написал: Кроме того, попробуйте провести тест в разное время, утром до торгов, утром при старте торгов, в обед и вечером. Сравните данные и сообщите нам.
Вот сейчас как раз пробовал. Похоже, причину разницы 20/500 понял. Значит, удаляем alltrade.dat, отключаем все фильтры ТВС, запускаем квик, подключаемся, убеждаемся, что ничего не едет (alltrade.dat 64кб, т.е. одна гранулярити отмэплена, скорей всего пустая). Запускаем (тиковую) подписку - подписались мгновенно, параллельно начинают дергаться OnAllTrade. Казалось бы, идиллия. Повторяем упражнение, подождав подкачки всех сделок в alltrade.dat (около 200 Мб), вот тут уже гораздо медленнее. И да, облигации сейчас где-то за 20 секунд и подписались (на глаз смотрел, плюс-минус километр). Вечером, когда в alltrade.dat будет весь день, думаю, все вернется на круги своя. Кстати, утром-то ситуация как раз такая, в alltrade.dat вся вчерашняя ТВС, так что хочешь не хочешь, а надо запускаться вот в таком окружении.
Sergey Gorokhov написал: для очистки dat файлов есть ключ -clear (в документации глава "Ключи запуска Рабочего места QUIK")
Спасибо, полезная штука в некоторых ситуациях, хотя в данном случае менее костыльным будет просто потребовать открытой ТВС.
Значит, нынче почистил все, до чего руки дотянулись, обновил квик (три длл подъехали), о дневных пробах писал уже. После закрытия биржи включил скрипт и вот до сих пор (скоро два часа как) он все жужжит, сейчас где-то в опционах ковыряется. То есть ничего нового. И такая резкая зависимость от количества записей в ТВС грустно намекает на "эн-квадрат" где-то внутри.
Таким образом, на текущий момент вариантов кроме "ТВС должна быть открытой" я не вижу, на будущее хотелось бы все же видеть что-то более легкое, чем CreateDataSource, без встроенного энквадрата.
Anton написал: Таким образом, на текущий момент вариантов кроме "ТВС должна быть открытой" я не вижу, на будущее хотелось бы все же видеть что-то более легкое, чем CreateDataSource, без встроенного энквадрата.
Еще раз повторяем (уже третий) Пожелания НЕ будет т.к. описанного поведения НЕ должно быть вообще. Вы описываете проблему с которой надо разобраться. И только если вдруг после разбора окажется что так и должно быть тогда да, будет пожелание. Сейчас это больше выглядит как баг, а не отсутствие функционала. И как уже было сказано, у нас проблема не воспроизводится.
Для анализа просьба прислать на quiksupport@arqatech.com копию всей папки с проблемным терминалом QUIK (без ключей доступа) В письме укажите ссылку на эту ветку форума.
Sergey Gorokhov написал: Ваши ~500 сек никуда не идут в сравнении с нашими ~20сек.
При каждом вызове CreateDataSource по тикам дергается info.ini: раз 15 повторяется цикл LockFile/ReadFile/UnlockFile/CloseFile и один раз даже WriteFile )) Скорость выполнения такого блока операций сильно зависит от скорости диска, на который установлен QUIK. И, как ни странно, может отличаться в десятки раз.
Ну ещё и сравнивать надо в одинаковых условиях, например, какие были установлены фильтры, что было в файлах info.ini (в частности в секции [ALL_TRADES_DATA]), alltrade.dat до запуска скрипта.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Для анализа просьба прислать на quiksupport@arqatech.com копию всей папки с проблемным терминалом QUIK (без ключей доступа) В письме укажите ссылку на эту ветку форума.
Отправил.
Цитата
Старатель написал: При каждом вызове CreateDataSource по тикам дергается info.ini: раз 15 повторяется цикл LockFile/ReadFile/UnlockFile/CloseFile и один раз даже WriteFile ))
Интересная информация по доступу к info.ini, спасибо. С одной стороны, винда должна кэшировать доступ к файлам, если, конечно, кодер сам не наставил флагов прямого доступа к диску, с другой, пара LockFile/UnlockFile может добавлять хороших тормозов. Косвенно также дан ответ на вопрос "что будет, если лезть в info.ini из скрипта", -- все будет хорошо, раз квик лочит файл перед чтением.
Цитата
Старатель написал: Ну ещё и сравнивать надо в одинаковых условиях, например, какие были установлены фильтры, что было в файлах info.ini (в частности в секции [ALL_TRADES_DATA]), alltrade.dat до запуска скрипта.
Получается два контура торможения (двухконтурная тормозная система, ага). Первый это доступ к info.ini, если там не стоят class_code=ALL, квик будет добавлять открываемые инструменты в список, а он не может их сразу все добавить, т.к. создает датасорцы по одному. Эти (и только эти) тормоза можно увидеть, запустив подписку при сброшенных фильтрах и пустом alltrade.dat. Второй контур - это когда в info.ini установлены фильтры ALL для всех классов, тогда записи в info.ini не будет, как и не будет поиска по info.ini, квик сразу увидит ALL. Тогда при пустом alltrade.dat подписка произойдет мгновенно, но при заполненном получим "тормоза второго рода", зависящие от размера alltrade.dat.
Sergey Gorokhov написал: важнее с какой скоростью данные поступают и обрабатываются нежели с какой скоростью происходит заказ.
Для сравнения: в день по опционам проходит биржевых сделок около 20 тыс. (±10 тыс.). Чтобы подписаться на сделки по всему классу опционов, нужно дёрнуть info.ini около 150 тыс. раз.
Надо делать так, как надо. А как не надо - делать не надо.
Появилось немного времени, решил потестить. При при пустом alltrade.dat заказ обезличенных сделок по классу EQOB (1393 бумаги) занимает 5 сек, при заполненном alltrade.dat (в конце торгов) 30 мин! Это на быстром диске, на HDD такое делать в середине-конце торгов не рекомендуется )) Посмотрел, что делает в это время QUIK: при подписке на каждый инструмент идёт множественное обращение к файлу alltrade.dat, и чем больше записей есть в таблице, тем больше будет обращений к файлу. Если заказывать обезличенные сделки не скриптом, а через меню, то обращения к alltrade.dat минимальны или отсутствуют.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: описанного поведения НЕ должно быть вообще. Вы описываете проблему с которой надо разобраться. И только если вдруг после разбора окажется что так и должно быть тогда да, будет пожелание. Сейчас это больше выглядит как баг, а не отсутствие функционала.
Что в итоге? Так и должно быть или баг?
Надо делать так, как надо. А как не надо - делать не надо.
После тестов признали багом. Однако ж тут вот было заявление, что квик перезапускает alltrade после каждой подписки, и ваш результат с множественными ковыряниями в этом файле как бы подтверждают это. По-хорошему в него лазить-то не нужно, он мэпится в память целиком, обнаруженное поведение может означать только одно: после каждой подписки файл анмэпится и потом мэпится заново зачем-то.
Есть идея костыля. Из длл открыть alltade.dat и создать мэппинг для чтения на весь его размер. Это приведет к тому, что при переподписке квик будет получать тот же самый мэппинг без выгрузки/загрузки всего и вся, т.е. вхолостую, это уменьшит накладные расходы, хотя неизвестно, насколько. Тут есть опасность, что при смене сессии квик попытается урезать файл и не сможет, т.к. мы держим мэппинг открытым. К чему это приведет - неизвестно, зависит от того, как ошибка обрезания обрабатывается. Надо попробовать на неделе. В любом случае, это не продакшен вариант, чисто исследовательский.
Старатель, набросал тут длл, которая создает мэппинг alltrade.dat и обновляет его каждые 5 секунд на случай изменения размера (плохое решение, чисто на пробу). Ежли еще не разобрали тестовый стенд и есть время и желание, запробуйте плиз, что будет, когда этот скрипт запущен перед массовой подпиской. У меня нынче брокер выключен.
Anton написал: при переподписке квик будет получать тот же самый мэппинг без выгрузки/загрузки всего и вся, т.е. вхолостую, это уменьшит накладные расходы
Тест проводился на виртуальном диске в ОЗУ. Т.ч., не могу подтвердить или опровергнуть ваше предположение.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: не могу подтвердить или опровергнуть ваше предположение.
Оно было неверным. Подписка EQOB без мэппинга - 1079 секунд, с мэппингом - 1108 секунд, второй тест проводился позже, в таблице было уже больше данных, поэтому можно считать, что удержание мэппинга не влияет никак. Тест проводился после 18 часов на HDD довольно убитом, квик 8.3.2.4, все фильтры на ALL.
Адок с фильтрами отдельная песня, тест на опционах с изначально сброшенными фильтрами пришлось грохнуть вместе с квиком, т.к. раздул info.ini до 80 мегов повторяющимися записями в SPBOPT и конца этому видно не было. Кстати говоря, квик потом сам не может этот info.ini поправить при сбросе фильтров из диалога, так все и остается, пока руками файл не почистишь. Не говоря уже о том, что по завершении скрипта с подписками слетают фильтры даже при открытой ТВС. Надо эти фильтры убирать к чертовой бабушке, один геморрой от них.
Вдогонку тест "что случится при попытке квика урезать alltrade.dat в то время, как скрипт удерживает мэппинг". Будет крэш квика, что, в общем-то, хорошо. Хотя я б добавил настроечку "резервировать [окошко] мегабайт на диске для таблицы обезличенных сделок" и резал бы файл до указанного лимита, а не под корень, было б меньше фрагментации (хитро щурится). Ну как в торрентах делается примерно.
Sergey Gorokhov написал: описанного поведения НЕ должно быть вообще. Вы описываете проблему с которой надо разобраться. И только если вдруг после разбора окажется что так и должно быть тогда да, будет пожелание. Сейчас это больше выглядит как баг, а не отсутствие функционала.
Что в итоге? Так и должно быть или баг?
Добрый день.
Запрошенную информацию Сергеем для разбора вы присылали?