На всякий случай: в кодах индикаторов папки LuaIndicators используется вызов стандартной функции unpack, который, в версиях Lua 5.3 - 5.4 ошибочен и должно быть: table.unpack(......). В коде модуля mod_IND.lua это учитывается как ошибочный вариант так и исправленный (строка в модуле: , unpack = unpack or table.unpack).
1. Инструкция приведена в комментариях теста модуля.
2. Код теста:
Код
-- Инструкция
-- 1. Скачать папку LuaIndicators (Примеры функций расчета индикаторов терминала QUIK на языке Lua) с сайта
-- https://arqatech.com/ru/support/files/ и переслать в папку расположения info.exe.
-- 2. Модуль подключения индикаторов(под именем mod_IND.lua) переслать в папку расположения info.exe.
-- 3. Запустить тест test_IND.
-- ----
-- P.S.
-- 1. Учитывать, что при расчете индикаторов первые значения (1 .... Период расчета индикатора - 1)
-- обычно nil.
-- 2. Результат расчета индикатора может иметь несколько значений и это определяется функцией OnCalculate
-- кода используемого индикатора папки LuaIndicators.
-- 3. В модуле mod_IND.lua представлены три примера объявления заголовочных функций описаний параметров
-- подключаемых индикаторов. Параметры такой функции это список полей из таблицы Settings соответствующего
-- индикатора папки LuaIndicators, для которых требуется задать значения, определяющие поведение создаваемого
-- замыкания.
---------------------------------------------------------------------
timeout = 300
is_run = true
function main()
-- GetDataSource подключается к графику --
local function GetDataSource(class_code, sec_code, timeframe)
local ds, Error = CreateDataSource(class_code, sec_code, timeframe)
-- Ждет 10 сек., пока данные будут получены с сервера --
for i = 1, 1000 do if not ((Error == "" or Error == nil) and ds:Size() == 0) then break end; sleep(10) end
if Error ~= "" and Error ~= nil then
message(debug.getinfo(1).currentline..': Ошибка подключения к графику: '..Error)
return nil
end
return ds
end
-------------------------------- Тест индикаторов -------------------------------------------------
local INDICATORS = require('mod_IND')
---------------------------------------------------------------------------------------------------
-- Подключение к источнику данных (графику)
local DS = GetDataSource(getClassInfo('QJSIM') and 'QJSIM' or 'TQBR', 'SBER', INTERVAL_M1)
if not DS then return end -- не удалось подключиться к источнику данных ---
local size = DS:Size()
message('size = ' .. size)
-------------------------------------------------------------------------------------------------
-- <Функция создания индикаторов> (<Параметры индикатора>)
-- Результат: функция-замыкание расчета индикатора.
------
-- Вызов полученного замыкания:
-- <Функция-замыкание>(<Очередное значение для расчета индикатора>)
-- Результат (возможно несколько значений, определяемых видом индикатора): значения индикатора,
-- определяемые параметрами создания замыкания на основе кода индикатора в папке ...Lua\\LuaIndicators.
-- !! В кодах индикаторов результат определяется функцией OnCalculate.
---------
-- ! Для сброса индикатора-замыкания в начальное состояние, его надо пересоздать.
---------------------------------------------------------------------------------------------------
local AC_IND1 = INDICATORS.AC(
3, -- Период короткой скользящей
5, -- Период длинной скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local AC_IND2 = INDICATORS.AC( -- return value
5, -- Период короткой скользящей
9, -- Период длинной скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local MA_IND1 = INDICATORS.MA( -- return value
5, -- Период скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local MA_IND2 = INDICATORS.ADX( -- return {['ADX'], ['+DI'], ['-DI']}
7, -- Период короткой скользящей
'EMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
-- Использование индикатора ---
for i = 1, size do
AC_IND1(DS:C(i))
end
for i = 1, size > 15 and 15 or size do
AC_IND2(DS:C(i))
end
for i = 1, size > 15 and 15 or size do
local tbl = {MA_IND1(DS:C(i))}
message('MA_IND1 : ' .. tostring(tbl[2]))
end
for i = 1, size > 100 and 100 or size do
MA_IND2(DS:H(i))
end
---- Сброс индикатора (запрос нового замыкания) ---
MA_IND2 = INDICATORS.MA( -- return value
100, -- Период скользящей
'EMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
-- Тест индикаторов Конец ----------------------------------------
while is_run do
sleep(timeout)
end
end
function OnStop()
is_run = false
return 10000 -- (млс.) ожидание завершения потока main прежде чем принудительное его завершение ---
end
------------------------------------------------------------------------------------------------ 2. Код модуля:
Код
--- Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/):
-- Примеры функций расчета индикаторов терминала QUIK на языке Lua.
--------------------------------------------
local IND = {}
---------------------------------------------------------------------------------------------------
--- КОНСТАНТЫ -------------------------------------------------------------------------------------
local SMA,MMA,EMA,WMA,SMMA,VMA = 'SMA','MMA','EMA','WMA','SMMA','VMA'
local OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = 'O','H','L','C','V','M','T','W','D','A'
---------------------------------------------------------------------------------------------------
---------------- Подключение к роботу индикаторы из папки LuaIndicators (с файлами кодов индикаторов) ------------
local pach_IND = getWorkingFolder() .. '\\LuaIndicators' -- Путь к кодам индикаторов --
-- ! Код индикатора из папки LuaIndicators помещаются в исходном виде внутрь оболочки-фабрики (на Lua),
-- обеспечивающей создание индикаторов-замыканий с параметрами заданными при вызове такой фабрики.
-- ! Пролог: начало функции-фабрики: ------
local Prologue = [[ -- создание окружения фабрики ---
local PRM = {...} ---
PRM = PRM[1] -- Таблица параметров индикатора ---
------------------------------------------------------
-- Таблица окружения создаваемого замыкания индикатора --
-- Начальная инициализация тиблицы-окружения замыканий-индикаторо (объектами, используемыми в вычислении индикаторов)
-- выполняется из ! текущего окружения фабрики. Существенно только то, что эти объекты должны существовать.
local ENV_IND = {
-- Объекты из _ENV, необходимые для расчета индикаторов --
tonumber = tonumber
, tostring = tostring
, type = type
, select = select
, table = table
, pack = pack or table.pack --
, unpack = unpack or table.unpack --
, string = string
, math = math
, package = package
, require = require
, debug = debug
, next = next
, os = os
, io = io
, RGB = RGB
, message = message
, getWorkingFolder = getWorkingFolder
, getScriptPath = getScriptPath
-- !! Переменнпой ENV_begin таблиц-окружения замыканий-индикаторов будет присвоено окружение-родитель (с чего все началось)
, ENV_begin = type(ENV_begin) == 'table' and ENV_begin or _ENV -- при первом формировании таблицы-окружения ENV_begin = _ENV
}
local ENV_ENV = _ENV -- Сохранения окружения --
_ENV = ENV_IND -- Переключение окружения перед инициализацией замыкания индикатора ---
]]
-- -- ! Эпилог: в конце функции-фабрики: ------
local Epilogue = [[
---- Начало эпилога ---
if not PRM then
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: не заданы параметры индикатора ' .. tostring(Settings.Name), 3)
return
end
---
for k, v in next, PRM do -- присвоение параметров индикатора --
if not Settings[k] then
-- #### Выдача сообщения об ошибки ---
message(debug.getinfo(1).currentline .. ' ! ОШИБКА в параметрах индикатора ' .. tostring(Settings.Name), 3)
end
Settings[k] = v
end
Init() -- Инициализация фабрики параметрами индикатора ---
-- Перегрузка function GetValueEX ---
function GetValueEX(I,VT, DS)
return ds_IND
end
-- Перегрузка function CandleExist(I,ds) -- проверка существования свечи ---
function CandleExist(I,ds)
return true
end
local Index_IND = 0 -- Внутренний счетчик обращения к индикатору (внешняя локальная переменная замыкания)---
------
_ENV = ENV_ENV -- Восстановление окружения ---
return -- возврат замыкания расчета очередного значения шндикатора --
function (DS) -- функция-замыкание для вычисления индикатора --
_ENV = ENV_IND -- ENV_IND - переменная хранения окружения, созданного для замыкания индикатора
ds_IND = DS -- Передача значения в расчет индикатора ----
Index_IND = Index_IND + 1
return OnCalculate(Index_IND)
end
]]
local Indicator_factories = {} -- таблица функций-фабрик создания индикаторов {<Имя индикатора> = <Функция>} --
----
-- Функция создает фабрики индикаторов на основе кодов из папки LuaIndicators --
-- Результат функция-замыкание индикатора: F_IND ---
-- Вызов функции: F_IND(val)
-- где val - очередное значение источника индикатора --
-- а результат функции: значения индикатора (их может быть несколько, в зависимости от вида индикатора)
local function Get_Indicator(Indic, Settings)
local func = Indicator_factories[Indic]
if not func then -- Ищется код индикатора и создается его фабрика ---
-- Создание фабрики индикатора (поиск кода индикатора, добавление пролога и эпилога,
-- компиляция и добавление в Indicator_factories)
local folder_of = pach_IND .. '\\' .. Indic .. '.lua'
local kod_IND
--- Чтениие источника ---
local kodZ, io_open, err = pcall( io.open, folder_of, 'r')
if io_open then
kod_IND = io_open:read('*a')
assert(io_open:close())
else
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: нет кода индикатора ' .. tostring(Indic), 3)
return
end
kodZ, func, err = pcall(load, Prologue .. kod_IND .. Epilogue)
if not func then
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: трансляции код индикатора ' .. tostring(Indic) .. '. Подробности: ' .. tostring(err), 3)
return
end
---
Indicator_factories[Indic] = func --
end
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова данной функции ---
return func(Settings) -- результат функция-замыкание индикатора ---
end
---------------------------------------------------------------------------------------------------
-- <Функция создания индикаторов> (<Параметры индикатора>)
-- Результат: функция-замыкание расчета индикатора.
------
-- Вызов полученного замыкания:
-- <Функция-замыкание>(<Очередное значение для расчета индикатора>)
-- Результат (возможно несколько значений, определяемых видом индикатора): значения индикатора,
-- определяемые параметрами создания замыкания на основе кода индикатора в папке ...Lua\\LuaIndicators.
-- !! В кодах индикаторов результат определяется функцией OnCalculate.
-----
-- ! Для сброса индикатора-замыкания в начальное состояние, его надо пересоздать.
---------------------------------------------------------------------------------------------------
--------------- Далее представлены три примера объявления заголовочных функций описаний параметров
-- подключаемых индикаторов. Параметры такой функции это список полей из таблицы Settings соответствующего
-- индикатора папки LuaIndicators, для которых требуется задать значения, определяющие поведение создаваемого
-- замыкания. Результат: значения функции OnCalculate (их может быть несколько) оответствующего индикатора.
-- AC (Accelerator/Decelerator Oscillator)
IND.AC = function(
SHORT_Period, -- Период короткой скользящей
LONG_Period, -- Период длинной скользящей
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
SHORT_Period = SHORT_Period,
LONG_Period = LONG_Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции--
return Get_Indicator('AC', Settings)
end
--Average Directional Movement Index ("ADX")
IND.ADX = function(
Period, -- Период
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
Period = Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции-
return Get_Indicator('ADX', Settings)
end
--Moving Average ("MA") ( 50000 циклов, Period = 100, Metod = SMA: 340 млс.)
IND.MA = function(
Period, -- Период
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
Period = Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции-
return Get_Indicator('MA', Settings)
end
-- И так далее (по образу и подобию уже представленных) ---
return IND
VPM написал: Проблема лежит в прямой плоскости озвученной в заголовке данной ветки - системе принятия решений.
Ну, надо же. какая глубокая мысль . Глаза нам открыли.
Цитата
VPM написал: проблема чисто на мой взгляд математическая, давно известная человечеству, да и мне, просто откладывал ее решения на потом, видимо настал тот потом.
Зачем откладывали? Ждем вашего решения и запасаемся поп-корном .
Цитата
nikolz написал: возникает маcштаб или фрактальность, всё б ни чего когда котировки цены разных инструментов одинаковы или близки.
Serge123 написал: Адрес структуры для локальной строки передаётся в виде указателя в параметре при вызове из Lua скрипта моей dll.
Далее: char* str_h = (char*) Адрес структуры; И с str_h (указатель открытый для записи) делаете все, что хотите (в пределах размера строки). Но, написанное выше не отменяет, то, что так делать не стоит. Вам интересно стрелять по своим ногам? Если вы так сильно озабочены эффективностью (только непонятно что вас не устраивает, конкретно для решения вашей задачи, в Lua?), то, наверное, для вас имеет смысл все, кроме интерфейса с QUIK, писать на C (а может быть на MASM ). Все остальное будет менее эффективно и скорее всего затратнее, с учетом необходимости выполнения научно-исследовательской работы по скрещиванию dll с Lua .
VPM написал: Так как складывается впечатление что Вы часть лекций пропускали, ни какой аргументации, одни эмоции, извините ну мне не интересно
У вас не только тексты, но впечатления сильно ошибочные . На всякий случай, я закончил ведущий московский институт с красным дипломом. И хорошо что вам стало неинтересно.
VPM написал: Они не имеют собственного стека вызовов, а используют стек вызовов основного потока.
Опять не поняли (хотя написали формально правильно), что сопрограммы не могут выполняться параллельно с потоком, в котором вызваны, Вы понимаете что представляет собой поток в windows?
VPM написал: что Вас так разволновало, Вы не знакомы сопрограммами или функциями обратного вызова? Или Вам не известно что в LUA реализована неблокирующая, асинхронная обработка сопрограммы : События обрабатываются в фоновом режиме, что позволяет приложению продолжать выполнять другие задачи без блокировки, до вызова события? Ну так попробуйте пример. Уже все рассказал и показал.
Если бы вы это писали в своем локальном дневнике, то мне бы было "по баробану", но вы это заявляете публично и безопяляционно, с уверенностью "отбитого" дилетанта. Вы же вводите в заблуждение тех пользователей, для которых программирование не является профессиональной деятельностью. Вы, что не понимаете, что сопрограммы выполняются в общем потоке с функцией, вызвавшей ее? Никакого фона выполнения сопрограмм не существует. Вообще, прежде чем выкладывать свои завиральные идеи, наверное, вам было бы полезно что-то почитать по IT.
VPM написал: Вы вообще о чем? Вы себя о позиционируете как опытного знающего программиста, не хотите обсудить код?
Причем тут опытный, знающий программист. Почитайте про взаимодействие коллеков и потока main в истории форума. Там много не моих сообщений. После чтения истории, вы, наверное, сможете понять, что коллбеки и поток main выполняются последовательно и тогда зачем мне читать ваш текст, в котором присутствуют какие то фоновые потоки вашего воображения.
VPM написал: TGB , "Зачем козе баян"? В Ваш "неокрепший ум смуту" внести мне не под силу. Вам бы не мешало для начало научиться читать, от начало до конца, улавливая смыслы. А поэтов здесь хватает и без Вас.
Вы меня, наверное, не поняли. Все-таки надо читать историю форума. Если вы хотите продолжить общение со мной в стиле (посмотрите начиная со ссылки и до конца ветки): https://forum.quik.ru/messages/forum10/message62917/topic7277/#message62917, то, при том что это мне не интересно, я вам это обеспечу.
Serge123 написал: И ещё я вижу торможение, когда окно "Доступные скрипты" располагаю поверх стаканов. В этом случае хорошо видно, что циферки занятости памяти напротив скрипта перерисовываются не мгновенно. Хотя, GPU в диспетчере тоже простаивает, как и CPU. Поэтому я не знаю, как объяснить это торможение.
Serge123 написал: В принципе, ясно. Тогда, получается, что у меня память не утекает? Надо попробовать запустить сборщик мусора явно и посмотреть, сколько памяти освободится.
Возможно я ошибаюсь, но вашей целью является получение прибыли на фондовом рынке. А если это так, то тестирование Qlua - это потеря вашего времени. Я понимаю, что вы по своей натуре перфекционист (все должно быть понятно и идеально), но вам приходится жить в этом неидеальном мире и поэтому, как мне кажется, стоит "забить" на его несовершенство. Среда, в которой вы реализуете свои алгоритмы несовершенна, но этим стоит заниматься только тогда, когда это вам мешает конкретно. Иначе вы будете решать чужие задачи (вроде отладки Lua).
VPM написал: Суть в следующем: В Lua относительно легко реализуется, событийно-ориентированная модель программирования, она хорошо подходит для обработки асинхронных событий. Такой подход позволяет приложениям Lua обрабатывать несколько событий одновременно без блокировки основного потока выполнения приложения. События обрабатываются в фоновом режиме, не прерывая поток выполнения приложения.
Вы зачем вносите "смуту" в неокрепшие умы ? Откуда вам известно, что коллбеки не блокируют поток main? Вы прежде чем писать свои сообщения, почитайте сообщения, квалифицированно объясняющие взаимодействие коллбеков и потока main (их много, написанных ранее чем вы появились на форуме). Оттуда вы сможете почерпнуть, что коды на Lua (это не C-функции) синхронизируются (выполняются последовательно, то есть, когда выполняется Lua-код, то Lua-код потока main блокируется и наоборот). Вообще, я не стал бы комментировать ваше сообщение, но вы своими безопеляционными сообщениями можете сбить с толку тех, кто не в теме. Свои неокрепшие мысли, наверное, можно записывать в своем локальном дневнике.
Serge123 написал: С каждой записью в файл утекает ~ 50 байтов памяти, а почему она не собирается сборщиком мусора??
Утечка есть. Это ошибка разработчика языка Lua 5.4.1 при реализации стандартных функций io. Файлы это не тип данных Lua и сборщиком мусора они не обрабатываются, поэтому и требуется функция close (в которой похоже есть ошибка).
Этот комментарий, сугубо, для поддержки QUIK. --- Как результат * в данной ветке, возникло дополнительное предложение: 4) На форумах ARQA для комментирующих пользователей ввести месячный лимит трафика, после которого не будет возможность вводить комментарии. Значением этого лимита могло быть: <Годовой трафик nikolz> / 12 / 10. Но, конечно, насчет значения лимита, решать ARQA. Наличие такого лимита, обеспечило бы: - экономию дискового пространства баз форумов; - автоматическое модерирование форумов за счет принуждения думать о краткости и четкости текстов, пишущих комментаторами; - удобство для читающих комментарии, в которых будет меньше флуда.
nikolz написал: Я на форуме не только предлагал, но и показывал как это работает у меня.
Вы опять не поняли. Я эту ветку создал не для того чтобы обсуждать свои или чужие решения. До сих пор я понимал и решал свои проблемы и при этом пользовался интернетом. Если вы читали мой первый комментарий, то в нем написано как можно улучшить QUIK. 2.
Несмотря на написанное мною в первом пункте, посмотрел и впечатлился: .
Цитата
nikolz написал: Смотрим первую картинку. Нижнее 3 окно в ней - это график прибыль/убыток за 2023 год. линия зеленая на оси справа показывает положительные 220% -это профит лонг. линия синяя на оси справа показывает положительные 150% - это профит short линия белая на оси справа показывает положительные 370% - это профит long+short.
Сдаюсь . Таких годовых процентов у меня не было. Вам мой совет возьмите кредит, ну хотя бы 1000000 руб., ну хотя бы под 20% годовых на 3 года. Вам светит за три года приблизительно следующая сумма: 1000000 * 3,7 * 3,7 * 3,7 - 1000000 - 3*1000000*0,2 = 49000000 руб. А может вы уже и сейчас миллиордер ?
Судя по тому, что вы всегда цитируете сообщения полностью (даже самые длинные), вы, наверное, спамер. Но нельзя исключать с учетом качества выдаваемого вами текста, что вы полуинтеллектуальный робот-спамер .
nikolz написал: Если Вы это сообщение выводите в файл, то пишите сразу в файл. куски сообщения. Каждый новый кусок добавится в конец файлаВ итоге Вам не надо наращивать строки.
nikolz писатель? Зачем вы пишите, то что было уже написано два раза?: 1)
Цитата
TGB написал: Почему бы не записывать строку сразу в файл (в системе это буферизуется). Вы проверяли, сколько записей выполняется в файл за 1 секунду, если писать напрямую? Если вы это сделаете, то, возможно, удивитесь.
2)
Цитата
Nikolay написал: У меня такие потоки для каждой новой записи просто пишутся в файл черезf:write(str..'\n')
nikolz написал: Это делается очень просто. ----------------------Применяю это с момента появления VMLua в КВИКЕ.---------------------Возьмите готовую библиотеку https://quik2dde.ru/viewtopic.php?id=78 ------------------и используйте всего две функцииCreateEvent и WaitForSingleObject-------------------Как реализовать очередь есть в документации QLUA
Опять вы не поняли. То о чем вы пишите, я у себя реализовал давно, как только начал разбираться с QUIK. Сутью 2-го пункта является;
Цитата
TGB написал: в такой схеме решается тяжелая задача подключения новых версий Lua в QUIK, так как не будет требоваться конфигурирования Lua для многопоточного использования (из-за запуска функций коллбеков в потоке, отличном от потока main, но в контексте пользователя). Подключение новых версий Lua в QUIK станет в описанной выше схеме рутинной задачей.
2.
Цитата
nikolz написал: TGB , Sleep - это функция, которая останавливает поток и возвращает управление OC. Что Вы будете модифицировать в ней?
Опять, та же фигня . Я пишу про sleep (это функция QLua):
Цитата
TGB написал: Это вызов функций обработки коллбеков в видоизмененной sleep с параметрами в нужном формате, считанными из предлагаемых очередей (очереди).
а вы про системную Sleep. Вы, что, не понимаете разницы?
3.
Цитата
TGB написал: Вы, похоже, очень наивны и полагаете, что разработчики работают за бесплатно? Можно, наверное как то сообразить, что часть комиссии, уплачиваемая брокерам пользователями, идет на зарплату разработчикам, а также в доход акционерам ARQA.
Serge123 написал: хочется копать вглубь и искать там золотые самородки. До сих пор ничего роботоподобного не сделал...
Прежде чем копать, наверное, стоит выбрать место для копания. То есть, сначала поторговать вручную, чтобы понять что это такое, но без фанатизма, чтобы не слить весь ваш депозит. При этом надо понимать, что реально работающую стратегию, стабильно, без провалов, приносящую доход хотя бы в 20% (в текущий момент) на годовом периоде, вам никто не предложит. Подумайте, зачем банкам бегать за клиентами с предложениями кредитов под 15% если на фондовом рынке можно заработать 20%. Фондовый рынок, локально, это игра с "псевдо-нулевой" суммой (деньги на нем не создаются а перераспределяются) и если какая то стратегия оказывается выигрышной, а затем получает широкое распространение, то она перестает работать. После некоторого периода ручной торговли сделайте простого робота исключительно на QLua, который смог бы вас заменить, а также торговать на истории. И только после этого начните поиск своей стратегии и оптимизацию того, что имеет смысл оптимизировать.
2.
Цитата
Serge123 написал: На этом форуме могут до кровохарканья обсуждать двойные и тройные очереди, показывать загадочные картинки, от которых рябит в глазах, но ничего действительно полезного не скажут.
Не согласен (частично). Конечно, на форуме много флуда, но тот же Nikolay написал вам практически все об обработке обезличенных сделок.
Евгений написал: Подскажите выскочила ошибка: "attempt to index a nil value" на строчку: "if getFuturesLimit(FIRM, ACCOUNT, 0, "SUR").cbplplanned==nil then"Вроде как раз на nil проверяю.
У вас getFuturesLimit(FIRM, ACCOUNT, 0, "SUR") равно nil, а его индексировать нельзя.
Мне интересна реакции разработчика QUIK, в лице поддержки, на те пункты, которые мною предлагаются. -------- На всякий случай, по пункту 2: Есть вариант его реализации таким образом. чтобы сохранить существующий интерфейс QLua c QUIK, с тем, чтобы пользователям не надо было изменять существующие скрипты. Это вызов функций обработки коллбеков в видоизмененной sleep с параметрами в нужном формате, считанными из предлагаемых очередей (очереди).
Serge123 написал: Тогда посмотрите на кусочек от вывода моего Луа скрипта, который обрабатывал OnAllTrade от 4 января 2023 г.:
Я согласен с тем, что написал Nikolay. Но если вы хотите разобраться с тем как вызываются коллбеки OnAllTrade реально, то в ваш вывод нужно добавить колонку времен вызова этого коллбека (используя функцию QLua os.sysdate() с детализацией до микросекунд).
Serge123 написал: Тут дело не в том, что есть запись на диск, а в том, что за 1 мкс десятки раз может выполняться оператор
Где вы обнаружили коллбеки QUIK, вызываемые десятки раз за 1 мкс? Не знаю, будет ли для вас это существенно, но одна из моих практических профессиональных специализаций: параллельное программирование и разработка систем реального времени. Возможно я ошибаюсь, но у меня возникло представление, что вы пытаетесь бороться с привидениями, многие из которых у вас не материализуются .
Serge123 написал: Есть строка mess (age), в которой коллбэки накапливают свой вывод, при превышении определённой длины строка записывается в файл.
Почему бы не записывать строку сразу в файл (в системе это буферизуется). Вы проверяли, сколько записей выполняется в файл за 1 секунду, если писать напрямую? Если вы это сделаете, то, возможно, удивитесь. Вообще то, если для вас важна эффективность, то имеет смысл, прежде чем заниматься оптимизацией, выяснять: а нужно ли это делать. Эффективнее всего выполняется то, что ничего не делает .
2.
Цитата
Serge123 написал: Мне кажется, что ничего не случится, если извне (из длл) строка будет изменена, ведь, если строка не находится внутри таблицы, вычисление хеша от неё не нужно?
Если нет желания заниматься длительной научно-исследовательской деятельностью, то для взаимодействия dll и Lua надо использовать только C API. ------ И «перегруженный» анекдот про чукчу: Чукча и геолог ловят рыбу зимой на льду. Геолог приехал на рыбалку на снегоходе, а чукча пришел на лыжах. Вдруг видят направляющегося к ним голодного белого медведя. Ружья нет. Чукча хватает лыжи и начинает их надевать. Геолог: - Бесполезно. Все равно ты не сможешь бежать быстрее медведя. - А мне и не надо бежать быстрее медведя. Мне достаточно того, что медведь сюда добежит раньше, чем ты заведешь свой быстро бегающий снегоход.
Constantin написал: Как я понимаю человек предлагает вызывать колбеки в потоке Lua-скрипта.
Один из возможных вариантов предлагаемой обработки событий Qlua: 1) вместо регистрации функций обратного вызова, регистрация соответствующих потокобезопасных очередей событий (возможно, с теми же именами); я бы сделал эти очереди (можно, в принципе, обойтись и одной) циклическими, с указанием их длины при регистрации, но не более некоторого значения; 2) вместо sleep, служебная функция с тем же именем ожидания либо истечения интервала времени (как в sleep), либо появления данных в очередях событий (с выдачей списка непустых очередей); 3) добавление функции чтения очередей событий (их параметров). Эта схема реализует рекомендованную ARQA обработку параметров событий в main (смотрите "Использование Lua в Рабочем месте QUIK"), с тем, чтобы не было проблем синхронизации в скриптах. Кроме того, в такой схеме решается тяжелая задача подключения новых версий Lua в QUIK, так как не будет требоваться конфигурирования Lua для многопоточного использования (из-за запуска функций коллбеков в потоке, отличном от потока main, но в контексте пользователя). Подключение новых версий Lua в QUIK станет в описанной выше схеме рутинной задачей.
nikolz написал: Вам не нравиться ,что в основном потоке терминала выполняется:запуск всех Lua Скриптов пользователя.--------------И что в этом плохого?
Это мелочь, но при условии, что пакеты в скриптах подключаются в потоке main. Иначе одновременный запуск нескольких скриптов выполняется долго (из-за того, что это это выполняется в одном потоке).
2.
Цитата
nikolz написал: Мое мнение:Колбеки не запускаются, а вызываются.
Пусть для вас вызывается, а для меня запускается . Кому непонятно, что это одно и тоже?
3. По остальной части вашего комментария: Пользовательские индикаторы в графиках обрабатываются в основном (единственном) потоке. Это медицинский факт. Если вы не знаете как это проверить экспериментально, то я вам расскажу как это сделать. дополнительно, в основном (единственном) потоке запускаются коллбеки всех скриптов пользователя, а также вызываются коллбеки всех таблиц QUIK, созданных пользователем. Наверное, понятно и ежу, что в текущий момент в одном потоке все это будет выполняться последовательно. Это значит, что на архитектурном уровне QUIK в текущий момент существует зависимость по выполнению для его различных функциональностей, что является некоторым дефектом. Кому это непонятно?
3.
Цитата
TGB написал: Вы, похоже, очень наивны и полагаете, что разработчики работают за бесплатно? Можно, наверное как то сообразить, что часть комиссии, уплачиваемая брокерам пользователями, идет на зарплату разработчикам, а также в доход акционерам ARQA.
VPM написал: получается что нужно отказаться от отдельного потока main и выполнение main разместить в основном потоке , при этом создав "активную очередь событий".
Я этого не писал. ------- Вообще то, не хочу вас, обидеть, но в моем сообщении пункты 1) и 2) написаны не для либеза. Думаю, что разработчикам QUIK понятно о чем я пишу в этих пунктах.
Где вы у меня прочитали, что все запущенные пользовательские скрипты работают в одном потоке? У меня написано:
Цитата
TGB написал: В текущей версии в одном основном потоке обслуживаются: - запуск всех Lua-скриптов пользователя; - запуск коллбеков всех Lua-скриптов пользователя; - обработка всех коллбеков таблиц QUIK (это не таблицы Lua); - обработка всех индикаторов пользователя.
Вам до сих пор неизвестно, что в QUIK существует служебный, так называемый основной единственный поток, выполняющий то, что перечислено мною выше? Когда же вы научитесь читать чужие сообщения?
2.
Цитата
nikolz написал: Разработчики дали решение этой проблемы. Оно прекрасно работает. Так как QUIK - это бесплатное приложение, то дареному в... не заглядывают. сделать что-то еще - это их право, но не обязанность.
Вы, похоже, очень наивны и полагаете, что разработчики работают за бесплатно? Можно, наверное как то сообразить, что часть комиссии, уплачиваемая брокерам пользователями, идет на зарплату разработчикам, а также в доход акционерам ARQA.
В Новосибирске, когда то была хорошая школа IT-шников. И что-то, наверное, от нее осталось. Я надеюсь, что архитектором QUIK в текущий момент является один из выпускников этой школы. В QUIK все равно будут вноситься изменения (чтобы оставаться «наплаву»). И мне видится, что улучшить QUIK, помимо исправления существующих, неизбежных ошибок, можно внеся в него следующие изменения/дополнения: 1) В текущей версии в одном основном потоке обслуживаются: - запуск всех Lua-скриптов пользователя; - запуск коллбеков всех Lua-скриптов пользователя; -- обработка всех коллбеков таблиц QUIK (это не таблицы Lua); -- обработка всех индикаторов пользователя. Притом, что в текущий момент у подавляющего количества ПК много ядер ЦП, написанное выше явный перебор. Мне, представляется, что нет проблем перечисленное выше обрабатывать в отдельных потоках. Иначе, это ограничение пользователя в использовании возможностей его ПК. 2) Интерфейс взаимодействия QUIK c Lua-скриптом пользователя, реализованный в виде коллбекков, предполагает многопоточный режим использования Lua,. порождающий неприятные проблемы параллельного программирования (для решения которых сами же разработчики предлагают использовать потокобезопасную очередь между коллбеками и потоком main). Мне представляется, что имеет смысл вместо коллбеков использовать активную очередь событий, При этом не требуется использовать Lua в многопоточном, редко используемом и не очень стабильном режиме. При этом не будет проблем с подключением новых версий Lua. Более того, скрипты пользователя будут выполняться несколько быстрее из-за отсутствия синхронизации, требуемой в многопоточном варианте использования Lua. 3) В QUIK реализована функциональность просмотра графика котировок бумаг QUIK. Но отсутствует возможность просмотра котировок бумаг, сохраненных во внешних файлах. С учетом существующей функциональности QUIK, как мне представляется, реализация этой возможности не потребует больших усилий.
nikolz написал: Мне даже показалось, что вы имеете отношение к этому сайту.
Действительно на этом сайте я написал несколько заметок. И когда я начал в 2019 г. разбираться с QUIK, то обнаружил, что для меня это самый полезный сайт. Но я в своем сообщении сослался не на ту заметку, про которую вы пишите, а на "Краткую справку по Lua", в которой, кстати есть и описание C API Lua с примерами. На этом же сайте есть как минимум один функционально законченный пример использования C API Lua от Дмитрия.
2
Цитата
Serge123 написал: А тут мощь dll, которая оттранслирована с оптимизацией и поддержкой наборов вплоть до AVX2, будет кстати.
И вы знаете как использовать эту мощь для получения дохода на рынке с помощью QUIK, обеспечивающего как минимум секундную реакцию на события рынка? Возможно я ошибаюсь, но мне представляется, что вы пытаетесь "запрягать лошадь с хвоста". Вообще то, существует известная и проверенная временем методология разработки программ. Суть этой методологии в том, чтобы быстро получить работающий, модульный прототип и в конкретном случае это проще сделать используя Lua (а при необходимости готовые пакеты dll). А дальше выяснять проблемы (в том числе и с производительностью) и вносить изменения. С учетом того что Lua тесно интегрирован с C/C++ проблем с переходом из Lua в C нет, но это может и не потребоваться.
Serge123 написал: Прямого ответа обычно не дают, а как-то ходят вокруг да около этого вопроса...
На форуме много сообщений о том, что не надо писать сложно. Надо писать модульно, стараясь не создавать "зоопарк" программных средств , чтобы потом не было больших проблем с неизбежными изменениями. Практически любого робота для QUIK можно написать используя только Qlua (Lua). В сети есть много описаний (достаточно коротких) о том, что собой представляют таблицы Lua и как с ними можно работать (например, на сайте https://forum.quik.ru/ выложена краткая справка по Lua). Зачем вы мучаетесь с C API Lua? Что вы не можете сделать в Qlua (Lua)?
Владимир написал: А ограничивать это НУЖНО! Софт и так на ладан дышит
Не заметил проблем с производительностью. Действительно, ни микросекунды, ни тысячи тикеров, ни параллельные потоки, если кто понимает, не нужны. Для индивидуалов вполне можно обойтись несколькими десятками тикеров и реакцией в секунды. Тем более, что QUIK не позиционируется для безумной высокочастотной торговли.
Владимир написал: КАКОМУ ДЕБИЛУ понадобился "расчёт количества лотов конкретного инструмента с учётом состояния портфеля"? При чём тут плечи и вообще брокеры? Какое моё собачье дело до ИХ "представлений о рисках предоставления плеч для разных инструментов и разных в разное время"? На кой мне "максимально возможное количество лотов в заявке"?
Ну, не все же гениальные как вы . И какой то дебил это хочет знать. Ну и пусть. Зачем кого то ограничивать при наличии своих неограниченных способностей ?
Владимир написал: Если чел не способен самостоятельно посчитать такую ерунду, его надо поганой метлой гнать из программирования.
Мысль интересная . Я не умею считать такую ерунду. Пожалуйста, напишите формулу расчета количества лотов конкретного инструмента с учетом состояния вашего текущего портфеля, с учетом допустимых плеч у брокеров, зависящих об их конкретных представлений о рисках предоставления плеч (возможно, разных для покупки и шорта, разных для разных инструментов и разных в разное время). Если бы я знал риски брокеров по инструментам, то такую формулу бы написал. Вы экстрасенс ?