Начну из далека. При заказе таблицы котировок используем
Код
Subscribe_Level_II_Quotes(class, sec) -- Для заказа котировок с сервера
getQuoteLevel2(class, sec) -- Для получения котировок
Мы либо получаем актуальные котировки, если стакан открыт, либо незаполненную таблицу, если стакан закрыт или котировки ещё не подгрузились с сервера. Если закрыть стакан (отменить заказ на получение котировок с сервера), то getQuoteLevel2 вернёт незаполненную таблицу. Т.о., мы понимаем, что, если getQuoteLevel2 вернул данные, то они актуальны. Использование простое:
Код
function main()
Subscribe_Level_II_Quotes(class, sec)
-- Получаем актуальные котировки, если они есть:
Quotes = getQuoteLevel2(class, sec)
end
-- Дальнейшие изменения в стакане можно ловить в OnQuote:
function OnQuote(class, sec)
Quotes = getQuoteLevel2(class, sec)
end
С getParamEx2 намного сложнее. Если getParamEx2 вернул данные, то они актуальные или старые? Может, пять часов назад их заказывали, потом подписку отменили, а данные остались в кеше. Если же брать парамтры только в OnParam, то по неликвидному инструменту их можно ждать бесконечно долго.
Надо делать так, как надо. А как не надо - делать не надо.
Здравствуйте, Старатель! Если речь идет исключительно об актуальности данных, то рекомендуем перед тем, как вызывать getParamEx (getParamEx2), сначала вызывать ParamRequest. Таким образом, после вызова getParamEx (getParamEx2) отобразятся только актуальные данные.
Alexander Kopyatkevich написал: Если речь идет исключительно об актуальности данных, то рекомендуем перед тем, как вызывать getParamEx (getParamEx2), сначала вызывать ParamRequest.Таким образом, после вызова getParamEx (getParamEx2) отобразятся только актуальные данные.
Вы уверены в том, что вы пишите? Актуальные данные клиент покажет только после того, как они попадут с сервера на клиента. И когда это будет нам неведомо. А до тех пор getParamEx2 может показывать что угодно.
Цитата
Старатель написал: Если getParamEx2 вернул данные, то они актуальные или старые? Может, пять часов назад их заказывали, потом подписку отменили, а данные остались в кеше.
Надо делать так, как надо. А как не надо - делать не надо.
Именно для этого и нужно предварительно выполнить подписку на получение определенного параметра через ParamRequest. После выполнения подписки с сервера QUIK отправятся последние данные, которые и будут являться актуальными.
Alexander Kopyatkevich, можете написать код для получения параметров через getParamEx2? С getQuoteLevel2 всё просто:
Код
if isConnected() ~= 1 then return end
function main()
-- Заказываем получение котировок:
Subscribe_Level_II_Quotes(class, sec)
-- Получаем актуальные котировки, если они есть:
Quotes = getQuoteLevel2(class, sec)
-- Если открыт стакан или котировки были раннее заказаны другим скриптом, то сразу получим актуальные данные
-- В противном случае в Quotes будет незаполненная таблица
...
end
-- Дальнейшие изменения в стакане можно ловить в OnQuote
function OnQuote(class_code, sec_code)
if sec_code == sec and class_code == class then
Quotes = getQuoteLevel2(class, sec)
...
end
end
Я уверен, что в Quotes будут актуальные котировки или незаполненная таблица. Таблицы с неактульными котировками не будет. Причём, даже если стакан по инструменту изменяется раз в час, получу текущие котировки, не дожидаясь следущего обновления стакана.
С getParamEx2 так не получается. Можете написать для следующего кейса: Получить зачение параметра для неликвидного инструмента с учётом того, что неизвестно был ли заказан параметр до запуска скрипта.
Надо делать так, как надо. А как не надо - делать не надо.
function main()
if ParamRequest(p_classcode, p_seccode, "bid")==true then
bid = getParamEx2(p_classcode, p_seccode, "bid")
message(bid.param_value,1)
end
end
Alexander Kopyatkevich, мне даже не удобно вас об этом спрашивать: полагаете ваш код покажет актуальную котировку? А если я два часа назад добавлял параметр "BID" в ТТТ, а потом убрал его. То какую котировку мне покажет ваш код: текущую или двухчасовой давности?
Надо делать так, как надо. А как не надо - делать не надо.
Старатель, ParamRequest() это добавление в список ожидаемых заказов. Сам заказ делается раз в период. Т.е. для более-менее успешного получения заказанных параметров нужно подождать. Для понимания что заказанный параметр начал ехать нужно ждать коллбэк OnParam(), после чего вызывать getParamEx2
Sergey Gorokhov написал: Для понимания что заказанный параметр начал ехать нужно ждать коллбэк OnParam()
С первого сообщения пытаюсь объяснить. Если параметр уже заказан (а проверить мы это никак не можем) до запуска скрипта (в ТТТ али другим скриптом), то если брать данные только в OnParam(), придётся ждать следующего обновления параметров. А для неликвидного инструмента это может быть очень не скоро. Глядишь к концу сессий чё-нить дождёмся... А если вызывать getParamEx2 до прихода OnParam(), то нет гарантии, что там не старьё.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Если параметр уже заказан (а проверить мы это никак не можем) до запуска скрипта (в ТТТ али другим скриптом), то если брать данные только в OnParam(), придётся ждать следующего обновления параметров. А для неликвидного инструмента это может быть очень не скоро. Глядишь к концу сессий чё-нить дождёмся...А если вызывать getParamEx2 до прихода OnParam(), то нет гарантии, что там не старьё.
Если параметр уже заказан, до запуска скрипта, то getParamEx2 и так получит "актуальные данные" без всяких ParamRequest и OnParam ждать нет нужды.
Sergey Gorokhov написал: Если параметр уже заказан, до запуска скрипта, то getParamEx2 и так получит "актуальные данные" без всяких ParamRequest и OnParam ждать нет нужды.
Вы поспорить или по делу? Как в скрипте узнать, что параметр уже заказан?
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov, сможете привести однозначный алгоритм получения параметра, который работает всегда и надёжно, и который даёт гарантированно актуальное значение, а не старые данные из кеша? И чтобы не нужно было ждать полдня, пока ожидаемый параметр поменяет своё значение.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Вам по сути нужен способ узнать включена ли подписка.
Пример с getQuoteLevel2 показателен. Если вы про аналог функции IsSubscribed_Level_II_Quotes, то она бесполезна, т.к. показывает, что подписка включена в то время когда, данные ещё не получены. Но дуэт Subscribe_Level_II_Quotes и getQuoteLevel2 самодостаточен и позволяет получать только актуальные данные. PS: Обратил внимание, что после остановки скрипта, подписка на стакан не закрывается автоматически. Надо бы исправить.
Для ParamRequest и getParamEx2 хотелось бы такой же работы.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Для ParamRequest и getParamEx2 хотелось бы такой же работы.
Поймите что стакан и ТТТ это кардинально разные таблицы которые обновляются кардинально разными способами. Нельзя сделать в ТТТ "аналогично" как в стакане.
Но чтобы она также давала информацию получен ли параметр с момента последней подписки: nil - подписка не включена false - подписка включена, но параметр ещё не получен true - подписка включена, параметр получен Или: 0, 1, 2
Надо делать так, как надо. А как не надо - делать не надо.
Старатель, Старатель, Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Sergey Gorokhov написал: Для понимания что заказанный параметр начал ехать нужно ждать коллбэк OnParam(), после чего вызывать getParamEx2
Даже в таком варианте вместо актуального значения можно получить не пойми что. Пример: в момент времени Т0 клиент был подписан на получение нескольких параметров по бумаге, затем подписка на параметр Р была закрыта. Через несколько часов в момент времени Т1 скрипт снова подписывается на параметр Р. Но пока сообщение о подписке дойдёт до сервера, тот будет слать раннее заказанные параметры (без Р). В результате, вызвав getParamEx2 в коллбэке OnParam(), мы получим старое значение параметра Р, сохранённое в кеше на момент времени Т0.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: В результате, вызвав getParamEx2 в коллбэке OnParam(), мы получим старое значение параметра Р, сохранённое в кеше на момент времени Т0.
Вот вот, нужно в OnParam помимо клсса и кода передавать список параметров которые изменились, а то их 100+, а какой(е) именно изменился - не понятно. А getParamEx2 это медленная функция.
С первого сообщения пытаюсь объяснить. Если параметр уже заказан (а проверить мы это никак не можем) до запуска скрипта (в ТТТ али другим скриптом), то если брать данные только в OnParam(), придётся ждать следующего обновления параметров. А для неликвидного инструмента это может быть очень не скоро. Глядишь к концу сессий чё-нить дождёмся... А если вызывать getParamEx2 до прихода OnParam(), то нет гарантии, что там не старьё.
Суть проблемы мне понятна, и я с вами согласен, что все это очень не гладко.
Однако, если посмотреть вот с какой стороны. В описанной ситуации откроем в терминале таблицу параметров. Она нам что-то покажет (т.к. когда-то данные были), какую-то цифру мы увидим. Актуальная это цифра или нет? когда она изменилась? когда приедет актуальное значение? Ведь никого это не волнует, правда? Видим цифру - отлично, с ней работаем. Но в скриптах почему-то неактуальность цифры становится принципиальной. Но почему? Это не в плане с пора с вами, это просто понять, порассуждать.
Александр, Ну так и получать надо эти "актуальные данные" тупым опросом ТТТ - тыщу раз уж об этом писал! Даже если интернет отрублен или биржа не работает - даже тогда там есть какие-то данные, вполне себе "актуальные" - просто курс не движется, и робот, который "используется для автоматизации", вполне в состоянии их читать. Что мой и делает раз в секунду. Данные - пальчики оближешь, актуальнее не бывает, надёжнее тоже не бывает, ждать ничего не надо. НУ НАФИГА вам искать на свою задницу приключений?
Старатель, Это Вы не в теме. Скрипт ТОЖЕ не может "выполнить действие" - он может лишь послать заявку, и за это время котировка ТОЖЕ может поменяться. Я вначале собирался ставить в заявку BID или OFFER - как раз для мгновенного исполнения, но потом передумал, ибо это ТОЖЕ ничего не гарантирует. Но для любого тикера всегда существует некий "дребезг", и потому в 99 случаях из 100 заявка по LAST всё равно сработает в течение пары минут, если не секунд, так что работает мой скрипт ТОЛЬКО по LAST и ТОЛЬКО опросом ТТТ. И только за сегодня у него уже есть одна сделка у одного брокера (рублёвая) и шесть сделок у другого (долларовые). ЧТД!
Владимир, как я понял, у вас всегда открыта ТТТ, и в неё добавлены все интересующие вас инструменты и параметры. И вы принципиально не пользуетесь ParamRequest, которая в таком случае и не требуется. Эта же тема для истинных ценителей автоматизации, у которых в терминале открыто только одно окно: Доступные скрипты, ну ещё могут быть окна, созданные скриптами.
Цитата
Владимир написал: за это время котировка ТОЖЕ может поменяться
Имелось ввиду, что пока трейдер примет решение, котировка обновится до актуальной, а не то, что вы подумали.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Но в скриптах почему-то неактуальность цифры становится принципиальной. Но почему?
Разное время реакции. Пока трейдер примет решение, котировка поменяется. А скрипт: получил котировку - выполнил действие.[/QUOTE]
Ну т.е. грубо говоря нужен функционал: 1) подписались на новые данные 2) взвели признак (таймер) "позови функцию2" через 1 сек (условный интервал типичной актуализации данных) 3) вышли из функции 4) через секунду считаем, что данные приехали - на этом основании получаем данные и принимаем решение.
Здесь мне видится принципиальным пункт 3), дабы не подвешивать QUIK на sleep() и точно дать ему обработать полученные данные.
Я про то, что QUIK (да и не только) в принципе ведь не позволяет вам узнать актуальные сейчас вы видите данные в терминале или нет. Просто считается что если человек что-то видит - то он принимает на этом основании решение - и это как бы никого не парит (хотя данные могут быть вовсе не актуальными). А вот при автоматизации почему-то непременно начинает всех волновать актуальность данных.
Так может вопрос лишь в подходе к написанию скрипта? Я прекрасно понимаю, что хочется писать скрипт максимально просто и прозрачно, я и сам так делаю: - подписался на данные - прочитал данные - вычислил формулы - принял решение
Причем тут даже не понятно что требовать от QUIK-то. В самом деле, предположим реализована схема "подписался на данные - передал call-back". Но когда это call-back должен вызваться? а) когда данные по подписке проехали - а толку? это ж не актуальные данные; не говоря уж о том, что данных объективно этих может не быть (неликвид) б) когда данные по подписке все доехали - так этого момента никто и не знает.
И как быть? в самом деле, реализацию какого функционала требовать от QUIK? у меня нет идей, увы
Старатель, Совершенно верно: у меня всегда открыта ТТТ, и в неё добавлены все интересующие меня инструменты и параметры. И я принципиально не пользуюсь ParamRequest - скрипт у меня работает только с Квиком, позволяя торговать и мне, в режиме кентавра - либо через команды скрипту, либо самостоятельно, через стаканы (о моих сделках в этом случае он узнаёт через OnTrade). Мало того: я ТОЖЕ "истинный ценитель автоматизации", у которого в терминале открыто не просто "только одно окно: Доступные скрипты", но и в окне этом только один скрипт. Я пока ещё торгую и сам "по инерции", но уже почти все тикеры отдал на откуп скрипту - доказано, что он торгует лучше меня. А потому ТТТ заказана, в основном, для него, и может быть свёрнута в иконку и тихонечко лежать там, не раздражая юзера своим мельтешением.
Да, есть ещё "окна, созданные скриптами" - сводная таблица и контекстное меню, всплывающее по клику на строчку этой таблицы. А ещё у меня есть таблица "состояние счёта" (для контроля - я туда редко заглядываю), таблица заявок (с той же целью), позиции по деньгам и клиентский портфель, показывающий мгновенную ликвидность. Всё для юзера. Я даже написал версию, которая торгует только сама и выводит только текущее состояние денег по каждой валюте (3 строчки, 5 столбцов), но на неё скучно смотреть - она показывает только "то, что было", но не "то, что будет".
swerg написал: не позволяет вам узнать актуальные сейчас вы видите данные в терминале или нет.
Про время передачи данных по каналам связи ведь все в курсе? Надеюсь вы не это хотите обсудить, а вопрос:
Цитата
Старатель написал: Но пока сообщение о подписке дойдёт до сервера, тот будет слать раннее заказанные параметры (без Р). В результате, вызвав getParamEx2 в коллбэке OnParam(), мы получим старое значение параметра Р, сохранённое в кеше на момент времени Т0.
Если последнее, то давайте начнём хотя бы с сообщения #19
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Про время передачи данных по каналам связи ведь все в курсе?
Я к тому, что выражение "актуальные данные" в данном случае относительно. И, надеюсь, это понятно, и мы не будем в 100500 раз мусолить тему, о том, что "сам QUIK не знает, что вот прям щас происходит на бирже".
Надо делать так, как надо. А как не надо - делать не надо.
Как временное решение, перезапуск квика с параметром "-clear", тогда кеш будет чистый, и определить что данные еще не загружены легко. Например для числовых значений getParamEx2 будет возвращать всегда 0 А адекватное на мой взгляд решение должно быть таким: При заказе подписки ParamRequest должен не просто слать запрос на подписку на сервер, а еще и получать в ответ от сервера актуальные данные и кидать их в кеш ТТТ При отмене подписки на параметр в кеш ТТТ должен заноситься nil
swerg, ну давайте пофантазируем, что в ближайшем десятилетии нам дали такую функцию:
Цитата
ParameterReceived(STRING class_code, STRING sec_code, STRING param_name) Возвращаемые значения: nil - при ошибке 0 - подписка не включена 1 - подписка включена, но параметр ещё не получен с момента последней подписки 2 - подписка включена, параметр получен
Либо можно возвращать то же значение дополнительным параметром received в таблице, возвращаемой getParamEx2 Значение 0 - можно и не делать, не вижу возможности его использовать. Возможно, и сам клиент, узнаёт об успешности подписки только по факту получения параметра с сервера. В любом случае, сервер что-то шлёт клиенту (хотя бы дефолтные нули и пустые строки), даже если
Цитата
swerg написал: данных объективно этих может не быть (неликвид)
Использование:
Скрытый текст
Код
function main()
ParamRequest(class_code, sec_code, param_name)
local r = ParameterReceived(class_code, sec_code, param_name)
if r == 2 then
-- Параметр уже был заказан и получен
local param = getParamEx2(class_code, sec_code, param_name)
-- Далее можно сразу работать с этим параметром или ждать колбека
...
elseif r == 1 then
-- Параметр ещё не получен, ждём колбек
elseif r == 0 or r == nil then
message("Что-то пошло не так", 3)
end
end
function OnParam(class_code, sec_code)
local r = ParameterReceived(class_code, sec_code, param_name)
if r == 2 then
-- Параметр получен
local param = getParamEx2(class_code, sec_code, param_name)
...
else
-- Ждём следующий колбек
return
end
end
Либо то же с использованием параметра в таблице, возвращаемой getParamEx2:
Код
function main()
ParamRequest(class_code, sec_code, param_name)
local param = getParamEx2(class_code, sec_code, param_name)
if param.received == 2 then
-- Параметр уже был заказан и получен
-- Далее можно сразу работать с этим значением или ждать колбека
...
elseif param.received == 1 then
-- Параметр ещё не получен, ждём колбек
elseif param.received == 0 or param.received == nil then
message("Что-то пошло не так", 3)
end
end
function OnParam(class_code, sec_code)
local param = getParamEx2(class_code, sec_code, param_name)
if param.received == 2 then
-- Параметр получен
...
else
-- Ждём следующий колбек
return
end
end
Если дальше фонтазировать, то в OnParam можно добавить третьим таблицу изменившихся параметров. Но есть мнение, что сервер шлёт клиенту сразу всю строку заказанных параметров, в не зависимости от того, какой из них изменился. И дальнейший разбор отдан на откуп скриптеру. Можно было бы на стороне клиента, разобрать этот список и в таблицу записать только те, что изменились, и вернуть в OnParam.
Цитата
BlaZed написал: При отмене подписки на параметр в кеш ТТТ должен заноситься nil
Так-то, да, было бы понятней, но боюсь, не все с этим согласятся.
Цитата
BlaZed написал: Как временное решение, перезапуск квика с параметром "-clear", тогда кеш будет чистый
В начале сессии кеш и так очищается, а ежели в течение сессии, да ну нафиг такое решение
Надо делать так, как надо. А как не надо - делать не надо.
BlaZed написал: определить что данные еще не загружены легко. Например для числовых значений getParamEx2 будет возвращать всегда 0
Это не показатель. Многие параметры легко могут быть равны нулю. И цена, наверное, тоже (?), тот же фьючерс на нефть. Но это не точно. Признаком, что данные в течение торговой сессии не были получены является пустая строка в param_image.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Если getParamEx2 вернул данные, то они актуальные или старые?
В ТТТ есть следующие поля: "TRADE_DATE_CODE" - дата торгов "TIME" - время последней сделки (с точностью до секунды)
По-хорошему, во всех записях обмена с сервером следовало бы иметь служебные поля <Дата и время передачи с точностью до млсек.> и <Дата и время приема с точностью до млсек.>, заполняемые соответствующими сторонами в момент приема/передачи таких записей. Эти поля должны быть доступны пользователю.
1. Инструмент и параметр есть в таблице: параметр status доступен в getParamEx2, ParamRequest=true. Всё верно.
2. Инструмент есть в таблице, параметра status нет (приходит «» вместо «торгуется»): параметр не доступен в getParamEx2, ParamRequest=true (почему true?)
3. Инструмент и параметр был в таблице, но потом удалён из таблицы: параметр доступен в getParamEx2, ParamRequest=true (запоминает до обновления справочников Система-Заказ данных…-Перезаказать данные-Торговые данные текущей сессии или новой сессии, перезапуск QUIK, не прекращает получение параметра, несмотря на отсутствие его в таблице)
Два вопроса.
1. ParamRequest – не работает должным образом, т.к. принимает true при отсутствии данных?
2. «Умный заказ» данных и заказ данных на основе открытых таблиц из прошлых версий ничем не отличаются?
Поддерживаю острую необходимость запроса параметров из LUA, независимо от открытых таблиц (по аналогии Subscribe_Level_II_Quotes).
Михаил Понамаренко написал: 1. Инструмент и параметр есть в таблице: параметр status доступен в getParamEx2, ParamRequest=true. Всё верно. 2. Инструмент есть в таблице, параметра status нет (приходит «» вместо «торгуется»): параметр не доступен в getParamEx2, ParamRequest=true (почему true?) 3. Инструмент и параметр был в таблице, но потом удалён из таблицы: параметр доступен в getParamEx2, ParamRequest=true (запоминает до обновления справочников Система-Заказ данных…-Перезаказать данные-Торговые данные текущей сессии или новой сессии, перезапуск QUIK, не прекращает получение параметра, несмотря на отсутствие его в таблице) Два вопроса. 1. ParamRequest – не работает должным образом, т.к. принимает true при отсутствии данных? 2. «Умный заказ» данных и заказ данных на основе открытых таблиц из прошлых версий ничем не отличаются? Поддерживаю острую необходимость запроса параметров из LUA, независимо от открытых таблиц (по аналогии Subscribe_Level_II_Quotes).
Добрый день.
ParamRequest будет корректно работать, если вручную в таблицу текущих торгов будет добавлен нужный параметр. ParamRequest() это добавление в список ожидаемых заказов.
Для понимания что заказанный параметр начал ехать нужно реализовать коллбэк OnParam()
Цитата
2. «Умный заказ» данных и заказ данных на основе открытых таблиц из прошлых версий ничем не отличаются?
Egor Zaytsev написал: ParamRequest() это добавление в список ожидаемых заказов. Для понимания что заказанный параметр начал ехать нужно реализовать коллбэк OnParam()
Для информации: после ParamRequest может пройти от 1 до 10-20 сек и десятки OnParam, прежде чем сервер обновит список транслируемых параметров.
Надо делать так, как надо. А как не надо - делать не надо.