поясняю для тех кто в танке -------------------------- текст в любой кодировке - это массив байт конец массива обозначается нулевым байтом, поэтому в массивах с текстом запрещен нулевой байт но если в массиве байтов нет нуля то это может быть массив не текста --------------------- знание кодировки требуется лишь генератору символов на устройстве отображения ------------------ поэтому если отображения нет , то кодировка не имеет значение, если все строки текста в программе имеют одинаковую кодировку то с ними можно работать как с массивами байт ---------------------- оператору tostring вообще не требуется знать кодировки так как его задача заменить хеш указателем на массив байт с нулем в конце
Николай Камынин написал: tostring работает со строками в коде ASCII (American Standart Code for Inmormation Interchange) вернее ASCIIZ
Абсолютно неверное утверждение. В случае автоматического преобразования числа в строку да, получается ASCIIZ (а можно сказать, что получается utf-8 или win-1251 или что угодно, т.к. первая страница у всех codepage одинаковая, если не учитывать экзотику), но в случае строки возвращается строка как она есть, ровно в том виде, в каком ее туда засунули, в том числе со внутренними нулями (что автоматически отвергает ASCIIZ и, кстати, позволяет при некоторой осторожности впихнуть даже utf-16).
Цитата
Николай Камынин написал: tostring вообще-то все равно какая кодировка
Иван написал: LogWrite("report", comment, {Trade=100, Code=Si, Q="-"..10, Price=10000, Pips=1}); В функции делаю чтение массива:Код function LogWrite(name, log_type, log_array)
local content = ""; local i = 1; for key, value in pairs(log_array) do content = content.."\t"..value..";"; content = string.gsub(content,"([.]+)",","); i = i + 1; end; message(tostring(content));
end;
function LogWrite(name, log_type,t) local content = ""; local i = 1; for m=1,#t do local value=tostring(t[m]) content = content.."\t"..value..";"; content = string.gsub(content,"([.]+)",","); i = i + 1; end; message(tostring(content)); end; local Si=123 LogWrite("report", "", {100,Si,"-"..10,10000,1}); ------------------- 100; 123; -10; 10000; 1; >Exit code: 0
Удаление элементов в больших таблицах., Крайне медленная работа table.remove и возможные обходные пути для быстрого удаления большого числа элементов крупных массивов/таблиц.
Удаление элементов в больших таблицах., Крайне медленная работа table.remove и возможные обходные пути для быстрого удаления большого числа элементов крупных массивов/таблиц.
в рассмотренных примерах для удаления данных требуется создание еще одной таблицы можно уменьшить требуемый объем памяти если переписывать данные в туже таблицу а в конце ставить nil при этом методе надо после записи последнего элемента записывать nil например так: --Новая реализация 2 tab1 = tabInit (N) numElement = #tab1 startElement = numElement - ElemToKeep + 1 minus = numElement - ElemToKeep start=hrt.clock() for i=1, ElemToKeep do tab1[i] = tab1[startElement+i] end tab1[ ElemToKeep+1] =nill time=t_mcs(hrt.clock()-start) ne1 = tabCount2 (tab1) print ("Новая2="..time..";"..ne1) --------------------------
для точного измерения времени исполнения надо отключать сборщик мусора ---------------- в итоге получим следующий результат время в мс: Первая=1.661;5000 Вторая=0.777;5000 Новая1=0.758;5000 Новая2=0.704;4999 >Exit code: 0
на самом деле переменная в которую записываем строку не содержит указатель на строку, а содержит хэш строки. поэтому сравнение строк в луа делается быстро как и для числе, так как сравниваются числа хэш
Удаление элементов в больших таблицах., Крайне медленная работа table.remove и возможные обходные пути для быстрого удаления большого числа элементов крупных массивов/таблиц.
Иван Ру написал: Пока что вижу для себя такое решение -- формируем временную таблицу куда записываем только те элементы большой таблицы, которые нужно сохранить. Затем ставим знак равенства между большой нуждающейся в "обрезке" таблицей и временным вариантом (второй вариант, см. код ниже). Быстрее стандартного варианта в несколько сотен раз.
function tabInit (number) local tab ={} for i =1,number do tab=i end return tab end
function tabCount2 (Thetab) local count = 0 for k,v in ipairs (Thetab) do count = count+1 end return count end
-- Первая реализация local start = os.clock() while #tab1 > ElemToKeep do table.remove (tab1,1) end local ne1 = tabCount2 (tab1) local finish1 = os.clock() local time1 = finish1 - start message (tostring(time1).."-"..tostring(ne1))
-- Вторая реализация local tempTab = {} local numElement = #tab2 local startElement = numElement - ElemToKeep + 1 local minus = numElement - ElemToKeep
for i=startElement, numElement do tempTab[i-minus] = tab2 end tab2 = tempTab local ne2 = tabCount2 (tab2) local finish2 = os.clock() local time2 = finish2 - finish1 message (tostring(time2).."-"..tostring(ne2))
У меня на машине обрезка первым способом заняла 1,69 сек, а вторым - 0,002 сек.
У вас ошибка в подсчете времени вы включили в него время подсчета числа элементов - local ne2 = tabCount2 (tab2) кроме того вместо удаления одного элемента можно удалять например половину копированием в новый массив и переприсвоением время будет таким же как во втором случае local ElemToKeep = 5000 local N=10000 --Новая реализация tab1 = tabInit (N) local tempTab = {} local numElement = #tab1 local startElement = numElement - ElemToKeep start = os.clock() for i=1, ElemToKeep do tempTab[i] = tab1[startElement+i] end tab1 = tempTab time1 = os.clock() - start ne1 = tabCount2 (tab1) print ("Новая="..tostring(time1)..";"..tostring(ne1)) ------------------ Первая=1.682;5000 Вторая=0.00099999999999989;5000 Новая=0.0010000000000001;5000
Игорь Б написал: Дмитрий , могу лишь предложить свой работающий вариант, от которого можно оттолкнуться.
Код
if string.len (Tl.hour) = = 1 then Tl.hour = "0" .. Tl.hour; end ;
if string.len (Tl.min) = = 1 then Tl.min = "0" .. Tl.min; end ;
if string.len (Tl.sec) = = 1 then Tl.sec = "0" .. Tl.sec; end ;
Это просто ужас какой-то. ----------------------------------- У вас изначально таблица Ti содержит время в формате чисел. ---------------------------- Вы их превращаете для сравнения в строки, а потом записываете в виде строк в таблицу ---------------------- В итоге у вас для отображения времени в виде строки 6 раз вызывается преобразование числа в строку а потом вы еще и уничтожаете числа в таблице Ti, заменяя их строками ---------------------- Куча операций и дополнительной памяти чтобы вывести на экран строчку. ---------------------- Мазохизм какой-то
Николай Камынин написал: if text~=nil and string.len(text)>0 and vObj:Speak~=nil then vObj:Speak (text) end
Данная функция запускается всего из нескольких мест, и там по определению не может содержание текст быть пустым или нулевым. И не совсем понятно, как объяснить, что при одних и тех же условиях, при запуске из одних и тех же процедур, все работает хорошо, до тех пор, пока что-то не произойдет, после чего начинает выдавать ошибку. Т.е. условия запуска одинаковые, а результат иногда происходит ошибочный. Что конкретно лечит ситуацию, перезагрузка компа или достаточно перегрузить терминал, не выяснял.
Возможно ситуация уже решилась за счет функции pcall, во всяком случае уже теперь весь скрипт не виснет, так что ситуация перестала напрягать
проблема ваша не решилась а просто заблокировалось сообщение об ошибке без pcall сообщение об ошибке получает система и так как нет обработки реагирует на нее зависанием pcall перехватывает ошибку, но вы эту ошибку не обрабатываете. Т е когда у Вас возникает ошибка эта строка просто не работает т е вы не получаете звука, но система не виснет В таком случае зачем вам звук если вы его можете и не получить когда надо? ------------------ если хотите исправить ошибку то поставьте вывод кода завершения pcall в lopg или печать и определите причину
Latrop написал: В соседних ветках много сообщений о проблемах с версией 8.5, но системы у всех сложные, грешить не понятно на что..
Вот очень простой скрипт, который рушит Квик во время торгов. Упасть может и не сразу, поработав недолго, видимо зависит от интенсивности потока тиков. Ошибок в скрипте нет, он элементарный. Да если бы и были ошибки, то рушиться весь Квик не должен, только скрипт. Для 100% краха можно перезаказать данные текущей сессии. Тогда упадет сразу.
Код
local ticksIn = 0
function OnAllTrade (tick)
if ( math.fmod (ticksIn, 5000 ) = = 0 ) then
message ( "OnAllTrade " .. ticksIn .. " tick: " .. tostring(tick.trade_num))
end
ticksIn = ticksIn + 1
end
mainRun = false
function OnStop (flag)
message ( "OnStop" )
mainRun = false
return 3000 ;
end
function main ()
mainRun = true
message ( "main run..." )
local n = 0
while mainRun do
local ticksNum = getNumberOf ( "all_trades" )
if (ticksNum > 0 ) then
local tick = getItem ( "all_trades" , ticksNum - 1 );
if ( math.fmod (n, 1000 ) = = 0 ) then
message ( "AllTrades num: " .. ticksNum .. " tick: " .. tostring(tick.trade_num))
end
end
n = n + 1
sleep ( 1 )
end
message ( "main exit" )
end
1) mainRun = false -- оператор лишний, так как если mainRun не определен, то он false 2) значение n может переполниться когда-нибудь , а вычислять остаток - долго вот вариант без этих проблем: ------------------------- local n = 0 while mainRun do local ticksNum = getNumberOf ( "all_trades" ) if ticksNum > 0 then local tick = getItem ( "all_trades" , ticksNum - 1 ); if n==0 then message ( "AllTrades num: " .. ticksNum .. " tick: " .. tostring(tick.trade_num)) end end n = n + 1 if n>=1000 then n=0 end sleep ( 1 ) end ------------------ проверка условия в два раза быстрее.
надо проверять не только на нил но и длину сообщения на ноль если мало, то добавим: ------------------ if text~=nil and string.len(text)>0 and vObj:Speak~=nil then vObj:Speak (text) end
Александр написал: Добрый день. Столкнулся с багом. Суть и последовательность действий, приводящих к багу. 1. Ставлю лимитную заявку на фьючерс SRM0 на продажу, выше рыночной цены. Всё прекрасно. 2. Ставлю через lua скрипт аналогичную лимитную заявку. 3. Двигаю эту заявку по цене, неважно вверх или в низ, можно даже со старой ценой. Заявка двигается нормально. 4. После этого блокируется возможность выставления заявок по текущему инструменту на продажу (так как изначально выставлял заявку на продажу, см. п.1). 5. В Quik возможность выставления заявок тоже блокируется даже вручную, до окончания текущего дня. Так с любым инструментом (пробовал SRM0, GZM0, RIM0, SiM0). Записал всё на видео. Исходные коды тоже прилагаю. Помогите пожалуйста, так как сижу уже 2 дня и не могу побороть эту напасть. Раньше всё работало, на этих же исходниках. Перестало работать после обновления утром 23 апреля. https://cloud.mail.ru/public/3GLt/4615oogiY/
Заранее спасибо за помощь!!!
такое сообщение вы получите, если неправильно указали торговый Счет либо указали "пусто". Т е пытаетесь выставить торговую операцию не от своего счета.
Николай Камынин написал: и еще что у вас в 31 строке library.lua ?
Вот полная функция function speak_only (text) w32.CoInitialize() local vObj = luacom.CreateObject("Sapi.SpVoice") vObj:Speak (text) w32.CoUninitialize() end --speak_only
строка 31 содержит оператор vObj:Speak (text)
А каким образом остальной код может влиять на абсолютно независимую от остального кода функцию? тут все переменные локальны. Текст всегда передается строковой переменной из одной и той же другой функции, в которой физически не может быть не строковой переменной. И главная проблема в том. что бОльшую часть времени все работает.
В общем на данный момент пока вопрос закрыл с помощью оператора pcall, если будут снова проблемы, опишу ситуацию.
Благодарю всех, кто откликнулся на помощь!
напишите строку 31 так: if text~=nil and string.len(text)>0 then vObj:Speak (text) end ------------------------------- и будет Вам счастье.
Добрый день, Просьба пояснить почему в качестве новой версии в QUIK выбрана lua5.3 мое тестирование показывает, что версия 5.3 работает так же медленно как и 5.1 ------------------ а вот luajit, которая основана на Lua5.1 работает в 2 раза быстрее при исполнении скриптов и позволяет исполнять очень быстро и просто вставки на СИ увеличивая скорость исполнения до 50 раз. ---------------------------- кроме того версия LuaVela на основе luajit решает проблему ограничения памяти 2Гб. -------------------- Так в чем же тайный смысл замены 5.1 на 5.3? Спасибо
Николай Камынин написал: это ошибка в вашей library.lua строка 31
в этой строке оператор vObj:Speak (text)
Цитата
Николай Камынин написал: оператор 386 выдает сообщение об ошибке, если она есть
так ведь ситуация в том. что бОльшинство раз все работает нормально, а потом что-то происходит, и начинает выдаваться ошибку. Возможно память не очищается и забивается. посмотрим что будет с добавленной командой CoUninitialize() и использованием pcall
сказать что-то конкретнее без текста скрипта сложно. могу предположить что какие-то данные в какой-то момент отсутствуют У вас скорее всего это не проверяется и возникает ошибка например сравнение с nil в итоге происходит вылет скрипта (по такой ошибке бывает пропуск операторов) и в итоге кирдык еще хуже если попадаете в память вне области массивов короче надо ставить контрольные точки и искать что и где можете выложить код, попробую что-то сказать конкретнее
Игорь написал: Ничего умнее не придумал для округления до 4 знаков: math.floor(num * 10000+ 0.5) / 10000
Только жалко время на расчеты тратится..
с какой целью Вы это делаете? В исходном варианте у Вас погрешность 0.0000000000000001 а в вашем - погрешность 0.00005 т е в 10000000000 раз больше. Оно Вам надо? ---------------------- Вам "шашечки" или ехать?
Sergey Denegin написал: В макросе использую произнесение голосом разных событий.
Функция чтения голосом выглядит вот так:
text = "тест"
w32.CoInitialize()
local vObj = luacom.CreateObject("Sapi.SpVoice")vObj:Speak (text)
Как правило все работает без проблем. Но иногда, почему-то данная функция выдает ошибку ...\Program\QuikRobots\автостоп\. .\автостоп\library.lua:31: COM exception:(..\src\library\tLuaCOM.cpp,386):
Самое неприятное, что весь скрипт после этого останавливается, и это напрягает. Как правило, если потом перезапустить скрипт, ошибка уже повторяется. пока терминал не перезагрузишь или даже компьютер.
Может кто-то знает как решить проблему? 1) либо устранить ошибку совсем 2 ) либо научиться определять, что эта ошибка есть, и как-то не давать скрипту останавливаться
комп исчисляет в двоичной чел - в десятичной из десятичной в двоичную и обратно не всегда можно точно. вот и получаем приближенно. -----------------------
Sergey Denegin написал: Здравствуйте. Для работы одного из луа скриптов (автологин) использую внешнюю dll - w32.dll Раньше все работало С переходом на 64х разрядную версию старая dll перестала работать, но на сайте разработчика https://quik2dde.ru/viewtopic.php?id=80 появилась версия для 64х битной винды. Заменил ею старую версию, но все равно на квике 8.5 выдает ошибку:
error loading module 'w32' from file 'M:\Sergey\Program\QuikFinam-bid\w32.dll': Не найдена указанная процедура.
Взял самый примитивные луа скрипт с одной строкой:
local w32 = require("w32")
Уже на ней выдает ошибку.
История повторяется на двух компьютерах с 6х разрядной виндой
Может кто-то знает в чем дело?
ошибка: Не найдена указанная процедура. обычно указывает что требуемая в вашем приложении функция отсутствует на вашем компе эта функция обнаруживается с помощью dependency https://freesoft.ru/windows/dependency_walker
local TecPos=FuncPops(Emit,MyAccount) -- далее у нас открылась длинная позиция, пишем позицию и бар (bar) в переменную Tpos Tpos={TecPos,bar} и вот теперь что бы из неё выйти мы делаем проверку if Tpos[1] > 0 then --если тек позиция больше нуля то... вот если это условие выполнено, то у нас открыта длинная позиция и теперь переменная Tpos[2] - содержит бар этой позиции
Николай Камынин написал: У вас выводится V(index), а оно есть. -----------------
Да, это я усвоил)) Нужно выполнять проверку на отсутствие значений.
отвечаю на ваш вопрос в письме. Если надо лишь последнее значение бара открытия позиции, то проще присвоить номер бара переменной и сравнивать это значение с текущим номером бара
Денис Лихачев написал: function OnCalculate(index) local VolUp = nil local VolDn = nil if V(index)>V(index-1) then VolUp=V(index); else VolDn=V(index); end return VolUp,VolDn; end
У вас выводится V(index), а оно есть. -----------------
примерно так: ... for k,bumaga in ipairs(sec_code) do LowDnya = getParamEx (class_code, bumaga, "LOW").param_value Last = getParamEx (class_code, bumaga, "LAST").param_value Raznica = math.abs(LowDnya - Last) if Raznica > 1 then message(tostring(bumaga .. " " .. Raznica )) table.remove((sec_code,k) sleep(3000) end end
Тут лучшая готовность - работать с теми, кто не первый год замужем, там народ адекватный в основном и запросы у них адекватные, как в плане временные затраты vs бюджет, так и в плане самой постановки вопроса.
Цитата
новичок написал: отсюда вывод, что не все понимают природу отрытых динамических систем
А можно и еще проще подойти. Пусть наш программист, хорошо понимающий в бирже, делает стабильные (учетная ставка + 10)% годовых за вычетом костов. Это уже как бы отметает вариант "ваще не шарит", да? Поскольку учетную ставку надо на депозите оставлять (иначе этот трейдинг вырождается просто в постепенное прожирание депозита), чистыми "на прожор" он получает 10% годовых. Ок, посчитаем, сколько ему надо держать на бирже, чтобы вынимать в месяц хотя бы зеленую штучку. Подсчет конкретных циферок оставляется в качестве упражнения заинтересованному читателю. Также ему оставляется решить, очень ли здорово торчать у компа с десяти до девятнадцати (а то и двадцати трех пятидесяти) пять дней в неделю за плюс-минус озвученный прайс, когда можно либо а) торчать восемь часов в день за куда более интересный прайс, либо б) вообще не торчать и заниматься тем, что интересно (например, написанием не совсем тривиального кода) в удобном для себя графике.
Часто в головах начинающих наблюдается путаница в понимании кто и что знает Знать что и как на бирже - это одно А уметь написать по тех заданию скрипт для квика - это совершенно другое Чтобы написать скрипт не надо ничего знать о бирже надо изучить луа и квик. Как правило "гениальный" алгоритм торговли придумывает начинающий Очень часто "гениальность" алгоритма обратно пропорциональна знаниям очередного "гения" торговли.
Знаю по форуму www.bot4sale.ru давно Появился он в первый раз в результате скандала. Я за него заступился, о чем потом пожалел. Скандал был связан с тем, что один его заказчик заказав скрипт на луа получил зашифрованный вариант. Стал возмущаться, что он просил текст а ему код. ну и так далее... Полагаю что чел либо сам писать умеет либо ему кто-то пишет. Об уровне его разработок ничего сказать не могу, не знаю. --------------------------------------- В защиту писателей замечу, что у потенциальных заказчиков часто очень низкий уровень понимания задачи и отсюда расплывчатое т з типа - хочу все быстро и дешево. Но дешевых роботов не бывает, а прибыльных в интернете вы тем более не купите. Но это уже другая история.
Добрый день, Собрал новую версию своей библиотеки для QLUA экспорта данных (числа, строки , элементы таблицы) из скриптов. Отличается от известных тем, что экспорт осуществляется через ссылки . Пока вариант для 32 бит. Если есть желающие и умеющие тестить , стучитесь.
для информации из своего опыта. 1) синхронизируйте комп с сервером точного времени (атомными часами) в итоге время сервера биржи будет совпадать с временем компа и как правило с сервером брокера с погрешностью не более 100 мс (можно получить и 10) 2) сверните окна в квике, которые не используете . Открытые графические окна могут сильно тормозить 3) по возможности закройте все приложения особенно браузер ( я для браузера и прочего использую второй комп) Успехов
это ВООБЩЕ не система реального времени. даже приблизительно. не путайте людей.
я вас не путаю, Полагаю Вы просто не понимаете чем отличается система обработки данных реального времени от ОС РВ. А это две большие разницы. ----------------- Поясняю кратко: система обработки данных реального времени - это аппаратно-программный комплекс , который должен обработать поступивший квант данных до прихода следующего. в противном случае происходит как минимум накопление необработанных данных и потеря актуальности результатов. -------------------- Про ОС РВ вы полагаю знаете, поэтому пояснять нет смысла. =============== торговый робот - это система обработки данных в реальном времени т е для прогноза на тик надо успеть обработать результат сделки до поступления следующего иначе результат будет не актуальным Примером таких систем являются HFT роботы.
на картинке 160403_000.jpg есть наклонные линии они вычисляются по экстремумам и строятся на графике. можно вычислить и построить любые наклонные линии
На самом деле если вы не используете гадание по кофейной гуще или подбрасывание монеты для совершение сделок, то вы используете технический анализ. --------------------------- Просто большинство игроков этого не понимают, так как для них тех- анализ ограничивается чтением популярных книжек про то, как стать ... -------------------- В итоге - если Вы не знаете что такое тех анализ и зачем его применяют, то смысла нет, но вы от него не избавитесь.. ================= Чтобы было понятнее Пример тех анализа: Вы берете цену последней сделки и предыдущей и делаете ПРОГНОЗ изменения цен в следующий момент вычисляя разницу цен. Ваш мозг это делаете всегда, когда Вы смотрите на график и пытаетесь угадать движение рынка. --------------------------
AndyJOKER написал: Весело. Я правильно понимаю, что фактически в индикаторах можно использовать только данные O, H, L, C, V, T , Size ?
Нет, категорически не верно, можно и другие данные, зависит от того что Вам нужно. Если Вам нужно получить данные в индикаторе из другого скрипта, то почему бы не воспользоваться обменом через файлы? Один сприпт пишет в файл, другой читает.
Эммм, несколько странно слышать это от Вас, как от разработчика. Разумеется, у меня большая часть подобного "обмена" реализована. Не не через файлы, а через mysql. Но это же костыль... Некошерно такое делать. Согласитесь, что намного быстрее и удобнее обращаться к таблицам внутри памяти квика (не важно "стандартные" или созданные юзером) через getcell или getitem, чем вешать индикатор ожидая обращения к файлу или запроса от БД? Интересно, в чем проблема в реализации? Много обработчиков писать?
проблема в том, что надо синхронизировать потоки. так как написание скриптов игрушка сугубо для клиентов брокеров, то разработчикам нет смысла с этим заморачиваться. Если очень надо -пишите сами. Я именно так и делал. В итоге у вас не будет дублирование одной и той же информации в различных скриптах и ускорится работа скриптов так как не надо будет много раз вызывать одни и те же колбеки.
Рекомендую отключить опцию "Исходя из настроек открытых пользователем таблиц" навсегда и настроить квик вручную так как нет надобности каждый день перестраивать все заново. ------------------ В итоге будете точно знать что у вас приходит.