Тема: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Я подписываюсь на данные стакана

subsc=Subscribe_Level_II_Quotes(klass, instr)
message(" is "..tostring(subsc))

получаю ответ true

далее

tab = getQuoteLevel2 (klass, instr)
kol=tostring(tonumber(tab.offer[1].price))
message('; tab='..kol..'; off_count='..off_count)

приходит ответ

attempt to index field 'offer' (a nil value)

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

есть предположение, что запрос от меня на получение данных из стакана уходит раньше,
чем успевают подгрузиться данные стакана.
Это действительно так?

нормально будет решить вопрос написав sleep(100) после Subscribe_Level_II_Quotes(klass, instr)  ?

2

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

dkostiunin пишет:

приходит ответ

attempt to index field 'offer' (a nil value)

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

Это нормально, getQuoteLevel2 ничего не знает, есть данные или только формируются таблицы , а данные ещё в них нет.

function GetBid(ql2, bc)
    if not ql2 then return {price = 0, quantity = 0} end
    local bid_count = ql2.bid_count
    if bc > bid_count then bc = bid_count end
    if bc == 0 then
        return {price = 0, quantity = 0}
    else
        bc = bid_count-bc+1
        local bid = ql2.bid
        if not bid then return {price = 0, quantity = 0} end
        return bid[bc] or {price = 0, quantity = 0}
    end
end
function GetAsk(ql2, ac)
    if not ql2 then return {price = 0, quantity = 0} end
    local ask_count = ql2.offer_count
    if ac > ask_count then ac = ask_count end
    if ask_count == 0 then
        return {price = 0, quantity = 0}
    else
        local ask = ql2.offer
        if not ask then return {price = 0, quantity = 0} end
        return ask[ac] or {price = 0, quantity = 0}
    end
end
function calc()
  local QL2 = getQuoteLevel2Ex("SPBFUT", "RIH0")
 --получить 5-ю строку бида
  local bid = ql2.GetBid(QL2, 5).price
  if bid == 0 then return end
  -- если цена есть, значит считаем дальше
  
end

--где-то в коде
calc()

3

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Чего то не получается
вот в этой строке

local bid = ql2.GetBid(QL2, 5).price

ошибка attempt to index global 'ql2' (a nil value)

То есть, если я правильно понимаю getQuoteLevel2Ex("SPBFUT", "RIH0")  -  не получает данные
я пробовал и со стаканом и без стакана
и пробовал вставлять строку subsc=Subscribe_Level_II_Quotes("SPBFUT", "RIH0")

перед вызовом calc

еще такой момент, я попробовал по своему,  с паузой, я вызываю это в функции OnOrder

function OnOrder (trade_data)

    subsc=Subscribe_Level_II_Quotes(klass, instr)
    message(" is "..tostring(subsc))
    ii = 1;
           
    repeat
        tab = getQuoteLevel2 (klass, instr)
        off_count= tab.offer_count
        message("Значение i = " .. ii..'; off_count='..off_count)       
        sleep(500)
        ii = ii + 1
    until off_count~='0.000000' or ii >10

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

получается что в процессе одного вызова OnOrder запрошенные данные в любом случае не придут, пока функция OnOrder не завершится

то есть, логику получения данных из стакана надо вынести из функции onOrder







kalikazandr пишет:
function GetBid(ql2, bc)
    if not ql2 then return {price = 0, quantity = 0} end
    local bid_count = ql2.bid_count
    if bc > bid_count then bc = bid_count end
    if bc == 0 then
        return {price = 0, quantity = 0}
    else
        bc = bid_count-bc+1
        local bid = ql2.bid
        if not bid then return {price = 0, quantity = 0} end
        return bid[bc] or {price = 0, quantity = 0}
    end
end
function GetAsk(ql2, ac)
    if not ql2 then return {price = 0, quantity = 0} end
    local ask_count = ql2.offer_count
    if ac > ask_count then ac = ask_count end
    if ask_count == 0 then
        return {price = 0, quantity = 0}
    else
        local ask = ql2.offer
        if not ask then return {price = 0, quantity = 0} end
        return ask[ac] or {price = 0, quantity = 0}
    end
end
function calc()
  local QL2 = getQuoteLevel2Ex("SPBFUT", "RIH0")
 --получить 5-ю строку бида
  local bid = ql2.GetBid(QL2, 5).price
  if bid == 0 then return end
  -- если цена есть, значит считаем дальше
  
end

--где-то в коде
calc()

4

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

это работает не так. вы должны подписаться на обновление стакана один раз в начале main() при помощи функции Subscribe_Level_II_Quotes(). затем определить колбэк OnQuote() как написано в документации, он будет срабатывать каждый раз при обновлении стакана. внутри этого колбэка вызываем getQuoteLevel2Ex()  - эта функция будет возвращать состояние обновленного стакана. никаких sleep(), естественно, не нужно.

5

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Спасибо за рекомендации.
Как раз под конец дня на акциях спб поэксперементировал.
Суть задачи такая.
У меня стоят заявки по облигациям лимитные. На покупку.
Когда они исполняются, мне надо выставить обратную заявку на исполненное количество.
При этом посмотреть стакан,выбрать нужное место , и встать перед ним.
Ну это я руками до сего момента делал.
То есть я следующий алгортим представляю.
получаю срабатывание функции OnTrade
в ней сразу подписываюсь на нужный мне стакан с помощью функции subsc=Subscribe_Level_II_Quotes (передавая ей параметры , полученные перед этим из OnTrade)
Затем Ontrade завершается и уже в Main у меня следущее

    while is_run do
        if subsc == true then
          tab = getQuoteLevel2 (klass, instr)
          off_count= tab.offer_count
                  subsc = false
                end
                sleep(50)
    end
       

вроде работает без всяких sleep попробовал на разных стаканах, без задержек и ошибок.

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



toxa пишет:

это работает не так. вы должны подписаться на обновление стакана один раз в начале main() при помощи функции Subscribe_Level_II_Quotes(). затем определить колбэк OnQuote() как написано в документации, он будет срабатывать каждый раз при обновлении стакана. внутри этого колбэка вызываем getQuoteLevel2Ex()  - эта функция будет возвращать состояние обновленного стакана. никаких sleep(), естественно, не нужно.

6

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

нет смысла подписываться на стаканы в OnTrade, это очень долго. вы получаете данные мгновенно из-за того, что у вас этот стакан, судя по всему, открыт в терминале, на него вообще можно не подписываться.

1. я бы сделал так: в начале main() подписылся бы на все стаканы по которым осуществляется торговля, и дальше в main() крутится пустой цикл while not exitflag do sleep(1) end
2. в колбэке onquote я бы получал стакан getQuoteLevel2 () и данные из него клал бы свои таблички в подготовленном для анализа виде; таким образом, в любой момент времени были бы стаканы по всем нужным инструментам
3. в колбэке ontrade просто брал бы подготовленные данные по нужному стакану и ставил бы заявку

ваш вариант - ужасен.

7

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

dkostiunin пишет:

Чего то не получается
вот в этой строке
local bid = ql2.GetBid(QL2, 5).price
ошибка attempt to index global 'ql2' (a nil value)

У вас не правильный подход. Выложите код, в котором вы используете предложенные функции. Тогда станет ясно, почему у вас не работает.

Удаляйте лишнее между тэгами, не нужно копировать все сообщение, еще и с кодом.

8

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Несколько ньансов мне не понятно.
Во первых по данным.
Однозначно стаканы не открыты.
В основную сессию у меня стоят заявки в основном на покупку как максимум по 400 инструментам.
Я эксперементировал с фукнцией OnOrder так как срабатывание  OnTradе редко бывает.
То есть,  просто ставил руками лимитные заявки по произвольным инструментам при запущенном скрипте.
единственное, все инстументы, по которым ставил заявки , добавлены в три разные таблицы текущих торгов (название таблицы у брокера ВТБ).
По поводу стаканов -я это заметил, когда стакан открыт, подписываться не надо, то есть с открытым стаканом прямо в OnOrder сразу приходят данные при вызове getQuoteLevel2, без  предварительного Subscribe_Level_II_Quotes.
И наоброт, как я ранее и писал, если стакан не открыт, после первого срабатывания в OnOrders данные не идут , хоть   подписывайся, хоть не подписывайся.
Ну это я к тому написал, что я понимаю, в чем разница, когда стакан откыт, а когда нет.
По поводу таблиц текущих торгов. У меня там облигации, и акции СПБ.
В настройках потока котировок (сейчас еще раз посмотрел), у меня заказаны все параметры и все бумаги по облигациям, но при этом ни по одной бумаге и ни одного соответственно параметра по акциям СПБ (галочка вообще не стоит на этом разделе).
При этом getQuoteLevel2 ведет себя одинаково и с облигациями и с акциями СПБ.
Еще один ньюанс по получению данных.
На примере акций СПБ довольно странный момент. Может это с брокерм ВТБ как то связано.
У меня на странице, где открыта таблица текущих торгов, еще открыто окно с графиком , и я связал таблицу и график цепочкой и якорем, чтобы визуально быстро видеть движение , кликая по инструментам.
Вот это работает без каких либо задержек (визуально).
Кликаешь на инструмент, и сразу отбражается в реальном времени меняющийся  график, даже если совсем маленький таймферйм.
При этом, в брокере ВТБ  я сижу где то полтора года, а до этого я торговал в Альфе, через терминал альфадирект 4.
У них там примерно такая же система, окно и график, и похожий принцип якоря и цепочки.
Вот только после выбора инструмента может пройти от 30 секунд до нескольких минут, пока график реальный появится. Подход к получению данных по разному видимо организован.
То есть, получается, что в ВТБ данные как бы уже есть, может быть у брокера на сервере, и приходят в терминал, как только кликаешь на инструмент,  в скрипте аналогом клика является OnOrder
ну это просто мои предположения в порядке бреда.

По поводу Вашей схемы, ну получается , что Вы предлагаете заранее собирать даные в таблицы скрипта по куче инструментов. Если я правильно понимаю, это же в оперативной памяти будет храниться, а у меня с запущенным квиком и другими прогами и так обычно занято 85 процентов из имеющихся 2ГБ, сервер слабенький.
почему я и пытаюсь придумать таких схемы, чтобы минимизировать использование железа.
У меня и  так квик иногда зависает (пару раз в месяц), когда одновременно запустишь несколько прог и плюс в браузере какую нибудь не правильную страницу запустишь.
и в Альфадиректе с ихним конструктором робота я эксперементировал, у них невозможно в одном скрипте отслеживать много инструментов, приходилось пок аждому отдельный скрипт запускать, и при запуске более 20 альфадирект начинал безбожно тормозить и отваливался от серверов брокера.
Просто не уверен, что это будет быстро работать, если заранее на все подписаться, и складывать изменения стаканов в талблицу




toxa пишет:

ваш вариант - ужасен.

9

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Вот в таком варинате я пробовал.
Сразу не заработало, и с учетом обшибки,  я попробовал сначала открыть стакан, а потом еще раз запустить,
и попробовал перед calc() добавить строку subsc=Subscribe_Level_II_Quotes ("SPBFUT", "RIH0")
в обоих случаях не сработало с той же ошибкой

is_run = true

function main()
    while is_run do
        sleep(50)
    end;
end

function OnStop()
    is_run = false
end

function GetAsk(ql2, ac)
    if not ql2 then return {price = 0, quantity = 0} end
    local ask_count = ql2.offer_count
    if ac > ask_count then ac = ask_count end
    if ask_count == 0 then
        return {price = 0, quantity = 0}
    else
        local ask = ql2.offer
        if not ask then return {price = 0, quantity = 0} end
        return ask[ac] or {price = 0, quantity = 0}
    end
end

function calc()
  local QL2 = getQuoteLevel2Ex("SPBFUT", "RIH0")
--получить 5-ю строку бида
  local bid = ql2.GetAsk(QL2, 5).price
  if bid == 0 then return end
  -- если цена есть, значит считаем дальше
end

function OnOrder (trade_data)

    calc()

end

10 (2020-03-07 14:23:47 отредактировано toxa)

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

В квике есть ограничение на количество заказанных стаканов. Вы не можете заказать и получать 500 стаканов. Если вы реально торгуете 500 инструментами, то это проблема, требующая специального подхода к своему решению.
500 стаканов в памяти - это не так уж и много. Вопрос лишь в скорости доступа. В lua быстрый доступ по ключу:
all_orderbooks={«tqbrsber”=<table sber>, “eqobru100500”=<table ru100500>}
И далее ordbook=all_orderbooks[class..code]

11 (2020-03-07 22:21:57 отредактировано kalikazandr)

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

dkostiunin пишет:

Вот в таком варинате я пробовал.

Конечно у вас не сработает, стакан должен быть открыт заранее или заказан функцией Subscribe_Level_II_Quotes ("SPBFUT", "RIH0")
В OnOrder, если по инструменту бот не видел событий, то и Subscribe_Level_II_Quotes вы не вызывали. На заказ стакана нужно время, а OnOrder уже закончил расчет.

function main()
    --заказываю стаканы заранее
    slist = {"RIH0", "BRJ0", "SiH0"} 
    for i=1,slist do
      Subscribe_Level_II_Quotes ("SPBFUT", slist[i])
    end
    while is_run do
        sleep(50)
    end;
end

function calc(market, ticker)
  local QL2 = getQuoteLevel2Ex(market, ticker)
--получить 5-ю строку бида
  local bid = ql2.GetAsk(QL2, 5).price
  if bid == 0 then return end
  -- если цена есть, значит считаем дальше
  message(market.." "..ticker.." bid= "..bid,2)
end

function OnOrder (trade_data)

    calc(trade_data.class_code, trade_data.sec_code)

end

12

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

ps: Если подходить к вопросу 500 стаканов "просто", то можно вести список инструментов, на которые осуществляется подписка. Дальше, при приходе OnOrder()/OnTrade() проверяем, есть ли подписка, если она есть, то берем подготовленный стакан и ставим заявку. Если подписки на этот инструмент нет, то подписываемся (предварительно от чего-то отписавшись, если подписок уже больше критического количества) и заявку ставим из колбэка OnQuote() в момент прихода заказанного стакана.
Таким образом, некоторые заявки будут ставиться быстро, некоторые - с лагом на запрос стакана с сервера квика. Если есть "часто торгуемые" и "редко торгуемые" инструменты, то можно сделать что-то вроде кэша со счетчиком срабатываний, чтобы понизить вероятность заказа.
Еще кэшем можно управлять следя за ценами своих активных заявок и заказывая стаканы, когда биды и аски получаемые в колбэке OnParam приближаются к ценам своих заявок.

13

Re: Должна ли быть задержка после вызова функции Subscribe_Level_II_Quotes

Ребята, огромное спасибо вам, очень выручаете, экономите массу времени на изучение ньюансов этого языка