swerg написал: Любопытно, кстати: зачем генерировать обработчики в run-time?
Один из случаев, который был бы удобен многим, чтобы упрощать слежение корректности стейта. Сейчас, например, если есть поведение, зависящее от стейта, то нужно в каждом коллбеке делать проверки на то, от чего он зависит. Если бы можно было переназначать обработчики, то вся вариативность бы укладывалась бы в одом if-е в каком-нибудь OnInit, где инициализируются и переменные, и функции обратного вызова. Таким образом, можно было бы добиться инкапсуляции данных и поведения "для бедных" в Lua.
Это эквивалентно динамическому полиморфизму в ООП языках.
Сейчас пришлось бы делать так:
Код
Инициализация_скрипта:
x = внешние_данные
OnQuote:
if (x = = A)
манипуляция над частью данных
if (x.z = = 1 )
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote1
.. .
if (x.z = = 2 )
.. .
if (x.z = = 3 )
OnAllTrade:
разбор для всех тех же случаев
В итоге получается, что вся вариативность поведения разбросана внутри каждого коллбека и нужно раздублировать все проверки на состояние внутри. Чуть более сложный сценарий, в зависимости от состояния переназначать коллбеки, например, чтоб не вызывался один OnAllTrade, пока не сработал другой колбек (сейчас альтернатива, опять же, засунуть все в один OnAllTrade и делать там разбор случаев). Вобщем-то даже в Lua при всей ее примитивности заложена философия first-class функций, и такая работа с функциями, как динамическое переназначение на имя другой лямбды, вполне в ее духе.
Как варианты: 1)Можно вынести разбор состояний в функцию 2) Можно ввести глобальный флаг и не разбирать снова если это тоже самое.
Есть желание поэкспериментировать в выходной день, но в выходной день DS:SetUpdateCallback(....) не приходят, но мы можем тиковый график сохранить в файл. Для имитации SetUpdateCallback(....) я хочу с помощью луа читать файл с тиковыми значениями (построчно) и заносить в DS. Ввиду отсутствия опыта, прошу помочь, как это реализовать - чтение из файла и введение новых значений в DS.
Спасибо
Так как DS:SetUpdateCallback(....) это просто функция в таблице DS, напишите новую под этим именем и она заменит старую.
Sergey Denegin написал: Здравствуйте. Подниму эту тему, потому что озадачился этой же проблемой. Можно ли как-то из одного скрипта, запустить другой, но так, чтобы его работа выполнялась аналогично тому, как если бы мы его запустили из панели ЛуаСкриптов? Т.е. полностью независимо от запускающего его скрипта и полностью со своими переменными.
Технически можно, но не просто. Для этого надо изучить потоки и владеть СИ. Сделать можно так: Запускаем все скрипты, которые будем в дальнейшем использовать. Скрипты, которые не нужны останавливают себя сами (останавливаем поток main) После этого из управляющего скрипта, при необходимости, пускаем поток нужного скрипта, который закончив работу снова останавливает себя.
Иван Иванов написал: В плане разработки ПО под FIX затраты как раз меньше - есть куча готовых библиотек.
По-моему была бы логичная линейка API, условно: а) нужен алгодоступ, но не нужна скорость : FIX >> QUIK сервер. 200 руб в мес. б) стала нужна скорость - легко мигрируем: FIX >> биржа. 10 тыс в мес.
Просто разработчиков приучили к пляскам с бубном с DDE/LUA для QUIK, но это не от хорошей жизни.
Полагаю, что Вы путаете кислое с зеленым. FIX - это протокол получения информации с биржи по распределенной и разнородной сети. DDE - это протокол обмена данным между приложениями на компе через оперативную память память. а LUA - это вообще просто язык описания задач. И тем более все это не связано с качеством жизни.
если хотите читать в конце файла не перебирая все содержимое, то используйте функцию: file:seek ([whence] [, offset]) Получает и выставляет текущую позицию в файле, отсчитываемую от начала файла, в позицию, заданную параметром offset плюс значение (исходная позиция), заданное строкой whence, следующим образом:
"set": исходная позиция равна 0 (начало файла);
"cur":исходная позиция – текущая;
"end": исходная позиция – конец файла.
В случае успешного выполнения, функция seek возвращает выставленную позицию в файле, отсчитываемую от начала файла. Если функция завершается неудачно, она возвращает nil и строку – описание ошибки. Значение по умолчанию для параметра whence равно "cur", а offset – 0. Т.о. вызов file:seek() возвращает текущую позицию в файле, не изменяя ее; вызов file:seek("set") перемещает указатель текущей позиции в начало файла (и возвращает 0); а вызов file:seek("end") перемещает указатель текущей позиции в конец файла, и возвращает его длину.
RC2 написал: В целом мне необходимо реализовать трейлинг-стоп, но без выставления заявки, т.е расчет трейлинг-стопа должен быть в скрипте. На сколько я понимаю это не сделать без сохранения цен во внешний файл, т.к. между итерациями все переменные обнуляются.
не определяйте переменные как локальные и они не будут обнуляться. Использовать запись в файл для реализации трейлинг-стопа нет необходимости.
Если быть точным, то сложение двух свечей и вычитание из суммы одной. На самом деле это азбука цифровой обработки сигналов в скользящем временном окне.
swerg пишет: Если же надо просуммировать 1000 свечей, да еще дифур решить для вычисления значения индикатора - лучше взять готовое значение из квика, если там есть такой индикатор, это и проще и надёжнее, ибо в своём алгоритме мы еще и наошибаться можем, а квиковый индикатор - хотя бы глазами видишь что он на самом деле считает.
Вот тут у Вас ошибочка Чтобы сложить 1000 свечей надо столько же время сколько для сложения двух. --------------------------------------- Вопрос же поставленный в начале вообще то не имеет однозначного решения Он из разряда "Как стать счастливым"
У меня ошибки нет, а вот вы - обманываете. Чтобы сложить 1000 свечей - требуется по крайней мере 1000 операций сложения. Я понимаю, что вы говорите про количество сложений на каждую свечу и итеративный подход, однако если уж взялись указывать на ошибки другим - будьте любезны и сами быть в этой ситуации непогрешимым в формулировках. Иначе, сами понимаете, лужа за углом может поджидать.
нет, я говорю о работе в реальном времени. В реальном времени циклы - это зло и их в правильных алгоритмах не применяют. Поэтому складывать надо текущую сумму с новым значением т е сложение двух свечей.
Николай Камынин написал: ff1(-8.8) Все работает правильно.
Вопрос был в другом
Код
function ff1 (dp)
for i = - 8.8 , - 0.8 do
if dp = = i then print (dp) end
end
end
for param, value in pairs({ - 8.8 , - 7.8 , - 6.8 , - 5.8 , - 4.8 , - 3.8 , - 2.8 , - 1.8 , - 0.8 }) do
ff1(value)
end
Я Вам про это и ответил. В данном варианте Вам надо написать функцию так: unction ff1(dp) for i=-8.8,-0.8 do print(i.."/"..dp) if string(dp)==string(i) then print(dp) end end end
а если передать строку: ff1(tostring(-8.8)) То получим: ------------------ -8.8/-8.8 -7.8/-8.8 -6.8/-8.8 -5.8/-8.8 -4.8/-8.8 -3.8/-8.8 -2.8/-8.8 -1.8/-8.8 -0.8/-8.8 >Exit code: 0 Т е строка -8.8 не равна числу -8.8. Это тоже правильная работа if .
сравнивать можно, но важно, чтобы тип у сравниваемых переменных был одинаковый. Так как тип указан неявно, то может возникать ситуация сравнения числа с текстом. поэтому при сравнении указывайте тип явно.
Космонавт написал: Добрый день. У меня робот мониторит больше сотни акций, по всем открыты графики. Это не праздный вопрос, а злободневный. Что продуктивнее - получать данные индикатора с графика через getCandlesByIndex или НЕ открывать графики и всё делать через заказ данных с помощью DataStore, а индикаторы считать внутри робота? 1. Что быстрее? 2. Что экономнее для ресурсов компьютера?
Спасибо.
Для большого числа акций делаю так: Получаю ТВС по подписке , в реале (налету) сортирую по инструментам и формирую необходимые индикаторы. Так как обработка делается в реале, то затраты ресурсов минимальные.
Vladimir написал: А если оперативки 8 ГБ, есть ли разница? Quik же бывает только 32битный, т.е. не может использовать всю память? Т.е. вопрос: можно ли на нем развертывать большие проекты на клуа с сотней ботов?
Размер оперативки - в QUIK-е - влияет лишь на количество одновременно открытых окон и то, до определённого предела. Как уже говорил - QUIK - относится к системам с обязательной сериализацией данных. То есть, любой "чих" пользователя, а также ЛЮБОЕ изменение в принимаемых и отправляемых транзакциях - он сериализует на ДИСК. Потому что биржевые данные - это реальные деньги. Отсюда и то, что он даже не сжимает данные при хранении на диске - потому что так быстрей.
Про сериализацию это конечно хорошо, но когда КВИК зачинали, это слово не применялось. В квике использованы проецируемые в память файлы - это основной метод винды для работы с большими массивами.
Николай Камынин написал: надо знать лишь две свечи в MA и одну в EMA.
Это если есть результаты предыдущих вычислений. А если они ==0, то не получится.
Это лишь в начале т е при запуске. но в это время данные поступают с сервера и они рассчитываются в реальном времени. И условия остаются теже - не более двух свечей.
действительно, какая-то каша. На самом деле, скорость вычисление скользящих не зависит от числа свечей , фактически для этого надо знать лишь две свечи в MA и одну в EMA. Просто надо изучить цифровую обработку сигналов.
Ivanco написал: Подскажите пожалуйста, возможно ли средствами языка QLUA делать какие-либо графические отметки на графике инструмента в QUIK? Например, если алгоритм находит удачный момент для сделки - ставить графическую отметку на графике и т.п.
Заранее благодарен.
Функции для работы с метками Предназначены для построения меток и установки их на графике.
AddLabel - добавляет метку с заданными параметрами
Теоретическая разница получения данных CreateDataSource+SetUpdateCallback или getNumCandles()+getCandlesByIndex(), В чем разница получения данных 1 способом и 2 способом
Владимир Б****ов написал: Теоретически, по времени, есть разница между колбэком и таймером (sleep()), а практически разница заметна? может кто проводил измерения/исследования?
колбек и sleep() - это две большие разницы. колбек - это функция LUA , которую вызывает терминал QUIK для обработки события. sleep() - это остановка исполнения потока(процесса) и досрочное освобождение процессора.
Теоретическая разница получения данных CreateDataSource+SetUpdateCallback или getNumCandles()+getCandlesByIndex(), В чем разница получения данных 1 способом и 2 способом
Теоретическая разница получения данных CreateDataSource+SetUpdateCallback или getNumCandles()+getCandlesByIndex(), В чем разница получения данных 1 способом и 2 способом
Николай Камынин написал: CreateDataSource+SetUpdateCallback - получаем данный в момент прихода их с сервера,
Т.е если таймфрейм установлен в 3 минуты - то получение данных ~ 1 раз в 3 минуты, т.е. объективную информацию по последней свечке(текущей) мы не знаем, знаем только по предпоследней?
нет не так. Будут приходить тики, которые отображаются как close не закрытой свечи. Т е фактически вне зависимости от тайма Вы будете получать тики.
Теоретическая разница получения данных CreateDataSource+SetUpdateCallback или getNumCandles()+getCandlesByIndex(), В чем разница получения данных 1 способом и 2 способом
Разница в следующем: ------------------------------------ CreateDataSource+SetUpdateCallback - получаем данный в момент прихода их с сервера, т е до помещения в хранилище в терминале. т е один раз, в момент поступления в терминал. ------------------------------------------ getNumCandles()+getCandlesByIndex() - читаем данные из хранилища. Сколько угодно раз после поступления в хранилище терминала.
В системах реального времени используется Watchdog. Это таймер, который необходимо перезапускать через время, меньшее, чем его срабатывание. Если его не перезапустили, то он вызывает прерывание и начинает посылает сообщения об ошибке. Если его вовремя кормят, то он молчит. Можете применить такой же способ.
Тогда при таком требовании, Вы должны отдавать себе отчет в том, что когда программа выжрет всю оперативку (а при наличии на машине ее меньше 4Г это случится очень быстро) вся система просто встанет колом.
...
А если оперативки 8 ГБ, есть ли разница? Quik же бывает только 32битный, т.е. не может использовать всю память? Т.е. вопрос: можно ли на нем развертывать большие проекты на клуа с сотней ботов?
Большой проект с сотней роботов невозможно развертывать в QLUA . По двум причинам - медленность VM LUA и медленная реакция QUIK. При сотнях роботов надо использовать многопоточность, API C for LUA, и выделенные сервера. При использовании API C нет проблем задействовать любой объем оперативной памяти.
Когда не было в квике луа решал эту задачу на avtoit. Сейчас это делается с помощью winAPI в LUA , используя модуль Alien. Если умеете писать на СИ, то с помощью API C for LUA. .
проблема в том, что на компе нет библиотек, которые есть на компе разработчика. проверьте свою dll на зависимости на компе разработчика и пользователя. Потом установите у пользователя недостающие библиотеки среды разработчика. обычно это делается через манифест. читайте у майкрософт.
помогите исправить ошибку attempt to index field(a nil value), при запуске скрипта если стакан не полный то вылезает ошибка attempt to index field(a nil value)
Роман написал: s_mike@rambler.ru - визжишь ты, сливая деньги на счете. Тебе написали что вопрос не в программирование, а в алгоритме запуска скрипта!
Вот так поедешь в отпуск, а на бирже очередной сбой, график косой, скрипт запрашивает Клоз, а его нет и программа падает и не запускается, а цена идёт против тебя. А ты жопу греешь на солнце не зная об этом. Если бы скрипт запустился следующий раз, то он пошел бы дальше работать оставив ошибку в логе, так как биржа бы исправила косяк.
Sergey Gorokhov - да, это же ваши косяки или косяки биржи - это ошибку вызывают.Как от вас избавишься? Или выпускайте продукт, что бы вообще не одной ошибки не было в нём. А то сидите и рассказываете задним числом как работать надо!
Посмотрите на проблему немного иначе. КВИК , по определению, это программа подачи поручений брокеру. Есть другие способы подачи таких поручений -телефон, бумажный носитель. -------------------------------------- Все , что есть в квике кроме возможности подачи поручений - это бесплатное приложение (Увы, но это юридически именно так). --------------------------------------- Поэтому получается, что никто ничего Вам не должен. --------------------------------------------- Полагаю, что не только Вам хочется, чтобы скрипт работал вечно и без вмешательства. Но увы, реалия такова, что если скрипт написан плохо, то КВИК то квик его закрывает. Так сделали разработчики и это их право. -------------------------------------- Хотите иначе - пишите пожелания, делайте проверки внутри скрипта, ставьте защиту от падения. Ваше право. ----------------------------- Успехов.
Sergey Gorokhov написал: Для решения проблемы не используйте относительные пути при доступе к сторонним файлам.
Там нет относительных путей! Понятно что скрипт доделывать нужно, но одно если он был запущен - то нужно и запускать каждый раз когда загружается квик, а не выключать загрузку скрипта при каком либо сиюминутном сбое! Там х.з. что может быть (биржа мутит как), мы же не можем прописать всё и вся сразу!
так как скрипт без ошибок надо запускать лишь один раз, то Полагаю,что у Вас следующая проблема: ------------------------- Когда Вы запускаете скрипт кнопкой, то в КВИКЕ уже загружены все данные, которые использует Ваш скрипт и он нормально запускается. ------------------------ Потом Вы выключаете КВИК. При следующем запуске КВИКА с включенным скриптом, скрипт начинает работу сразу же при запуске КВИКА, но информация с сервере еще не пришла. В результате Ваш скрипт натыкается на nil и завершает свою работу по ошибке. ------------------------- Вы полагаете, что скрипт был выключен при закрытии КВИКА, а он просто не может возобновить свою работу. ------------------------- В результате Вы опять вынуждены его запускать нажатием кнопки при новом запуске КВИКА. -------------- Верно ?
не совсем то, так как QLUA на основе Lua 5.1 в которой /* @@ LUAI_MAXCALLS limits the number of nested calls. ** CHANGE it if you need really deep recursive calls. This limit is ** arbitrary; its only purpose is to stop infinite recursion before ** exhausting memory. */ #define LUAI_MAXCALLS 20000 /* @@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function @* can use. ** CHANGE it if you need lots of (Lua) stack space for your C ** functions. This limit is arbitrary; its only purpose is to stop C ** functions to consume unlimited stack space. (must be smaller than ** -LUA_REGISTRYINDEX) */ #define LUAI_MAXCSTACK 8000
дополню предыдущий ответ. Полагаю, что такая ситуация не возникает, так как свечи рассчитывает сервер. Поэтому терминал принимает их пакетом . Пропуск внутри пакета невозможен, так как сервер рассчитал пакет свеча за свечой.
При открытии графика все свечки строятся сразу или возможна ситуация что данные по какой то свече не пришли а через пару тиков появились и эта свеча нарисовалась?
Должны всегда строиться сразу, согласно таблицы обезличенных сделок.
Вот слово должны немного смущает. Вопрос возник по следующей причине: В мт5 могут быть получены не все данные, но при появлении новых данных, в индикаторе, есть параметр: prev_calculated (рассчитанных баров ранее) который обнуляется и на следующем тике я проведу расчёт по более полной истории. Здесь у меня ничего подобного нет, поэтому и решил уточнить. В таком случае, если мне нужно в одном индикаторе для расчёта получать данные по разным бумагам, синхронизировав данные единожды, я больше к этому вопросы могу не возвращаться ? или с синхронизацией есть какие-то другие подводные камни ?
Это не так просто как кажется, так как могут быть интервалы в которых нет сделок в одном из инструментов.
Вызов в форме return functioncall называется концевым вызовом. Lua также поддерживает концевой вызов «себя» (или рекурсивный концевой вызов): в этом случае вызванная функция использует стек вызывающей функции. Поэтому количество вложенных концовых вызовов может быть любым. Заметим только, что концевой вызов стирает отладочную информацию о вызывающей функции.
А разве это не верно: Для получения размера стека используйте функцию lua_checkstack. Для вызова из Lua кода на C необходимо иметь в наличии свободной памяти по крайней мере на LUA_MINSTACK позиций стека. LUA_MINSTACK по умолчанию равно 20. Если размера стека не хватает, его можно увеличить функцией lua_checkstack.