paluke написал: Поддержка вместо 1. #### и 2.#### предлагала SetEmptyCallback() перед Close().
Да. Это работает. Но в документе: функция SetEmptyCallback позволяет получать данные с сервера. И нет описания, что Close не закрывает источник без предварительного вызова SetEmptyCallback.
VPM написал: На самом деле проблема стара как этот мир (в нашем случае квик)
Скрипты в QUIKе это программы реального времени, в которых существенен фактор времени. В коде, выложенном ниже, определена функция CreateDS, которая дожидается появления данных DS.
Код
stopped = false
function main()
-------------------------------------------------------
-- Создание параметризированной функции-замыкания коллбека (с дополнительными (кроме index)
-- параметрами ds и par, задаваемыми в момент создания).
-- Использование ds:SetUpdateCallback(CreateUpdateCallbackDS(func, ds, par))
-- параметр par необязателен, но если он fаlse, то тело функции не выполняется.
-- ! Исключения в функции коллбека перехватываются. Коллбек при этом отключается с выдачей сообщения об исключении.
-- Параметры:
-- func(index, ds, par) - функция обработки коллбеков (вызываемых по изменениям свечи) --
-- ds - открытый источник;
-- par - параметр (может отсутствовать) --
-- index - индекс свечи при выполнении коллбека;
-- Результат: параметризированная функция-замыкание - параметр для функции ds:SetUpdateCallback ---
local CreateUpdateCallbackDS = function(func, ds, par)
return
function(index) -- Обертка для func --
if par ~= false then
local kod, mes = pcall(func, index, ds, par) -- в защищенном режиме --
if mes then
message('Исключение в коллбеке (он отключен, его 3-й параметр : '.. tostring(par) .. '). Текст исключения: ' .. mes, 3)
par = false
end
end
end
end
--------------------------------------------------
--- Cl - класс, Sec - код бумаги, Int - таймфрейм.
--- T - ожидание поступления данных источника в сек. (по умолчанию 15 сек.)
local CreateDS = function(Cl, Sec, Int, T)
T = (T or 15) * 10
local ds, Error = CreateDataSource(Cl, Sec, Int)
for i = 1, T do
if not ((Error == "" or Error == nil) and ds:Size() == 0) then break end
if i == T then error('Не дождались DS: ' .. Sec .. '. Ошибка: ' .. tostring(Error)) end
sleep(100)
end
return ds
end
---------------------------------------------------
-- Вариант многократно используемой параметризированной заготовки для создания коллбеков в CreateUpdateCallbackDS --
local function cb_p(index, ds, sec_code)
local t = ds:T(index)
local _str = string.format("#%d of %d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f %02d.%02d.%04d %02d:%02d:%02d.%04d\n",
index, ds:Size(),ds:O(index), ds:H(index), ds:L(index),
ds:C(index), ds:V(index),
t.day, t.month, t.year, t.hour, t.min, t.sec, t.ms)
message(sec_code .. ': ' .. _str)
end
---------
local ds
local function cb(index) -- одноразовая функция коллбека -
local t = ds:T(index)
local _str = string.format("#%d of %d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f %02d.%02d.%04d %02d:%02d:%02d.%04d\n",
index, ds:Size(),ds:O(index), ds:H(index), ds:L(index),
ds:C(index), ds:V(index),
t.day, t.month, t.year, t.hour, t.min, t.sec, t.ms)
message(_str)
end
ds = CreateDS("QJSIM", "GAZP", INTERVAL_M1)
message('Size = ' .. ds:Size())
-- Вариант с созданием функции-замыкания, выдающей сообщение об исключениях во время ее выполнения ---
ds:SetUpdateCallback(CreateUpdateCallbackDS(cb))
-- ds:SetUpdateCallback() -- 1. #### это не помогает
-- ds:SetUpdateCallback(function() end) -- 2. #### и это не помогает
ds:Close() -- ?? После Close повторно установленные один раз коллбеки не срабатывают (
-- хотя источник открывается)
ds = CreateDS("QJSIM", "GAZP", INTERVAL_M1)
-- ds:SetUpdateCallback(function() end) -- 3. #### это тоже помогает вместо последующего ds:SetUpdateCallback(cb)
ds:SetUpdateCallback(cb) -- Обычный вариант (если в функции коллбека cb возникает исключение,
-- то коллбек перестает выполняться, но сообщения об этом нет)
ds:SetUpdateCallback(
CreateUpdateCallbackDS(cb_p, ds, "GAZP")) -- 4. #### Повторная установка параметризированного
-- коллбека. Если это закомментировать, то коллбек не запускается
-- ds:SetUpdateCallback(cb) -- 5. #### Это , вместо пункта 4, тоже проходит
while not stopped do
sleep(3000)
-- message('while Size = ' .. ds:Size())
end
end
function OnStop(row)
stopped = true
end
---
-- Резюме (смотрите комментарии, выделенные строкой ####).
--- После ds:Close(), ds = CreateDataSource(...) повторно установленный коллбек cb не срабатывает
-- (хотя источник открывается и свечи приходят).
-- Но если устанавливать два раза: ds:SetUpdateCallback(cb) ds:SetUpdateCallback(cb),то cb срабатывает --
2. В том же коде определена функция CreateUpdateCallbackDS - создание параметризированных замыканий-коллбеков на основе функций заготовок (в коде примера: функция cb_p). Функцию-заготовку можно использовать, создавая коллбеки для многих разных источников DS. При этом обеспечивается выдача сообщений об исключениях времени выполнения колбека (что не делается штатными средствами).
3. В коде комментариями, помеченными строкой ####, описываются "танцы с бубном" с тем, чтобы повторно подключить коллбек к повторно открытому DS. Вопрос к поддержке: что еще надо показать, чтобы стало ясно, что в ds:Close() есть ошибка?
Да, не потокобезопасна в ванильном режиме. Но разработчик Lua предусмотрел (и, возможно, напрасно) вариант использования инстанции Lua в нескольких потоках в режиме разделения, когда коды Lua могут быть использованы только одним потоком. Для этого варианта надо вносить изменения в исходники Lua, обеспечивающие синхронизацию разделения. С чем разработчик QUIK немало "покувыркался". Если исходить из того, что синхронизация сейчас реализована корректно, то перед выполнением коллбеков мусорщик можно было бы не останавливать. Отсутствие сборки мусора при выполнении коллбека обеспечивает: 1) сокращение времени его выполнения; 2) и что не менее важно, дополнительную страховку от возможных ошибок синхронизации, запрещая работу коллектора, который обрабатывает все стеки инстанции Lua. Но после выполнения коллбека должно быть восстановлено то состояние коллектора, которое было перед выполнением коллбека. Вообще то, я уже пару раз описывал, как можно изменить схему взаимодействия скриптов Lua с QUIK, чтобы уйти от "интересных" проблем синхронизации потоков. Более того это несколько бы ускорило выполнение скриптов (освобожденных от выполнения кода синхронизации).
nikolz написал: Т е в каком стеке Вы вызовите сборщик, тот стек он и будет чистить.
Цитата
TGB написал: В конце концов, можно почитать книгу Р. Иерузалимски
Вы умеете читать? Или только пишите ? Цитата из книги 32.2 Сборщик мусора: "Фаза очистки обходит все объекты Lua." Вы понимаете, что в Lua объектами являются и его стеки? В конце концов, детали сборки мусора вы можете посмотреть в исходниках Lua.
TGB написал: Надо: 1) сохранять состояние сборки мусора скрипта перед выполнением коллбека; 2) отключать сборку сборку мусора; 3) выполнять коллбек; 4) восстанавливать состояние сборки мусора.
Если это непонятно, то в переводе на коды это, примерно, следующее (три строки не считая комментариев и пробелов):
Код
--- Перед выполнением коллбека ---
local isrunning = collectgarbage('isrunning')
if isrunning then collectgarbage('stop') end
--- Выполнить коллбек ---
--- После выполнения коллбека ---
if isrunning then collectgarbage('restart') end
nikolz написал: сборщик мусора собирает мусор в в стеке основном VM.но при этом он не видит стек коррутины
Кто вам это рассказал или где вы это прочитали ?
Цитата
nikolz написал: Я полагаю что делается запуск сборщика для области стека корутины main.
Зачем что то предполагать, когда можно узнать точно как это устроено? И для этого на сайте разработчика существуют свободно доступные исходники Lua. Из них вы бы узнали, что управление памятью в Lua общее для всех его стеков и нет специального запуска сборщика для области стека корутины main. В конце концов, можно почитать книгу Р. Иерузалимски.
TGB написал: В версии QUIK 12.2.2.8 (а, похоже, и в более ранних) при запуске любого коллбека отключается сборка мусора (collectgarbage('stop')), а после его отработки включается (collectgarbage('restart')). Это ошибка. Коллбеки не должны менять состояние уборки мусора после своего выполнения, а должны восстанавливать то, которое было перед их выполнением.
Вроде, написано понятно, но если непонятно, то демонстрирую кодом:
Код
local OK = false
function OnParam()
OK = true
end
function main()
_RUN_ = true
collectgarbage('stop') -- Сборка мусора отключена --
while _RUN_ do
if not collectgarbage('isrunning') then
if OnParam and OK then
message(' Ошибка обработки коллбеков устранена. '
.. 'В скрипте где то был остановлен сбор мусора. '
.. 'Вызов коллбека OnParam не меняет состояние сборки мусора', 3)
end
end
sleep(3000)
end
end
function OnStop()
_RUN_ = false
return 10000
end
Если код выполняется при подключенном к серверу QUIKе и при этом нет сообщения: "Ошибка обработки коллбеков устранена. ............" , то понятно, что коллбек OnParam включил сборку сборки мусора, отключенную разработчиком в скрипте.
TGB написал: Коллбеки не должны менять состояние уборки мусора после своего выполнения, а должны восстанавливать то, которое было перед их выполнением.
В версии QUIK 12.2.2.8 (а, похоже, и в более ранних) при запуске любого коллбека отключается сборка мусора (collectgarbage('stop')), а после его отработки включается (collectgarbage('restart')). Это ошибка. Коллбеки не должны менять состояние уборки мусора после своего выполнения, а должны восстанавливать то, которое было перед их выполнением. ----- Разработчик скрипта может в какой-то момент отключить на какое то время уборку мусора (имеет право), а тут прилетает любой коллбек и все портит.
В версии QUIK 12.2.1.2 (а, похоже, и в более ранних) при запуске любого коллбека отключается сборка мусора (collectgarbage('stop')), а после его отработки включается (collectgarbage('restart')). В общем, решение разумное, повышающее надежность, но не сохраняющее состояние сборки мусора скрипта. Это неправильно. Надо: 1) сохранять состояние сборки мусора скрипта перед выполнением коллбека; 2) отключать сборку сборку мусора; 3) выполнять коллбек; 4) восстанавливать состояние сборки мусора.
Вы живете в идеальном математическом мире ? Кто вам сказал, что рынок описывается вашей математической моделью? Есть хорошая Ньютоновская модель описания макромира, но она не сильно подходит для описания микромира и это определяется эмпирически (на экспериментах). Вы не поняли, что авторы, предлагающие универсальные доходные стратегии торгов либо сильно наивные люди, но скорее хорошие предприниматели. Я написал:
Цитата
TGB написал: принципиальной особенностью прибыльной стратегии является ее зависимость от поведения участников фондового рынка (многие из которых используют роботы) и ограниченность круга участников, ее использующих.
где "ограниченность круга участников" является ключевым утверждением. --- Представьте на минуту, что вы сумели найти доходную стратегию торгов устойчиво обеспечивающую прибыль 60% годовых. Если вы хоть что-то понимаете в фондовом рынке, то как только эту стратегию станут использовать другие участники рынка, то они будут разрушать вашу стратегию. ----- Я допускаю что многочисленные авторы что-то заработали на рекламируемых ими стратегиями торгов, но сейчас они зарабатывают на издаваемых ими книгах.
VPM написал: Разработка и оптимизация торговой стратегии — это сложный процесс, который требует глубокого понимания рынка и инструментов анализа.
Согласен. -------- Но не надо питать особых иллюзий относительно написанного VPM в декларотивном / рекламном стиле . Фондовый биржевой, краткосрочный (с периодом до полгода) рынок — это, во многом, рефлексивная игра с локально псевдо-нулевой суммой. Во-первых, он существенно зависит от действий его участников, а во-вторых, на нем деньги не создаются, а, в основном, перераспределяются между его участниками. Прибыль любого его участника — это, в конце концов, в значительной части, чьи-то убытки. Если предположить, что все участники такого рынка, используют некоторую общую прибыльную стратегию торгов, то, понятно, что все они, одновременно, в прибыли не окажутся. Таким образом, не существует общей прибыльной стратегии торгов для приблизительно описанной реальности, в которой есть еще и приток/отток финансовых средств в рынок из вне. Рефлективность фондового рынка порождает возможность манипуляции рынком крупными его участниками. Причем, не только своими действиями на нем, но информационными вбросами, влияющими на поведение его участников. Кроме того, этот рынок является инсайдерским, так как среди его участников всегда присутствуют те, которым раньше других доступна информация, влияющая на его поведение. Надо понимать, что использование вероятностных моделей поведения рынка, во многих случаях это сильное допущение из-за отсутствия более адекватных моделей. В каком-то смысле, фондовый рынок подобен локально неустойчивой, но, до поры до времени, самовосстанавливающейся финансовой пирамиде. Собственно говоря, все социальные процессы, в том числе, происходящие в локальных, а также в глобальной экономике, имеют «пирамидальный» характер. Наблюдаемые политико-экономические кризисы – это, во многом, проявление такой «пирамидальности», обусловленной природой человека. Из написанного выше следует, что принципиальной особенностью прибыльной стратегии является ее зависимость от поведения участников фондового рынка (многие из которых используют роботы) и ограниченность круга участников, ее использующих. С учетом того, что фондовый рынок меняется, для обеспечения прибыльности, должна меняться стратегия торгов.
Anton Belonogov написал: Демо-доступ предоставляется сроком на один месяц, учетная запись U0222125 была действительна в период 16.01.2025-16.02.2025. Сейчас Вы можете повторно пройти регистрацию и получить новую учетную запись.
Спасибо. После получения новой записи заработало. Но, наверное, когда заканчивается срок учетной записи, сообщение могло бы быть таким: "Срок вашей учетной записи истек. Вы можете зарегистрироваться повторно". И еще: я регистрировался 14.02.36, но похоже слишком рано, когда не истек срок предыдущей учетной записи.
Anton Belonogov написал: В ответ на Ваше письмо мы попросили уточнить UID, это было в 10:30. Ответ не получили.Дублируем наш запрос - можно ответить здесь или в письме.
Похоже партизаны перерезали нашу с вами связь . Я от вас сообщений не получаю. в том числе дублирующих. 1. Из интернета: "Ваш UID терминала QUIK (UID – это несколько цифр, которые видны при подключенном к бирже терминале QUIK в левом верхнем углу рядом с фамилией)" 2. Я в в своей почте не нашел вашего ответа. 3. Я запускаю Quik_Junior_v11.4.1 и не вижу, хоть убейте , "несколько цифр, которые видны при подключенном к бирже терминале QUIK в левом верхнем углу рядом с фамилией)" 4. Для меня загадка, что такое UID в Quik_Junior? Пожалуйста, объясните где его искать.
При попытке подключиться (с полученным логином и паролем) к демоверсии (Quik_Junior_v11.4.1) выдается сообщение: "Срок лицензии истек". В чем причина? Почему? Я лишенец ?
local str, x, account
local class_code = getClassInfo('QJSIM') and 'QJSIM' or 'TQBR' -- в песочнице 'QJSIM', а в продуктиве 'TQBR'
str="trade_accounts";
for i=0, getNumberOf(str)-1 do
x=getItem(str,i)
if string.find(x.class_codes, class_code) then account=x.trdaccid; break; end
end
nikolz написал: у меня библиотека в 3 раза меньше.(43кБ)
А вот тут, пожалуйста, поподробнее. Ваша библиотека функционально эквивалентна разработки swerg? Где можно увидеть ее код? Каким образом ее могут использовать пользователи?
VPM написал: выше привел код подключения модулей, в том числе алгоритмов, которые ныне упаковываю в класс луа. Вот еще из рабочей программы и здесь уже алгоритмы есть индикаторов
И где же индикаторы из папки LuaIndicators? Покажите маленький тест их использования.
VPM написал: Вся библиотека индикаторов от любезно предоставленная разработчиками копируется и вставляется в папку LuaIndicators. Что тут можно показать?
Вы ускользаете от вопроса. Покажите как вы используете эти индикаторы в своем скрипте?
VPM написал: Да нет просто скопировать и вставить.
А это уже интересно. Покажите какой нибуть просто скопированный, вставленный (без последующей модификации) и работающий индикатор из папки LuaIndicators.
То есть, если вам в скрипте надо использовать уже существующий индикатор, то вам интересно его программировать и отлаживать. Если это так, то ваша позиция понятна. Действительно, нет проблем реализовать самому любой индикатор. Но вопрос зачем, когда есть готовые коды некоторых индикаторов? Интересно. зачем вы к своему сообщению "присобачили" код? Вы, что, хотите им кого-то напугать ?
На всякий случай: в кодах индикаторов папки 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 выполняются последовательно и тогда зачем мне читать ваш текст, в котором присутствуют какие то фоновые потоки вашего воображения.