Артем (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 2 3 4 5 6 7
Lua скрипты теряют конфигурацию среды (?)
 
Нет. Скрипт лежит в папке QUIK, модуль в той же папке.
запуск из работающего скрипта другого скрипта или скриптов
 
Цитата
Юрий С написал:
Цитата
Артем написал:
QUIK в этом плане ничем не отличается от обычного программирования - изо всех модулей и файлов допустимо иметь ровно один бесконечный цикл, тот который в main(). Все остальные модули должны работать по вызову и должны возвращать управление обратно в main. В Lua можно имитировать многопоточность с помощью сопрограмм ("coroutine").
Антон, НО в квике же это реализовано!!! Мы же вручную можем запустить несколько файлов(скриптов), и они могут работать параллельно!! Я только это имею ввиду, мне не надо распараллеливать задачи по процессорам, только лишь обратиться к ответственному за запуск модулю квика из своего скрипта передав ему путь и имя файла со скриптом, который я хотел бы запустить, точно так же как я это делаю через таблицу доступных скриптов. И запускай хоть с main,хоть с бесконечным циклом. Вот в чем задача.
Можете попросить разработчиков добавить С++ API функцию для запуска через QUIK сторонних скриптов.
CreateDataSource возвращает пустой набор данных, Функция CreateDataSource возвращает пустой набор данных, сообщений об ошибках нет
 
Использую вот такой код для получения большого количества свечек. Он их сбрасывает в файлы но можно что угодно делать. Возвращает (возможно пустой) список инструментов которые заглохли, их можно повторно запросить, в случае ошибки не возвращает ничего. Входные данные это массив объектов в формате { 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
Lua скрипты теряют конфигурацию среды (?)
 
Время от времени скрипты Lua при загрузке внешних модулей начинают сыпать ошибки что модуль не найден, хотя он не был затронут и работал за минуту до этого. Чтобы исправить нужно удалить скрипт и добавить заново, что довольно неприятно.

Я имею опыт программирования С/С++ API для Lua но я понятия не имею как такая ошибка может получиться. Быстрый и грязный способ исправить это переустанавливать скрипт под капотом при каждом запуске.
запуск из работающего скрипта другого скрипта или скриптов
 
QUIK в этом плане ничем не отличается от обычного программирования - изо всех модулей и файлов допустимо иметь ровно один бесконечный цикл, тот который в main(). Все остальные модули должны работать по вызову и должны возвращать управление обратно в main. В Lua можно имитировать многопоточность с помощью сопрограмм ("coroutine").
module 'mime.core' not found:, mime\core.dll
 
Все файлы должны были быть включены в дистрибутив модуля, либо на странице модуля должно быть указано где их скачать.
module 'mime.core' not found:, mime\core.dll
 
Сопутствующие файлы и папки нужно сбросить либо в корневую директорию скрипта либо в системную (у QUIK) директорию Lua.
Добавить в CreateDataSource():SetUpdateCallback() аргумент, указывающий на DataSource
 
Можно лямбдами бахать но это принуждает копипастить замыкания повсюду. Гораздо лучше когда можно объявить колбек и отправлять его в датасорс, и при вызове он сам объявит к какому датасорсу он принадлежит.
Код
local function tickerUpdateCallback ( datasource, candle )
  foo( datasource )
  bar ( datasource, candle )
  if xyz then baz ( datasource, candle ) end
end

CreateDataSource ( 'TQBR', 'FOO', INTERVAL_TICK ):SetUpdateCallback ( tickerUpdateCallback )
CreateDataSource ( 'TQBR', 'BAR', INTERVAL_TICK ):SetUpdateCallback ( tickerUpdateCallback )
CreateDataSource ( 'TQBR', 'BAZ', INTERVAL_TICK ):SetUpdateCallback ( tickerUpdateCallback )
Как смоделировать виртуальные торги?, нужно для отладки робота
 
С целью только отладки скриптов подойдет 1-мерный шум перлина с крупными параметрами низких частот (месяцы), заниженными параметрами высоких частот (минуты), и околонулевыми параметрами средних частот. Приблизительно симулирует рыночную динамику кроме крупных скачков. Волатильность можно регулировать редактируя коеффиценты высоких частот. Целесообразно добавить небольшую компоненту на самой высокой частоте чтобы симулировать тики, но не требуется если скрипты работают с минутными или длиннее свечками.
Добавить в CreateDataSource():SetUpdateCallback() аргумент, указывающий на DataSource
 
Колбек указывает только на порядковый номер обновлённой свечки в источнике данных, но не указывает к какому источнику данных она принадлежит. Проблематично при открытии нескольких источников данных с колбеками.
Я новичок, мне нужно знать как отправлять заявку по текущей цене(купля).
 
По цене рынка покупка производится с параметром TYPE='M', стоимость указывается как '0' (кроме FORTS где надо указывать максимально невыгодную цену).
Как понять, что скрипт загружен через require?
 
При загрузке скрипта как модуля, в него первым аргументом передаётся название модуля. Функция loadfile загружает файл в виде метода, который можно выполнить с аргументами. Функция dofile автоматически исполняет файл без аргументов. Таким способом можно отличить метод загрузки.

Код
require ( 'test' ) ( 'require' )
loadfile ( 'test.lua' )( 'foo' )( 'loadfile' )dofile ( 'test.lua' ) ( 'dofile' )

test.lua

Код
local args = { ... or 'no arguments' }
for k, v in pairs ( args ) do print ( k, v ) end
return function ( s ) print ( s ) end
вывод:
Код
1   test
require
1   foo
loadfile
1   no arguments
dofile
Всегда загружайте скрипты как модули, то есть с помощью функции require. Это исключает повторное исполнение кода в файле и перезапись измененных значений на исходные. Обратите внимание, что require не принимает путь к файлу, а только название модуля. Точка и расширение файла не указываются (можно таже загрузить совместимые .dll и .so) и если модуль расположен внутри папки, то разделителем нужно использовать точку а не слэш.
Код
--/module/interpreted.lua
--/module/HWaccelerated.dll
require ( 'module.interpreted' )
require ( 'module.HWaccelerated' )
Страницы: Пред. 1 2 3 4 5 6 7
Наверх