Не могу заставить работать функцию Subscribe_Level_II_Quotes()

Страницы: 1
RSS
Не могу заставить работать функцию Subscribe_Level_II_Quotes()
 
Есть функция, в которую передается массив. Каждый его элемент - массив из двух элементов: код класса и код инструмента.

function Subscribe(list)
for i = 1, #list do
   local classCode = list[i][1]
   local secCode = list[i][2]

   local x = Subscribe_Level_II_Quotes(class_code, sec_code)

   while not x do
    sleep(10)
   end

   Calculate(classCode, secCode)
 end
end

В ней я по очереди подписываюсь на котировки по каждому инструменту функцией Subscribe_Level_II_Quotes(). Дальше цикл (на всякий случай), чтобы убедиться, что функция вернула true. И дальше какое-то вычисление.
Здесь у меня все работает нормально.

Дальше я прохожусь циклом по этому же списку, чтобы отписаться от каждой котировки.

function Unsubscribe(list)
 for i = 1, 100 do
   local classCode = list[i][1]
   local secCode = list[i][2]

   local x =Unsubscribe_Level_II_Quotes(class_code, sec_code)

   while not x do
     sleep(10)
   end
 end
end

Здесь на первом же элементе из списка я застреваю в цикле while. Если цикл убрать, то функция отрабатывает, а отписка не происходит.

Подскажите как справиться с этой проблемой. Нужно сначала подписаться на инструменты, потом отписаться от них.

Версия квика 9.2.3.15. Может дело не в моих кривых руках, а в версии?
 
Нет, это все таки руки.
classCode и class_code - не одно и то же
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
Нет, это все таки руки.
classCode и class_code - не одно и то же
Эта путаница в переменных произошла когда я писал функцию для отправки сюда в чат. Старался максимально просто и понятно написать и налажал немного. В рабочем коде, поверьте, с переменными все в порядке (перепроверил только что). Если учесть, что дело не в названиях переменных, есть еще варианты почему код не работает?
 
Цитата
Вася написал:
while not x do  
   sleep(10)    
end

Внутри цикла while переменная x не меняется. Если окажется not x эквивалентно true то цикл бесконечный.
 
Цитата
TGB написал:
Цитата
Вася написал:
while not x do  
   sleep(10)    
end

Внутри цикла while переменная x не меняется. Если окажется not x эквивалентно true то цикл бесконечный.
Ну этот цикл я сделал на тот случай, что вдруг отписка от котировок происходит не сразу, а через сколько-то миллисекунд. Если это произойдет, то x должен поменяться, я думаю. Но даже если я ошибаюсь, то, если цикл убрать, то функция отрабатывает и отписки не происходит. Unsubscribe_Level_II_Quotes() возвращает false. А в первой функции Subscribe_Level_II_Quotes() возвращает true. Хотя функции Subscribe(list) и Unubscribe(list) в основе своей идентичны. Вот этого я никак уразуметь не могу.
 
1. Кроме Subscribe_Level_II_Quotes и Unsubscribe_Level_II_Quotes, есть функция
IsSubscribed_Level_II_Quotes
Функция позволяет узнать, заказан ли с сервера стакан по указанному классу и инструменту.
Формат вызова:
BOOLEAN IsSubscribed_Level_II_Quotes (STRING class_code, STRING sec_code)
Параметры:
• class_code – код класса;
• sec_code – код инструмента.
Функция возвращает «true», если стакан по классу class_code и инструменту sec_code уже заказан.
---
2. Посмотрите сайт https://quikluacsharp.ru/quik-qlua/poluchenie-stakana-iz-quik-v-qlua-lua/ ,  на котором обсуждается работа со стаканом.
 
Цитата
Вася написал:
цикл убрать, то функция отрабатывает и отписки не происходит.
Как определили, что не происходит?
 
Цитата
swerg написал:
Цитата
Вася написал:
цикл убрать, то функция отрабатывает и отписки не происходит.
Как определили, что не происходит?
Если в функции 'Unsubscribe(list)' после 'local x =Unsubscribe_Level_II_Quotes(class_code, sec_code)'  написать 'local y = IsSubscribed_Level_II_Quotes(classCode, secCode)', а затем вывести значения x и y в таблицу, то x будет false, а y будет true.
 
Задача такая возникла из-за того, что мне нужно вывести в таблицу данные на основании расчетов 2000 стаканов. Т.к. у многих брокеров есть ограничение на 200 стаканов, то я хотел по очереди открывать и закрывать котировки 150 стаканов.  
 
Цитата
Вася написал:
Цитата
swerg написал:
 
Цитата
Вася  написал:
цикл убрать, то функция отрабатывает и отписки не происходит.
 Как определили, что не происходит?
Если в функции 'Unsubscribe(list)' после 'local x =Unsubscribe_Level_II_Quotes(class_code, sec_code)'  написать 'local y = IsSubscribed_Level_II_Quotes(classCode, secCode)', а затем вывести значения x и y в таблицу, то x будет false, а y будет true.
тут опять я скопировал разные названия переменных sec_code и secCode, но прошу не обращать внимания на это - в коде названия переменных одинаковое.
 
Продублирую еще раз: если в функции 'Unsubscribe(list)' после 'local x =Unsubscribe_Level_II_Quotes(class_code, sec_code)'  написать 'local y = IsSubscribed_Level_II_Quotes(class_code, sec_code)', а затем вывести значения x и y в таблицу, то x будет false, а y будет true.
 
Вася, Справиться с этой проблемой невозможно никак. Даже если у Вас будет десяток стаканов. А обслуживать 2000 тикеров не так просто даже моему скрипту, у которого ни одного стакана нет, не было, и не будет (Борис, слышишь меня? :smile: ). Ваша же задача просто безнадёжна, в принципе невыполнима.
 
Цитата
Владимир написал:
Вася, Справиться с этой проблемой невозможно никак. Даже если у Вас будет десяток стаканов. А обслуживать 2000 тикеров не так просто даже моему скрипту, у которого ни одного стакана нет, не было, и не будет (Борис, слышишь меня? :: ). Ваша же задача просто безнадёжна,  в принципе  невыполнима.
А по функции 'Unsubscribe_Level_II_Quotes()' что можете сказать? Почему она не выполняет ту задачу, которую должна выполнять? Или может я не правильно ее применяю?
 
Цитата
Владимир написал:
Вася, Справиться с этой проблемой невозможно никак. Даже если у Вас будет десяток стаканов. А обслуживать 2000 тикеров не так просто даже моему скрипту, у которого ни одного стакана нет, не было, и не будет (Борис, слышишь меня? :: ). Ваша же задача просто безнадёжна,  в принципе  невыполнима.
Вопрос скорости обработки в этой задаче не критичен.
 
Это почему она не выполнима...

Решается она в виде очереди обработки, раз скорость не так важна. Оставим в стороне вопрос самого этого анализа.

Создаете очередь задач. Очередь - массив. Задача - объект, содержащий методы подписки, анализа отписки.
Далее в цикле начинаете обрабатывать, например по 10 за раз. Если в какой-то момент не происходит подписка, то просто переключаетесь на следующую еще не выполненную задачу. И так пока очередь не опустеет.
Можете обрабатывать простым циклом, можете корутинами - как угодно.

В книге автора языка есть хороший пример по скачиванию файла из интернета кусками. Это, по сути, та же задача.
 
Тоже не понял почему задача не выполнима. Я ее выполнил, и это было не так уж сложно для меня с небольшим опытом программирования. Данные, нужные мне, в таблицу выводятся. Но только до 200-го инструмента. И все - я упираюсь в количество открытых стаканов. А функция 'Unsubscribe_Level_II_Quotes()', которая должна их закрывать - их не закрывает. Я пробовал в одном цикле: открыть стакан, получить данные и тут же закрыть. Не получается. Пробовал порциями (вот эти 2 функции, которые сюда скинул): в одном цикле открываю 150 стаканов, получаю данные. В следующем цикле эти же стаканы пытаюсь закрыть. Опять не выходит. Пробовал на 9-й версии квика и на 8-й. Так скажите мне, господа - это все-таки я криворукий или эта гребаная функция 'Unsubscribe_Level_II_Quotes()' не работает.
 
Ну так Вы выполняете Unsubscribe_Level_II_Quotes один раз. Если она вернула false, то можете ее вызывать в цикле еще раз (но не бесконечно), пока она не вернет истину.
Это Вам выше и написали.
 
Вася, Объясняю по пунктам:
1. И по Вашему собственному признанию, и по задаваемым здесь вопросам, Вы новичок в программировании, а здесь требуется уровень СУПЕРпрофессионала.
2. Мне совершенно наплевать на все эти '[Un]subscribe_Level_II_Quotes: во-первых, для принятия решение о сделках стакан практически бесполезен. Более того, он частенько используется именно в качестве разводки для лохов. Во-вторых, информация в стакане меняется очень быстро, и любыми своими "подписками и отписками" Вы безнадёжно теряете время. В-третьих, если "вопрос скорости обработки в этой задаче не критичен", то у меня просто фантазии не хватает, за каким хреном Вам понадобился стакан. И не 2000, а хотя бы один.
3. Если Ваша задача "выполнить функцию", а не "получить достоверные данные", то - извиняюсь - задача выполнима.  :smile:  
 
Цитата
Владимир написал:
Вася, Справиться с этой проблемой невозможно никак. Даже если у Вас будет десяток стаканов. А обслуживать 2000 тикеров не так просто даже моему скрипту, у которого ни одного стакана нет, не было, и не будет (Борис, слышишь меня? :: ). Ваша же задача просто безнадёжна,  в принципе  невыполнима.
Слышу и вижу.  Но не совсем согласен с этим , тем более что знаю точно что твой скрипт отслеживает в полу секундном прерывании  бид и аск , а это уже значит что и твой скрипт постоянно следит за стаканами всех отслеживаемых тикеров твоим скриптом.
А вот мой принцип слежения за стаканами гораздо глубже чем следить за бид и аск , в моем принципе заложено дополнительное отслеживание и более дальних заявок вплоть до 0,2-0,5 % от Аска и Бида. и аналитика их изменения  с учетом своих собственных  заявок и их  очередности на исполнение по отношению к чужим на этом же уровне.  
 
БорисД, Это не стакан, Борь, это ТТТ, т.е. на несколько порядков более быстрый способ. Стакан идеологически примерно та же хрень, как и со свечами: подписаться на него и Квик сам будет как-то менять там данные. И если даже со свечами работать практически невозможно (а свечи меня интересовали от 15 минут и выше!), то в стакане информация меняется тоже на несколько порядков быстрее. Так что по ТТТ за бид и аск следить можно и при паре тысяч тикеров, и при большем их количестве, а за стаканами или даже за свечами следить нельзя и при десятках, если не единицах - даже если не принимать во внимание бесконечные глюки Квика - только его тормоза. Тем более, что частота сделок у тебя намного выше, чем у меня, и я хочу её замедлить, чтобы сделки совершались не чаще, чем раз в секунду.
 
В данном случае, я тоже не очень понимаю смысл этого анализа, т.к. за время цикла задержки потока стакан изменится много раз. И это если анализировать всего один, не то что тысячи.
Можно догадываться, какая задача решается, но часто пытаются через стакан посчитать сумму заявок. Хотя это берется из ТТТ одной строкой. При этом, анализируя стакан, также стоит учитывать, что через Квик доступна только малая часть глубины стакана - в лучшем случае 50 строк, а чаще всего 20.

Но обсуждали чисто техническую реализацию, поэтому все это лирика.
 
Цитата
Вася написал:
function Subscribe(list) for i = 1, #list do    local classCode = list[1]    local secCode = list[2]    local x = Subscribe_Level_II_Quotes(class_code, sec_code)    while not x do     sleep(10)    end    Calculate(classCode, secCode)  endendВ ней я по очереди подписываюсь на котировки по каждому инструменту функцией Subscribe_Level_II_Quotes(). Дальше цикл (на всякий случай), чтобы убедиться, что функция вернула true. И дальше какое-то вычисление.Здесь у меня все работает нормально.Дальше я прохожусь циклом по этому же списку, чтобы отписаться от каждой котировки.function Unsubscribe(list)  for i = 1, 100 do    local classCode = list[1]    local secCode = list[2]    local x =Unsubscribe_Level_II_Quotes(class_code, sec_code)    while not x do      sleep(10)    end  endendЗдесь на первом же элементе из списка я застреваю в цикле while. Если цикл убрать, то функция отрабатывает, а отписка не происходит.Подскажите как справиться с этой проблемой. Нужно сначала подписаться на инструменты, потом отписаться от них.Версия квика 9.2.3.15. Может дело не в моих кривых руках, а в версии?
если актуально, то ловите  решение:
--------------------------
фрагмент скрипта  
Код
while Subscribe_Level_II_Quotes(cl,se)==false do sleep(5) end  --подписываемся на стакан
local z=IsSubscribed_Level_II_Quotes (cl,se);                          --проверяем подписку
Log:write(tostring(cl)..","..tostring(se)..",z="..tostring(z).."\n");   --выводим в файл результат
while Unsubscribe_Level_II_Quotes(cl,se)==false do  sleep(5) end   -- отписываемся от стакана
z=IsSubscribed_Level_II_Quotes (cl,se);                               --проверяем отписку        
Log:write(tostring(cl)..","..tostring(se)..",z="..tostring(z).."\n");   --выводим в лог файл результат
результат:
---------------------------
QJSIM,VTBR,z=true
QJSIM,VTBR,z=false
QJSIM,ABRD,z=true
QJSIM,ABRD,z=false
QJSIM,CHMF,z=true
QJSIM,CHMF,z=false
QJSIM,AFKS,z=true
QJSIM,AFKS,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,GAZP,z=true
QJSIM,GAZP,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFLT,z=true
QJSIM,AFLT,z=false
QJSIM,AFKS,z=true
QJSIM,AFKS,z=false
QJSIM,AFKS,z=true
QJSIM,AFKS,z=false
QJSIM,AFKS,z=true
QJSIM,AFKS,z=false
 
nikolz, не понимаю почему у вас этот код работает, а у меня нет. Я пробовал в версиях квика 9.2.3.15 и 8.9.0.107. Я застреваю в первом же цикле while Unsubscribe_Level_II_Quotes(cl,se)==false do  sleep(5) end. Т.е. я получаю true при первой проверке на подписку на первый инструмент. Отписка у меня не происходит - цикл бесконечный.  
 
nikolz, пробовал акции, облигации, фьючерсы. Без разницы.
 
Нет, прослеживается зависимость от типа инструмента.
Если написать:

x = Subscribe_Level_II_Quotes('SPBFUT','RIM2')
y = Unsubscribe_Level_II_Quotes('SPBFUT','RIM2')

то x == true и y == true;

А если написать:

x = Subscribe_Level_II_Quotes('TQOB','SU24020RMFS8')
y = Unsubscribe_Level_II_Quotes('TQOB','SU24020RMFS8')


то x == true и y == false.

На облигациях не работает что-ли... Вроде же 'RIM2' - это код инструмента фьючерса, а 'SU24020RMFS8' - код инструмента облигации. Или я что-то напутал? Может для облигаций какие-то другие значения подставлять нужно?
 
Что вообще происходит с заказом стакана котировок кто-нибудь может пояснить? Если есть открытый стакан, то никаких проблем нет. Проверка на подписку функцией  IsSubscribed_Level_II_Quotes всегда показывает, что подписка есть, т.е. она возвращает true и стакан нормально читается через getQuoteLevel2. Но если стакан не открыт в квике, то если запустить скрипт:

ClassCode = "SPBOPT"
SecCode = "RI107500BF3"

if (not IsSubscribed_Level_II_Quotes(ClassCode, SecCode)) then
    message("Подписываемся на стакан по инструменту")
    if Subscribe_Level_II_Quotes(ClassCode, SecCode) then
        message("Подписались на стакан по инструменту")
    end
    Subscribed = true
end

quotes = getQuoteLevel2(ClassCode, SecCode)

if quotes.bid and quotes.bid[ 1 ] then
   message("Есть котировки")
else
   message("Котировок нет")
end

if Subscribed then
   message("Отписываемся от стакана по инструменту")  
   Unsubscribe_Level_II_Quotes(ClassCode, SecCode)
end

то по очереди выводятся сообщения в следующем порядке:

Подписываемся на стакан по инструменту
Подписались на стакан по инструменту
Котировок нет
Отписываемся от стакана по инструменту

И запускай хоть сто раз - будет то же самое! Хоть и подписались на стакан, а читать нечего!

Далее делаем следующее - последние 4 строчки закомментируем, т.е. в любом случае отписку от стакана не делаем. Тогда если запустить такой скрипт, то вывод будет такой:

Подписываемся на стакан по инструменту
Подписались на стакан по инструменту
Котировок нет

Но если запустить этот же скрипт теперь второй раз, то вывод будет:
Есть котировки

И потом хоть сто раз запускай - вывод будет - Есть котировки

Что за ерунда такая? Чтобы нормально читать стакан при подписке = true надо завершить скрипт и запустить его заново, при этом не отписываясь при первом запуске? Как нормально подписаться и нормально сразу читать стакан? Мне нельзя скрипт останавливать. Ранее работал со стаканами - всё нормально подписывалось и читалось сразу. Но там всё в цикле было и проверка на подписку и подписка если нет подписки, потом чтение стакана. Мне надо один раз подписаться и чтобы потом в цикле читать стакан. А то выходит полный бред какой-то - подписался нормально, Subscribe_Level_II_Quotes(ClassCode, SecCode) вернула true, а стакан не читается.
 
Цитата
Alexander написал:
Что за ерунда такая?
Все так как и должно быть. Просто вы не учитываете, что процедура Subscribe_Level_II_Quotes выполняется асинхронно и требует значительного времени на выполнение.
 
Цитата
Станислав написал:
Цитата
Alexander написал:
Что за ерунда такая?
Все так как и должно быть. Просто вы не учитываете, что процедура Subscribe_Level_II_Quotes выполняется асинхронно и требует значительного времени на выполнение.
Ставил задержку после подписки и перед чтением стакана в 1 минуту - Котировок нет. Но я вот только что нашёл как надо. Задержка по любому нужна на срабатывание. Но нужна обязательно функция main, а все действия делаем в отдельной функции и задержку ставим 100 мс хоть внутри этой функции хоть в main, тогда корректно можно дождаться срабатывания чтения стакана. А по поводу асинхронно, то разработчики об этом должны писать в документации и так же указать, что никакие задержки не сработают если не будет функции main()
Так же возможно и вообще всё делать чисто в main() и с задержкой на срабатывание - наверняка сработает, но я не проверял. Просто быстро накатан был скрипт для проверки без main(). И кто бы знал, что одни и те же действия будут работать по разному с main() и без? А началось всё с того что в рабочем скрипте не было задержки и стакан не читался, сейчас поставлю и посмотрю на результат.
 
Любая обработка клиент-сервер требует той или иной обработки ожидания. А по поводу main - так любой скрипт, предполагающий длительную работу в среде терминала, должен содержать эту функцию.

Документация "Использование Lua в Рабочем месте QUIK.pdf", раздел 2. Взаимодействие потоков Lua скрипта
 
Цитата
Alexander написал:
while Subscribe_Level_II_Quotes(cl,se)==false do sleep(5) end  --подписываемся на стакан
local z=IsSubscribed_Level_II_Quotes (cl,se);                          --проверяем подписку
Log:write(tostring(cl)..","..tostring(se)..",z="..tostring(z).."\n");   --выводим в файл результат
while Unsubscribe_Level_II_Quotes(cl,se)==false do  sleep(5) end   -- отписываемся от стакана
z=IsSubscribed_Level_II_Quotes (cl,se);                               --проверяем отписку        
Log:write(tostring(cl)..","..tostring(se)..",z="..tostring(z).."\n");   --выводим в лог файл результат
все работает.
вот вам тест (это лишь колбек):
Код
function OnParam(c,s)
   local z=IsSubscribed_Level_II_Quotes (c,s);
   if z==false then  -- если подписки нет то подписываемся
      while Subscribe_Level_II_Quotes(c,s)==false do sleep(5) end  --подписываемся на стакан
         z=IsSubscribed_Level_II_Quotes (c,s);                   --проверяем подписку
         Log:write("подписались сейчас,"..tostring(c)..","..tostring(s)..",z="..tostring(z).."\n");   --выводим в файл результат
   else    Log:write("подписались раньше,"..tostring(c)..","..tostring(s)..",z="..tostring(z).."\n");   --выводим в файл результат
   end
end
в тесте подписываемся на новые
вот результат:
Код
подписались сейчас,SPBFUT,SPM3,z=true
подписались сейчас,QJSIM,CBOM,z=true
подписались сейчас,QJSIM,ETLN,z=true
подписались сейчас,QJSIM,FLOT,z=true
подписались сейчас,QJSIM,GAZP,z=true
подписались раньше,QJSIM,LKOH,z=true
подписались сейчас,QJSIM,LNZLP,z=true
подписались сейчас,QJSIM,LSRG,z=true
подписались сейчас,QJSIM,NLMK,z=true
подписались сейчас,QJSIM,POLY,z=true
подписались сейчас,QJSIM,RENI,z=true
подписались сейчас,QJSIM,SBERP,z=true
подписались сейчас,QJSIM,SFTL,z=true
подписались сейчас,QJSIM,SVAV,z=true
подписались сейчас,QJSIM,VTBR,z=true
подписались сейчас,CETS,CNYRUB_TOM,z=true
подписались сейчас,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались сейчас,SPBFUT,GDM3,z=true
подписались сейчас,SPBFUT,EuM3,z=true
подписались раньше,SPBFUT,EuM3,z=true
подписались сейчас,SPBFUT,RTM3,z=true
подписались сейчас,SPBFUT,CRM3,z=true
подписались раньше,SPBFUT,EuM3,z=true
подписались раньше,SPBFUT,EuM3,z=true
подписались сейчас,SPBFUT,RNU3,z=true
подписались сейчас,SPBFUT,SRM3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,GDM3,z=true
подписались раньше,SPBFUT,RNU3,z=true
подписались раньше,SPBFUT,RNM3,z=true
подписались раньше,SPBFUT,RNU3,z=true
подписались раньше,SPBFUT,RNU3,z=true
подписались раньше,SPBFUT,RNU3,z=true
подписались раньше,SPBFUT,RNU3,z=true
подписались раньше,SPBFUT,CRM3,z=true
подписались сейчас,SPBFUT,SiM3,z=true
подписались раньше,QJSIM,ETLN,z=true
подписались раньше,QJSIM,FLOT,z=true
подписались раньше,QJSIM,GAZP,z=true
подписались раньше,QJSIM,LKOH,z=true
подписались раньше,QJSIM,LNZLP,z=true
подписались раньше,QJSIM,NLMK,z=true
подписались раньше,QJSIM,POLY,z=true
подписались раньше,QJSIM,RENI,z=true
подписались раньше,QJSIM,SBERP,z=true
подписались раньше,QJSIM,SVAV,z=true
подписались сейчас,SPBFUT,SRU3,z=true
 
Результат - (подписка) есть, а стаканов - [данных с заголовком onQuote] нет.

Вопрос : как заставить Quik либо отдавать стаканы, либо сообщить о импотенции ?

При этом функция getQuote() стаканы (иногда пустые :cry: ) возвращает.      
 
Subscribe_Level_II_Quotes работает нормально, ищите проблему у себя.
onQuote передает только изменения стакана, возможно вы торгуете неликвид, где стаканы обновляются раз в час.
Страницы: 1
Читают тему
Наверх