Получение в QLua(Lua) данных из графиков и индикаторов

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

QUIK-Qlua-poluchenie-dannyhЧтобы получить доступ к графику(не индикатору) какого-либо инструмента нужно создать источник данных при помощи функции CreateDataSource().
ВАЖНО!!! Для получения новых данных, кроме тех, что уже есть в открытом графике на текущий момент (тем более, если он не открыт), требуется использовать одну из следующих функций: SetUpdateCallback(), или SetEmptyCallback(), о которых будет написано ниже.

Описание функции CreateDataSource()

Функция CreateDataSource возвращает таблицу QLua с параметрами, получать значения которых можно следующим образом:

local O = ds:O(i); -- Получить значение Open для указанной свечи (цена открытия свечи)
local H = ds:H(i); -- Получить значение High для указанной свечи (наибольшая цена свечи)
local L = ds:L(i); -- Получить значение Low для указанной свечи (наименьшая цена свечи)
local C = ds:C(i); -- Получить значение Close для указанной свечи (цена закрытия свечи)
local V = ds:V(i); -- Получить значение Volume для указанной свечи (объем сделок в свече)
local T = ds:T(i); -- Получить значение Time для указанной свечи (время открытия свечи (таблица datetime))
   -- Где i - индекс свечи (от 1 до ds:Size())
 
local Size = ds:Size(); -- Возвращает текущий размер (количество свечей в источнике данных) 
ds:Close(); -- Удаляет источник данных, отписывается от получения данных
 
ds:SetUpdateCallback(MyFuncName); -- Позволяет задать пользователю функцию обратного вызова для обработки изменившихся свечей, т.е. когда по выбранному в CreateDataSource параметру в терминал поступит новое значение (возможно такое же), автоматически будет вызвана данная функция, в которую будут передан индекс последней свечи графика, а так же добавятся новые данные в таблицу ds
-- Пример функции:
function MyFuncName(index)
   message('На '..index..'-й свече объем вырос до '..ds:V(index));
end;
 
-- Чтобы получать новые данные без использования функции обратного вызова, а просто получать новые данные в ds и брать их оттуда по необходимости существует функция:
ds:SetEmptyCallback(); -- Которая подписывается на получение новых данных

Списки возможных параметров, используемых в функции CreateDataSource():

Список для АКЦИЙ
Список для ВАЛЮТЫ
Список для ОПЦИОНОВ
Список для ФЬЮЧЕРСОВ

Так же, в QLua есть функции для получения данных как графиков, так и индикаторов по их уникальным идентификаторам(тэгам), для этого необходимо нужному графику(индикатору) назначить уникальный идентификатор, о том как это делается можете ознакомиться в самом начале "Инструкции по использованию" Индикатора "Мои Сделки". Идентификатор для индикатора добавляется аналогичным способом.

После этого, можно использовать следующие функции для доступа к данным:

-- Функция предназначена для получения КОЛИЧЕСТВА ЛИНИЙ в графике (индикаторе) по выбранному идентификатору
getLinesCount(tag); -- Возвращает число
   -- tag - (STRING) идентификатор графика (индикатора), о котором писалось выше
 
-- Функция предназначена для получения информации о КОЛИЧЕСТВЕ СВЕЧЕЙ по выбранному идентификатору
getNumCandles(tag); -- Возвращает число
   -- tag - (STRING) идентификатор графика (индикатора), о котором писалось выше
 
-- Функция предназначена для получения информации о свечах по идентификатору (заказ данных для построения графика функция не осуществляет, поэтому для успешного доступа нужный график должен быть открыт)
t, n, l = getCandlesByIndex (tag, line, first_candle, count);
   -- Параметры:
      -- tag          – (STRING) строковый идентификатор графика или индикатора 
      -- line         – (NUMBER) номер линии графика или индикатора. Первая линия имеет номер 0 
      -- first_candle – (NUMBER) индекс первой свечи. !!! ПЕРВАЯ (САМАЯ ЛЕВАЯ) СВЕЧКА ИМЕЕТ ИНДЕКС 0 !!!
      -- count        – (NUMBER) количество запрашиваемых свечей
   -- Возвращаемые значения:
      -- t – таблица, содержащая запрашиваемые свечи, пример работы: 
         local O = t[i].open; -- Получить значение Open для указанной свечи (цена открытия свечи)
         local H = t[i].high; -- Получить значение High для указанной свечи (наибольшая цена свечи)
         local L = t[i].low; -- Получить значение Low для указанной свечи (наименьшая цена свечи)
         local C = t[i].close; -- Получить значение Close для указанной свечи (цена закрытия свечи)
         local V = t[i].volume; -- Получить значение Volume для указанной свечи (объем сделок в свече)
         local T = t[i].datetime; -- Получить значение datetime для указанной свечи
            -- Где i - индекс свечи от 0 до n-1
      -- n – количество свечей в таблице t
      -- l – легенда (подпись) графика

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

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

Получение в QLua(Lua) данных из графиков и индикаторов: 327 комментариев

  1. Здравствуйте.

    С графиками и индикаторами понятно. Интересует возможность при помощи qlua или сторонних библиотек получить координаты точек линии тренда, построенной вручную. (не индикатора)

    Пробовал узнать их используя программу ArtMoney, однако, адреса ячеек памяти, в которые записаны координаты, меняются при перезапуске quik и на них нельзя полагаться. С winApi также не получается, потому что дальше окна графика Chart Window он не может смотреть.

    Есть какие-то идеи по поводу возможного решения, хотя бы в каком направлении двигаться?

      1. А вы не могли бы вспомнить, что она ещё делает, по какому принципу работает? У меня, на самом деле, идей нету, так как не понятен механизм получения данных из закрытого процесса quik.

    1. У меня так же нет вариантов влезть внутрь графика Квика, а хотелось бы, но если речь идет о "линии тренда", то есть немого другая идея.
      Получить доступ к линиям построенным вручную нет возможности, но линия тренда не такая сложная, ее можно создать на LUA, а управлять из терминала.
      Суть в следующем:
      Создать индикатор (именно индикатор, не скрипт).
      Для графика цены задать Идентификатор.
      Индикатор создает 2 метки в виде картинки, к примеру квадратик 3x3 пикселя, на графике цены используя Идентификатор. Эти метки пользователь может двигать мышью.
      Перемещая эти метки пользователь задает 2 точки, а индикатор, основываясь на координатах этих меток, рисует линию. Нужно лишь только опрашивать эти метки, что бы узнать, не изменились ли координаты.
      Опрашивать метки можно двумя способами:
      При поступлении новой сделки. Когда рынок активный и сделки поступают часто, линия будет реагировать на действия пользователя практически мгновенно, но если сделки поступают раз в несколько секунд, тогда после перемещения метки, линия изменится лишь только когда придет новая сделка.
      Другой вариант. Использовать DLL библиотеку, где создать функцию с бесконечным таймером с интервалом например 100мс. Запускаем индикатор, запускается таймер и вызывает функцию с интервалом 100 мс, а внутри этой функции происходит опрос координат меток. В этом случае линия будет реагировать на действия пользователя практически мгновенно независимо от сделок поступающих в терминал.
      Это все теоретически, на практике скорее всего нужно будет решить много задач, но думаю идея рабочая.
      Что касается остальных фигур, например прямоугольника, то тут уж ни как, линиями индикатора прямоугольник не построить.

  2. Дмитрий,здравствуйте. Функция SetUpdateCallback(MyFuncName) вызывается на каждый тик. Можно ли сделать так (через эту функцию или другую, но не запоминаем параметров свечи) чтобы вызов был именно после формирования ЦЕЛОЙ свечи выбранного таймфрейма?

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      
      local market = "SPBFUT"
      local ticker = "SiZ9"
      local tag = market.."_"..ticker.."_"..INTERVAL_M1
      local tag15 = market.."_"..ticker.."_"..INTERVAL_M15
      local DS = {}
      DS[tag] = CreateDataSource(market, ticker, INTERVAL_M1)
      local old_index = DS[tag]:Size()
      DS[tag15] = CreateDataSource(market, ticker, INTERVAL_M15)
      local old_index15 = DS[tag15]:Size()
       
      local function sourcecallback(interval, market, ticker, tag, index)
        if index > old_index then
          if interval == INTERVAL_M1 then
            message("new bar M1:\n C= "..DS[tag]:C(index),2)
          elseif interval == INTERVAL_M15 then
            message("new bar M15:\n C= "..DS[tag]:C(index),2)
          end
        end
      end
      DS[tag]:SetUpdateCallback(function(...) sourcecallback(INTERVAL_M1, market, ticker, tag, ...) end)
      DS[tag15]:SetUpdateCallback(function(...) sourcecallback(INTERVAL_M15, market, ticker, tag15, ...) end)
      1. Дмитрий, категорически приветствую!
        Есть куча не WordPress, у которых отлично построен и РАБОТАЕТ! форум, с редакцией и прочими плюшками и не каверкает символы.
        Всякое желание тут чего-то писать пропадает.

      2. после message нужно old_index и(не обозначил) old_index15 приравнять к текущему index. иначе квик захлебнется сообщениями (аркаводы - дебилы не могут отключить процесс, который начинает спамить message)

  3. Привет, Дмитрий.
    Подключаю график так -

    1
    
    DS = CreateDataSource("SPBFUT", Fut, TF)

    -- Получает доступ к свечам графика
    Отключаюсь так -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    function OnStop() -- Функция вызывается терминалом QUIK при остановке скрипта из диалога управления
       is_run = false
    	DS:Close() -- Прекращает доступ к свечам графика
       KillAll() -- Снять все заявки
       DestroyTable(t_id_Menu) -- Закрыть таблицу меню
       ToLog(3) -- Пишет лог-файл
       Log:close() -- Закрывает лог-файл
       SaveCurrentState()
    end

    При остановке робота - терминал подвисает. Что не так я сделал?

              1. 1
                2
                3
                4
                5
                6
                7
                8
                9
                
                function KillAll() -- Функция снимает все заявки
                   if Status == 1 then -- Торговля разрешена
                      for n = 1, 8, 1 do -- Перебираем инструменты
                         if OpCl[n] > 0 and Num[n] > 0 then Kill(n) end -- Заявка есть, снять заявку
                         if OpCl[n] == -1 then OpCl[n] = 0 end -- Не хватило денег открыть/закрыть - разрешим открыть/закрыть
                      end
                      SaveCurrentState()
                   end
                end

                Здесь виснуть нечему

  4. Добрый день, Дмитрий!
    Каким образом можно получить с открытого графика данные фьючерса SiM9 (ГГГГMMДД, ЧЧММСС, OPEN, LOW, HIGH, CLOSE) для дальнейшего сохранения в файл (это уже умею)?
    И еще, как можно проверить отсутствие части котировок в файле, чтобы затем получить недостающие свечи? Все на форуме прочитано, вижу, истина где-то рядом, но как всегда знаний не хватает 🙂
    Заранее благодарен!

  5. Доброго времени суток! Могли бы мне помочь. У меня такая ситуация. Я не могу понять как обратиться к каждой линии в индикаторе price Channel когда создаю сигнал на покупку или продажу
    if ind~=nil and ind~="" then
    local N=getNumCandles(ind);
    if N 10 then
    -- upper
    t,n,i=getCandlesByIndex(ind, 0, N-2, 2);
    prevCloseUpper = math.floor(tonumber(t[0].close) * precision) / precision; -- предыдущее закрытие верхней линии индикатора PriceChannel
    closeUpper = math.floor(tonumber(t[1].close) * precision) / precision; -- закрытие верхней линии индикатора PriceChannel

    -- lower
    t,n,i=getCandlesByIndex(ind, 2, N-2, 2);

    prevCloseLower = math.floor(tonumber(t[0].close) * precision) / precision; -- предыдущее закрытие нижней линии индикатора PriceChannel
    closeLower = math.floor(tonumber(t[1].close) * precision) / precision; -- закрытие нижней линии индикатора PriceChannel
    ДАЛЕЕ ХОЧУ СРАВНИТЬ
    if PRICE<0 then
    SIGNAL="BAY"
    if PRICE==2 then
    SIGNAL="SELL"

    1. Здравствуйте, на сколько можно понять из этого кода (в следующий раз оборачивайте его в теги луа, над полем ввода комментария написано) подход, вроде бы, верный. Но если что-то работает не так, как ожидается, то для этого можно при помощи message выводить значения переменных и тогда станет ясно где ошибка.

  6. Здравствуйте, я вот не понял, а как получить значение индикаторов то на свече? Вызываю функцию getCandlesByIndex с идентификатором индикатора получаю таблицу, где все параметры (open ... volume), кроме datetime нулевые...