Алексей (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 2 3 4 След.
Локальные переменные
 
Вы создали объект (тип функция) "function()  print(var) end", в замыкании которого (по сути, в исходной настройке стека для вызова этой функции) сохранили строку 'abc' в качестве стартового значения теперь уже локальной для созданной функции переменной var.
Указатель на этот объект (функцию) вы сохранили в глобальной переменной func_2, затем значение этого указателя скопировали в локальную для модуля переменную var_func.
Когда завершилось выполнение функции, указатель на которую Вы сохранили в глобальной переменной func, стек этой функции выгрузился из памяти, а вместе с ним и выгрузилась из памяти переменная var.
Но, повторюсь, в стеке функции, указатель на которую сохранился в переменных func_2 и var_func, сохранилось значение var (а не указатель на нее), которое в ней хранилось на момент создания объекта - функции.
Дело в том, что при создании функции в ее объекте сохраняется не только сам ее код, но и ее стартовый стек, в котором сохраняются, кроме всего прочего, значения всех внешних по отношении к ней локальных переменных, использованных в ее коде.
Почитайте про "замыкания функций lua".
Локальные переменные
 
В lua нет прямого объявления глобальных переменных, но я для простоты понимания "внесу" в программу этот "оператор" для лучшего понимания Вами Вашего кода:
Код
global func, func_2

local var_func -- локальная переменная, время жизни которой - это время пока данный модуль находится в памяти. 
               -- Если не заморачиваться с выгрузкой модулей из памяти, то эта переменная существует пока исполняется программа (как и все глобальные), просто она не видима в других модулях.

func = function()
   local var = 'abc' -- Создаем локальную переменную
   
   func_2 = function()
      print(var)
   end
   
   var_func = func_2 -- сохраняем во внешнюю переменную созданную функцию
   
   -- Выход из функции, локальная переменная 'var' уничтожается.
end

func()

var_func() -- по сути запускаем ранее созданную функцию func_2

-- ВЫВОД: 'abc'
Локальные переменные
 
Цитата
Алексей написал:
При выходе из функции переменные var1-5 будут уничтожены. С самой таблицей data нечего не случится.
Уточнение: под самой таблица data, подразумевается переменная, переданная в функцию в качестве аргумента. Что касается переменной, видимой внутри функции в качестве аргумента, то она является локальной и, соответственно, "живет" только пока функция выполняется. Как-то специально ее уничтожать для экономии памяти не нужно.
Локальные переменные
 
При выходе из функции переменные var1-5 будут уничтожены. С самой таблицей data нечего не случится.
Если в функции выполнить data = nil, где data - внешняя по отношению к функции переменная, то таблица будет уничтожена. Если data - это аргумент функции (по сути - её локальная переменная), то с внешней таблицей (переданной в функцию в качестве аргумента) ничего не случится.
Модификация переменных var1-5 никак не отразится на содержимом внешней таблицы data, за исключением ситуации, когда элементом таблицы data, в свою очередь является таблица. Тогда модификация ее элементов (полей) будет менять содержимое data (например, var4.code = 5 - меняет содержимое data[4].code)
Поведение OnOrder() при ошибках исполнения заявки.
 
Подскажите, пожалуйста, сколько и с какими flags придут колбеки OnOrder() в случае возникновения ошибок на этапе исполнения выставленной заявки (получен OnOrder с непустым reject_reason)?
Точнее, скорее интересует как можно понять, что поступил, наконец, последний вызов OnOrder()?

Так же прошу подсказать, как можно определить, что пришел наконец последний OnTrade() по конкретной сделке?
Сейчас, как правило, приходит 3 идентичных вызова OnTrade() для каждой сделки.
Подсчёт проскальзывания
 
my_tab = { }
my_tab[12345].order_price = 123.55
В OnTransReply() приходит информация по транзакциям, отправленным самим терминалом. Это нормально?
 
Добрый день.

Мой брокер - сбербанк. Модуль подключен, но я им не пользуюсь. Алго-заявок не отправлял.
Поставил голый quik 7.6.1.1 (текущий для сбера) на другом компе, подключился к серверу, картина та же.
Однако в службе техподдержки сбера были удивлены и сказали, что никаких подобных транзакций не должно уходить с клиентского места, если не отправлять алго-заявки.

Вы подтверждаете, что это нормальная работа quik?
Как обойти невозможность получения данных?
 
Проверяйте, что CreateDataSource предоставил Вам доступ к данным запрашиваемого инструмента, т.е. DS ~= nil
В OnTransReply() приходит информация по транзакциям, отправленным самим терминалом. Это нормально?
 
Проясните для меня, пожалуйста, следующую ситуацию.

Обнаружил, что терминал сам отправляет на сервер транзакции с заполненным trans_id, и соответственно они попадают в Таблицу транзакций, а также провоцируют вызов OnTransReply().
Первые 2 уходят в момент соединения с сервером, последующие, ровно раз в 120 секунд:
1. trans_id = 10, result_msg = Запрос описания таблицы алго-заявок успешно выполнен.
2. trans_id = 14, result_msg = Initialization user successful.
3. trans_id = 11, result_msg = Транзакция успешно выполнена.
4. trans_id = 12, result_msg = Транзакция успешно выполнена. и т.д. каждые 120 секунд

Это нормальная работа терминала? Quik 7.7.0.89
Запущенных скриптов нет, ни lua, ни qpile. Trans2Quik не пользуюсь, обработка внешних транзакций отключена. Файлов *.tri нет, импорт транзакций из файла отключен.
Откуда они берутся?
Исполнение рыночной заявки
 
Спасибо, наконец я получил исчерпывающий ответ.
Действительно, в этой ситуации не нужно править руководство.
А при написании достаточно универсального скрипта нужно исходить из того, что у брокера эта настройка может быть отключена.
Просто в ответе #8 не упоминалось, что такая транзакция пройдет только при определенных настройках со стороны брокера.
Исполнение рыночной заявки
 
Цитата
s_mike@rambler.ru написал:
Цитата
Алексей   написал:
Цитата
Sergey Gorokhov   написал:
На бирже нет рыночных заявок по срочному рынку и никогда не было.
То что в QUIK называется "рыночной" для срочного рынка, это обычная лимитированная заявка с признаком "Снять остаток" и указанной ценой.
Если пользователь цену   не указывает  , то автоматом подставляется минимально/максимально возможная цена, в зависимости от направления
В описании формата .tri-файла для параметра PRICE сказано, что:
Цитата
Цена заявки, за единицу инструмента. Обязательный параметр. При выставлении рыночной заявки (TYPE=M) на Срочном рынке FORTS   необходимо указывать значение цены   – укажите наихудшую (минимально или максимально возможную – в зависимости от направленности)...
Так нужно или нет указывать цену при выставлении рыночной заявки на срочном рынке средствами lua?
Другими словами, можно ли указать PRICE = "0", или надо обязательно лезть в Таблицу текущих торгов за соответствующими параметрами мин-макс цены инструмента?
если у вас нормальный брокер и программное обеспечение он своевременно обновляет, то можно указывать type=m и нулевую цену. Шлюз обработает.

если же на такую транзакцию приходит ответ что цена не может быть 0 - задумайтесь, правильно ли вы выбрали брокера.
Вопрос не к брокеру, а разработчикам QUIK, которые дают советы, противоречащие их же документации.
to s_mike@rambler.ru; Если сервер брокера "нормально" обработает такую транзакцию (срочный рынок FORTS, TYPE=M, PRICE=0), отправленную из lua, т.е. выставит заявку по минимальной/максимальной цене инструмента в зависимости от направления сделки (S/B), то как раз тогда стоит задуматься, правильно ли вы выбрали брокера, у которого сервер QUIK работает не так, как это описано в документации разработчика.

Повторяю вопрос к разработчикам QUIK:
Вопрос касается ситуации, когда транзакция отправляется из lua, а не вручную из диалогового окна подачи заявки:

Допустимо ли из lua отправлять рыночную заявку на рынке FORTS с нулевой ценой? Если да, то поправьте, пожалуйста, описание формата .tri-файла для поля PRICE.
OnTransReply(). Вопросы по полям таблицы, передаваемой callback
 
Цитата
Egor Zaytsev написал:
Цитата
4. exchange_code STRING Биржевой номер заявки.         Это опечатка во всех руководствах? То есть нужно читать: Код биржи в торговой системе, или это еще какой-то номер заявки, отличный от order_num?
Нет, не опечатка. Поле EXCHANGE_CODE соответствует колонке Код биржи таблицы Заявок.
Вы не находите, что сами себе противоречите? Или Биржевой номер заявки и код биржи - это одно и то же?
Поправьте, пожалуйста, ошибку во всех руководствах.
OnTransReply(). Вопросы по полям таблицы, передаваемой callback
 
Цитата
Egor Zaytsev написал:
Цитата
3. client_code STRING Код клиента, brokerref STRING Поручение.         При выставлении заявки вручную, можно предположить, что могло бы попасть в client_code, а что в brokerref. Но в этом случае OnTransReply не вызывается.         При отправке транзакции вызовом sendTransaction(), можно задать только CLIENT_CODE. Это значение, насколько я понимаю, попадает в brokerref таблицы trans_reply (а также в brokerref таблиц заявок и сделок в OnOrder и OnTrade). Так что же тогда мы получаем в client_code при вызове OnTransReply? Действительно Код клиента или там дублируется brokerref?
В параметре CLIENT_CODE указываете код клиент слеш комментарий, и при колбеке получите его в brokerref.
Так а что же получаем в колбеке OnTransReply в поле client_code? Действительно Код клиента или туда дублируется brokerref?
OnTransReply(). Вопросы по полям таблицы, передаваемой callback
 
Про "balance NUMBER Остаток" понял для транзакции на снятие неисполненной (в т.ч. частично) заявки. https://forum.quik.ru/forum10/topic2978.
OnTransReply(). Вопросы по полям таблицы, передаваемой callback
 
Помогите, пожалуйста, разобраться со следующими полями таблицы trans_reply, передаваемой в callback OnTransReply(TABLE trans_reply).

1. server_trans_id NUMBER Идентификатор транзакции на сервере.
        Он отличается от trans_id, указанного при вызове sendTransaction()? Если да, то для чего он нужен?
        trans_id, который мы получаем в таблицах, передаваемых в OnTrade и OnOrder, соответствует trans_id переданному в sendTransaction, или он соответствует server_trans_id?

2. balance NUMBER Остаток.
        О каком остатке может идти речь на этапе регистрации заявки?
        Или уже после регистрации заявки OnTransReply все еще продолжает вызываться также как и OnOrder по мере частичного исполнения заявки?

3. client_code STRING Код клиента, brokerref STRING Поручение.
       При выставлении заявки вручную, можно предположить, что могло бы попасть в client_code, а что в brokerref. Но в этом случае OnTransReply не вызывается.
       При отправке транзакции вызовом sendTransaction(), можно задать только CLIENT_CODE. Это значение, насколько я понимаю, попадает в brokerref таблицы trans_reply (а также в brokerref таблиц заявок и сделок в OnOrder и OnTrade). Так что же тогда мы получаем в client_code при вызове OnTransReply? Действительно Код клиента или там дублируется brokerref?

4. exchange_code STRING Биржевой номер заявки.
       Это опечатка во всех руководствах? То есть нужно читать: Код биржи в торговой системе, или это еще какой-то номер заявки, отличный от order_num?

Заранее благодарен за разъяснения.
Исполнение рыночной заявки
 
Цитата
Sergey Gorokhov написал:
На бирже нет рыночных заявок по срочному рынку и никогда не было.
То что в QUIK называется "рыночной" для срочного рынка, это обычная лимитированная заявка с признаком "Снять остаток" и указанной ценой.
Если пользователь цену не указывает, то автоматом подставляется минимально/максимально возможная цена, в зависимости от направления
В описании формата .tri-файла для параметра PRICE сказано, что:
Цитата
Цена заявки, за единицу инструмента. Обязательный параметр. При выставлении рыночной заявки (TYPE=M) на Срочном рынке FORTS необходимо указывать значение цены – укажите наихудшую (минимально или максимально возможную – в зависимости от направленности)...
Так нужно или нет указывать цену при выставлении рыночной заявки на срочном рынке средствами lua?
Другими словами, можно ли указать PRICE = "0", или надо обязательно лезть в Таблицу текущих торгов за соответствующими параметрами мин-макс цены инструмента?
Исполнение рыночной заявки
 
В виду того, сколько мнений, отличающихся в нюансах, было получено по поднятому мной вопросу от форумчан, зарегистрированных "не вчера", прошу пояснений от ТЕХПОДДЕРЖКИ QUIK:

Заявка "FORTS MARKET PUT_IN_QUEUE" АБСОЛЮТНО ИДЕНТИЧНА "FORTS LIMITED KILL_BALANCE", или они обрабатываются сервером quik и/или биржей по разному?
Исполнение рыночной заявки
 
Вопрос снимается, нашелся ответ в руководстве:
(Вопрос, разумеется, был для PUT_IN_QUEUE)

«Рыночная» – при установленном признаке и при наличии встречного
предложения заявка исполняется по цене не хуже, чем значение, указанное в поле
«Цена». Неисполненный остаток, на который отсутствует встречное предложение,
снимается с торгов.

Получается, что на forts, по сути, нет рыночных заявок?
Ведь это поведение лимитированный заявки в режиме KILL_BALANCE.
Исполнение рыночной заявки
 
Подскажите, пожалуйста, как будет исполнена рыночная заявка FORTS, если в качестве цены указать не максимально (минимально) возможную цену для инструмента, а цену, отстоящую от лучшего предложения только на несколько шагов цены (разумеется, в правильном направлении), при условии, что количество предлагаемых лотов в биржевом стакане в этом диапазоне цен будет меньше, чем указано в заявке?
KILL_ALL_ORDERS на ММВБ
 
Спасибо, понятно!

Если можно, последний вопрос на эту тему:
Из окна Таблица заявок доступна команда "Снять все активные заявки Ctrl+F8".
Понятно, что можно самим написать простенькую процедуру, которая займется перебором содержимого таблицы заявок и по одной (по ее ORDER_KEY) снимет активные заявки.
Но может быть есть простой доступ к этой команде из qlua? Вызовом одной какой-то функции или формированием одной определенной транзакции?
KILL_ALL_ORDERS на ММВБ
 
Разбираясь далее, я понял, что для KILL_ALL_FUTURES_ORDERS «BASE_CONTRACT» является обязательным параметром,
но остался вопрос про ТИП ЗАЯВКИ.
KILL_ALL_ORDERS на ММВБ
 
Спасибо за разъяснения!

Прошу тогда сделать соответствующие поправки в руководстве пользователя quik!
А именно :
1.убрать ACCOUNT из перечня дополнительных параметров
2. для KILL_ALL_FUTURES_ORDERS указать следующие возможные дополнительные параметры:
«OPERATION», «BASE_CONTRACT» и «???»

Прошу разъяснить, как работает 3-й параметр отбора заявок для группового снятия  KILL_ALL_FUTURES_ORDERS, который в форме ввода транзакции обозначен как ТИП ЗАЯВКИ: ВСЕ, ОБЫЧНЫЕ, ВНЕСИСТЕМНЫЕ.
Что это за градация заявок на рынке Forts?
Как обозначаются сам параметр и его возможные значения при формировании заявки из qlua?
KILL_ALL_ORDERS на ММВБ
 
В продолжении темы хотел бы прояснить для себя ряд противоречий в руководстве пользователя quik 7.7

Цитата
Команды снятия группы заявок по условию («KILL_ALL_ORDERS»,  «KILL_ALL_STOP_ORDERS», «KILL_ALL_NEG_DEALS», «KILL_ALL_FUTURES_ORDERS»)  обрабатываются следующим образом:
  1. Параметры «CLASSCODE», «TRANS_ID», «ACTION»,  «ACCOUNT» являются обязательными.
  2. Возможные дополнительные параметры для команд снятия заявок по условию:
    • «KILL_ALL_ORDERS»: «SECCODE», «ACCOUNT», «OPERATION», «CLIENT_CODE», «COMMENT»
    • «KILL_ALL_STOP_ORDERS»: «SECCODE», «ACCOUNT», «OPERATION», «CLIENT_CODE», «COMMENT», «EXPIRY_DATE»
    • «KILL_ALL_NEG_DEALS»: «SECCODE», «ACCOUNT», «OPERATION», «CLIENT_CODE», «COMMENT», «PARTNER», «SETTLE_CODE»
    • «KILL_ALL_FUTURES_ORDERS»: «ACCOUNT», «OPERATION»
1. Так все же ACCOUNT - это обязательный параметр или дополнительный? (можно ли не указывать ACCOUNT, чтобы, например, разом сбросить заявки и на основном счете и на инвестиционном?)
2. Из qlua KILL_ALL_FUTURES_ORDERS работает или нет?
3. «ACCOUNT», «OPERATION» являются единственными возможными параметрами для KILL_ALL_FUTURES_ORDERS, или можно применять и другие параметры, например, SECCODE?
3-й вопрос обусловлен тем, что в том же руководстве в примерах есть следующее:
Цитата
Снятие всех заявок на срочном рынке FORTS
на покупку  контрактов на курс акций Ростелеком -ао
TRANS_ID=50; ACCOUNT=SPBFUT00001;  ACTION=KILL_ALL_FUTURES_ORDERS; OPERATION=B; CLASSCODE=SPBFUT;  BASE_CONTRACT=RTKM;
Видим, что для отбора снимаемых заявок используется BASE_CONTRACT.
Проблема запуска скрипта на Lua, Квик не видит core.dll
 
ТЕЛЕГРАМ ПРИКРУЧИВАЕМ  :lol:
Проблема запуска скрипта на Lua, Квик не видит core.dll
 
Никаких глюков в кодах ssl.dll и core.dll нет!

Речь идет о бинарниках версий "LuaSocket 3.0-rc1" (core), "LuaSec 0.6" (ssl)  от https://github.com/brunoos/luasec. Взять их в готовом виде можно, например, из последней версии ZeroBraneStudio.

2 часа танцев с бубном и вот ответ:
ssl.dll требует, чтобы libeay32.dll и ssleay32.dll находились в одной папке с lua5.1.dll, причем именно с той dll, что использует QUIK, т.е., например, в C:\sberbank\quik_sms
а core.dll даже не подозревает, что в природе существует lua5.1.dll, ему нужен только lua51.dll !!! Лечение: делаем нужный файл из копии ИМЕННО Квиковского lua5.1.dll.

P.S. Строго говоря, ssl.dll тоже требует именно  lua51.dll, просто у него не вылезает связанная с этим ошибка, т.к. он загружается после core.dll, т.е. когда проблема с lua51.dll уже решена.
Possible unhandled exception выскакивала скорее всего, когда core.dll каким-то образом находил стороннюю lua51.dll (например, от той же ZeroBraneStudio), только вот она не совместима с QLua.
Обмен данными между Lua-скриптами
 
Цитата
Stanislav Tvorogov написал:
Цитата
Старатель   пишет:
Я не знаю как там в Metatrader, но представляю себе следующим образом:
В любом из скриптов создаётся переменная и обозначается как глобальная в общем "пространстве имён", доступ к которой возможен из любого скрипта.
Обращение к этой переменной должно осуществляться по ссылке (без создания нового объекта) по аналогии с таблицами в Lua.
Возможно ли это сделать?
Добрый день,

Мы рассмотрели Ваше пожелание. По итогам его анализа сообщаем Вам, что реализация пожелания признана потенциально целесообразной. Если по результатам дальнейшего анализа, включающего юридические аспекты, анализ на непротиворечивость с общей политикой компании, никаких возражений не возникнет, мы постараемся включить Ваше пожелание в план доработок при выпуске одной из следующих версий нашего ПО.
Решили не реализовывать?
Время сервера сильно отстает от эталонного
 
Цитата
Sergey Gorokhov написал:
Алексей  ,
Время сервера это время сервера брокера. А время на сервере брокера совершенно не обязано совпадать со временем на Вашем компьютере и временем в торговой системе. Тем более что разных торговых систем великое множество, а не только МБ.
Если время отставания всегда примерно одинаковое, можно судить о том что где-то часты отстают, либо на оборот спешат.
И что такое "эталонные часы"? Какой-то супер NTP сервер? Если так, то никто обещал, что все биржевые площадки и все брокера и все компьютеры мира синхронизируются именно с ним и добиться этого, при нынешнем уровне технологического развития, не представляется возможным.
Вопрос был не о том, почему Сбербанк не выставляет время на своих серверах по моему компьютеру :cool:, а о том, что, похоже, данные на клиентский QUIK поступают с задержкой в более 3 секунды?

"Эталонные часы" я действительно забыл взять в кавычки. Разумеется - это время какого-либо популярного NTP сервера (timeserver.ru, time.windows.com, time.nist.gov, *.vniiftri.ru или случайного из ru.pool.ntp.org и т.д.) Только вот друг от друга они не отличаются более, чем на 1 с, а часы 2-х серверов Сбера всегда отстают на 3-5 с.
На активно торгующихся инструментах видно, что свечки обновляются явно по часам "SERVERTIME".
Кроме того, насколько я понимаю, getInfoParam("SERVERTIME") ЭТО ВОВСЕ НЕ ВРЕМЯ НА СЕРВЕРЕ БРОКЕРА!
Это время заключения последней обезличенной сделки по часам БИРЖЕВОГО сервера (время торговой системы), информация о которой дошла наконец до клиентского терминала QUIK.
Другими словами, это getInfoParam("LASTRECORDTIME"), только без "отмотки" времени назад из-за запоздавших данных.

Отсюда и вопрос:
Клиентский терминал QUIK получает биржевую информацию с запаздыванием на 3-5 секунд от времени фактического заключения сделок на бирже или часы сервера брокера синхронизированы с часами серверов биржи и, значит, запаздывания нет, а просто они все скопом отстают от тех NTP серверов, которыми я пользуюсь?

P.S.
Скрытый текст
Цитата
Binary protocol TWIME for derivatives market specification:
2.1.4. Date and time
<type name="DeltaMillisecs" description="Milliseconds per one timeout" maxValue="60000" minValue="1000" presence="required" primitiveType="uint32"/>
<type name="TimeStamp" description="Time in number of nanoseconds since Unix epoch, UTC timezone" maxValue="18446744073709551614" minValue="0" nullValue="18446744073709551615"
presence="optional" primitiveType="uint64"/>
Если биржа на срочном рынке использует в протоколах выставления заявок Timestamp такой точности (10e-9 с), то я сильно сомневаюсь, что часы торговой системы выставлены "от балды". Уверен, что они действительно отклоняются от Эталонного (без кавычек) UTC не более, чем на 10мс.
Нынешний уровень технологического развития позволяет получить через интернет от Российских Stratum-1 ntp серверов (тот же vniiftri.ru) эталонное время с точностью не ниже +-1мс, а по специальным каналам связи на 1-2 порядка точнее.
При этом все мировые Stratum-1 серверы синхронизируются друг с другом с точностью до 1 мкс, иначе никакой GPS или Глонас не работали бы.
Время сервера сильно отстает от эталонного
 
Обратил внимание, что у меня время сервера, отображаемое в нижней строке состояния QUIK (=getInfoParam("SERVERTIME")), как правило, более, чем на 3 секунды отстает от эталонных часов.
Брокер Сбербанк. Каких-либо запредельных значений "Задержек данных при обмене с сервером" (=getInfoParam("LASTPINGDURATION")) не наблюдаю (не более 0.2 с, обычно на порядок меньше: 0.02-0.04).
Что это значит?
Информация о сделках на бирже поступает на мой терминал с запаздыванием более, чем на 3 секунды?
Или это просто кривые часы на сервере брокера? Но тогда индикаторы по любому отстают от событий на бирже более чем на эти 3 секунды, т.к. информация о свечках формируется сервером брокера по его часам.
Почему нил?
 
Для справки:
nm=somefunctionname(10,string.gsub())
от string.gsub() берутся все результаты
Почему нил?
 
Цитата
валерий написал:
Так в 2 строчки и у меня также. А хотелось одной...
имеем
a=string.gsub()
nm=tonumber(a)

то же самое в одну строчку:
nm=tonumber((string.gsub()))
дополнительные скобки отбрасывают все результаты функции, кроме первого.

или:
nm=tonumber(string.gsub(),10)
опять же в этом случае от string.gsub() берется только первый результат
Прошу дополнить руководство по эксплуатации QLua в отношении папки LuaIndicators
 
Цитата
Egor Zaytsev написал:
Цитата
Где-то я встречал на просторах форума жалобы пользователей на тормоза quika при вызове контекстного меню в окнах графиков, а также на старте терминала, но не видел от технической поддержки внятных комментариев по этому поводу.
С каждым случаем нужно разбираться. Если у Вас проявляются вами описанные проблемы, то сообщите версию рабочего места QUIK, а также опишите, тормоза именно при запуске QUIK или при старте после подключения к серверу QUIK ?

Так я же в своем посте собственно и написал в чем была причина жутких тормозов у меня.

В подпапках папки LuaIndicators у меня было много разного "хлама", недописанные lua скрипты и т.п. Во многих из них в BODY (код вне функций) были тяжелые вычисления. При каждом нажатии на правую клавишу мыши в окне графика получалось, что QUIK все эти тысячи строчек кода запускал на исполнение (пытаясь безуспешно найти таблицу Settings, хе-хе, нашел где искать), да еще и не по одному разу (они же еще друг друга перезапускали по dofile, pcall и т.п.)
А на старте QUIKа количество этих запусков "мусора" еще умножалось на количество выведенных в окна графиков пользовательских индикаторов.
Как только я убрал все подпапки из папки LuaIndicators, так все сразу стало летать.
Перенумерация свечек и SetUpdateCallback
 
Sergey Gorokhov,

по п.2
Сомневаюсь, что что-то не так со скриптом, поскольку он элементарный: заказ через CreateDataSource и установка callbackа - просто сброс лога в файл. В рамках одного скрипта идентичным механизмом параллельно запрашиваются данные сразу для нескольких инструментов Forts.
Проблема же 10.02.2017 опять воспроизвелась и только для SiH7. Только в этот раз скрипт я не выключал. В 10:25 связь была принудительно разорвана со стороны сервера (крайне редкое явление во время торгов, на моей памяти это в 3-й или 4-й раз), далее сработало автоподключение, и, вуаля, имеем 3000+ свечек.
Перенумерация свечек и SetUpdateCallback
 
Sergey Gorokhov,

Заранее прошу простить, если задаю тупой вопрос. Но я недавний пользователь QUIK.

А откуда мне взять свежую версию терминала, если брокер предоставляет 7.2.2.3?
И будет ли она корректно работать с таким брокером?
Sleep в индикаторе
 
Цитата
валерий написал:
Алексей  ,
Как правило меняются максимум только два последних значения и можно было бы попробовать подумать как не перерисовывать остальные. Но при первом расчете (применить \/ добавить \/ ОК) квик все перерисовывает, потом вроде нет... Как узнать намерения квика в каждом конкретном случае я не вижу.
Скорость обновления меня практически не волнует. И 5 сек устроит. Что было бы существеннее экономии на перерисовке. Но можно ли применять слип и куда его вставить  техподдержка молчит.

Sleep() категорически не поможет. Код OnCalculate() выполняется в основном потоке QUIKа. Слипом вы просто подвесите QUIK.
Идея, заложенная разработчиками QUIKa, заключается в том, что через механизм вызова callback-функции OnCalculate(), QUIK сообщает какую свечку Вам сейчас надо обработать, и ожидает, что Вы вернете значение индикатора именно для этой свечки. Это только для особых индикаторов, формируемых с запаздыванием (например, фракталы), была предоставлена функция SetValue(). При этом подразумевается, что "задним числом" может поменяться значение индикатора только для конечного кол-ва свечек, но никак не вся история индикатора (кому нужен индикатор, история которого постоянно меняется задним числом?)

1-й вариант (противоречит логике работы QUIK):
Если у Вас ГАРАНТИРОВАНО меняется не более 2-х последних свечек, то и перерисовываейте индикатор только для них. Точнее, перерисовывайте (SetValue) только для предпоследней свечки, а значение индикатора для текущей свечки возвращайте как результат OnCalculate(). Как в первый раз вывести весь индикатор? Как только получите index == Size(), нарисуйте его весь и установите флаг, что все отрисовали. Соответственно, при поступлении от QUIK последующих вызовов OnCalculate() Вы уже будете перерисовывать только две последние свечи.
Также обязательно отлавливайте ситуацию index == 1. Это значит, что QUIK по одной из многочисленных причин (не важно каких) решил заставить Вас пересчитать весь индикатор. Делайте то, что он просит, т.е. сбросьте вышеупомянутый флаг отрисовки.

2-й вариант (в логике QUIK):
У Вас же должно быть жесткое соответствие для какой (по времени) свечки соответствуют какие по счету значения в таблицах из файла *.txt?
Quik у Вас запрашивает через OnCalculate() значение индикатора для свечки со временем T(index), ну так и верните ему значение индикатора, соответствующее этому времени.
А чтобы каждый раз не считывать с диска файл *.txt надо придумать механизм принятия решения, когда же именно его считывать.
Для этого надо понимать как часто он меняется (или как часто Вы хотите выводить новую информацию на график), т.е. вывод через равные интервалы времени - это один механизм.
Или надо понимать в связи с какими событиями происходит смена содержимого *.txt и как их отловить - это другой механизм.
Sleep в индикаторе
 
Цитата
валерий написал:
Алексей  ,
Меня интересует просто рисовалка готовых данных. Никаких расчетов нет. Все рисуется на последнем баре - SetValue. Скорость не важна. Лишь бы при большом количестве индикаторов не тормозился сам квик.
В выложенном Вами коде получается, что по мере совершения на бирже каждой обезличенной сделки по инструменту, к которому Вы "прикрутили" свой индикатор, у Вас заново перерисовываются все 300-500 свечек (точнее точек 2-х линий индикатора). В принципе это накладно, но если так и задумано...
Чтобы Вам что-нибудь посоветовать, нужно понимание того, как часто обновляется информация в Вашем txt файле? И какого характера это обновление: после очередной обезличенной сделки на бирже в файле может всё поменяться (тогда, собственно, ничего нового тут не придумать) или меняется/добавляется только последнее значение в таблицах pos и eq.
Также хочу уточнить, к чему относятся последние данные в таблицах: к последней завершенной свечке (т.е. к Size()-1) или к текущей формируемой?
Прошу дополнить руководство по эксплуатации QLua в отношении папки LuaIndicators
 
Использую QUIK 7.2.2.3, который предоставляет Сбербанк.

Возможно, я лишь для себя открыл Америку..

Обнаружилось, что QUIK ищет скрипты индикаторов не только в самой папке LuaIndicators, но и во всех её подпапках.
Хотелось бы, чтобы на это было обращено внимание начинающих пользователей в руководстве по эксплуатации QLua, что бы предостеречь их от пустой траты времени.

Сейчас в руководстве об этой особенности не упоминатеся:
Цитата
При создании нового индикатора (пункт Добавить график (индикатор)… контекстного меню
графика) РМ QUIK сканирует папку LuaIndicators в директории РМ QUIK на наличие в ней
скриптов, отвечающих следующим требованиям:
1. В скрипте определена глобальная таблица Lua с именем Settings;
2. Определена функция Init();
3. Определена функция OnCalculate().

Кроме того, QUIK занимается подобным сканированием ещё и на старте, причем, столько раз, сколько пользовательских индикаторов должно быть выведено в окнах графиков.

Я в подпапках хранил всякие "эксперименты", естественно, иногда недописанные.

Когда я сегодня утром включил QUIK, а он напрочь отказался запускаться, я только через полчаса вспомнил, что накануне вечером бросил на полдороги работу над скриптом, в Body которого был цикл, который без правильной инициализации становился бесконечным.


Надо иметь в виду, что когда
Цитата
...РМ QUIK сканирует папку LuaIndicators...
он, по сути,запускает на исполнение все файлы с расширением lua и в самой папке LuaIndicators, и во всех ее подпапках. И, если в найденных скриптах в Body присутствуют тяжелые вычисления, то это заметно подвешивает терминал.

Где-то я встречал на просторах форума жалобы пользователей на тормоза quika при вызове контекстного меню в окнах графиков, а также на старте терминала, но не видел от технической поддержки внятных комментариев по этому поводу.

Похоже не я один использую подпапки LuaIndicators для хранения экспериментального мусора...
Точнее, до сего дня использовал...
Sleep в индикаторе
 
Если речь идет об индикаторе, как о скрипте для рисования линий в окне графиков QUIK, то это особый вид скриптов, в которых нет своего выделенного потока main().
Почитайте "Создание индикаторов технического анализа с помощью скриптов Lua.pdf" на официальной страничке QUIK.
Вся текущая работа такого скрипта по сути сводится к тому, что QUIK вызывает вашу callback-функцию OnCalculate() каждый раз по мере изменения текущей или появления новой свечи.
Вы же должны максимально быстрым алгоритмом рассчитать значения индикатора для текущего состояния свечи и вернуть QUIKу получившееся значение индикатора. Никаких sleep() !
Кроме того, те алгоритмы, которые, например, предложены в обсуждаемых на форме INDICATORS.zip являются, на самом деле, лишь демонстрация базовых принципов написания индикатора, а не готовым продуктом. Использованные там алгоритмы можно (и нужно!) оптимизировать так, что вычисления будут происходить на порядок быстрее. (Ничуть не хочу обидеть разработчиков :)

Если же речь идет об организации расчетов значений индикатора для внутренних нужд торгового робота, написанного так, чтобы не зависеть от случайного закрытия окна, на котором рисуется интересующий индикатор, то здесь требования, как к обычному скрипту qlua: все "тяжелые" вычисления - в потоке main(), в callback-ах - лишь мгновенное сохранение поступивших данных (например, в очередях) и возврат управления обратно QUIKу. Потом уже main() должен разбираться, что делать с поступившей информацией.
Применительно к расчету индикатора для внутренних нужд робота, можно предложить следующую схему: в main() до основного цикла или внутри цикла по мере наступления событий, требующих начать расчет нового индикатора, запрашиваете у QUIKа нужный поток свечек вызовом CreateDataSource(), и вешаете обработчик события "изменение текущей / поступление новой свечки" через SetUpdateCallback().
Единственное отличие в написании этого обработчика от OnCalculate() в том, что он не должен ничего возвращать QUIKу, а новое вычисленное значение индикатора нужно каким-то устраивающим Вас образом передать в поток main().
INDICATORS.ZIP
 
В quik 7.2.2.3 непосредственно после установки фильтра прогоняется цикл вызовов OnCalculate() c первой свечки, подавая на вход в т.ч. свечки, которые должны быть отфильтрованы, как нулевые (работает только T(I), остальное по нулям). При последующих перезапусках цикла OnCalculate() (например, после вызова окна настроек индикатора) эти отфильтрованные свечки уже не попадают в OnCalculate().
Также этой беды не происходит, если индикатор добавляется в окно графика с уже установленным фильтром.
QUIK clients support в свое время писал, что в более поздних версиях QUIK этот баг был исправлен.

Но на самом деле, это не проблема.
Существуют вполне логичные ситуации, когда в OnCalculate() должны попадать пустые свечки. Это стандартная ситуация, когда в одно окно графиков выводятся два разных инструмента, например, RIH7 и RTSI, или ликвид и неликвид на малом тайм-фрейме.
Не важно какова причина попадания пустой свечки в OnCalculate() - вышеописанная или баг терминала. Пустые свечки должны либо игнорироваться (OnCalculate() возвращает nil, получаем дырку на графике, так поступает сам QUIK), либо OnCalculate() должен возвращать прежнее значение индикатора (получаем горизонтальную линию, если Вам так больше нравится).
Что же касается расчета индикаторов, основанных на истории свечек, то выше уже было дано достаточно советов как организовать вычисления при наличии пустых свечек, главное, повторю, объявите счетчик непустых свечек и используйте его при обращении к массивам с историей.
Перенумерация свечек и SetUpdateCallback
 
Кстати, повнимательнее проанализировал лог с 6000+ свечками:
была выдана история с 27.01.2017 14:05:00 по 01.02.2017 23:49:00 свечи 1-3000 и далее с 03.02.2017 14:05:00 по 08.02.2017 23:49:00 свечи 3001-6000.
Quik 7.2.2.3 Настройка "Очищать данные после смены даты: На сервере (при установлении связи)".
Связь установлена в 09:50, данные запрошены через CreateDataSource в 10:20. Окон с графиком на минутном таймфрейме открыто в терминале не было, т.е. именно скрипт был инициатором запроса этих данных.
Это баг терминала или сервера?
Перенумерация свечек и SetUpdateCallback
 
Хорошо, переформулирую вопрос.
Понятно, что номера свечкам в OnCalculate присваивает терминал. И он же в случае перенумерации гарантировано перезапустит цикл вызовов OnCalculate c 1-й свечки.

А номера свечкам, получаемым от CreateDataSource, также присваивает терминал, или сервер брокера?

Я хочу сказать, что если присваивает сервер брокера, то при перенумерации он должен заново послать пакетом всю историю на терминал.
В этом случае, по идее, терминал должен обеспечить вызовы callbackа от CreateDataSource аналогично OnCalculate, т.е. начиная с 1-й свечки "новой" истории.
Перенумерация свечек и SetUpdateCallback
 
Меня больше интересовал ответ на второй вопрос:
Речь идет не о работе индикатора (там с OnCalculate все понятно), а о принципе работы callback от CreateDataSource.

2. Если терминал запустить круглосуточно и скрипт вообще не останавливать, то как себя ведет callback от CreateDataSource при смене сессии?
Он в конце торгов выдаст свечу 23:49 за номером 3810, а потом в 10:00 выдаст свечу 3001?
Или же callback в случае перенумерации будет вызван для всех свечей в новой нумерации, начиная с 1?
Перенумерация свечек и SetUpdateCallback
 
В 10:20 запустил скрипт, анализирующий свечки SiH7 на минутном интервале.
CreateDataSource предоставил историю в 6021 свечек (свеча 10:00 имела номер 6001), callback стал вызываться для текущих свечек, начиная с 6021 свечки.
Через несколько минут скрипт был остановлен, а, затем, в 10:42 запущен вновь.
И что мы видим?  :shock:
CreateDataSource предоставил историю в 3043 свечек (свеча 10:00 имела номер 3001), callback стал вызываться для текущих свечек, начиная с 3043 свечки.

1. Если бы скрипт не останавливался, произошла бы перенумерация свечек?
Если бы произошла, то callback просто выдал бы следующую свечу в новой нумерации? Например, если перенумерация произошла бы ровно в 10:30: была свеча 6031, а следом за ней, вдруг пришла бы свеча 3031?
Или же callback бы в этом случае был бы вызван для всей истории в новой нумерации, начиная с 1-й свечи.

2. Если терминал запустить круглосуточно и скрипт вообще не останавливать, то как себя ведет callback от CreateDataSource при смене сессии?
Он в конце торгов выдаст свечу 23:49 за номером 3810, а потом в 10:00 выдаст свечу 3001 (или 6810 ->6001 соответственно)?
Или же callback в случае перенумерации будет вызван для всех свечей в новой нумерации, начиная с 1?
В чём преимущество OnInit
 
Небольшая поправка:
В script_path Вы получаете не просто полной путь к папке запускаемого скрипта (как при вызове getScriptPath()), а полный путь, включая имя файла самого скрипта.
В чём преимущество OnInit
 
Цитата
Космонавт написал:
Зачем у Oninit в скобках параметр (script_path)?
У меня работает и без него: OnInit ()

имеется в виду, что нужно делать так?Кодscript_path=getScriptPath()
function OnInit (script_path)
--задаём переменные
end
Имеется ввиду, что quik уже за Вас вызвал getScriptPath() и результат Вам подсовывает в качестве параметра при вызове OnInit(script_path).
А уж будете Вы использовать этот "подарок" внутри OnInit или нет, дело Ваше  :smile:
Многократный вызов CreateDataSource
 
Подскажите, пожалуйста.

Допустим скрипт внутри себя рассчитывает множество индикаторов на основании свечек одного конкретного инструмента с одним и тем же тайм-фреймом (речь идет о внутренних "индикаторах" для нужд робота, т.е. запросы делаются в рамках работы одного скрипта).

1. Будет ли нагружать систему многократный вызов CreateDataSource (каждый для своего экземпляра класса, обсчитывающего конкретный индикатор) в плане расхода памяти, или же QUIK кеширует идентичные запросы CreateDataSource, возвращая каждый раз ссылку на одну и ту же таблицу свечек?

2. Тоже в плане нагрузки на трафик: Если QUIK получил множество запросов от CreateDataSource с одним и тем же инструментом и одним и тем же тайм-фреймом, он организует для каждого запроса свой идентичный поток свечек с сервера или ограничится одним потоком?
Как использовать Param в CreateDataSource?
 
Да, чуть не забыл!
Param = "bid"
ds = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1, Param)

Так как же потом получить из свечек значения заказанного параметра?
ds:[Param](Index) или ds[Param][Index], или как-то иначе?
Как использовать Param в CreateDataSource?
 
Спасибо!
Как использовать Param в CreateDataSource?
 
В других местах нашел схожие перечни, но часть параметров была указана прописными буквами, да и в примере в руководстве qlua указаны bid и last тогда как в перечне с quikluasharp все идентификаторы указаны в верхнем регистре (в т.ч. BID и LAST). Lua - регистрозависимый язык.
Как правильно указывать параметр: "bid" или "BID", или без разницы?
Как использовать Param в CreateDataSource?
 
Нашел на просторах инета "Список возможных идентификаторов параметров, передаваемых в функцию getParamEx()": http://quikluacsharp.ru/quik-qlua/poluchenie-dannyh-iz-tablits-quik-v-qlua-lua/
Эти наименования параметров подходят для Param в CreateDataSource?
Этот список исчерпывающий?
Как использовать Param в CreateDataSource?
 
Подскажите, пожалуйста, как можно использовать CreateDataSource, если передавать в нее необязательный Param?

Какие значения может принимать Param?
Если это наименование параметра Таблицы обезличенных (всех) сделок (ТВС), то будет ли это работать, если задать интервал, отличный от тикового?
Хотя в руководстве сказано, что "Если параметр не задан, то заказываются данные на основании Таблицы обезличенных сделок, если задан – данные по этому параметру"
Получается, что если параметр задан, то данные берутся не из таблицы обезличенных сделок, а, значит, с использованием Param нельзя заказать данные из ТВС.
Тогда откуда можно заказать данные с использованием Param? Из Таблицы текущих торгов? Из стакана?

Примеры из руководства:
ds3 = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1, "bid")  
ds1 = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1, "last")

bid и last - это поля таблицы текущих торгов? Где можно увидеть исчерпывающий перечень всех полей из этой таблицы? Я в руководстве qlua не нашел.

Как из обработчика, установленного через SetUpdateCallback, получить значение заказанного Param? ds:[Param](index) или ds:[Param][index]?
Страницы: Пред. 1 2 3 4 След.
Наверх