Любой скрипт lua не проблема запустить из командной строки, используя интерпретатор lua. Но с скриптами для Квика так не выйдет, т.к. окружение у qlua специфическое. В частности, интерпретатор, по сути, это и будет терминал. Если только Вы не эмулировали набор методов и переменных их глобального контекста qlua.
Как облегчить работу с метками на графике, Медленное перемещение графика при просмотре и масштабировании
Пользователь
Сообщений: Регистрация: 27.01.2017
21.01.2021 20:32:17
У меня тестер наносит на график метки сделок. Их, конечно не тысячи, но 500 и более спокойно может быть. График "подтормаживает" только при масштабировании. Особых "тормозов" при перемещении нет.
Памяти на рабочей станции немного - 32 ГБ. Правда быстрый SSD.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
18.01.2021 14:38:09
Скрипт с таблицей имеет очередь передачи сообщений - она же таблица в staticVаr, допустим. При возникновении события в таблице в эту очередь записывается информация. Как Вы и написали проблем с передачей нет.
Другой скрип, смотрит на эту очередь и читает информацию, если в ней что-то появилось. Опрашивать, допустим по увеличению размера. Не такая и проблема выполнить что-то типа: last_count < #Table
На самом деле, даже если это один скрипт, некоторые команды нежелательно исполнять в колбеке таблицы. А значит их надо передавать в дополнительный поток скрипта, через любую переменную видимого контекста. Это мало отличается от схемы с разделяемой переменной. Неэффективность будет только в том, что все события пойдут через очередь.
Либо мы не понимаем друг-друга.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
18.01.2021 10:02:25
Цитата
Легко давать советы не особенно вникая.) Передать колбэк не проблема только вот что бы принять его другим скриптом механизма прерывания и включения параллельного потока нет. Или вы предлагаете main() в цикле опрашивать переменную на случай наступления события?
Да, опрашивать по изменению количества в очереди. Собственно, это не такая и редка задача: Квик исполнитель, а интерфейс может быть в базе данных, на таблицах. Ясно, что лучше написать прямую библиотеку, но раз ее нет, надо передавать команды по каналам связи.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
17.01.2021 15:02:08
Раз необходимо иметь разные события для разных окон, то дайте имена этим событиям разные или сопровождайте их разным наборов параметров, чтобы обработчик понимал с чем имеет дело.
А что касается интерфейса, то он может быть расположен на устройстве на Марсе. А сервер должен получить события, что пользователь инициировал и как-то прореагировать: ракету запустить или вернуть ответ в тот же интерфейс. Интерфейс и сервер (обработчик и т.д.) это не обязательно единое целое.
Что касается групп событий, то здесь надо формализовать как эта группа формируется. Возможно на клиенте с интерфейсом надо сгруппировать по какому-то признаку и уже передать эту группу в очередь как единое целое.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
17.01.2021 10:41:21
Если у Вас ячейки привязаны к конкретному скрипту (т.е. реакция на нее однозначно для скрипта №2), особой разницы нет, где событие прошло. Делаете очередь событий и передаете события с параметрами обратно в скрипт через тот же механизм. А скрипт уже, в свою очередь, опрашивает на предмет нового события из своей области обмена.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 19:21:18
Цитата
А в других перечисленных вами вариантах ждать не будут?
Так смотря что ждать. Если база данных, то смотрим какой уровень изоляции транзакции оная поддерживает. Можно сделать несколько таблиц для каждой пары (примерно как и с файлами). Писатель блокирует таблицу, другие таблицы доступны. Читатель читает те таблицы, что доступны.
Если библиотеки обмена, то их авторы доступны.
Если socket, то он по умолчанию блокирующий. Т.е. надо ждать. В книге Роберту Иерузалимски. «Программирование на языке Lua» есть пример Невытесняющая многонитевость.
named pipes позволяют сделать многопоточное подключение, к серверу. Хотя именованные каналы - это по сути файлы, только в памяти.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 18:24:17
Для чтения. Записать одновременно в один файл с двух сторон, то еще занятие. Да, файл-флаг здесь решит проблему, чтоб все ждали пока он есть. А когда его нет, то все писатели одновременно ринутся писать в один тот-же файл.
Если источник-приемник один, то достаточно в источнике открыть файл в режиме записи, а в приемнике в режиме чтения и просто проверять новые данные в этом файле через read("*l"). Писатель записал, читатель их прочитал. Скрипт индикатору может спокойно так передавать информацию.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 17:54:45
Цитата
Старатель написал: Второй файл как раз служит для писателей индикатором, что первый файл занят, и запись не возможна. Как только приёмник прочитает данные, он удаляет 2-й файл, что сигнализирует о возможности записи. Т.е. организуются синхронные запись/чтение.
Кстати, ни разу не видел, блокировок файлов, одновременно открытых несколькими Lua-скриптами. Если файл открыт другим приложением, то, да, было.
Блокировки видел, хоть lua и очень быстр в части работы с файлами. Если пара одна, то это приведет к тому, что все будут ждать пока он освободится. А если несколько, то приемник сможет переключаться между парами, чтобы не ждать.
Конечно, все это для обмена большими объемами и несколькими источниками-потребителями. Если данных мало и они редки, то все это излишне.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 16:58:36
Цитата
Старатель написал: Вот пример организации обмена с двумя файлами: 1-й файл для передачи данных, 2-й - пустой файл, служит флагом для индикации готовности данных к считыванию.
Это надо для каждый пары источник-приемник создавать пару файлов. Как только несколько писателей, с двумя файлами может быть блокировка. А приемник должен псевдо-асинхронно это читать.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 13:30:32
Правда если только вывод в таблицу, то да, надо знать только id окна.
Подкиньте идею
Пользователь
Сообщений: Регистрация: 27.01.2017
16.01.2021 13:27:53
Вариант 1. in memory database. Самая простая - sqlite3 Вариант 2. Библиотеки обмена: раз - StaticVar от swerg два - luashare от toxa
Вариант 3 - файлы. Но взаимные блокировки будет проблемой.
Вариант 4 - socket. Да, поднять свой socket server и обмениваться.
Вариант 5. Named Pipes. пишем библиотку клиента и сервера.
Утечка памяти, Происходит утечка памяти
Пользователь
Сообщений: Регистрация: 27.01.2017
15.01.2021 19:26:00
Есть такая "особенность": Вызов С функции форсирует более агрессивный режим работы сборщика мусора. Если код содержит много циклов с формированием локальных переменных, то мусор неохотно убирается.
Конструкция такого вида помогает, вместо прямого вызова сборщика. _G.SearchItems('money_limits', 0, 0, empty_func, "currcode")
---@param num number
---@param idp any
local function round(num, idp)
if num then
local mult = 10^(idp or 0)
if num >= 0 then
return math.floor(num * mult + 0.5) / mult
else
return math.ceil(num * mult - 0.5) / mult
end
else
return num
end
end
Обычно, все же, применяют округление к итоговому результату. У Вас math.ceil(price/options.price_step) * options.price_step есть результат работы с вещественными числами. Его и надо привести к нужной точности, а потом уже сравнивать.
Status это работает ?
Пользователь
Сообщений: Регистрация: 27.01.2017
10.01.2021 11:02:46
Владимир, Вы опять смешиваете язык и его синтаксис с поведением терминала. Даже не терминала, а особенностям потока данных, получаемого от ядра биржи. Статус, биржа отдает, либо брокера на серверной части "режет" его.
И да, точно также, у многих есть претензии к поведению исполнительного механизма (терминала), потоку данных и т.д. Сообщениям о нескольких вызовах колбеков на одно событие уже много лет.
Но язык здесь причем.
Что касается tonumber(GetCell(T,p1,0).value), то чтобы ответить надо понять из какого поля получаются данные. Если из колонки типа "строка", то и не будет работать, т.к. у него value нет.
Цитата
BOOLEAN SetCell(NUMBER t_id, NUMBER key, NUMBER code, STRING text, NUMBER value) Функция задает значение для ячейки в строке с ключом «key», кодом колонки «code» в таблице «t_id». Параметр «text» задает строковое представление значение параметра «value». Параметр «value» необязательный и по умолчанию равен «0». Для столбцов со строковыми типами данных параметр «value» не задается. Если параметр «value» не задан для ячеек всех остальных типов, то по столбцам, содержащим такие ячейки, не будет корректно работать сортировка, фильтрация и условное форматирование (см. Приложение 2). Функция возвращает «true» в случае успешного завершения, иначе – «false».
Как сделать пересылку сообщений от скриптов на смартфон?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.01.2021 23:00:34
Цитата
Andy написал: Бота создал, токен вписал Попробовал запустить тестовый скрипт, теперь другая ошибка: Подскажите пожалуйста что дальше?
Чтобы не засорять форум, напишите мне в личные сообщения.
Как сделать пересылку сообщений от скриптов на смартфон?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.01.2021 19:23:14
В сообщении написано же, что нужен валидный токен. Необходимо сначала создать бота в телеграме, узнать его токен, вписать его в настройки: файл settings.ini.
Как сделать пересылку сообщений от скриптов на смартфон?
Пользователь
Сообщений: Регистрация: 27.01.2017
04.01.2021 16:42:12
как обычно: require('luaPipe')
Есть же пример, тестовый скрипт.
Как сделать пересылку сообщений от скриптов на смартфон?
Пользователь
Сообщений: Регистрация: 27.01.2017
04.01.2021 10:08:56
На этом форуме и на Smart-Labe и MFD выкладывались такого рода утилиты. Даже с открытым кодом.
Вопросы Новичка
Пользователь
Сообщений: Регистрация: 27.01.2017
22.12.2020 21:01:34
Я для себя не отключал его. Привык жить без глобальных переменных. Неучтенная глобальная - это повод проверить.
добавить параметр -d при вызове luacheck добавить в файл .luacheckrc allow_defined = true
Также по другим сообщениям
Часть из них можно добавить в список исключений ignore В принципе, все есть в документации
Вопросы Новичка
Пользователь
Сообщений: Регистрация: 27.01.2017
22.12.2020 18:27:08
Я использую luacheck (по мне самый лучший). В VS Code он не сложно подключается. Но и сами плагины lua для VS Code тоже умеют отлавливать простые ошибки. Если используете всеми любимый Notepad ++, то для него надо искать плагины, поддерживающие проверку синтаксиса. Или запускать в командной строке luacheck с проверяемым скриптом, что, конечно, не так удобно.
Вопросы Новичка
Пользователь
Сообщений: Регистрация: 27.01.2017
22.12.2020 17:54:03
Если у Вас не синтаксическая ошибка, а логическая, то, конечно, ошибки не будет при компиляции. Такие ошибки ловятся дебагом. Но для индикатора, лучше делать print-debug. Т.е. выводить значения в некий поток (файл лога) и смотреть на данные.
Типовая ошибка в индикаторах связана с дырявыми массивами данных. Т.е. не заполнены данные для каждого индекса. Если индекса нет, т.е. дырка на графике, это не повод пропустить данные в массиве.
А чтобы Квик не умирал от бесконечного потока сообщений об ошибке, лучше завернуть критическую секцию в pcall и перехватывать текст ошибки, выводя его все один раз для одного и того же сообщения.
как определить окончательный расчет индикатора, при создании или редактировании индикатор рассчитывается несколько раз
Пользователь
Сообщений: Регистрация: 27.01.2017
22.12.2020 16:17:58
Цитата
Александр написал: Ещё вопрос по функции SetValue. Она не работает по последней формирующейся свече?
Для последнего индекса происходит возврат данных из функции OnCalculate. Эти данные устанавливаются на график. Так что даже если вы используете функцию, все равно произойдет переопределение.
Вопросы Новичка
Пользователь
Сообщений: Регистрация: 27.01.2017
22.12.2020 16:16:02
Добавляете индикатор в доступные скрипты lua и запускаете. Будет ошибка. А лучше пользоваться линтерами, чтобы легче было.
FIFO (англ. First In, First Out – ), Вопрос
Пользователь
Сообщений: Регистрация: 27.01.2017
20.12.2020 10:57:44
Это методика учета. Никаких проблем реализовать FIFO, LIFO, по средней нет. Вопрос для чего. Обычно ее используют для исчисления прибыли. Собственно, если я правильно помню эту картинку, то это сетка заявок (сделок), где как раз фин.рез так и считают. При этом брокер может считать совсем по-другому.
А с токи зрения баланса инструмента - нет разницы. Одни все одинаковые.
Перехват события
Пользователь
Сообщений: Регистрация: 27.01.2017
17.12.2020 11:43:15
Вы можете прочитать дату экспирации в свойствах инструмента. Используя свой календарь, заменить инструмент даже раньше или позже чем это предложит терминал.
Заявка по минимуму последней свечи
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 19:40:25
Вот Вам документация и примеры
Заявка по минимуму последней свечи
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 19:37:17
Подписываетесь на поток данных один раз
local ds, err = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL); if not ds then действия при ошибке end
Далее можете в бесконечном основном цикле просто тыкать в поток и проверять изменился ли ds:Size(). Для этого, естественно нужны переменная, где хранится прошлое значение. Можете ее глобальной сделать, можно через замыкаение все сделать, можно через класс, как угодно.
Если интервал минута, то индекс и будет увеличиваться раз минуту при наличии сделок, не раньше. Это же индекс временного интервала. Пока новый не наступил, чего ему увеличиваться.
Заявка по минимуму последней свечи
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 18:26:42
Цитата
Сергей написал: Если я правильно понимаю мне в моём случае нужно писать так, да? DS,Error = CreateDataSource('QJSIM', 'SBER', INTERVAL_H1); local Last = math.max -- что-то там, что даст мне индекс последней полученной свечи local Price = DS:L(Last); message('Price: '..Price);
Если задача получить последний бар (текущий), то это ds:Size()
Заявка по минимуму последней свечи
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 18:25:15
ds:Size() - это текущий бар. Но новый бар появляется только по совершению сделки. Допустим минутный бар. Он может быть уже по факту завершенным, т.е. уже началась новая минута. Но т.к. еще нет сделок в новом интервале, то нового бара (увеличения индекса) еще не будет.
Если алгоритм требует простого увеличения номера бара, то можно просто контролировать увеличение номера при получении ds:Size(). А если алгоритм требует совершения действий именно при наступлении нового временного интервала, то надо контролировать время сервера и время бара.
Заявка по минимуму последней свечи
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 18:04:49
У объекта ds есть метод Size(), который вернет последний индекс бара. При этом закрытый он или нет надо проверять по времени. В большинстве случаев ds:Size() - это послдений текущий бар. Т.е. закрытый будет ds:Size().
А 1 - это будет первый бар. В Квике, в отличии от MT, нумерация от 1.
Также важно отметить, что получать поток данных через CreateDataSource надо делать один раз, сохранив его в переменную.
Все методы объекта ds описаны в документации к языку.
Отладка QUIK 8.11
Пользователь
Сообщений: Регистрация: 27.01.2017
14.12.2020 17:59:47
А зачем перешли на lua 5.4.1? Опять библиотеки перекомпилировать, скрипты перекомпилировать. Что такого важного увидели в этом релизе, что надо было переходить. При этом, что текущий релиз 5.4.2.
Неприятность таблицы "Клиентский портфель", Вопрос "совсем новичка":
Пользователь
Сообщений: Регистрация: 27.01.2017
12.12.2020 11:30:56
А зачем два раза получать строку через getItem? Строку проще получить один раз, проверить что она не пустая, т.к. такое бывает и потом уже из нее получать данные, сверив, что она по нужному инструменту, счету.
Кто как решает вопрос с заявками/сделками?
Пользователь
Сообщений: Регистрация: 27.01.2017
10.12.2020 10:44:26
Владимир, на самом деле, действительно на грани, как минимум непонимания.
Вам, как только Вы появились на форуме, было уже сказано, что есть много тонкостей и нюансов.
Теперь Вы просто собираете все. При этом все это обсуждалось на этом форуме уже много много лет, предложены разные варианты решений.
Я Вам могу еще одну особенность дать - в таблице trades (это там где сделки хранятся, она же по колбеку OnTrade), номер транзакции появляется не всегда сразу. Он может быть 0, а потом меняется на корректный.
Изменение цены стоп-ордера через график
Пользователь
Сообщений: Регистрация: 27.01.2017
10.12.2020 10:36:00
Все зависит от алгоритма. Если предполагается один ордер, то его можно отловить просто. Надо писать комментарий в ордер, тогда при перетаскивании он сохранится. Далее надо ввести некую задержку ожидания появления нового ордера - это самый "тонкий" момент, т.к. все зависит от сервера брокера, канала связи.
В колбеке ловите момент, что старый ордер был снят, хотя можно и не ловить, т.к. если Вы снимаете ордер через скрипт, то это итак известно. Остальное - это внешнее воздействие. Теперь просто ждете пока не появится новый ордер с тем же комментарием, а если не появился через введенную задержку - выполняете какие-то действия, например, перевыставляете.
Получение подтаблицы в отдельную таблицк
Пользователь
Сообщений: Регистрация: 27.01.2017
06.12.2020 10:02:53
Если это не массив, то необходимо использовать другой итератор pairs. ipairs только для непрерывных массивов.
for i,tab_data in pairs(ind) do
Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2020 18:01:17
Цитата
Владимир написал: , И что делать? А по OnOrder это дело ловится? Если верить описанию, при любом изменении параметров заявки эта штуковина должна бы вызываться (именно по ней вкупе с OnTrade я и собираюсь отслеживать состояние торгов).
Делать что? Колбеком OnOrder Вы можете отследить изменение параметров ордера, только не забывайте, что он приходит не один раз. Если же при снятии была ошибка, то она придет только в OnTransReply, OnOrder не будет вызван. Так что надо либо контролировать транзакцию, либо опрашивать ордер, проверяя его состояние.
Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
В ответе на транзакцию снятия заявки (KILL_ORDER) номер снимаемой заявки не приходит. В ответе на транзакцию передвижения заявки (MOVE_ORDERS) приходит только номер новой заявки.
Также, заметим, что данный ответ идет от Торговой Системы, а не от терминала.
Все же при удачном снятии номер заполнен в поле order_num, по крайней мере на вашем тестовом контуре.
Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2020 12:16:40
Вопрос был понятен. Не понятна проблема. При подаче транзакции мы знаем номер модифицируемого ордера и номер поданной транзакции. Т.е. есть структура {trans_id, order_num}
Ели транзакция прошла успешно, то номер снимаемого ордера заполнен в ответе транзакции. Если возникла ошибка то он не заполнен. Но у Вас есть структура, где по номеру транзакции есть номер ордера по которому возникла ошибка.
Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2020 09:31:46
Если задача перехватить ответ для отправленной транзакции, то это лучше делать по номеру транзакции, который был передан. Номер транзакции тоже известен при ее подаче, а ответ этот номер содержит.
Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
Пользователь
Сообщений: Регистрация: 27.01.2017
16.11.2020 18:11:44
Чтобы снять ордер надо знать его номер, а если он известен, то зачем его получать в колбеке?
Изменения в работе с колбеками LUA в новой версии
Пользователь
Сообщений: Регистрация: 27.01.2017
06.11.2020 15:03:35
А с чего вообще что-то должно поменяться для "наблюдателя" скрипта? С его точки зрения каким был колбек таким и остался. На то он и колбек, назание само за себя говорит.
Не думаю что пойдут на изменение синтаксиса. Я бы больше ожидал стабильности и предсказуемости в вызовах. Сейчас только несколько колбеков типа подключения-отключения-ответ транзакции можно использовать. Остальные не вызывают доверия и надежней баз них. А то когда у тебя колблек от событий прошедших часы назад прилетает после перезапуска терминала, то проще не смотреть на них.
Обсудим диалог на Lua?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2020 20:13:03
Здесь я с Владимиром согласен, не очень понятно зачем вносить лишние сущности в виде сторонних библиотек, если почти все что надо от скрипта можно сделать на qlua. Да, нельзя показать картинки, не очень удобно выводить многострочный текст и т.д., но бантики не имеют отношения к тому что надо от интерфейса скрипта.
Писали же как-то программы раньше. Даже некое подобие 3-х мерного изображения выводили до Open GL. И ничего, научная работа велась.
Если уж интерфейс такой сложный, что он должен определять поведение скрипта, то проще написать весь скрипт на плюсах (QScalp), зачем мучить LUA, да еще VCLua на турбо паскале, которое притянет за собой свои зависимости и проблемы синхронизации. Не говоря уже про то, что она, мягко говоря, устарела.
Обсудим диалог на Lua?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2020 09:49:11
Владимир, а в чем, собственно, проблема?
И команды и переключатели, и поля ввода, горячие клавиши прекрасно делаются на qlua. Просто к таблице надо подойти как к объекту, наполнив его методами, обратными вызовами. Я бы даже сказал, что надо написать свой DSL. Тогда, вызывая конструктор окна с настройками, получим уже готовый объект. В частности, у меня окно рисуется через таблицу настроек, все остальное уже заложено в объект. Надо добавить переключатель или что-то другое - одна строка таблице настроек.
Как к этому подойти - ну явно не надо писать простыню в main. Придется использовать очереди событий, сообщений и др. Также не советую использовать номера колонок, строк как идентификатор ячейки - это затрудняет модификацию окна. Часто просят переставить местами что-то. Это не должно приводить к переписыванию всего кода. Надо просто в одном месте поменять описание поля (колонки) таблицы.
Добавление Индикаторов.
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2020 19:53:14
Ну код индикатора не оптимален. Это влияет на производительность, особенно если запущено на склейке графика, с очень большим количеством баров.
Добавление Индикаторов.
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2020 18:58:50
Вот исправленное. Прогнал через линтер, помимо кавычек еще вместо минус было тире. Явно хранили текст в Word или в чем-то подобном.
Код
Settings = {
Name = "*StohRSI",
round = "off",
Period = 5,
Per_K = 9,
PeriodSO = 5,
Shift = 3,
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference
line = {
{Name = "RSI", Type = TYPE_LINE, Color = RGB(255, 255, 128)},
{Name = "SO", Type = TYPE_LINE, Color = RGB(255, 0, 0)},
{Name = "Sign", Type = TYPE_LINE, Color = RGB(128, 255, 128)},
{Name = "line 20", Type = TYPE_LINE, Color = RGB(0, 128, 255)},
{Name = "line 80", Type = TYPE_LINE, Color = RGB(0, 128, 255)}
}
}
function Init()
func = RSI()
return #Settings.line
end
function OnCalculate(Index)
if not CandleExist(Index) then
return nil
end
return func(Index, Settings)
end
function RSI() --Relative Strength I("RSI")
local Up = {}
local Down = {}
local val_Up = {}
local val_Down = {}
local K_MA1=MA()
local K_MA2=MA()
local D_MA=MA()
local proSO={}
local Out = {}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local PK = (Fsettings.Per_K or 5)
local PerSO = (Fsettings.PeriodSO or 5)
local S = (Fsettings.Shift or 3)
local PD = (Fsettings.Period_D or 3)
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
local MD = (Fsettings.Metod_D or "SMA")
local M = (Fsettings.Metod or "SMA")
if I <=PerSO then
Up[I] = 0
Down[I] = 0
end
if I>PerSO then
local Val = Value(I,"T",ds)
local ValPrev = Value(I-1,VT,ds)
if ValPrev < Val then
Up[I] = Val - ValPrev
else
Up[I] = 0
end
if ValPrev > Val then
Down[I] = ValPrev - Val
else
Down[I] = 0
end
if (I == P) or (I == P+1) then
local sumU = 0
local sumD = 0
for i = I-P+1, I do
sumU = sumU + Up[i]
sumD = sumD + Down[i]
end
val_Up[I] = sumU/P
val_Down[I] = sumD/P
end
if I > P+1 then
val_Up[I] = (val_Up[I-1] * (P-1) + Up[I]) / P
val_Down[I] = (val_Down[I-1] * (P-1) + Down[I]) / P
Out[I] = 100 / (1 + (val_Down[I] / val_Up[I]))
end
end
if I > PK*2 then
RsiOut=D_MA(I,{Period=PK, Metod = M, VType="Any", round=R}, Out)
end
_,_,proSO[I]= MaxMin(I,5,ds,3)
if I>=(PK+3-1) then
SignSO=D_MA(I, {Period=3, Metod = "SMA", VType="Any", round="off"}, proSO)
end
return rounding(RsiOut, 4),rounding(proSO[I], 4),rounding(SignSO, 4),rounding(Out[I], 4)
end
end
-------------------------------------------------------
-------------------------------------------------------
function MA() --Moving Average ("MA")
local t_SMA = F_SMA()
local t_EMA = F_EMA()
return function(I, Fsettings, ds)
local Out = nil
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 9)
local M = (Fsettings.Metod or "EMA")
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
if M == "SMA" then
Out = t_SMA(I, P, VT, ds, R)
elseif M == "EMA" then
Out = t_EMA(I, P, VT, ds, R)
else
Out = nil
end
return rounding(Out, R)
end
end
------------------------------------------------------
function MaxMin(ind,Pk,ds,Sk)
if ind < Pk+Sk then
return nil
else
local suCM=0
local suMM=0
for i = ind - Sk+1, ind do
MAX = Value(i-Pk+1,"High",ds)
MIN = Value(i-Pk+1,"Low",ds)
for k = 0, Pk-1 do
MAX=math.max(MAX,Value(i-k,"High",ds))
MIN=math.min(MIN,Value(i-k,"Low",ds))
end
--message('тран:'..OutWR,1)
suCM=suCM+(Value(i, "Close", ds)-MIN)
suMM=suMM+(MAX-MIN)
end
local TenKu=(MAX+MIN)/2
local OutWR=100*(Value(ind,"Close", ds)-MIN)/(MAX-MIN)
local proKol =100*suCM/suMM
local wpr = ((MAX - Value(ind,"Close", ds)) / (MAX - MIN)) * (-100)
return rounding(TenKu, 6),rounding(OutWR, 6),rounding(proKol, 6)
end
end
------------------------------------------------------------------
function F_SMA()
return function (I, Period, VType, ds, R)
local Out = nil
if I >= Period then
local sum = 0
for i = I-Period+1, I do
sum = sum +Value(i, VType, ds)
end
Out = sum/Period
end
return rounding(Out,R)
end
end
---------------------------------------------------------
function F_EMA()
local EMA_TMP={}
return function(I, Period, VType, ds, R)
local Out = nil
if I == 1 then
EMA_TMP[I]=rounding(Value(I, VType, ds),R)
else
EMA_TMP[I]=rounding((EMA_TMP[I-1]*(Period-1)+2*Value(I, VType, ds)) / (Period+1),R)
end
if I >= Period then
Out = EMA_TMP[I]
end
return rounding(Out,R)
end
end
-------------------------------------------------------
function Value(I,VType,ds)
local Out = nil
VType=(VType and string.upper(string.sub(VType,1,1))) or "A"
if VType == "O" then --Open
Out = (O and O(I)) or (ds and ds:O(I))
elseif VType == "H" then --High
Out = (H and H(I)) or (ds and ds:H(I))
elseif VType == "L" then --Low
Out = (L and L(I)) or (ds and ds:L(I))
elseif VType == "C" then --Close
Out = (C and C(I)) or (ds and ds:C(I))
elseif VType == "V" then --Volume
Out = (V and V(I)) or (ds and ds:V(I))
elseif VType == "M" then --Median
Out = ((Value(I,"H",ds) + Value(I,"L",ds)) / 2)
elseif VType == "T" then --Typical
Out = ((Value(I,"M",ds) * 2 + Value(I,"C",ds))/3)
elseif VType == "W" then --Weighted
Out = ((Value(I,"T",ds) * 3 + Value(I,"O",ds))/4)
elseif VType == "D" then --Difference
Out = (Value(I,"H",ds) - Value(I,"L",ds))
elseif VType == "A" then --Any
if ds then Out = ds[I] else Out = nil end
end
return Out
end
function rounding(num, round)
if round and string.upper(round)== "ON" then round=0 end
if num and tonumber(round) then
local mult = 10^round
if num >= 0 then return math.floor(num * mult + 0.5) / mult
else return math.ceil(num * mult - 0.5) / mult end
else return num end
end
Одновременная работа двух Торговых систем с одним инструментом, подкиньте идей
Пользователь
Сообщений: Регистрация: 27.01.2017
28.10.2020 09:42:24
Владимир, это же написано в документации к расширению языка от разработчика, документ Использование Lua в Рабочем месте QUIK Простая схема передачи данных через очередь из колбека в дополнительный поток скрипта.