Получение стакана из QUIK в QLua(Lua)

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 3, среднее: 5,00 из 5)
Загрузка...

QUIK-Qlua-poluchenie-dannyh
Для получения стакана в QLua(Lua) служит функция обратного вызова OnQuote(). Эта функция вызывается терминалом QUIK при получении изменения стакана котировок. Для получения данных самого стакана служит функция getQuoteLevel2().

В терминале должен быть открыт стакан по нужному инструменту!!!

 

Пример:

 

--- Функция вызывается терминалом QUIK при получении изменения стакана котировок
function OnQuote(class, sec )
   -- 
   if class == "SPBFUT" and sec == "RIM5" then
      ql2 = getQuoteLevel2(class, sec);
      -- Представляет снимок СТАКАНА в виде СТРОКИ
         QuoteStr = "";
         for i = tonumber(ql2.bid_count), 1, -1 do
            if ql2.bid[i].quantity ~= nil then   -- На некоторых ценах могут отсутствовать заявки
               QuoteStr = QuoteStr..tostring(tonumber(ql2.bid[i].quantity))..";"..tostring(tonumber(ql2.bid[i].price))..";";
            else
               QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.bid[i].price))..";";
            end;
         end;
         for i = 1, tonumber(ql2.offer_count), 1 do
            if ql2.offer[i].quantity ~= nil then   -- На некоторых ценах могут отсутствовать заявки
               if i < tonumber(ql2.offer_count) then 
                  QuoteStr = QuoteStr..tostring(tonumber(ql2.offer[i].quantity))..";"..tostring(tonumber(ql2.offer[i].price))..";";
               else 
                  QuoteStr = QuoteStr..tostring(tonumber(ql2.offer[i].quantity))..";"..tostring(tonumber(ql2.offer[i].price));
               end;
            else 
               if i < tonumber(ql2.offer_count) then
                  QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.offer[i].price))..";";
               else
                  QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.offer[i].price));
               end;
            end;
         end;
   end;
end;
 
-- В результате при каждом обновлении стакана по инструменту RTS-6.15 в переменной QuoteStr будет строка, типа:
   -- "15;86130;17;86120;16;86110;22;86100;16;86090;24;86080;26;86070;29;86060;97;86050;51;86040;99;86030;88;86020;143;86010;140;86000;15;85990;49;85980;58;85970;28;85960;49;85950;36;85940;71;85930;115;85920;95;85910;25;85900;5;85890;13;85880;62;85870;3;85860;36;85850;26;85840;11;85830;9;85820;99;85810;86;85800;41;85790;24;85780;2;85770;36;85760;162;85750;22;85740;44;85730;76;85720;229;85710;121;85700;5;85690;5;85680;2;85670;10;85660;148;85650;119;85640;12;86150;19;86160;26;86170;32;86180;71;86190;49;86200;26;86210;20;86220;91;86230;57;86240;47;86250;25;86260;34;86270;41;86280;21;86290;66;86300;36;86310;57;86320;50;86330;34;86340;38;86350;22;86360;17;86370;15;86380;18;86390;13;86400;3;86410;34;86420;29;86430;80;86440;26;86450;68;86460;226;86470;371;86480;30;86490;64;86500;99;86510;11;86520;2;86530;23;86540;9;86550;3;86560;52;86570;23;86580;25;86590;73;86600;17;86610;88;86620;52;86630;150;86640"
   -- Такую строку удобно, в последствии, передавать в C# и разделять на элементы
 
-- Функция getQuoteLevel2() принимает 2 параметра: Код класса и Код бумаги, а возвращает таблицу, которая имеет следующие поля:
bid_count    -- Количество котировок покупки (STRING)
offer_count  -- Количество котировок продажи (STRING)
bid          -- Котировки спроса (покупки) (TABLE)
offer        -- Котировки предложений (продажи) (TABLE)
   -- Таблицы «bid» и «offer» имеют следующую структуру: 
      price     -- Цена покупки / продажи (STRING)
      quantity  -- Количество в лотах (STRING)

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!

Добавить комментарий

Получение стакана из QUIK в QLua(Lua): 90 комментариев

  1. Здравствуйте, у меня вопрос-должен ли стакан быть открыт чтобы луа мог прочитать стакан?
    У меня почемуто при закрытом стакане не работает.

          1. Еще раз спасибо! Думаю организовать маленький проверочный цикл-мол если стакан он прочитать не может то заказываем и снова по кругу пока не прочитает.

  2. Привет. Сделал проверку на nil таким образом, результат - все равно вырубается робот

    1
    2
    3
    4
    5
    
          C_Glass = getQuoteLevel2("SPBOPT", Call) -- Стакан
          if C_Glass ~= nil then -- 2я цена в стакане
             if C_Glass.bid[tonumber(C_Glass.bid_count)-1].price ~= nil then C_Bid_2 = tonumber(C_Glass.bid[tonumber(C_Glass.bid_count)-1].price) else C_Bid_2 = 0 end
          else C_Bid_2 = 0
          end
      1. да, в 3 стр. пишет ошибка, это возникает после клиринга вечернего - точно - дневной не помню и сегодня с утра терминал запустил как обычно (робот был включен), после обновления данных - отключился

          1. а понял, значит надо все эти строки на нил проверять? я то думал

            1
            2
            
                  C_Glass = getQuoteLevel2("SPBOPT", Call) -- Стакан
                  if C_Glass ~= nil then -- 2я цена в стакане

            этого достаточно

  3. Добрый день!
    Не получается считать данные из стакана, код следующий:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
     IsRun = true
    time = os.clock()
    class ="SPBFUT"
    sec = "SiH7"
    --[[ function OnParam(class, sec)
       if (class =="SPBFUT" and  sec == "SRH7") then
          tbid = tonumber(getParamEx(class, sec, "bid").param_value)
          tbidvol = tonumber(getParamEx(class, sec, "BIDDEPTH").param_value)
          if tbidvol ~= 0 then
             message(string.format('Цена покупки в таблице %d , объем %0.0f ,Время %0.3f сек',tbid,tbidvol, os.clock()-time), 1)
          else message(string.format("Нет покупки в таблице, время %0.3f сек",os.clock()-time),1)
          end
       end
     end   ]]
     function OnQuote(class, sec )
       if (class =="SPBFUT" and  sec == "SiH7") then
          ql2 = getQuoteLevel2(class, sec)
          if ql2 ~= nil then
             gbid = tonumber(ql2.bid[ql2.bid_count].price)
             gbidvol = tonumber(ql2.bid[ql2.bid_count].quantity)
             message(string.format('Цена покупки в стакане %d , объем %0.0f, Время %0.3f сек',gbid,gbidvol, os.clock()-time), 1)
          else message(string.format("Нет покупки в стакане, время %0.3f сек",os.clock()-time),1)
          end
       end
     end
     
    function main()
       while IsRun do
          sleep(10) -- Пауза 10 мс, чтобы не грузить сильно процессор
       end
    end
     
    function OnStop()
       IsRun = false
    end

    Все время идет по варианту ql2 == nil, т.е. выдает сообщение :"Нет покупки в стакане...", стакан открыт и данные в нем меняются. Если убрать сравнение с nil - выскакивает ошибка.
    При этом из "Текущей таблицы параметров" все считывается прекрасно - закомментированная часть кода.

    1. Вот так попробуйте:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
       function OnQuote(_class, _sec )
         if (_class =="SPBFUT" and  _sec == "SiH7") then
            ql2 = getQuoteLevel2(_class, _sec)
            if ql2 ~= nil then
               gbid = tonumber(ql2.bid[ql2.bid_count].price)
               gbidvol = tonumber(ql2.bid[ql2.bid_count].quantity)
               message(string.format('Цена покупки в стакане %d , объем %0.0f, Время %0.3f сек',gbid,gbidvol, os.clock()-time), 1)
            else message(string.format("Нет покупки в стакане, время %0.3f сек",os.clock()-time),1)
            end
         end
       end

      У Вас здесь, скорее всего, конфликт в названии переменных. В OnParam Вы, кстати, другой инструмент смотрите.

      1. Поменял, теперь выскакивает ошибка: Test3.lua:19: attempt to index field '?' (a nil value).
        Этого я совсем не понимаю:(, ведь я ее с nil и сравниваю.
        Подскажите, что принципиально меняет символ подчеркивания: "_class" вместо "class"? Я думал, это просто разные названия переменных, но по-видимому я ошибаюсь?
        Какой конфликт в названии переменных Вы имеете ввиду? Если: class ="SPBFUT"
        sec = "SiH7", то это ничего не меняет, я могу их просто закомментировать.
        В OnParam (да и в OnQuote) я смотрел разные инструменты, в том числе и этот, но в 1-м случае читаются все переменные, во вторм ни один:(.

        1. Подчеркивание просто другое имя дает, т.к. у Вас в начале скрипта объявлены переменные с такими же именами, что Вы в функции OnQuote использовали:
          строки 3,4
          class ="SPBFUT"
          sec = "SiH7"

          можете вместо символа подчеркивания любую букву использовать, или удалить строки 3,4 просто

          По поводу ошибки, то Вы проверяете только ql2 на nil, а он не nil, но, возможно, nil'ом является bid, или bid_count, или price.
          Ведь в этой статье есть пример, воспользуйтесь им и подкорректируйте под себя.

        2. Теперь вообще началась мистика!
          Вернул все к первозданному виду, но вместо сообщения :"Нет покупки в стакане...", идет ошибка: "Test3.lua:19: attempt to index field '?' (a nil value)."
          Как такое возможно??? Квик перегружал - не помогает.
          Решил, что где-то ошибся при восстановлении текста - просто скопировал свое первое сообщение отсюда и запустил - снова та же ошибка???

          1. строки 3,4
            class ="SPBFUT"
            sec = "SiH7"
            я просто закомментировал - результат тот-же.
            Естественно ql2 не nil, так как стакан полон, и так же естественно, что bid, или bid_count, или price тоже не nil, по той же самой причине. Но почему тогда ошибка: Test3.lua:19: attempt to index field '?' (a nil value).

            1. Если бы они были все не nil, то не было бы ошибки, Вы не гадайте, а выведите каждый из этих параметров в message, только оберните в tostring, потому что иначе nil не выведется. А конфликта переменных значит не было.

              1. разобрался, строка должна выглядеть так:
                "gbid = tonumber(ql2.bid[tonumber(ql2.bid_count)].price)"
                а то я уже решил, что у меня глюки начались:).
                Правда остается непонятным, почему первоначальный код работал по варианту ql2 == nil, ведь стаканы не были пустыми?
                И, кстати, вопрос: если первоначально определять переменные class и sec, то function OnQuote(class, sec ) будет срабатывать только в случае указанного стакана или при изменении любого стакана открытого в Квике?

        1. по идее, это значение в текущей таблице параметров должно отображаться, но у меня, почему-то, не отображается, значит только в цикле перебирать стакан и считать сумму лотов во всех заявках на покупку, или на продажу

          1. А из стакана почему напрямую нельзя?Нужен объем по стакану(индикатор нарастающего объема).ТТП тут не поможет,она ведь весь стакан не отображает.Получается из стакана только два параметра можно вызвать Цена и Количество?

            1. Уточню,может я плохо сформулировала вопрос,есть два параметра в стакане
              price -- Цена покупки / продажи (STRING)
              quantity -- Количество в лотах (STRING)

              Как называется колонка Сумма лучших(STRING)?Этот параметр отображается в стакане при добавлении Параметра вручную.

            2. цена и количество, но их можно взять по каждой цене, которая есть в стакане, если посчитать сумму всех количеств в заявках на покупку, находящихся в данный момент в стакане, то получится то, что Вам нужно.
              bid и offer это массивы, каждый элемент которых имеет поля price и quantity, вверху же есть пример