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

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

  1. добрый вечер
    local O = ds:O(i); -- Получить значение Open для указанной свечи (цена открытия свечи)
    подскажите в каком формате возвращается значение, номер, строка или пр.?

  2. Здравствуйте! При запуске кода выскакивает ошибка: Переменная Channel не объявлена как глобальная.
    Подскажите, плиз, как это можно исправить

    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
    
    is_run = true
     
    -- присваивание переменным начальных базовых значений торгового алгоритма
     
    Account = "SPBFUT11lPS"     -- торговый счет
     
    function OnInit()
       dofile(getWorkingFolder()..'\\LuaIndicators\\Channel.lua' )
       funcChannel = Channel()
       ds = CreateDataSource('SPBFUT', 'SiM2', INTERVAL_M1)
       ds: SetEmptyCallback()     
    end
     
    function main()
      sleep(100)
      for i=1,ds:Size() do
        High, Low = funcChannel(i, {Period = 5, }, ds) 
      end 
     
       while true do
            High = funcChannel(ds:Size(), {Period = 5 },  ds)
            Low = funcChannel(ds:Size(), {Period = 5 }, ds)
     
            message("H = "..tostring(High).."\nL  = "..tostring(Low))
            sleep(1000)
       end        
    end
     
    function OnStop(stop_flag)              
         is_run=false
         stop_flag=1
         ds:Close()
    end
      1. В файле \\LuaIndicators\\Channel.lua глобальной переменной является массив Settings ,
        который содержит в себе переменные параметров индикатора, тип линии для отображения,
        толщину, цвет и т.п.

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        
        Settings=              
                {                          
                    Name = "Channel",           -- название индикатора
                    period=5,                   -- параметр индикатора                          
                    line=                                     
                        {                               
                            {  
                                Name = "High",
                                Type =TYPE_LINE,
                                Width = 2,
                                Color = RGB(1,254, 255)
                            },
                            {
                                Name = "Low",
                                Type =TYPE_LINE,
                                Width = 2,
                                Color = RGB(1,254,255)
                            }
                        }
               }

        Как теперь мне его вызвать вместо funcChannel = Channel(), м.б. funcChannel = Settings{{{}}} или как-то по другому присвоить?

        1. т.е. вы хотите использовать функционал индикатора в роботе, передав в качестве источника datesourse?
          так у вас ничего не получится.
          нужно скопировать функцию Channel() в отдельный файл и переписать в ней обращения к источнику с H(i) на ds:H(i)

  3. Здравствуйте. Только начал изучать LUA. С

    1
    2
    3
    
      ds = CreateDataSource("TQBR",  "SBER", INTERVAL_TICK) 
    sleep(300)
    local Size = ds:Size()

    вроде понятно. Запрашиваю, всё приходит. Могу получить все параметры секции Open, High, Low,Close,Time и даже миллисекунды выдаёт

    1
    2
    3
    
     for i = 1, Size, 1 do 
    ds:T(i) .ms
     end;

    Но вот как мне из ds получить, к примеру, значение "BIDDEPTHT" (из списка параметров для акций) ?

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

      1. Добрый день. А есть где-нибудь пример кода или что-то похожее для ознакомления алгоритма написания робота для macd? Месяца три уже пытаюсь разобраться с программированием, но для меня это совсем тёмный лес.

        1. Добрый день,
          forum.quik.ru -> Все индикаторы на Lua -> сообщение #54,
          качайте примеры, разбирайтесь.
          Вам нужен сам алгоритм расчета, который можно приспособить для робота.

          1. и да, на своем опыте вам скажу, я тоже самоучка, на это уйдет у вас от 3 до 5 лет - в никуда!!! займитесь изучением с++ под unix-операционную систему . потратите 3-5 лет самостоятельно или около года с с хорошими курсами - будете зарабатывать,
            а на луа - просто потратите столько же жизни без результата. То что вы прям сейчас хотите анализировать, не пригодится вам для заработка - никогда!

            1. Честно говоря, я уже не в том возрасте чтобы планировать что-то на 3-5 лет вперед). А луа меня заинтересовал только потому, что он работает с терминалом Quik. Увлекся в прошлом году торговлей на ММВБ, но устаётся смотреть пару сотен разных графиков для поиска сигналов и последующего анализа. Я хочу разработать робота, который будет формировать и обновлять таблицу по следующему алгоритму:
              1) робот постоянно смотрит на все инструменты рынка или какие нибудь выбранные по выбранному ввременно интервалу
              2) при обнаружении, что обе линии MACD ниже 0 и одна из них пересекает другую снизу вверх для какого нибудь инструмента, то данный инструмент отражается в таблице.
              3) если у проверенного инструмента пересечения нет, то он не отражается в таблице или удаляется оттуда
              4) я просто анализирую отображаемые инструменты и уже сам решаю входить в рынок или нет.
              Я так хочу освободить себя от просмотра лишних графиков, которые не имеют нужных мне сигналов)
              Такая реализация возможна?
              Буду не против услышать Ваши советы)))

              1. 1. все инструменты - это вряд ли;
                2.- 3. если четко сравнивать 2 бара на предмет возникновения условия, то этот инструмент при следующем расчете не выполнит условия и не будет отображен в таблице;
                Реализовать можно.
                99,99% времени таблица будет пустой, значит нужна какая-то звуковая привлекалочка.

              2. Нормальная задача, разобраться как написать помощника для трейдинга можно за пару месяцев на платных курсах, еще 4-6 месяцев на обкатку и доведения до боевого варианта, так что вполне можно. Но проще заказать изготовление по нужной стратегии, правда ТЗ тоже придется месяц писать.

                1. Привет! Для инфо:
                  з/п синьёра около 2,5 - 10$/час,
                  з/п человека, который пишет ТЗ - около 600$/час.
                  Иначе, если возложить разработку ТЗ на широкие плечи программиста, то проект затянется на долго, либо потребует найма доп.-синьёров.
                  Так что же такое ТЗ?
                  Это не кучка хотелок и кнопка "БАБЛО" 😉
                  Это четкие инструкции, что должен сделать робот, реагируя на то или иное событие.
                  Тогда, программисту не нужно думать над тем или иным алгоритмом - а время - деньги, а тупо просто перевести в код за разумное время.
                  Человеку, который далек от тематики и только вступил на рыночную тропу - тяжело объяснить на словах то, чего он хочет, тем более научиться, и написать правильное ТЗ - это не месяц и не два.
                  По этому у Человека стоит выбор:
                  - либо переплачивать программисту за разработку "грааля", но медленно и соответственно - дорого.
                  - либо нанять специалиста по разработке ТЗ (естественно, который разбирается в рынке и понимает событийность торговых процессов). И он быстро напишет ТЗ, которое в короткие сроки, программист воплотит в жизнь идею "грааля".
                  Как-то так 😉

              3. В amibrokere с подключенным к нему квиком. Это легко делается создаете список нужных бумаг и следите за ним. Получается робот советник, который может уведомлять по email, telegram, звуковые оповещения, всплывающие окна и тд. Плюсом вы сможете проверить любую свою стратегию и подобрать параметры.

  5. Здравствуйте!
    Подскажите, пожалуйста, как на основе полученных из CreateDataSource() данных получить максимальный объем внутри текущей(последней) свечи, который сформировался на каком-либо уровне?

    1. Здравствуйте!
      Как вы себе представляете ситуацию, когда цена несколько раз прошла через уровень "вверх/вниз"?
      Какой объем нужно фиксировать на уровне? по первому касанию уровня ценой или последнему, или строго 4-е касание?

          1. Расшифрую дополнительно свою запутанную мысль. Хочу в скрипте написать условия: если максимальный объем предшествующей по отношению к текущей свече находится вверху свечи, то....., если внизу, то....., если в середине, то.....

  6. Плохо получается. Я дату и время беру из таблицы, которую возвращает getCandlesByIndex. Там год, месяц, день, час, минута и секунда лежат в разных числовых полях. Я собираю их в строковую дату "ГГГГММДД" и время "ЧЧММСС" и потом преобразую в число так:

    1
    2
    
    date = tonumber(string.format("%s%s%s", ChartTable[i].datetime.year, ChartTable[i].datetime.month, ChartTable[i].datetime.day))
    time = tonumber(string.format("%s%s%s", ChartTable[i].datetime.hour, ChartTable[i].datetime.min, ChartTable[i].datetime.sec))

    Получаются некорректные даты и время вида 202163 и 1500, т.е. не хватает нулей перед одноциферными месяцами, днями, часами и минутами. Метка не добавляется.
    Можно как-то напрямую (без преобразования в строку) превратить дату и время, которую возвращает getCandlesByIndex, в дату и время, которые принимает AddLabel ?

    1. Уже сам придумал:

      1
      2
      
      label_param.DATE = ChartTable[i].datetime.year*10000 + ChartTable[i].datetime.month*100 + ChartTable[i].datetime.day
      label_param.TIME = ChartTable[i].datetime.hour*10000 + ChartTable[i].datetime.min*100 + ChartTable[i].datetime.sec
      1. конструкция ChartTable[i][param1][param2] не правильная, вы обращаетесь к элементу таблицы 3-го уровня вложенности, в вашем примере 6 раз, что долго и ужасно выглядит эстетически.
        правильно объявить локально бар и потом к нему обращаться:
        local bar = ChartTable[i]
        local close = bar.close
        local px = os.time(bar.datetime)
        os.date и os.time, работают быстро.