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

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 8, среднее: 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) данных из графиков и индикаторов: 242 комментария

  1. Добрый день.
    Непосредственно получать данные из графика - все ОК, но хочется получить данные через

    1
    2
    3
    4
    
     ds1, err=CreateDataSource ("SPBFUT", "SRZ7", INTERVAL_M1);
    message(err);
    ds1:SetEmptyCallback();
    message(ds1:Size());

    Пишет

    1
    2
    3
    
     	message - >16.11.2017	21:33:41	invalid context
    и
    2.000000	3.000000	16.11.2017	21:33:41	C:\QUIK_AD\Quik\Lua\new1.lua:5: attempt to index global 'ds1' (a nil value)
  2. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    local dt = {}
    dt.day, dt.month, dt.year = string.match(getInfoParam("TRADEDATE"),"(%d*)\.(%d*)\.(%d*)")
    dt.hour, dt.min = 10, 0
    start_time = os.time(dt)
    dt.hour, dt.min = 14, 36
    end_time = os.time(dt)
    tag = "RTS"
    min, max = 1000000, -1
    t, n, l = getCandlesByIndex (tag, 0, 0, getNumCandles(tag))
    if n > 0 then
      for i = n-1, 0, -1 do
       local bar = t[i]
       if bar then
         posix = os.time(bar.datetime)
         if posix < start_time then break end
         if posix  max then max = bar. high end
             if bar.low > 0 and bar.low < min then min = bar.low end
         end
       end
      end
  3. Добрый день!
    Как можно вернуть максимальное/минимальное значение инструмента с открытия до некоторого времени?
    Например по фьючерсу РТС нужно узнать максимальное/минимальное значение с 10:00:00 до 14:36:00 в текущей торговой сессии и время их наступления.

    1. День добрый!
      Макс/Мин значений одинаковых по цене, но разных по времени может быть много, какое вас конкретно будет интересовать?))
      С точностью до таймфрейма - с помощью обратного перебора таблицы полученной с помощью getCandlesByIndex или CreateDataSource.
      Если на графике, можно заморочиться, добавить метки руками/программно на интересующие экстремумы и программно их считывать.
      Более точный - из таблицы всех сделок.

      1. Таймфрей - минутки. Нужен первый по времени наступления мин/макс за указанный период, например с 10:00:00 до 14:36:00 в текущей торговой сессии
        С точностью до таймфрейма - с помощью обратного перебора таблицы полученной с помощью getCandlesByIndex или CreateDataSource.

  4. Дмитрий, здравствуйте. Столкнулся с проблемой.
    Не могу получить нужные мне параметры в функции обратного вызова ds:SetUpdateCallback(function)
    Не понятно могу ли я получить в функции на которую я подписываюсь по индексу последней свечи все параметры этой свечи... такое ощущение, что в этой функции невозможно обратиться к таблице ds... Действительно ли это так... Вроде в вашем примере вы обращаетесь к объему таблицы в строке message('На '..index..'-й свече объем вырос до '..ds:V(index));
    но я никак не могу получить ни одного параметра в этой функции

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    function main()
    ds =
    {    DataSource("SPBFUT", "GZZ7",INTERVAL_M1),
         DataSource("SPBFUT", "RIZ7",INTERVAL_M1),
         DataSource("SPBFUT", "SiZ7",INTERVAL_M1),
    	 DataSource("SPBFUT", "BRX7",INTERVAL_M1)	 
    }
    local Candle = "";
       while not IsStop do
       if QluaCSharpConnector.CheckGotCandle() then
       Candle = GetFromStack();
       -- если стек не пустой
       message(Candle);
             if Candle ~= nil then 
                -- отправляет стакан роботу
                QluaCSharpConnector.SendCandle(Candle);
             end;
          sleep(10)
       end
    end
    end
     
    function mycallbackforallstocks(index)
    candleStr = "";
             if ds:O(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:O(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    		 if ds:C(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:C(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    		 if ds:H(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:H(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    		 if ds:L(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:L(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    		 if ds:V(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:V(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    		 if ds:T(index) ~= nil then
                candleStr = candleStr..tostring(tonumber(ds:T(index)))..";";
             else
                candleStr = candleStr.."noData;";
             end;
    	  AddToStack(candleStr);
    end
        1. У Вас "миллион" ошибок, а Вы еще коннектор тут воткнули, начните сначала, научитесь получать данные с графика, просто выводя OHLC последней свечи в сообщении (message), когда поймете как все работает, тогда усложняйте задачу коннекторами, сейчас я вижу у Вас просто непонимание базовых основ. Вот, например, пишите Вы такую строку:

          1
          
          if ds:O(index) ~= nil then

          Вы задумывались что у Вас хранится в переменной ds ? Каким образом она у Вас стала экземпляром класса источника данных и приобрела метод O(), который в экземпляре класса источника данных возвращает цену открытия свечи по переданному в метод индексу? Кучу вопросов таких могу еще позадавать по Вашему коду...

          Простите, если я немного грубо скажу дальше, просто хочу сразу Вас уберечь от одной очень распространенной ошибки среди начинающих "программистов", заключается она в подобной мысли: "Программирование это просто, каждый дурак справиться, накидаю сейчас в программу разных кусков кода, которые считаю пригодятся в ней, компьютер там сам разберется что мне от него нужно, он же умный", имея такой подход на старте, такие "программисты" думают, что программирование это накидать в файл какие-то куски кода, функционал которых они примерно (очень отдаленно) понимают. И надеются что компьютер сам додумает за них, они же объяснили ему своими словами что хотят от него, именно этим же все программисты и занимаются, считают они. Спешу Вас расстроить, программирование это точная наука, как математика, все "слова", которые Вы включаете в свою программу интерпретируются в конкретные команды для процессора компьютера, которые он выполняет, между Вами и процессором нет промежуточного звена "переводчика", который переведет Ваши не совсем корректные команды компьютеру на строгий, понятный ему язык. Программа это не сочинение на тему, а четкий набор инструкций, которые пишутся строго в соответствии с синтаксисом конкретного языка программирования, на котором Вы пишите.

          Рекомендую Вам удалить весь Ваш код и начать с основ программирования: что такое переменные, что такое функции, как это все работает и т.п. И только после того, как Вы это все будете знать и легко это применять в простых задачах, только после этого можно приступать к реальному проекту.

          Если хотите, я могу Вам обучить в кротчайшие строки, я недавно стал заниматься обучением по Скайпу, очень удобно считаю и не дорого, если интересно, пишите мне на почту reply@quikluacsharp.ru, обсудим подробности, кучу времени себе сэкономите.

  5. Здравсвуйте!
    Подскажите пожалуйста как можно получить данные прошлых свечек.
    Например мне нужно узнать разницу high и low свечи которая была пять баров назад?

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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      function main()
         -- Функция предназначена для создания таблицы Lua и позволяет работать со свечами, полученными с сервера QUIK, а также реагировать на их изменение.
         DS, Error = CreateDataSource ('SPBFUT', 'RUI7', INTERVAL_M1)
         -- Ждет, пока данные будут получены с сервера (на случай, если такой график не открыт)
         while (Error == "" or Error == nil) and DS:Size() == 0 do sleep(1) end
         if Error ~= "" and Error ~= nil then message("Ошибка подключения к графику: "..Error) end
       
         -- High 5 свечей назад
         local High_5 = DS:H(DS:Size() - 4)
         -- Low 5 свечей назад
         local Low_5 = DS:L(DS:Size() - 4)
       
         message('High 5 свечей назад = '..High_5..' Low 5 свечей назад = '..Low_5)
      end
      1. Спасибо за помощь!
        А можно сделать тоже самое но брать данные с открытого графика?
        Я как понял если использовать данные с графика то можно с помощью getCandlesByIndex ограничить количество получаемых свечей( что бы не грузить скрипт )
        Например:
        t, n, l = getCandlesByIndex (tag, 0, n-5, 5)
        t[i0].high
        t[i0].low

            1. Дмитрий, добрый день!

              Подскажите, пожалуйста, можно ли привязать скрипт к открытому графику, без явного указания инструмента. Т.е. открыт график фьючерса на золото, подставляем в class_code, sec_code его данные, а если я меняю график на нефть, то подставляются его данные. Спасибо.

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

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