Получение данных из таблиц QUIK в QLua(Lua)

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

QUIK-Qlua-poluchenie-dannyh Для получения данных из таблиц терминала QUIK удобно пользоваться 3-мя функциями: getItem(), getNumberOf() и getParamEx().

Пример:

-- Перебирает строки таблицы "Позиции по клиентским счетам (фьючерсы)", ищет Текущие чистые позиции по инструменту "RIH5"
for i = 0,getNumberOf("FUTURES_CLIENT_HOLDING") - 1 do
   -- ЕСЛИ строка по нужному инструменту И чистая позиция не равна нулю ТО
   if getItem("FUTURES_CLIENT_HOLDING",i).sec_code == "RIH5" and getItem("FUTURES_CLIENT_HOLDING",i).totalnet ~= 0 then
      -- ЕСЛИ текущая чистая позиция > 0, ТО открыта длинная позиция (BUY)
      if getItem("FUTURES_CLIENT_HOLDING",i).totalnet > 0 then 
         IsBuy = true;
         BuyVol = getItem("FUTURES_CLIENT_HOLDING",i).totalnet;	-- Количество лотов в позиции BUY				
      else   -- ИНАЧЕ открыта короткая позиция (SELL)
         IsSell = true;
         SellVol = math.abs(getItem("FUTURES_CLIENT_HOLDING",i).totalnet); -- Количество лотов в позиции SELL
      end;
   end;
end;

Далее перечислены таблицы, их идентификаторы и поля, к которым можно обращаться:

Фирмы:
Классы:
Инструменты:
Торговые счета:
Коды клиентов:
Обезличенные сделки (Таблица всех сделок):
Денежные позиции:
Заявки:
Позиции по клиентским счетам (фьючерсы):
Лимиты по фьючерсам:
Лимиты по денежным средствам:
Лимиты по бумагам:
Сделки:
Стоп-заявки:
Заявки на внебиржевые сделки:
Сделки для исполнения:
Отчеты по сделкам для исполнения:
Текущие позиции по бумагам:
Текущие позиции по клиентским счетам:
Обязательства и требования по деньгам:
Обязательства и требования по активам:
Для получения значений всех параметров биржевой информации из таблицы "Текущие торги" существует специальная функция
getParamEx (STRING class_code, STRING sec_code, STRING param_name),
которая принимает 3 параметра:
   - Код класса
   - Код инструмента
   - Имя параметра из таблицы "Текущие торги".

Функция возвращает таблицу Lua со следующими полями:
   param_type    STRING Тип данных параметра, используемый в таблице "Текущие торги". Возможные значения: 
      «1» - DOUBLE ,
      «2» - LONG, 
      «3» - CHAR, 
      «4» - перечислимый тип, 
      «5» - время, 
      «6» - дата 
 
   param_value   STRING Значение параметра. Для param_type = 3 значение параметра равно «0», в остальных случаях – числовое представление. Для перечислимых типов значение равно порядковому значению перечисления  

   param_image   STRING Строковое значение параметра, аналогичное его представлению в таблице. В строковом представлении учитываются разделители разрядов, разделители целой и дробной части. Для перечислимых типов выводятся соответствующие им строковые значения

Пример использования:

Status =  tonumber(getParamEx("SPBFUT",  "RIM5", "STATUS").param_value);
-- Выводит сообщение о текущем состоянии
if Status == 1 then message("RIM5 торгуется"); else message("RIM5 не торгуется"); end;
Список возможных идентификаторов параметров, передаваемых в функцию getParamEx()

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

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

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

  1. Добрый день. Если вдруг кому не трудно, запустите пожалуйста сие творение и объясните доступным языком чего он от меня хочет...
    ошибку пишет "attempt to index global 'c' (a nil value)". вот код:
    local is_run = true
    local delta = ""

    function OnAllTrade(alltrade)

    local a = getNumberOf("all_trades")
    if a == 0 then
    delta = 0
    else
    for i = a, a-1 do
    local c = getItem ("all_trades", i)
    end
    if c.sec_code == "RIZ9" and c ~= 0 then
    delta = delta + c.qty
    end
    message (delta)
    end
    end
    function main()
    while is_run
    do
    sleep(1)
    end
    end

    function OnStop()
    is_run = false
    return 1000
    end

    1. Код не запускал, но насторожил вот этот момент

      1
      2
      3
      
      for i = a, a-1 do
          local c = getItem ("all_trades", i)
      end

      Во первых цикл. во время инициализации цикла, переменной i присваиваете некое значение a, которое не может равняться 0. Предположим что в Таблице Обезличенных Сделок всего 1 сделка. В этом случае переменная a = 1, значит переменная i = 1, а цикл продолжается до a-1, то есть до 0. Так как не указан step в цикле, значит счет идет на прирастание, следовательно цикл не выполнит не одной итерации.
      Тоже самое будет, если в Таблице Обезличенных Сделок 100 000 сделок. Переменная a = 100 000, значит i = 100 000, а цикл запускаете до a-1, то есть до 99 999, цикл не выполнит ни одной итерации.
      Второй момент. Внутри цикла объявлена локальна переменная с, значит она не видна за пределами цикла, по этому обращение к переменой с в строке "if c.sec_code == "RIZ9" and c ~= 0 then" приводит к тому что переменная с не имеет значения, то есть nil, о чем и сообщает ошибка. Хотя в ошибке даже сказано что программа пытается найти глобальную переменную с, но ее нету вообще ни где, по крайней мере в этом куске кода.
      Как поправить код. Тут одним исправлением не отделаться.
      1. Исправить локальную переменную с на глобальную, можно, но это ни даст результата, так как цикл все равно не выполняет ни одной итерации, то функция getItem не вызывается ни разу, значит даже если переменная с станет глобальной и ее будет видно, то в нее все равно ничего нет, она nil
      2. Исправить цикл. Запускать я так понимаю нужно с первой сделки до последней, значит i=0, а не a=1, на счет окончания цикла верно a-1, потому что сделки номеруются с 0. Но и это исправление не приведет к нужному результату. Дело в том что Вы запускаете цикл по всем сделкам, внутри цикла запрашиваете каждую сделку и помешаете ее в переменную c. когда все сделки запросили, начинаете работать со сделкой, повторю со сделкой. Возникает вопрос, какая сделка из 100 000 будет лежать в переменной c когда код придет в строку "if c.sec_code == "RIZ9" and c ~= 0 then" ? Там будет последняя сделка. Я не думаю что Вам нужно именно это.
      3. Дальше догадки. Скорее всего Вы хотите перебрать все сделки, найти там сделки по бумаге RIZ9 и просуммировать объемы. Конечно не понятно почему переменная называется delta, судя по коду в ней будет лежать сумма всех объемов, ну да ладно. Что бы так сделать, нужно код

      if c.sec_code == "RIZ9" and c ~= 0 then
         delta = delta + c.qty
      end
      {/LUA}
      положить внутрь цикла, а вот "message (delta)" за пределами цикла, иначе получите 100 000 сообщений, а то и больше.
      Но и в строке "if c.sec_code == "RIZ9" and c ~= 0 then" имеется непонятный момент "c ~= 0" вообще то переменная с это таблица, зачем ее сравнивать с 0 не ясно. Если переживаете что с может оказаться nil и код упадет, тогда во первых проверяйте переменную на nil, а не на 0, то есть так c ~= nil, а во вторых поставьте это сравнение вперед, перед c.sec_code == "RIZ9". Иначе получается что если вдруг переменная с окажется nil? то сначала из нее нужно получить значение поля таблицы sec_code, а так как с = nil, то это приведет к ошибке и код упадет, так и не добравшись до проверки переменной с на nil, а если переменная c является таблицей, то нет смысла потом проверять что она не nil, она точно не nil, раз код не упал.
      Ну и еще один момент. Вы код пишите внутри функции OnAllTrade, которую вызывает терминал при поступлении новой сделки. Вот и представьте. Пришла сделка, терминал вызвал функцию OnAllTrade а дальше Ваш код читает всю Таблицу Обезличенных Сделок, на чтение которое может потребоваться несколько секунд, например 5 секунд. То есть терминал вешается на 5 секунд. Спустя 5 секунд терминал отвисает, но сразу же приходит новая сделка и терминал снова вешается на 5 секунд. Получается что терминал повесится и никогда не отвиснет.
      Я расписал происходящее в коде, а дальше Вам решать как Вы будете решать все эти вопросы. Может конечно то то напишет Вам готовый код, но я так не делаю.
      1. 1) таблица FUTURES_CLIENT_HOLDING должна быть обязательно открыта, что бы все работало?
        2) И еще вопрос почему именно перебором ведь , если FUTURES_CLIENT_HOLDING - 1 выдаст объем позиции по последней сделки или, если единственная сделка, то выдаст объем по ней? То зачем в случае одной открытой позиции нужен именно цикл с перебором что бы узнать ее объем? Или я что то не так понимаю

  2. Привет, а как - CLASS_CODE Код класса - получить? Его же изначально уже надо знать для того что бы использовать - tonumber(getParamEx("SPBFUT", "RIM5", "STATUS").param_value)

    1. Здравствуйте, Константин.
      А Код класса чего получить? Что известно?
      Если Вы индикатор пишите, можете использовать функцию getDataSourceInfo она вернет код бумаги и код класса той бумаги, на которой установлен индикатор.
      А если Вы скрипт пишите, тогда не понятно какие данные имеются. Запустили скрипт и просите, дай код класса...
      Есть таблица classes Классы и с помощью getItem можете получить Код класса
      Есть таблица securities Инструменты в ней тоже есть код класса, так же через getItem можно получить
      Да и вообще код класса еще есть во многих таблицах, например:
      trade_accounts Торговые счета
      all_trades Обезличенные сделки
      и другие, почитайте Руководство.
      И еще есть функция getClassesList она возвращает строку типа PTEXP,USDRUB,PSOPT,PSFUT,SPBFUT,

      Думаю что нибудь из этого подберете.

  3. Здравствуйте.
    У меня по разным счетам по одному инструменту открыты и Buy и Sell.
    Подскажите, как вывести Текущие чистые позиции по инструменту SEC_CODE на счете ACCOUNT ?
    дописал условие по .trdaccid, но результат не изменился.
    получился такой код:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    	BuyVol = 0 
    	SellVol = 0 
    	-- Перебирает строки таблицы "Позиции по клиентским счетам (фьючерсы)", ищет Текущие чистые позиции по инструменту SEC_CODE
    	for i = 0,getNumberOf("FUTURES_CLIENT_HOLDING") - 1 do
    	   -- ЕСЛИ строка по нужному инструменту И чистая позиция не равна нулю ТО
    	   if getItem("FUTURES_CLIENT_HOLDING",i).sec_code == SEC_CODE and getItem("FUTURES_CLIENT_HOLDING",i).totalnet ~= 0 and getItem("FUTURES_CLIENT_HOLDING",i).trdaccid == ACCOUNT then
    		  -- ЕСЛИ текущая чистая позиция > 0, ТО открыта длинная позиция (BUY)
    		  if getItem("FUTURES_CLIENT_HOLDING",i).totalnet > 0 then 
    			 IsBuy = true;
    			 BuyVol = getItem("FUTURES_CLIENT_HOLDING",i).totalnet;	-- Количество лотов в позиции BUY				
    		  else   -- ИНАЧЕ открыта короткая позиция (SELL)
    			 IsSell = true;
    			 SellVol = math.abs(getItem("FUTURES_CLIENT_HOLDING",i).totalnet); -- Количество лотов в позиции SELL
    		  end;
    	   end;
    	end;
     
    	message('BuyVol '..BuyVol..' Количество лотов в позиции BUY ')
    	message('SellVol '..SellVol..' Количество лотов в позиции SELL ')

    выводит сообщение:
    BuyVol 1 Количество лотов в позиции BUY
    SellVol 1 Количество лотов в позиции SELL
    Укажите, что подправить?
    Спс.

    1. С утра перезапустил терминал, и скрипт начал выводить актуальную информацию.
      Поправочка
      строка 8

      1
      
       if getItem("FUTURES_CLIENT_HOLDING",i).totalnet > 0 then

      А чтоб не изобретать велосипед, зайдите на страничку "Нужные функции" и посмотрите закладку -
      GetTotalnet() -- Получает текущую чистую позицию по инструменту
      Дмитрию спасибо.

  4. Добрый день! Наладил оправку уведомлений из квика с помощью луа по вашем советам и статьям. Осталось получить данные из окна сообщений.
    Думал это будет где то описано, и это будет не трудно сделать. Но по этим сообщениям вообще нет информации. Можно ли получить данные из окна сообщений квик? Те самые которые выскакивают...

      1. Кроме тех что есть в стандартных таблицах, позиция, сделки. Хотел еще получать информацию от бота помощника который следит за ценой. И выводит информацию в свою таблицу и в окно сообщений. Было бы хорошо, сообщение вышло. Уведомление ушло. Наверное можно информацию передать из одного луа бота в другой? Это наверное будет первый способ. Часть информации брать со стандартных таблиц часть передавать в бот для уведомлений. Или отправлять уведомления непосредственно из помощника.

  5. Здравствуйте.
    Есть интересный вопрос, а может даже странным показаться.
    Как можно узнать какой параметр принимает функция?
    Объясню как раз на примере функции getParamEx.
    Есть функция getParamEx в справочнике QLUA описано что принимает 3 параметра и третий параметр param_name в справочнике не описан, по крайней мере я не нашел. Известно что функция получает данные из таблицы текущих торгов, идем в эту таблицу и пробуем передать название столбца, но это не подходит. Других вариантов как узнать название параметра не знаю.
    Конечно на этом сайте описан список всех параметров, но предположим такой вариант что на сайте нет этого списка и в Интернете тоже нет нигде этого списка параметров, как в таком случае узнать что передать в функцию? Или вопрос такой. как Вы получили этот список что описан на этой странице выше?
    У меня есть один вариант, запустить перебор. Для ускорения взять только заглавные буквы латинского алфавита и смотреть что функция вернет.
    Но может есть какой то другой способ это узнать?

    1. Здравствуйте, QLua это потомок Qpile, языка, который до этого был основным в квике, данная функция и ряд других перекочевали оттуда, по этому их описание можете посмотреть в файле справки info.chm (находится в папке терминала), там я их и нашел.

      1. Все оказалось так просто.
        Совершенно не разбирался с QPILE, когда начал использовать Квик в нем уже был LUA, так что за него и взялся, а info.chm смотрел ранее, но очень бегло, а сейчас даже не подумал туда заглянуть.
        Спасибо большое за подсказку.

    2. Как вариант, заказать все параметры(заказ данных), в эксель скинуть по дде табл.текущие торги с формальными заголовками столбцов, либо файл справки info.chm раздел 8.

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

      1. Этот Параметр находится в Доске Опционов. Некоторые параметры из Доски опционов есть в getParamEx(), а Временную стоимость я не нашел - Это самый основной параметр, на основание которого, рассчитываются цены опционов.

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

  6. Это скриншот таблицы сделок в квике, а бот, который такие сделки делает на с++ fix/fast в ко-локации. Там 13 сделок за 1 секунду, эта самая меньшая по времени нахождения в позиции