Тут что-то попроще. Вот только один график. Ни свечи, ни объема. Версия 7.6. Индикаторы ломаются. Геометрия поломается. [img]file:///F:/!!ScreenCaptures/PFE/gold.png[/img]
Возможно у Вас в параметрах диаграммы стоит галочка в "Показывать пустые интервал" Попробуйте ее убрать.
Sergey Gorokhov написал: И это правильно, так как отсутствие свечи это отсутствие данных.
Что же тут правильного? Если свечи нет, то не должно быть и вызова OnCalculate на эту свечу. Если же свеча вызывается, то логично, чтобы для этой свечи существовали те параметры, которые про нее известны. Логично, что цена отсутствует, тогда и пусть будет nil. Но у этих пропущенных свечей есть время. ТАк почему тогда время должно равняться для них nil? В чем логика?
Вызов OnCalculate происходит потому, что на одном графике свечи есть, поэтому он вызывается и для другого, где свечей нет, но оба графика в одном окне. Попросите разработчиков разделить вызов для графиков.
Космонавт написал: Хм. Тогда ещё вопрос. Вот мой колбек.
Код
function mycallbackforallstocks (class,sec,index)
расчёт логики, трудоёмкий процесс анализа
end
function DataSource (class,sec,interval)
ds[sec] = CreateDataSource (class,sec,interval)
ds[sec]: SetUpdateCallback ( function ( .. .) mycallbackforallstocks(class,sec, .. .) end )
return ds[sec]
end
пока считается логика, успевает прийти ещё одна сделка по другому инструменту. Или по этому же инструменту. Обработается ли она? Или будет пропущена и забыта?
Космонавт написал: Уж простите за странный вопрос. Можно ли писать на Луа роботов для Плазы? Увы, я кроме Луа ничего не знаю... А то корявое что я умею писать на Луа - далось с огромным трудом. Учить Си++, Джаву и Си# для меня долго... Спасибо за ответ.
Если найдете модуль луа для работы с плазой. Фактически это библиотека аналогично QLUA. Т е кто-то напишет на СИ вызов функций плазы из VMLua.
при экспорте надо закачивать данные последовательно с нарастанием даты иначе амиброкер начинает перебирать и замещать данные и все делается очень долго.
Orange2000 написал: Добрый день. Являюсь клиентом Альфы. Перешел на квик. Возникла проблема.
Скачиваю с финама минутки (примерно за 1 год) фьючерса РТС. И в формате txt и как тут ниже советовали в формате csv. экспортирую в ами. Все хорошо отображается, но экспорт не идет. На чистую идет, но там (у Альфы) история с 1 декабря почему-то.
менял всячески настройки экспорта в квике. Ничего не получается. В свое время с Альфа Директом таких траблов не было.
Подскажите где копать?
рекомендую делать так. Скачивайте с сайта финам в формате txt порядок значений настраиваете при экспорте в амиброкер аналогично скаченному. Все склеивается без проблем. Склеивал историю за 10 лет на минутке по любым инструментам.
Космонавт написал: Добрый день. Два дня мучился, осваивал работу через DataSourse. Заработало. Но код работает в 5 раз медленнее, чем когда я получал данные индикатора через идентификатор.
Прошу подсказать почему. Вот код. Боллинджер считается внутри файла BB.lua, который выложили разработчики вот здесь: ftp://ftp.quik.ru/public/INDICATORS.zip
Код
А теперь - самое интересное. Места с задержками. Где скорость как у ласточки я не трогал, подсветил только места задержек:
Цитата
То есть задержка то есть, то нету. Она равна 15 миллисекунд. И она бывает не только между 3 и 4, но и на разных участках кода. Вот например между 1 и 2 шагом.
Цитата
Вопросы.
1. Почему происходят эти задержки? 2. Почему на разных участках кода? 3. Рационально ли составлен код?
Спасибо.
задержка в 15 ms смахивает на квант для процесса Попробуйте оставить из запущенных задач лишь квик и посмотрите задержку.
Космонавт написал: Николай, спасибо за ответ. Приведите пожалуйста формулу мувинга, которую Вы рекомендуете, там где 1 деление +1 вычитание+1 сложение.
вот код мувинга без циклов:
Код
Settings = {
Name = "*nkSMA",
Period = 9,
line = {{Name = "nkSMA",Type = 1, Color = RGB(255, 0, 0)}}
}
function Init()
return #Settings.line
end
local P,i1,NP;
function OnCalculate(i)
local Out=C(i);
if i==1 then
S={}; P=Settings.Period; NP=1/P;
else
if i<=P then Out=(Out+i1*S[i1])/i;
else Out=S[i1]+ NP*(Out-C(i-P)); end
end
i1=i; S[i]=Out;
return Out
end
Космонавт написал: Сейчас формула такая. На примере 5-периодной Moving Average:
Код
.. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
ds = CreateDataSource (p_classcode, p_seccode, INTERVAL_M1)
ds: SetUpdateCallback (cb)
while is_run do
length = ds: Size ()
sum = 0
for i = 0 , 4 , 1 do
sum = sum + ds:C(length - i)
end
moving5 = sum/ 5
sleep ( 100 )
end
end
Есть два момента, которые необходимо учитывать: ---------------------------------------------- 1) Расчет надо делать для двух состояний: а) свеча закрыта б) свеча открыта. Либо лишь состояние а), которое надо обнаружить. состояние б) существует лишь на последней свече и лишь в режиме торгов. Поэтому у Вас расчет последней свечи содержит ошибку. -------------------------------------------------------------------- 2) Не надо использовать циклы. Циклы -это зло в системах реального времени. Можно вычислить мувинг затратив лишь 1 деление +1 вычитание+1 сложение для любого значения параметра N. У Вас N всего 4, а некоторые (обращались ко мне с такой проблемой) используют 1000000 (сто тысяч) Вот и посчитайте мколько времени у Вас будет считаться мувинг встроенным индикатором или вашим ( у обращавшихся квик виснул ) -----------------------------
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)