Получение обезличенных сделок из QUIK в QLua(Lua)

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

QUIK-Qlua-poluchenie-dannyh   Для получения обезличенных сделок в QLua(Lua) служит функция обратного вызова OnAllTrade(). Эта функция вызывается терминалом QUIK каждый раз при получении новой обезличенной сделки по инструменту, на который есть подписка. Чтобы сделать подписку на нужные инструменты, необходимо пройти: "Связь" -> "Заказ всех сделок...". В окне "Выбор инструментов для заказа всех сделок" выбрать нужные инструменты и нажать кнопку "Сохранить". Так же,  в терминале должно быть открыто окно "Таблицы" -> "Таблица всех сделок", в котором должно быть настроено отображение нужных инструментов (правой кнопкой мыши в окне -> "Редактировать таблицу").

 

Пример:

-- При вызове в функцию передается новая строка таблицы, которая имеет следующие поля:
trade_num   -- Номер сделки в торговой системе (NUMBER)
flags       -- Набор битовых флагов  (NUMBER)  
price       -- Цена  (NUMBER)  
qty         -- Количество бумаг в последней сделке в лотах  (NUMBER)  
value       -- Объем в денежных средствах  (NUMBER)  
accruedint  -- Накопленный купонный доход (NUMBER)   
yield       -- Доходность  (NUMBER)  
settlecode  -- Код расчетов  (STRING)  
reporate    -- Ставка РЕПО (%)  (NUMBER)  
repovalue   -- Сумма РЕПО  (NUMBER)  
repo2value  -- Объем выкупа РЕПО  (NUMBER)  
repoterm    -- Срок РЕПО в днях  (NUMBER)  
sec_code    -- Код бумаги заявки  (STRING)  
class_code  -- Код класса  (STRING)  
datetime    -- Дата и время  (TABLE)  
period      -- Период торговой сессии (NUMBER)   
   -- Возможные значения: 
      "0" -- Открытие 
      "1" -- Нормальный 
      "2" -- Закрытие 
 
--- Функция вызывается терминалом QUIK при получении обезличенной сделки
function OnAllTrade(alltrade)
   -- Если сделка по инструменту RTS-6.15(RIM5), то
   if alltrade.sec_code == "RIM5" then
      -- создает строку информации о сделке			
      DealStr = tostring(alltrade.trade_num)
              ..";"
	      ..tostring(alltrade.datetime.year)
	      .."-"
	      ..tostring(alltrade.datetime.month)
	      .."-"
	      ..tostring(alltrade.datetime.day)
	      .." "
	      ..tostring(alltrade.datetime.hour)
	      ..":"
	      ..tostring(alltrade.datetime.min)
	      ..":"
	      ..tostring(alltrade.datetime.sec)
	      .."."
	      ..tostring(alltrade.datetime.mcs)
	      ..";"
	      ..tostring(alltrade.price)
	      ..";"
	      ..tostring(alltrade.qty)
	      ..";"
	      ..tostring(alltrade.flags); -- "1" - ПРОДАЖА, "2" - КУПЛЯ
   end;
end;
-- В результате, при каждой новой сделке по RTS-6.15 в переменной DealStr будет строка, следующего вида:
   -- "1074452502;2015-3-24 16:19:55.710000;85940;1;2"
   -- Такую строку удобно, в последствии, передавать в C# и разделять на элементы

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

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

Получение обезличенных сделок из QUIK в QLua(Lua): 156 комментариев

  1. Хэлп ! хочу написать индикатор по обезличенным сделкам, в виде гистограмм. В общем что не могу разобраться с вашей функцией, все время выдает ошибку "C:\BCS_Work\QUIK_BCS\LuaIndicators\Vi3.lua:14: attempt to index global 'alltrade' (a nil value)" типа в переменной ничего нет. Как решить данную проблему ?

    1. Здравствуйте, функция OnAllTrade является одной из функций обратного вызова, которые работают в роботах, но не работают в индикаторах. Для того чтобы в индикаторе получать обезличенные сделки, нужно обращаться к таблице обезличенных сделок. О том как работать с таблицами можете посмотреть здесь: https://quikluacsharp.ru/quik-qlua/poluchenie-dannyh-iz-tablits-quik-v-qlua-lua/

  2. Подскажите, люди добрые, начинающему товарищу.
    Возможно ли считать с сервера не текущие обезличенные сделки, а исторические, те что были неделю или месяц назад.

    1. Нет, можно получить только сделки с 19:00 прошлого дня и до текущего момента. Остальные сделки нужно собирать и сохранять в файл самостоятельно в процессе торговли.

        1. Из Таблицы Обезличенных Сделок.

          1
          
          local trade = getItem("all_trades", index);

          Где index - номер строки в Таблице Обезличенных Сделок
          Перебирая строки сверяете время сделки, если время сделки 19:00. значит такая сделка Вам подходит. Будут обработаны сделки у которых время 19:00, остальные пропущены.
          Ну а дальше задача не описана.

          1. Таблица Обезличенных Сделок одна.
            Если Вы в терминале создадите к примеру 2 Таблицы Обезличенных Сделок, в первой будет бумага SBRF, а во второй GAZR, то при обращении по "all_trades" получите сделки и SBRF и GAZR.

  3. Я пробовал писать message, но он мне ошибку писал) судя по всему я не там message писал)) у меня был после обоих end... попробую, спасибо большое за помощь)

  4. доброго времени суток. нужна помощь. прямо очень нужна. видимо я один настолько туп, что вот нихрена не понимаю я в программировании сколько бы ни бился. вот вторую неделю смотрю на скрипт который якобы -"В результате, при каждой новой сделке по RTS-6.15 в переменной DealStr будет строка, следующего вида:
    -- "1074452502;2015-3-24 16:19:55.710000;85940;1;2""
    так вот, запускаю данный скрипт ииии...... я не вижу ровно никакой строки ни в каком формате....
    что еще то дописать туда надо чтоб это в таблицу превратилось?????????
    умоляю помогите...

      1. IsRan=true
        function main()
        while IsRan do
        sleep(1)
        end
        end
        function OnStop()
        IsRun = false;
        end
        function OnAllTrade(all_trade)
        if alltrade.sec_code == "RIZ8" then
        -- создает строку информации о сделке
        DealStr = tostring(alltrade.trade_num)
        ..";"
        ..tostring(all_trade.datetime.year)
        .."-"
        ..tostring(all_trade.datetime.month)
        .."-"
        ..tostring(all_trade.datetime.day)
        .." "
        ..tostring(all_trade.datetime.hour)
        ..":"
        ..tostring(all_trade.datetime.min)
        ..":"
        ..tostring(all_trade.datetime.sec)
        .."."
        ..tostring(all_trade.datetime.mcs)
        ..";"
        ..tostring(all_trade.price)
        ..";"
        ..tostring(all_trade.qty)
        ..";"
        ..tostring(all_trade.flags); -- "1" - ПРОДАЖА, "2" - КУПЛЯ
        end
        end

        1. А Вы строку пробовали как-то эту выводить? Попробуйте вот так:

          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
          36
          37
          38
          39
          
          IsRun = true
           
          function main()
             while IsRun do
                sleep(1)
             end
          end
           
          function OnStop()
             IsRun = false
          end
           
          function OnAllTrade(all_trade)
             if alltrade.sec_code == "RIZ8" then
                -- создает строку информации о сделке
                DealStr = tostring(alltrade.trade_num)
                ..";"
                ..tostring(all_trade.datetime.year)
                .."-"
                ..tostring(all_trade.datetime.month)
                .."-"
                ..tostring(all_trade.datetime.day)
                .." "
                ..tostring(all_trade.datetime.hour)
                ..":"
                ..tostring(all_trade.datetime.min)
                ..":"
                ..tostring(all_trade.datetime.sec)
                .."."
                ..tostring(all_trade.datetime.mcs)
                ..";"
                ..tostring(all_trade.price)
                ..";"
                ..tostring(all_trade.qty)
                ..";"
                ..tostring(all_trade.flags) -- "1" - ПРОДАЖА, "2" - КУПЛЯ
                message(DealStr)
             end
          end

          И убедитесь в том что у Вас в терминал поступают сделки по нужному инструменту.

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

    1
    
     OnAllTrade

    , может ли она пропустить сделку при очень волатильном моменте? Например 1-у сделку функция обработала, и резка появились много сделок, 2, 3, 4, 5, и пока она обрабатывала 2-ю, появились 3-5 сделки, так вот, она потом начнет с 5? Или квик ведет некий кеш, где хранит обработанные номера сделок, и обработает все по порядку? Или лучше самому завести некий счетчик и обрабатывать все сделки в цикле например в

    1
    
    repeat/ until

    Заранее спасибо)

      1. Например что-то типа этого :

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        
         
        count = 1
         
         function OnAllTrade(alltrade) 	
            if alltrade.period == 1 or alltrade.period == 0 then 	
        	    repeat     			
        		    trd = getItem("all_trades", count) 	
        		     if trd.sec_code == Settings.seccode then			  		
                                    if CheckBit(trade.flags, 1) then 
                                    else 						    
                                    end
                             end		
        		     count = count + 1		
                   until count == getNumberOf("all_trades")	
            end
        end
          1. Здравствуйте! В функциях обратного вызова нужно делать самый минимум, потому что они тормозят работу всего терминала, самый идеальный вариант внутри OnAllTrade добавлять сделку в какой-то массив и все, а сам массив уже обрабатывать внутри main, которая работает в отдельном потоке и терминал не тормозит.

            1. подскажите что я делаю не так. оформил коллбек функцию вот так
              [lua]
              function OnAllTrade(alltrade)

              table.insert(arrtotal,{{
              ticker=alltrade.sec_code,
              price=alltrade.price,
              operation=alltrade.flags,
              quanity=alltrade.qty
              }})

              end

              [/lua]

              и дальше хочу обращаться к элементам этого массива
              sleep сделал чтобы успели подгрузиться сделки и записаться в массив
              [lua]
              function main()
              sleep(3000)
              message(tostring(arrtotal[1]["ticker"]))
              end

              [/lua]

              на любое поле показывает nil. почему так происходит?

              1. А вы проверяли длину массива arrtotal?
                Может он пустой, потому что у вас не было вызвано событие OnAllTrade, т.к. у брокера не заказаны обезличенные сделки или еще чего.

                1. да, сейчас я проверил так

                  1
                  2
                  3
                  4
                  
                      function main()
                      sleep(3000)
                      message(tostring(#arrtotal).."  "..tostring(arrtotal[2]["ticker"]))
                      end

                  показывает определенную длину, но при обращении к самим элементам все равно nil

                  1. Сразу не заметил, вы лишние скобки фигурные поставили в table.insert, по этому доступ к параметрам будет таким:
                    arrtotal[2][1].ticker
                    т.е. в массив arrtotal вы добавляете массив из одного элемента, содержащий таблицу, которая содержит и тикер и прочее.

                    Настоятельно рекомендую пользоваться sinsert, т.к. тут вы используете разные потоки.
                    И по утверждению арки в колбэки попадают события, в которых все параметры не nil, если иное не определено в документации (например в трансрепли могут быть некоторые поля быть nil)

                    1. и специально выбирать параметры в колбеке нет нужды, овчинка выделки не стоит, делайте так:
                      table.sinsert(arrtotal, alltrade)

                    2. спасибо! действительно проблема была в лишних скобках
                      позвольте еще один вопрос. я перебираю таблицу всех сделок в цикле. в процессе перебора формирую массив вида [date][ticker][price]["1025"]=value разбитый
                      date в моем случае это даты разбитые по 10 секунд, т.е на каждой итерации проверяю не равно ли +10 секунд от определенного момента и если равно то прибавляю еще 10 секунд и так далее до конца.
                      В конце я циклами обхожу весь этот массив и записываю в базу данных результат также как он экспортировался бы из таблицы обезличенных сделок только по 10 секунд а не каждую сделку

                      так вот скрип вроде работает но даты в базе совершенно рандомно раскиданы. т.е я вижу сначала сделки в 23 часа потом в 10 часов потом в 14, затем в 13 и снова в 23 и так далее. Я понимаю что желательно скрипт приводить в такой ситуации но может подскажете что не так в логике самой.
                      Инструментов несколько (3 сделал сейчас) но вроде и при одном было тоже самое

                    3. У вас [date][ticker][price]["1025"]=value не массив.
                      Скрипт приводить не нужно, ваша цель мне понятна.
                      Такой формат хранения данных не удобен для последующей обработки. Нужно в скрипте создать каталоги если их еще нет, например:
                      local si_path = "C:\Claster\SiZ9\20191030\claster.log"
                      И открыть соответствующий файл:
                      local SAVE={}
                      SAVE["SiZ9"] = io.open(si_path, 'a+')
                      local function save(file, text)
                      file:write(text); file:flush()
                      end
                      В процессе расчетов скрипт формирует массив будущей строки в файле:
                      local TOLOG = {}
                      TOLOG["SiZ9"]= {posix, price, value}
                      где posix это дата и время в секундах, округленное до текущего таймфрейма.
                      В начале нового таймфрейма производите сохранение этого массива:
                      local str = tab_to_str(TOLOG["SiZ9"])..","--дописываем в конце запятую
                      tab_to_str преобразует таблицу в строку формата "{1572420770, 66000, 257000000}," https://quikluacsharp.ru/quik-qlua/sohranenie-parametrov-skripta-qlua-lua-mezhdu-zapuskami/
                      save(SAVE["SiZ9"], str)
                      TOLOG["SiZ9"]= {} --готов к новому таймфрейму
                      в итоге в файле получаем набор строк по возрастанию posix:
                      {1572420760, 66000, 257000000},
                      {1572420770, 66050, 154000000},
                      {1572420780, 66070, 63000000},
                      который при необходимости можно считать из файла сразу в массив при помощи этой функции:
                      function read(dir)
                      local f, err = io.open(dir, "r")
                      if not f then return nil, err end
                      local str = "{"..f:read("*a").."}"; f:close()
                      fn, err = loadstring("return "..str)
                      if type(fn) == "function" then
                      return fn()
                      end
                      return nil, err
                      end
                      local claster = read("C:\Claster\SiZ9\20191030\claster.log")
                      И в каталоге C:\Claster\SiZ9\20191030 необходимо сделать список дат date.log:
                      20191028, 20191029, 20191030 --суть ссылки на существующие файлы кластера

          2. Хотя, я вообще перебираю таблицу обезличенных сделок внутри main в цикле while, т.е. перебрали всю таблицу, запомнили индекс последней обработанной сделки, в следующий раз уже с этого индекса +1 обрабатываю и опять до конца, так ничего не пропустить, только нужно еще делать проверку, бывает что сделка в таблице появилась, но у нее еще не все поля заполнены, тогда в переменной сохраняем предыдущий индекс и в следующей итерации цикла возвращаемся снова к этой сделке.

    1. local item = getItem("all_trades", getNumberOf("all_trades")-11) --item будет 10 строкой таблицы обезличенных сделок с конца
      if item then ... end -- item может быть не только nil, но и пустой таблицей

        1. Что то зашел в тупик. По образцу в статье сделал так:
          IsRun=true
          function main()
          while IsRun do
          sleep (500);
          end
          end
          --- Функция вызывается терминалом QUIK при получении обезличенной сделки
          function OnAllTrade(alltrade)
          -- Если сделка по инструменту RTS-6.15(RIM5), то
          if alltrade.sec_code == "RIM8" then
          -- создает строку информации о сделке
          DealStr = tostring(alltrade.qty)
          message("bool"..DealStr)
          end;
          end;
          А вот как использовать Ваш пример кода не особо понимаю(

                1. Что то не выходит, то выводит какие то цифры и терминал виснет и вырубает, то ничего не происходит. Не могу понять структуру в целом. И пример не могу найти, где getItem используется в том варианте как мне нужно((

                  1. Не проверял, но, вроде бы, должно работать

                    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
                    
                    SEC_CODE = 'RIM8'
                     
                    RUN = true
                     
                    main = function()
                       local last_index = -1
                       while RUN do
                          -- Получает количество строк в таблице
                          local lines_count = getNumberOf('all_trades')
                          -- Перебирает строки до последнего индекса (lines_count - 1)
                          while lines_count - 1 > last_index do
                             -- Увеличивает счетчик обрабатываемых индексов
                             last_index = last_index + 1
                             -- Получает строку таблица под индексом last_index
                             local trade = getItem('all_trades', last_index)
                             -- Если сделка по нужному инструменту и количество в сделке больше 100
                             -- если выводить сообщение по каждой сделке, то терминал будет подвисать из-за большого количества сообщений
                             if trade.sec_code == SEC_CODE and trade.qty > 100 then
                                -- Выводит сообщение
                                message(trade.sec_code..':'..trade.qty)
                             end
                          end
                          sleep(10)
                       end
                    end
                     
                    OnStop = function()
                       RUN = false
                    end
                    1. Спасибо огромное, разобрался, переделал под себя)))) И такой вопрос - а подвисания терминала из-за расчетов в коде или из-за большого количества вывода сообщений?
                      Цитата " -- если выводить сообщение по каждой сделке, то терминал будет подвисать из-за большого количества сообщений
                      if trade.sec_code == SEC_CODE and trade.qty > 100 then"

  6. tostring(alltrade.flags); -- "1" - ПРОДАЖА, "2" - КУПЛЯ - не правда ваша, Дмитрий.
    Это битовые флаги и как правило так и есть, но не всегдааааа!!! (мне попадались совершенно другие числа).
    Для работы с битовыми флагами есть специальные функции, все знают какие)))

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

  7. Добрый день.
    Написал скрипт (по вашему примеру выше и скрипту BuySell из соседней ветки, вывожу сделки в таблицу), запускаю и у меня выводится только одна строка.
    Подскажите, счетчик внутри OnAllTrade() может менять глобальную переменную? И почему-то в OnAllTrade() функция message() тоже не срабатывает. Не пойму в чем дело. Терминал версии 7.5.

    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
    36
    37
    38
    39
    
    IsRun = true;
     
    function OnInit()
       valfiltr = 500000;
       k  = 0;
       dts = getTradeDate().day;
       message("скрипт запущен")
    end;
     
    function main()
       CreateTable(); ---стандартная
       while IsRun do
          sleep(1);
       end;
    end;
     
    function OnAllTrade(alltrade)
       if alltrade.value > valfiltr then            --tonumber(alltrade.value) > valfiltr then
          if alltrade.datetime.day == dts then
             if alltrade.class_code == "SPBFUT" then
                --message("скрипт запущен")
                SetCell(t_id, k, 0, tostring(k));
                SetCell(t_id, k, 1, tostring(alltrade.datetime.year) .. "-" .. tostring(alltrade.datetime.month) .. "-" ..tostring(alltrade.datetime.day));
                SetCell(t_id, k, 2, tostring(alltrade.datetime.hour) .. ":" .. tostring(alltrade.datetime.min));
                SetCell(t_id, k, 3, tostring(alltrade.price));
                SetCell(t_id, k, 4, tostring(alltrade.qty));
                SetCell(t_id, k, 5, alltrade.sec_code);   
                nu = nil 
                alltrade = nil
                k = k + 1
             end
          end
       end
    end;
     
    function OnStop()
       if t_id ~= nil then DestroyTable(t_id) end
       IsRun = false;
    end