Николай Камынин пишет: действительно, нет надобности обновлять историю которая уже есть в терминале. Было бы хорошо, если бы история в терминале в начале сессии не обновлялась, а добавлялась.
Специально проверил: На выходных с помощью QMinEditor изменил значение одной свечи на графике. Сегодня подключился к серверу, и свеча не обновилась.
Причём, если график не открыт в терминале, то значения "старых" свечей мы получаем только в колбеке (не зависимо, сохранён кэш графиков или нет). Если график открыт, то "старые" свечи возвращаются в CreateDataSource. Эту информацию можно добавить в документацию.
Но в любом случае, значение изменённой свечи не обновляется.
Добрый день,
Мы рассмотрели Ваше пожелание. По итогам его анализа сообщаем Вам, что реализация пожелания признана потенциально целесообразной. Если по результатам дальнейшего анализа, включающего юридические аспекты, анализ на непротиворечивость с общей политикой компании, никаких возражений не возникнет, мы постараемся включить Ваше пожелание в план доработок при выпуске одной из следующих версий нашего ПО.
1) В одном скрипте создаются несколько объектов DataSource по одному инструменту на одном таймфрейме. Внутри QUIK это будут независимые объекты, каждый из которых хранит свои данные, или объекты, имеющие ссылку на общий массив свечных данных?
2) В разных скриптах создаются объекты DataSource. Вопрос тот же.
Спрашиваю потому, что по моим наблюдениям при переходе от использования данных с графиков на использование данных из DataSource выросло использование памяти терминалом QUIK и были прецеденты, когда вылетало окно о нехватке памяти. Хочется стабильности и приходится понимать, при какой реализации потребуется меньше памяти.
Нет ли в QUIK ситуации, когда сборщик мусора не может избавиться от каких-то старых данных DataSource из-за того, что не все ссылки сброшены в nil?
_sk_ пишет: Нет ли в QUIK ситуации, когда сборщик мусора не может избавиться от каких-то старых данных DataSource из-за того, что не все ссылки сброшены в nil?
Есть такая ситуация. Когда данные стали не нужны, их необходимо принудительно сбросить в nil, иначе они ещё долго могут висеть в памяти (даже при ручном вызове collectgarbage()).
Надо делать так, как надо. А как не надо - делать не надо.
_sk_ пишет: 1) В одном скрипте создаются несколько объектов DataSource по одному инструменту на одном таймфрейме. Внутри QUIK это будут независимые объекты, каждый из которых хранит свои данные, или объекты, имеющие ссылку на общий массив свечных данных?
Сам спросил, сам провёл эксперимент, создав 10 000 экземпляров DataSource, имеющих по 3000 свечей, в рамках одного скрипта. Использованная память практически не изменилась, так что у всех этих объектов один массив свечных данных.
Вопросы по CreateDataSource Беру скрипт для расчёта греков опционов, предложенный Sergey Gorokhov в #11 21.07.2015 14:48:09 (https://forum.quik.ru/messages/forum10/message7203/topic748/#message7203) Т.е. код именем разработчика рассматривается как образцовый. Запустил, работает, но остаются вопросы: 1) Для каждого опциона (а это могут быть десятки и сотни) открываются три потока:
Код
--заказ данных
CreateDataSourceEX(BaseClassCode,T.Optionbase,"settleprice") --цена базового актива
CreateDataSourceEX(ClassCode,T.SecCode,"strike") -- страйк
CreateDataSourceEX(ClassCode,T.SecCode,"volatility") --волатильность
...
function CreateDataSourceEX(Class,Sec,Par)
local ds,err = CreateDataSource(Class, Sec, INTERVAL_TICK, Par)
if ds==nil then
message("Ошибка при получении параметра "..Par..":\n"..err, 3)
return false
else
ds:SetEmptyCallback()
while ds:Size()==0 do
sleep(100)
end
return true
end
end
Видим, что потоки в переменных не сохраняются, а какое-то время живут как локальные переменные. При выходе из скрипта потоки не закрываются с помощью DS:close(). Вопрос 1: Это нормально не хранить и не закрывать после себя потоки ?
2) Часть параметров в скрипте запрашивается без создания потока, они комментируются как статичные
Т.е. по непонятным мне причинам Страйк рассматривается как более изменчивая величина (по сути, она никогда не изменяется), чем кол-во дней до Экспирации (изменяется каждый вечер) Вопрос 2: Как узнать способ обращения к ПАРАМЕТРу? Есть ли список ПАРАМЕТРОВ, для которых обязательно/необязательно перед первым обращением создавать поток?
3) В функции, создающей поток, используется тиковый интервал INTERVAL_TICK.
Код
function CreateDataSourceEX(Class,Sec,Par)
local ds,err = CreateDataSource(Class, Sec, INTERVAL_TICK, Par)
if ds==nil then
message("Ошибка при получении параметра "..Par..":\n"..err, 3)
return false
else
ds:SetEmptyCallback()
while ds:Size()==0 do
sleep(100)
end
return true
end
end
Посчитал, что тиковые данные очень трафико-ёмкие, изменил на интервал INTERVAL_H1. После этого скрипт не запустился, погрязнув в слипах(100) при ожидании открытия потоков Вопрос 3: Поток с интервалом INTERVAL_TICK почему открывается быстрее и действительно ли для расчёта греков надо использовать именно тиковый интервал, не увеличит ли это катастрофически трафик и память?
А у меня попутно вопрос к разработчикам - чем функция CreateDataSourceEX отличается от CreateDataSource ? И почему CreateDataSourceEX не описана в документации?
Дмитрий пишет: А у меня попутно вопрос к разработчикам - чем функция CreateDataSourceEX отличается от CreateDataSource ? И почему CreateDataSourceEX не описана в документации?
Прошу прощения, невнимательно прочитал текст скрипта. Подумал, что это встроенная в терминал функция.
Здравствуйте, Начнем с того что данный скрипт не "образцовый". Да, его написал лично я. Да, я сотрудник компании. Но данный скрипт это лишь пример, который был написан с одной и только одной целью - помочь Вам, как пользователям, понять расчет греков, не более. И этот скрипт вполне замечательно справляется конкретно с этим. Я вполне допускаю, что этот скрипт не идеален и не скрываю этого, но он работает и, выполняет именно те фундаментальные функции, которые на него возложены. Если есть адекватные претензии к логике решения тех или иных задач в скрипте, я с радостью приму их и внесу соответствующие изменения. Однако, следует заметить что данный код нигде в виде ссылки на сайте не публикуется, а значит, решение будет опубликовано только при очередном запросе на форуме.
А теперь к делу:
Цитата
Антонио пишет: Видим, что потоки в переменных не сохраняются, а какое-то время живут как локальные переменные. При выходе из скрипта потоки не закрываются с помощью DS:close(). Вопрос 1 : Это нормально не хранить и не закрывать после себя потоки ?
А зачем закрывать? Мы потом с этими данными работаем.
Цитата
Антонио пишет: Вопрос 2: Как узнать способ обращения к ПАРАМЕТРу? Есть ли список ПАРАМЕТРОВ, для которых обязательно/необязательно перед первым обращением создавать поток?
Списка нет, так как для разных бирж или рынков, он может быть разный. Есть секретный способ, если при выводе по DDE с формальными заголовками, параметр написан БОЛЬШИМИ буквами, значит он статичный и его заказывать нет нужды. Публиковать в документации эту фишку мы не будем, по своим внутренним причинам.
Цитата
Антонио пишет: Вопрос 3: Поток с интервалом INTERVAL_TICK почему открывается быстрее и действительно ли для расчёта греков надо использовать именно тиковый интервал, не увеличит ли это катастрофически трафик и память?
Тиковый поток - это есть то что мы запрашиваем в ТТП или в ТВС, а интервальный - это агрегированная информация в виде графика. Если проще, заказывая тиковый поток по ТТП мы получаем саму таблицу ТТП. Если по ТВС, то мы получаем саму таблицу ТВС и можем с ними работать минуя функции работы с графиками. Но если мы заказываем интервал, то мы НЕ получаем ТТП или ТВС, а получаем только график, с которым данный скрипт не работает. И да, мы эту фишку тоже не будем публиковать, по своим внутренним причинам.
Антонио пишет: Вопрос 2: Как узнать способ обращения к ПАРАМЕТРу? Есть ли список ПАРАМЕТРОВ, для которых обязательно/необязательно перед первым обращением создавать поток?
В текущих версиях QUIK создавать поток для параметров бумаг с помощью функции CreateDataSource, если в дальнейшем вы собираетесь обращаться к этим параметрам через getParamEx, нет никакого смысла.
Надо делать так, как надо. А как не надо - делать не надо.
Антонио пишет: Вопрос 2: Как узнать способ обращения к ПАРАМЕТРу? Есть ли список ПАРАМЕТРОВ, для которых обязательно/необязательно перед первым обращением создавать поток?
В текущих версиях QUIK создавать поток для параметров бумаг с помощью функции CreateDataSource , если в дальнейшем вы собираетесь обращаться к этим параметрам через getParamEx , нет никакого смысла.
Здравствуйте, Можете обосновать или привести пример? В том скрипте, о котором идет речь, CreateDataSource используется именно для заказа данных. То есть, для случая когда параметр нигде не заказан, но его нужно получить через getParamEx.
Вы указываете на частный случай, о статусе которого я к сожалению сейчас не готов ответить. Однако в общем случае, решение доступа к данным в виде заказа через CreateDataSource должно работать.
Антонио пишет: Видим, что потоки в переменных не сохраняются, а какое-то время живут как локальные переменные. При выходе из скрипта потоки не закрываются с помощью DS:close(). Вопрос 1 : Это нормально не хранить и не закрывать после себя потоки ?
А зачем закрывать? Мы потом с этими данными работаем.
Я имею в виду закрывать не сразу, пока данные нужны для работы, а по окончании работы перед выходом из скрипта, например в OnStop(), Не нужно разве заботиться, чтобы почистить за собой мусор? Если скрипт завершится с незакрытыми потоками, а Квик продолжит работу, разве не останется захваченной и недоступной для других процессов память ? Или при завершении скрипта вся память под объекты скрипта автоматически и без пропусков "подчистится"?
p.s. Спасибо за ответы, многое прояснилось из того, на что даже намёка нет в документации.
Sergey Gorokhov пишет: Вы указываете на частный случай, о статусе которого я к сожалению сейчас не готов ответить. Однако в общем случае, решение доступа к данным в виде заказа через CreateDataSource должно работать.
Что есть частный случай и что есть общий случай в данной ситуации?
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov пишет: Вы указываете на частный случай, о статусе которого я к сожалению сейчас не готов ответить. Однако в общем случае, решение доступа к данным в виде заказа через CreateDataSource должно работать.
Что есть частный случай и что есть общий случай в данной ситуации?
Речь о том, что в общем случае, если делается заказ данных через CreateDataSource с параметром INTERVAL_TICK (это важно) то мы получаем саму таблицу (вернее ее поток данных) и можем с ней работать минуя функции работы с графиками. Но, если мы заказываем интервал, то мы не получаем саму таблицу, а получаем только график, с которым функции доступа к таблицам не работают.
Антонио пишет: Не нужно разве заботиться, чтобы почистить за собой мусор?
Конкретно в моем примере расчета греков, нет не нужно. В общем случае, нет представления о ситуации когда это действительно требуется.
Прошу прощения, ответ не совсем верный. Ситуация все же есть. для экономии трафика все же есть смысл закрывать поток, однако в случае указанного примера это второстепенно
Sergey Gorokhov пишет: Однако в общем случае, решение доступа к данным в виде заказа через CreateDataSource должно работать.
У вас работает? Если вы получаете данные через getParamEx, то заказывать их через CreateDataSource нет смысла, поскольку заказываемые параметры должны быть по-любому в списках принимаемых параметров, независимо от вызова этой функции CreateDataSource.
Цитата
Sergey Gorokhov пишет: Речь о том, что в общем случае, если делается заказ данных через CreateDataSourceс параметром INTERVAL_TICK (это важно) то мы получаем саму таблицу (вернее ее поток данных) и можем с ней работать минуя функции работы с графиками. Но, если мы заказываем интервал, то мы не получаем саму таблицу, а получаем только график, с которым функции доступа к таблицам не работают.
Не совсем понял ваш комментарий. Общий случай - это когда заданы все параметры функции CreateDataSource(STRING class_code, STRING sec_code, NUMBER interval, [, STRING param]) Так вот в общем случае "решение доступа к данным в виде заказа через CreateDataSource" не работает. Оно работает в частном случае, когда не задан последний параметр param, да и то с оговорками.
Это я так, не спора ради, даю информацию Антонио и, видимо вам.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель пишет: Если вы получаете данные через getParamEx, то заказывать их через CreateDataSource нет смысла, поскольку заказываемые параметры должны быть по-любому в списках принимаемых параметров, независимо от вызова этой функции CreateDataSource.
Мой практический опыт подтверждает это утверждение. Если требуется последнее (текущее) значение параметра из ТТП, то getParamEx выдаёт это значение без предварительного заказа потока через CreateDataSource. Я не проверял на всех Параметрах, но полтора десятка точно использовал.
Т.е. получается так: 1) Если требуется получить только текущее значение параметра ТТП, то достаточно использовать getParamEx без предварительного CreateDataSource, вне зависимости отображён этот параметр в ТТП или нет. 2) Если требуется история значения параметра, то требуется CreateDataSource, дождаться ненулевой длины потока, и затем уже читать значения из полученных баров. 3) В вышеприведённом скрипте от Sergey Gorokhov создание потоков требуется лишь для того, чтобы назначить КолБэк и с помощью КолБэка подсвечивать строки, по которым данные обновились.
Антонио пишет: Мой практический опыт подтверждает это утверждение. Если требуется последнее (текущее) значение параметра из ТТП, то getParamEx выдаёт это значение без предварительного заказа потока через CreateDataSource. Я не проверял на всех Параметрах, но полтора десятка точно использовал.
Это работает только если включена настройка "Исходя из настроек открытых пользователем таблиц"
getParamEx и CreateDataSource - абсолютно никак не связаны. Однако, вполне может получиться так, что для получения исключительно текущих параметров - быстрее использовать именно и исключительно getParamEx.
тот самый пишет: getParamEx и CreateDataSource - абсолютно никак не связаны.
Оказывается, связаны.
Цитата
Sergey Gorokhov пишет: Это работает только если включена настройка "Исходя из настроек открытых пользователем таблиц"
Если включена настройка "Исходя из настроек открытых пользователем таблиц", то CreateDataSource автоматически добавляет бумагу/параметр в список получаемых параметров.
Таким образом, с помощью getParamEx можно будет получить значения параметров. (Выше я был не прав: CreateDataSource всё же не совсем бесполезна в этой ситуации).
Правда, ds:Close() бумагу уже не из списка не удаляет.
Надо делать так, как надо. А как не надо - делать не надо.
в любом случае, getparamEx - берёт информацию из текущего и внутреннего источника данных QUIK-клиента. CreateDatasource же, скорей всего, выделен в отдельный LUA-поток, да ещё и работает через метатаблицу со своими методами Close и т. д. и т. п. Кроме того, скорей всего, под него заводится отдельный запрос на получение данных с сервера. Поэтому, конкретно с getParamEx - он никак не связан. То есть, я более чем уверен, что он не использует эту функцию в недрах QLUA, чтоб иметь доступ к внутренним и текущим данным QUIK-клиента. Кроме того, большой вопрос, что будет в реале действительно быстрее. Лично мне, думается, что для текущих данных - именно getParamEx.
почему я думаю, что CreateDatasource - автономна, т.е. имеет свой LUA-поток? Потому что она служит для прямого получения данных с сервера QUIK и имеет свои коллбеки, которые не связаны со стандартными QLUA-коллбеками, выполняющимися в основном потоке квика для всех скриптов.
Антонио пишет: Видим, что потоки в переменных не сохраняются, а какое-то время живут как локальные переменные. При выходе из скрипта потоки не закрываются с помощью DS:close(). Вопрос 1 : Это нормально не хранить и не закрывать после себя потоки ?
А зачем закрывать? Мы потом с этими данными работаем.
При включённой настройке "Исходя из настроек открытых пользователем таблиц" функция CreateDataSource добавляет параметр в списки принимаемых параметров. Метод :Close() не удаляет этот параметр из списков. Таким образом, :Close() не влияет на возможность получения данных при работе с ними через getParamEx.
Это нормальная ситуация?
Надо делать так, как надо. А как не надо - делать не надо.
Да Close() не удаляет параметр из списков. Такова текущая реализация. Ранее мы уже регистрировали от другого пользователя пожелание по данной теме. Можем зарегистрировать еще одно от Вас.
тот самый пишет: почему я думаю, что CreateDatasource - автономна, т.е. имеет свой LUA-поток? Потому что она служит для прямого получения данных с сервера QUIK и имеет свои коллбеки, которые не связаны со стандартными QLUA-коллбеками, выполняющимися в основном потоке квика для всех скриптов.
полагаю, что отдельный поток может иметь (или не иметь ) луа машина. У нас есть два потока -функция main и основной поток QUIK. ------------------------------------------ CreateDatasource запускается либо в Main, либо вне ее ( в основном раньше не работало, поэтому сейчас запускаю лишь в main) ------------------------------------- Таким образом, получаем либо в потоке main, либо в основном потоке. ------------------------------------
Да Close() не удаляет параметр из списков. Такова текущая реализация. Ранее мы уже регистрировали от другого пользователя пожелание по данной теме. Можем зарегистрировать еще одно от Вас.
Давайте зарегистрируем. А то в текущем виде смысла нету в :Close(). Это с таким же успехом можно просто удалить сам объект ds = nil.
Надо делать так, как надо. А как не надо - делать не надо.
Главное, чтобы не получилось так: 1) Скрипт А создаёт DataSource, параметр добавляется. 2) Скрипт Б создаёт DataSource. 3) Скрипт А закрывает DataSource, параметр удаляется. 4) Скрипт Б обламывается.
Для справки: Реализовал открытие источников без графиков для индикаторов. ------------------- алгоритм следующий: 1) сделал библиотеку для запуска функций любого скрипта из других скриптов 2) Написал скрипт, который отвечает за открытие источников и находится в спящем потоке. 3) Если индикатору или скрипту нужны данные по истории, то он обращается за данными к спящему скрипту, который возвращает индикатору требуемые данные. --------------------