CreateDataSource возвращает пустой набор данных

Страницы: 1
RSS
CreateDataSource возвращает пустой набор данных, Функция CreateDataSource возвращает пустой набор данных, сообщений об ошибках нет
 
добрый день. терминал Quik 7.11.1.5.
пример кода скрипта:
Код
function main()

    arrTickers = {  "MICEXINDEXCF", "MICEX10INDEX", "MICEXBMI", "MICEXCGS", "MICEXCHM", "MICEXFNL",
                    "MICEXM&M", "MICEXMNF", "MICEXO&G","MICEXPWR","MICEXSC", "MICEXTLC", "MICEXTRN",
                    "MICEXINNOV", "MICEXMBICP", "MICEXMBITR" }

    for n = 1, 16, 1 do

        strTicker = arrTickers[ n ]

        dsData, strError = CreateDataSource( "INDX", strTicker, INTERVAL_MN1 )

        if dsData == nil then
            message( "CreateDataSource( "..strTicker.." ) error: "..strError, 3 )
        else

            if dsData:Size() == 0 then
                if strError == nil then
                    message( "CreateDataSource( "..strTicker.." ) is empty", 2 )
                else
                    message( "CreateDataSource( "..strTicker.." ) is empty: "..strError, 2 )
                end
            else
                message( "CreateDataSource( "..strTicker.." ) success "..dsData:Size() )
            end

        end

        sleep( 3000 )
    end
end
в результате работы скрипта все наборы данных пустые - dsData:Size() == 0, ошибок нет - strError == nil. графики необходимых интервалов для соответствующих инструментов в терминале открыты.
что я делаю не так и почему так происходит? самое интересное что две недели назад то же самое работало без проблем ...
заранее большое спасибо за ответы
 
Вода из крана начинает капать с некоторой задержкой после того как вы начали поворачивать вентиль.

здесь то же самое. Данные будут несколько позже.
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
Вода из крана начинает капать с некоторой задержкой после того как вы начали поворачивать вентиль.
здесь то же самое. Данные будут несколько позже.
то есть такую процедуру надо делать в конце дня? после обеда? или когда?
как узнать когда наступило это время?
прошу прощения за вопросы которые может быть имеют очевидные ответы - новичок в этом деле. спасибо за помощь
 
Процедуру можно делать в тот момента когда она вам нужна.

Схематично эта процедура стучится к брокеру с просьбой послать терминалу данные по требуемому вам инструменту.


весточек должны доставить (dhl или голуби), сервер после ее получения докушает чай, отошлет назад данные (может снова голубями), потом терминал их рассует по полкам т только после этого они станут доступны вам.

сколько времени пройдет на все эти пассы -гетзвестно. Но явно больше, чем выполняется один оператор lua в вашей программе.
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
Процедуру можно делать в тот момента когда она вам нужна.
Схематично эта процедура стучится к брокеру с просьбой послать терминалу данные по требуемому вам инструменту.
... сервер после ее получения докушает чай, отошлет назад данные (может снова голубями), потом терминал их рассует по полкам только после этого они станут доступны вам.
сколько времени пройдет на все эти пассы -гетзвестно. Но явно больше, чем выполняется один оператор lua в вашей программе.
логика работы процедуры понятна, большое спасибо.
в документации написано что есть возможность установить для получаемого набора данных функцию обратного вызова - SetUpdateCallback - для обработки изменившихся данных. насколько я понимаю, данная функция будет вызываться столько раз, сколько данных (свечей) есть в наборе (это как минимум), кроме этого она будет вызываться каждый раз по мере изменения последней свечи. если изменения последней свечи можно каким-то образом обработать, то все равно непонятно когда переставать получать данные - я же не знаю сколько данных на сервере брокера (сколько свечей).
также в документации написано, что есть у функции GetDataSource необязательный параметр STRING param, про который написано только что если этот параметр не задан, то заказываются данные на основании Таблицы обезличенных сделок, если задан – данные по этому параметру. однако возможные значения этого параметра не приводятся.
так как все-таки делать-то - через функцию обратного вызова и сравнивать даты свечей с тем, что необходимо получить или использовать какое-то значение этого необязательного параметра?! где тогда взять это значение, непонятно ...
 
вот так вот нормально будет?
Код
function main()

        strTicker = "MICEXINDEXCF";

        dsData, strMessage = CreateDataSource( "INDX", strTicker, INTERVAL_MN1 )

        if dsData == nil then
            message( "CreateDataSource( "..strTicker.." ) error: "..strMessage, 3 )
        end

        tmTic = os.time()
        while dsData:Size() == 0 do
            sleep( 5000 )
            message( "Waiting for "..os.difftime( os.time(), tmTic ).." seconds so far .." )
        end
        tmTac = os.time()
        message( "Getting data took "..os.difftime( tmTac, tmTic ).." seconds. Data source size: "..dsData:Size() )

        -- Do something with the data ...
        
        dsData:Close()

end
можно не с нулем сравнивать а с каким-либо значением, но в любом случае это по-моему бред, джентльмены, хоть и работает.
вопрос с параметрами все-таки остается открытым - подскажите пожалуйста где можно посмотреть возможные значения
 
Примерно так и надо делать при инициализации скрипта. Только цикл ожидания лучше сделать другим:
Код
ждём, пока не будет ds:Size() > 0, периодически засыпая на 100 мс, но не более 15-20 секунд
Практика показывает, что если за это время не пришли данные, то дальше ждать бесполезно.
 
Ставлю ожидание на 30 секунд, однако, всё равно возвращает пустые значения. Что-то долго голуби летят, или я чего-то не так делаю?
Код
DS,Error = CreateDataSource(CLASS_CODE, cur_sec, INTERVAL);
      -- Проверка
      if DS == nil then
      message('Входила:ОШИБКА получения доступа к свечам! ');
      end;
      
      t=0;
       while DS:Size() == 0 and t<30000 do
            sleep( 1000 )
         t=t+1000;
        end
      if t>29000 then message(cur_sec.." Empty") end;

При этом, что характерно - если у меня открыт график с каким-либо инструментом, он без проблем выцепит данные с него. Однако по задумке требуется работать с большим количеством инструментов и содержать армию графиков не вариант (собсно, cur_sec у меня и содержит название инструмента, берёт верно)
 
Цитата
Егор Масалкин написал:
Ставлю ожидание на 30 секунд, однако, всё равно возвращает пустые значения. Что-то долго голуби летят, или я чего-то не так делаю?
...
При этом, что характерно - если у меня открыт график с каким-либо инструментом, он без проблем выцепит данные с него ...

у меня работает вот такой код (что в принципе то же самое):
Код
dsData, strMessage = CreateDataSource( "INDX", strTicker, INTERVAL_MN1 );

if dsData == nil then
    message( "CreateDataSource( "..strTicker.." ) error: "..strMessage, 3 );
else
    tmTic = os.time();
    repeat
        sleep( 1000 );
    until ( dsData:Size() == 0 ) or ( os.difftime( os.time, tmTic ) <= 15 );
    tmTac = os.time();

    if dsData:Size() == 0 then
        message( strTicker..", size:"..dsData:Size()..", "..os.difftime( tmTac, tmTic ).." seconds", 2 );
    else
        message( strTicker..", size:"..dsData:Size()..", "..os.difftime( tmTac, tmTic ).." seconds" );
    end;
end;

НО! работает только во время торговой сессии - после 19:00 MSK даже после ожидания 15 секунд набор данных пустой, не знаю нормально ли это ...
 
Alexegin,

попробуйте после вызова функции CreateDataSource() добавить следующую строку:
if  (not dsData:SetEmptyCallback())  then  message("Server returns no data")  end
Если сообщение у вас появится, вероятнее всего, что проблема на стороне брокера (возможно, "слетели" какие-то настройки либо появились новые ограничения частного характера).
 
Цитата
Andrei2016 написал:
попробуйте после вызова функции CreateDataSource() добавить следующую строку:
Код
if  (not dsData:SetEmptyCallback())  then  message("Server returns no data")  end
Если сообщение у вас появится, вероятнее всего, что проблема на стороне брокера (возможно, "слетели" какие-то настройки либо появились новые ограничения частного характера).
Andrei2016, попробую обязательно, хотя и не понятно почему на основании этого можно делать какие-то выводы.
после закрытия торговой сессии на фондовом рынке все равно должна работать возможность получения данных через CreateDataSource, я правильно понял?
а необязательный параметр STRING param - кто-нибудь знает возможные значения?
 
Цитата
Alexegin написал:
а необязательный параметр STRING param - кто-нибудь знает возможные значения?
Добрый день.
Для определения кода параметра, включите в настройках рабочего места Quik настройку Формальное представление данных (раздел 'Программа->Буфер обмена'), добавьте в Таблицу текущих торгов необходимые параметры, скопируйте ее содержимое в буфер обмена (Ctrl+C) и вставьте, например, в блокнот, и Вы увидите, какие значения нужно передавать в STRING param.
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
 
Цитата
Nikolay Pavlov написал:
Для определения кода параметра, включите в настройках рабочего места Quik настройку Формальное представление данных (раздел 'Программа->Буфер обмена'), добавьте в Таблицу текущих торгов необходимые параметры, скопируйте ее содержимое в буфер обмена (Ctrl+C) и вставьте, например, в блокнот, и Вы увидите, какие значения нужно передавать в  STRING param.
в документации про возможные значения параметра ничего не написано, упоминается Таблица обезличенных сделок, а не текущих параметров. тайные знания и волшебство какое-то ...
спасибо, Nikolay Pavlov
 
Цитата
Alexegin написал:
в документации про возможные значения параметра ничего не написано,

Таблица торгов, меняется в зависимости от рынка. На разных рынках разные параметры.
Даже более того, на одном рынке, у разных брокеров, набор может быть разным.
Таким образом, даже если бы в документации были описаны параметры, то не факт что они у Вас есть.
В связи с чем, правильней всего с начала посмотреть что Вам нужно в таблице, а потом узнать какой для этого нужен заголовок.
И пути два. Либо через DDE (что надежней), либо через документацию info.chm
-Раздел 8. Алгоритмический язык QPILE
--Функции для получения значений Таблицы текущих торгов
---Значения параметров функций

через документацию не надежней т.к. как уже говорилось и еще раз, набор параметров в таблице торгов может быть разным.
описать вообще все возможные варианты параметров к сожалению не представляется возможным.
 
Цитата
Sergey Gorokhov написал:

Таблица торгов, меняется в зависимости от рынка. На разных рынках разные параметры. Даже более того, на одном рынке, у разных брокеров, набор может быть разным.
Таким образом, даже если бы в документации были описаны параметры, то не факт что они у Вас есть.
В связи с чем, правильней всего с начала посмотреть что Вам нужно в таблице, а потом узнать какой для этого нужен заголовок. И пути два. Либо через DDE (что надежней), либо через документацию info.chm.
-Раздел 8. Алгоритмический язык QPILE
--Функции для получения значений Таблицы текущих торгов
---Значения параметров функций

через документацию не надежней т.к. как уже говорилось и еще раз, набор параметров в таблице торгов может быть разным. описать вообще все возможные варианты параметров к сожалению не представляется возможным.
большое спасибо, Sergey Gorokhov. я лишь говорю о том, что в соответствующем разделе документации по Lua (а не QPILE) нет никакой информации ни о возможных значениях параметров, ни о том где это можно посмотреть, ни о том о чем вы пишите тем более.

а после закрытия торговой сессии фондовой секции функция CreateDataSource должна работать или нет, не подскажите? или это от брокера зависит и надо у него спрашивать (ВТБ24)?
 
Alexegin,

Должна работать.
 
Цитата
Alexegin написал:
по Lua (а не QPILE)

а какая разница, если параметры одни и те же?
 
Цитата
Sergey Gorokhov написал:
Должна работать.
спасибо, значит будем звонить товарищам брокерам :)

Цитата
Sergey Gorokhov написал:
а какая разница, если параметры одни и те же?
ну не знаю ... просто если я при использовании Lua читаю про функцию CreateDataSource в соответствующем разделе соответствующего документа, у меня почему-то не возникает мыслей посмотреть значения параметров другого языка для другой функции другой таблицы - наверное потому что про это ничего не написано?
 
Цитата
Alexegin написал:
DS:Size() == 0
У меня днем выводит, что все источники данных пусты...

В чем проблема? ЧЯДНТ?
 
Цитата
Егор Масалкин написал:
У меня днем выводит, что все источники данных пусты...
у меня приведенный выше код работает. может неправильно указан код класса, бумаги или интервал не знаю ... например для месячных данных по акциям ГАЗПРОМ:
Код
dsData, strMessage = CreateDataSource( "TQBR", "GAZP", INTERVAL_MN1 )
 
Ваш код работает.
Но как только меняют параметры, пишу
dsData, strMessage = CreateDataSource( "SPBFUT", "RIU7", INTERVAL_MN1 )

то выдаёт, что размер будет 0.
НО как только я делаю график, то он спокойно получает данные... но ведь он с сервера должен брать свечи, а не с графика?

ну серьёзно... может я такой аутист что правильно не могу переписать коды? Но нет... может опять какая-то беда с фьючерами?
 
Цитата
Егор Масалкин написал:
Ваш код работает.
Но как только меняют параметры, пишу
Код
dsData, strMessage = CreateDataSource( "SPBFUT", "RIU7", INTERVAL_MN1 )

то выдаёт, что размер будет 0. НО как только я делаю график, то он спокойно получает данные... но ведь он с сервера должен брать свечи, а не с графика?
  1. еще раз проверьте коды класса и инструмента - отображается после нажатия в терминале Alt+I при соответствующей выбранной строке в Таблице текущих параметров
  2. попробуйте следующий код - просто скопируйте и сохраните в файле test.lua:
Код
function main()

    dsData, strMessage = CreateDataSource( "SPBFUT", "RIU7", INTERVAL_MN1 )

    if dsData == nil then
        message( "CreateDataSource() error: "..strMessage, 3 )
    else

        tmTac = os.time()
        repeat
            sleep( 1000 )
        until ( dsData:Size() == 0 ) or ( os.difftime( os.time, tmTac ) <= 15 )
        tmTic = os.time()
         
        if dsData:Size() == 0 then
            message( "CreateDataSource() returned empty dataset. Waiting timeout: "..os.difftime( tmTic, tmTac ), 2 )
        else
            message( "CreateDataSource() success. Waiting timeout: "..os.difftime( tmTic, tmTac ) )
        end

        dsData:Close()
    end

end
Цитата
Егор Масалкин написал:
ну серьёзно... может я такой аутист что правильно не могу переписать коды? Но нет... может опять какая-то беда с фьючерами?
скорее всего просто досадная ошибка, которую вы в упор не видите - так бывает
 
Методом проб и ошибок понял в чем ошибка.

Проблема была в функции OnInit(), в которой я писал весь код. Как только я поменял на функцию main, что было у товарища Alexegin, всё сразу заработало.
 
Цитата
Егор Масалкин написал:
Методом проб и ошибок понял в чем ошибка.
Проблема была в функции OnInit(), в которой я писал весь код. Как только я поменял на функцию main, что было у товарища  Alexegin , всё сразу заработало.
еще одно добавление (полученное опять же методом проб и ошибок):
Код
tmTac = os.time()
repeat
   sleep( 1000 )
until ( dsData:Size() > 0 ) or ( os.difftime( os.time(), tmTac ) > 15 )
изменилось условие цикла
 
Здравствуйте!

Можно ли как-то создать в скрипте на lua источник данных с пустыми интервалами?
Может быть как-то через CreateDataSource?
 
Mikhail Ran, добрый день!

В Qlua подобный функционал отсутствует.
 
Использую вот такой код для получения большого количества свечек. Он их сбрасывает в файлы но можно что угодно делать. Возвращает (возможно пустой) список инструментов которые заглохли, их можно повторно запросить, в случае ошибки не возвращает ничего. Входные данные это массив объектов в формате { class = "TQBR", sec = "SBER", int = "TICK", param = "" }.

Код
local _is_running = 1
function OnStop ( )
    _is_running = 0
    return 10000
end
function isOnline ( )
    return isConnected ( ) + _is_running == 2
end

local function dumpbatch ( batch, timeout, batchsize )
    local batchsize = batchsize or 8
    local timeout = timeout or 2
    local basestr = getScriptPath ( ) .. "/dump/"
    local filestr = basestr .. "%s %s %s%s.csv"
    local liststr = basestr .. "_list.txt"
    local stallstr = basestr .. "_stall.txt"

    local intervals = {
        ['TICK'] = INTERVAL_TICK,
        ['1'] = INTERVAL_M1, ['2'] = INTERVAL_M2, ['3'] = INTERVAL_M3, ['4'] = INTERVAL_M4, ['5'] = INTERVAL_M5, ['6'] = INTERVAL_M6, ['10'] = INTERVAL_M10, ['15'] = INTERVAL_M15, ['20'] = INTERVAL_M20, ['30'] = INTERVAL_M30,
        ['1H'] = INTERVAL_H1, ['2H'] = INTERVAL_H2, ['4H'] = INTERVAL_H4, ['D'] = INTERVAL_D1, ['W'] = INTERVAL_W1, ['M'] = INTERVAL_MN1 }
    do -- sanitization
        assert ( type ( batch ) == 'table', "Invalid argument: 'batch' is not 'table'." )
        assert ( type ( batchsize ) == 'number', "Invalid argument: 'batchsize' is not 'number'." )
        assert ( type ( timeout ) == 'number', "Invalid argument: 'timeout' is not 'number'." )
        for i = 1, #batch do
            assert ( type ( batch[ i ] ) == 'table', "Invalid batch item: not 'table'.")
            assert ( type ( batch[ i ].class ) == 'string', "Invalid batch item: 'class' is not 'string'." )
            assert ( type ( batch[ i ].sec ) == 'string', "Invalid batch item: 'sec' is not 'string'." )
            assert ( type ( batch[ i ].int ) == 'string', "Invalid batch item: 'int' is not 'string'." )
            assert ( type ( batch[ i ].param ) == 'string', "Invalid batch item: 'param' is not 'string'." )
            assert ( intervals[ batch[ i ].int ], "Invalid batch item: 'int' is not a valid time interval ( TICK, 1, 2, 3, 4, 5, 6, 10, 15, 20, 30, 1H, 2H, 4H, D, W, M )." )
        end
    end

    local runbatch, stalled = { }, { }

    while #batch + #runbatch > 0 do
        if #runbatch < batchsize and #batch > 0 then -- process batch item
            local entry = table.remove ( batch )
            local fname = string.format ( filestr, entry.class, entry.sec, entry.int, entry.param )
            local file = io.open ( fname, "r" )
            if file then file:close ( ); goto runbatch end -- skip existing dumps

            for i = 1, #stalled do -- skip stalled securities
                if entry.class == stalled[ i ].class and entry.sec == stalled[ i ].sec then
                    table.insert ( stalled, entry )
                    goto runbatch
                end
            end

            local source, error
            if entry.param ~= "" then
                source, error = CreateDataSource ( entry.class, entry.sec, intervals[ entry.int ], entry.param )
            else
                source, error = CreateDataSource ( entry.class, entry.sec, intervals[ entry.int ] )
            end
            if source then
                source:SetEmptyCallback ( )
                table.insert ( runbatch, { entry = entry, source = source, fname = fname, time = 0 } )
            else
                message ( string.format ( "Failed to create data source: %s\n%s %s %s %s" , error, entry.class, entry.sec, entry.int, entry.param ) )
            end
        end

        ::runbatch::
        for e = #runbatch, 1, -1 do -- run batch
            local entry = runbatch[ e ]
            if entry.source:Size ( ) == 0 then
                entry.time = entry.time + 0.100
                if entry.time >= timeout then
                    table.insert ( stalled, entry.entry )
                    table.remove ( runbatch, e )
                end
            else
                local file = io.open ( entry.fname, "w" )
                local source = entry.source
                for i = 1, source:Size ( ) do
                    file:write ( string.format ( "%04d%02d%02d,%02d%02d,%f,%f,%f,%f,%f\n",
                        source:T ( i ).year, source:T ( i ).month, source:T ( i ).day, source:T ( i ).hour, source:T ( i ).min,
                        source:O ( i ), source:H ( i ), source:L ( i ), source:C ( i ), source:V( i ) ) )
                end
                file:close ( )
                source:Close ( )

                file = io.open ( liststr, "a" )
                file:write ( string.format ( "%s\n", entry.fname ) )
                file:close ( )

                table.remove ( runbatch, e )
            end
        end
        if #runbatch > 0 then sleep ( 100 ) end
        if not isOnline ( ) then return end
    end

    local file = io.open ( stallstr, "w" )
    for i = 1, #stalled do
        file:write ( string.format ( "%s %s %s %s\n", stalled[ i ].class, stalled[ i ].sec, stalled[ i ].int, stalled[ i ].param ) )
    end
    file:close ( )
    return stalled
end
Страницы: 1
Читают тему
Наверх