При запуске Квик работет в процессах , в приложениях его нет . В окне нет ., Кошмарит уже год , два .
Пользователь
Сообщений: Регистрация: 30.01.2015
27.01.2024 19:38:28
Цитата
Александр Васильев написал: Да как то , у вас таблица процессов , там нихера ничего сделать нельзя , а нет квика в приложениях , и фиг вы его увидите .
Приложение QUIK называется info.exe
Робот в виде скрипта индикатора
Пользователь
Сообщений: Регистрация: 30.01.2015
27.01.2024 19:35:57
Написал робота. Получилось 180 строк, примерно 200 операторов. --------------------- Робот позволяет написать правило для индикаторов на графике и по сигналам этого правила покупает или продает заданное количество. При этом снимает заявки, если они не исполняются заданное время. ------------------- Сейчас процесс отладки. ----------------- Отладил режим советника. Вот картинка сигналов робота. На графике два мувинга . это основная часть робота-индикатора:
Код
paths = "D:/QUIK_SCRIPT/" -- путь к файлу nkbot24_func.luac
dofile(paths.."nkbot24_func.luac")
Settings.account=""; Settings.client=""; --вписать счет и клиент
Settings.Nind=2;
function OnCalculate(i)
Hi,Li=H(i),L(i);
if i==1 then _nkInit(); return end--инициализация
_getI(i); --читаем значения индикаторов
f=_cross(1,1,2,1,i); -- сигнал пересечение линий индикаторов
_torg(f,i); --выставляем заявки по пересечению
return SE,BU; -- отображаем сигналы в режиме советника
end
Хотел выложить nkbot24_func.luac, но форум не принимает такие файлы. --------------
При запуске Квик работет в процессах , в приложениях его нет . В окне нет ., Кошмарит уже год , два .
Пользователь
Сообщений: Регистрация: 30.01.2015
27.01.2024 19:23:12
Цитата
Александр Васильев написал: Ну тогда внимательно читаем заголовок , в процессах квик есть , работает , а в приложениях его НЕТ ( не развернуть , не свернуть ) а из процесса его никак не выдернуть в окно . Смыл сообщения , я столько мучился и во на тебе , нашёл в 2016 году . А ведь всегда искал . А скрипт дело 10 е пару дней пока .
Ну внимательно читаем - написано на картинке Приложений(7) седьмое- это КВИК. Что не так,
Индикаторы. OnCalculate. Количество полных проходов по всем свечам
Пользователь
Сообщений: Регистрация: 30.01.2015
27.01.2024 17:57:58
можно еще проще сделать:
Код
function OnCalculate(index)
if index == 1 then
_ds = getDataSourceInfo()
--....
end
return 0
end
вообще не определять, будет глобальным.
При запуске Квик работет в процессах , в приложениях его нет . В окне нет ., Кошмарит уже год , два .
отвечу на заголовок: приложения - это процессы. И КВИК там и работает. Вот картинка диспетчера задач: Читаем внимательно надписи вкладок и открытого окна ==================== Относительно ошибок при загрузке скрипта. Уверен, что ошибки в Вашем скрипте. Покажите Ваш скрипт, если хотите их иcправить.
Индикаторы. OnCalculate. Количество полных проходов по всем свечам
Пользователь
Сообщений: Регистрация: 30.01.2015
27.01.2024 17:06:13
Цитата
Илья написал: Есть ли вариант сохранения состояния расчета между вызовами OnCalculate?
Вчера пытался в таблицу Settings добавить свою таблицу рассчитанных при первом проходе значений, чтобы при следующих просто из нее вытащить. Знаю, что в руководстве написано "Типы пользовательских параметров: числа и строки" До перезапуска терминала (накидал скрипт, пока терминал работал), вроде, получилось: значения и сохранялись, и выбирались. Но при последующем запуске терминала выводилась ошибка об отсутствии моей таблицы. Хотел сделать через замыкание, но, опять же, где хранить этот объект?
Опишите переменную вне функции OnCalculate. Например, у Вас выше написано так:
Код
function OnCalculate(index)
local _ds = nil
if index == 1 then
_ds = getDataSourceInfo()
--....
end
return 0
end
переменная _ds всегда затирается при входе в OnCalculate чтобы этого не было сделайте так:
Код
local _ds;
function OnCalculate(index)
if index == 1 then
_ds = getDataSourceInfo()
--....
end
return 0
end
Робот в виде скрипта индикатора
Пользователь
Сообщений: Регистрация: 30.01.2015
26.01.2024 14:21:04
Добрый день, Рассказываю, как просто сделать робота в виде скрипта индикатора. Сначала картинка работы такого робота.
В чем достоинство такого робота по сравнению с роботом на основе колбеков. Робот значительно проще написать Он загружается на график торгуемого инструмента, Если для реализации алгоритма торговли достаточно встроенных в QUIK индикаторов, то нет надобности их программировать. ---------------- Пример варианта основного фрагмента такого робота:
Код
name="nkbot24"
Settings={["Name"] =name,["line"] ={},["account"]="",["client"]="",["Q"]=1;["wt"]=1000,["short"]=0}
Settings.Nind=0;
paths = "D:/QUIK_SCRIPT/"
package.cpath =package.cpath ..";"..paths.."?.dll";
package.path =package.path..paths.."?.lua;"
fnlog=paths..name..".log"; Log=io.open(fnlog,"w")
loadfile(paths.."nkbot24_func.lua")
function nkbuy(i,f)
---алгоритм покупки
-- f=cross(1,1,2,1,1);
return f;
end
function nksell(i,f)
--алгоритм продажи
-- f=cross(1,1,2,1,1);
return f;
end
function nobuy(i,f)
--фильтр покупки
return f;
end
function nosell(i,f)
--фильтр продажи
return f;
end
function OnCalculate(i)
local i1=i-1;
if i==1 then nkInit(); return end
if i~=i_ then getI() end
N,torder=order(N); Q=depo();
if #t==0 then
-- f,j=cross(1,1,2,1,5); --пересечение двух индикаторов
if i~=i_ then torg(nkbuysel(i));end
M=os.clock();
else
del_ord(M);
end
i_=i;
return M1,M2;
end
Продолжение вероятно следует...
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 09:06:53
чтобы массив был ограничен по размеру, его надо закольцевать. Очевидно, Виктор это не проходил.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 09:04:09
, Я ранее написал, что Ваш вариант - это недоделанный циклический массив, тест которого я привел вторым. Рекомендую доделать, тогда будет работать , но чтение из него в луа, как тоже уже писал, медленнее чем из сдвигового.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 09:00:14
, Можете пояснить, как в вашем варианте прочитать весь массив с 1 по последний и сколько времени на это уйдет по сравнению с чтением типа t[i] где i от 1 до #t. -------------- И для какой задачи Вы планируете его применять. ------------- Я определил область применения моего варианта. А как применять Вашу очередь?
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 08:43:49
, вот результаты тестов: это тест моих функций сдвиговый массив.
Код
local M=1000000
local t=newCA(1024)
for i=1, M do setCA(t,i) end
count1 = collectgarbage("count") print("объем занятой памяти",count1//1);
--------------------------------
collectgarbage("collect") count1 = collectgarbage("count") print("объем занятой памяти после сборщика мусора",count1//1);
результат:
Код
>D:/lua53/lua53.exe -e "io.stdout:setvbuf 'no'" "Test_List.lua"
объем занятой памяти 82.0
объем занятой памяти после сборщика мусора 76.0
>Exit code: 0
тест циклический массив:
Код
local M=10000000
local t=nk_newV(1024)
for i=1, M do nk_push(t,i) end
count1 = collectgarbage("count") print("объем занятой памяти",count1//1);
collectgarbage("collect") count1 = collectgarbage("count") print("объем занятой памяти после сборщика мусора",count1//1);
результат:
Код
>D:/lua53/lua53.exe -e "io.stdout:setvbuf 'no'" "Test_List.lua"
объем занятой памяти 97.0
объем занятой памяти после сборщика мусора 91.0
>Exit code: 0
тест для Вашей функции
Код
local M=10000000
local list=List.new()
local count1 = collectgarbage("count") print("начальный объем занятой памяти",count1//1);
--------------------------
for i=1, M do List.pushlast(list,i) end
collectgarbage("collect") count1 = collectgarbage("count") print("объем занятой памяти после сборщика мусора",count1//1);
результат:
Код
>D:/lua53/lua53.exe -e "io.stdout:setvbuf 'no'" "Test_List.lua"
начальный объем занятой памяти 65.0
объем занятой памяти после сборщика мусора 262203.0
>Exit code: 0
Какой еще тест сделать?
Уникальный номер заявки
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 08:06:53
Цитата
bespalex написал: это конечно вариант, но мне он не нравится отсутствием изящества, громоздкостью что ли. Кроме того, как справедливо раньше вы подметили, при работе с питоном приходится экономить операции. На эту проблему накладывается возможное отсутствие trans_id в сообщениях, который я поддерживаю уникальным на своей стороне. Городить два индекса совсем не хотелось. И что делать, если order_num не приходит? Ждать? Сколько? получается заявка в неопределенном статусе может находиться неопределенное время.
Можете показать пример громоздкости или затрат на вычисления? --------------------- Вся история предыдущих дней в худшем случае обрабатывается один раз до начала торгов. в лучшем случае обрабатывается вчера.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 08:03:27
Если Вы считаете, что Вы правы, то просто покажите свой тест и результаты и будет предмет обсуждения. Пока же у Вас лишь программа и ваша вера, что она экономит память.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 08:02:49
Если Вы считаете, то просто покажите свой тест и результаты и будет предмет обсуждения. Пока же у Вас лишь программа и ваша вера, что она экономит память.
Сдвиговые регистры, циклические массивы. Экономим память
Стек — это коллекция, элементы которой получают по принципу «последний вошел, первый вышел» (Last-In-First-Out или LIFO). Это значит, что мы будем иметь доступ только к последнему добавленному элементу.
Очереди очень похожи на стеки. Они также не дают доступа к произвольному элементу, но, в отличие от стека, элементы кладутся (enqueue) и забираются (dequeue) с разных концов. Такой метод называется «первый вошел, первый вышел» (First-In-First-Out или FIFO). То есть забирать элементы из очереди мы будем в том же порядке, что и клали. Как реальная очередь или конвейер.
Двусторонняя очередь (Double-ended queue), или дек (Deque), расширяет поведение очереди. В дек можно добавлять или удалять элементы как с начала, так и с конца очереди. Такое поведение полезно во многих задачах, например, планирование выполнения потоков или реализация других структур данных.
Позже мы рассмотрим вариант реализации стека с помощью двусторонней очереди .
Будем считать, что у нас разные определения этих понятий. ------------------------------ Но это не важно. Важно, что ваш вариант не работает.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 07:58:14
Цитата
VPM написал: , Это я и хотел сравнить, сделать один размер массивов, один размер окна прогнать на скорость на память, на время исполнения?
Цитата
написал: и еще... ваша стек-очередь напоминает недоделанный циклический массив. Если его доделать, то он будет делать ровно тоже самое, что и мой вариант сдвига массива выше. -------------------- Циклический массив работает быстрее, чем сдвиг массива. Но в луа из него медленнее брать данные. Его интереснее делать на C и встраивать сразу в индикаторы и фильтры. Но это уже другая тема.
Вы нем поняли. В вашем случае нельзя сделать размер постоянным. Он будет лишь увеличиваться при записи в конец. Но не будет уменьшаться. ---------------- Это я показал Вам в своем тесте. Там в конце Ваша очередь-стек имеет ноль элементов , но размер памяти занятый массивом остался такой же как при записи миллиона элементов. -------------------- В моем варианте Вы изначально фиксируете длину массива и она остается всегда такой же.
CalcBuySell. Что не так?
Пользователь
Сообщений: Регистрация: 30.01.2015
24.01.2024 07:54:18
, Вы прежде, чем писать херню, прочитали бы о чем тема. ------------------------------- Специально для вас, поясняю. Речь идет о работоспособности функций библиотеки QLUA, а не о написании примитивных вычислений.. ------------------------------- Вы уже написали свой "гениальный" шедевр очереди, которая стек и которая лишь увеличивает размеры используемой памяти. Но почему молчите о том что написали говно? ------------------ Если у Вас проблема с написанием таких программ, то пишите конкретно вопрос, а не скулите. -------------- Программатор Вы наш.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 17:25:07
и еще... ваша стек-очередь напоминает недоделанный циклический массив. Если его доделать, то он будет делать ровно тоже самое, что и мой вариант сдвига массива выше. -------------------- Циклический массив работает быстрее, чем сдвиг массива. Но в луа из него медленнее брать данные. Его интереснее делать на C и встраивать сразу в индикаторы и фильтры. Но это уже другая тема.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 17:11:21
Цитата
, Возможно я не понял, вопроса, Но так как Вы возвращаетесь к этой идеи уже многократно, то поясню подробнее в чем у Вас ошибка. --------------------- Во-первых, в терминологии. Вы уж не обижайтесь, но прежде, чем обсуждать надо быть уверенным , что мы с вами горшками называем горшки, а цветами -цветы. ------------------ Так вот, Стек и очередь это две большие разницы. Стек - это кипа - т е представьте кипу листов бумаги на столе. Вы положили лист сверху и взяли его. -------------------- или еще пример стека - это обойма в автомате патрон лежащий сверху выйдет первым. ----------------- Т е принцип последним зашел -первым вышел. ------------------------- Очередь -это первый зашел и первым купил. Наглядный пример - очередь в магазине за яйцами. ------------------------ Поэтому невозможно стек сделать из очереди. Если конечно Вы не сторонник смотреть гланды через зад. ==================== Но это не главное. ======================== Давайте посмотрим на то как вы пытаетесь уменьшить память, создав нечто, в котором Вы синхронно выкидываете первый элемент и запихиваете последний. ---------------------------- Ничего это вам не напоминает? А посмотрите эту мою тему Про сдвиговые регистры. Именно это и происходи в них. -------------------- Но они реализуются методами, которые я описал выше. =================== Если же Вы будете просто в массиве луа стирать первый элемент, записывая туда nil и добавлять в конец новый, то массив будет увеличиваться на этот новый элемент. ---------------------------------------- В луа для хранения одного числа в таблице тратится 12 байт. Когда Вы пишите nil в первый элемент, то память из под него не освобождается, так как ее невозможно удалить из того блока памяти, который уже выделен для этого массива. ------------------- В лучшем случае освободится память на элемент массива, если он является тоже таблицей. ====================== вот ваш вариант.
Код
---- Операции вставки -- table.insert
function List.pushlast (list, value) local last = list.last + 1; list.last = last; list[last] = value; end
---- Операции удаления -- table.remove
function List.popfirst (list)
local first = list.first; if first > list.last then return nil end
local value = list[first] list[first] = nil list.first = first + 1 return value end
list[last] = value; -- этот оператор записывает в таблицу новое значение. -------------------------------- При создании таблицы , ей выделяется место в оперативной памяти. ---------------------------------- Если при записи нового значения места не хватает, то оно будет увеличено. ----------------------- C точки зрения сборки мусора. Объектом для сборки является вся таблица, а не отдельная ее ячейка. ================ Когда Вы в функции popfirst делаете это: list[first] = nil то в ячейке таблицы в параметр тип элемента записывается ноль. Но память для хранения этого типа и значения элемента не может быть освобождена, так как она не является самостоятельным объектом. Это часть память таблицы. ======================= Таким образом, в вашем варианте таблица может только увеличивать объем занимаемой памяти, но не уменьшать ее. ========================= Уменьшать, можно лишь так, как я рассказал в этой теме.
Уникальный номер заявки
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 14:09:09
номер сделки и дата торгов
Уникальный номер заявки
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 14:08:50
Цитата
bespalex написал: Уникальность номеров заявок order_num поддерживается только внутри одного торгового дня. Также как и trade_num для сделок. Получается при использовании этих параметров в качестве индекса может возникнуть ситуация, что записи имеющиеся совпадут по индексу с новыми заявками и сделками дня, что может привести к труднопредсказуемым последствиям. Использовать trans_id в качестве уникального индекса тоже ненадежный способ, т.к. логика его передачи в сообщениях нестабильна. Также например случаются существенные задержки с поступлением OnTransReply и тогда невозможно отменить заявку, т.к. для этого необходим order_num, которого у нас еще может не быть. Кто как решает эту проблему?
Внутри дня используем номе сделки А между днями - дополнительно дату. Устроит такое решение?
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 14:06:18
Цитата
VPM написал: , Вы можете сравнить это метод с local lifo=List.new() List.pushlast(lifo,i) List.popfirst(lifo), и где какой использовать лучше или предпочтительней
Я уже сравнивал и вам в вашей теме выложил результат. Вы очевидно его не читали. ------------ Если кратко, то Ваш вариант ничего не экономит. Вы посмотрите там результат работы сборщика и пояснение почему Вы заблуждаетесь с этим вариантом. -------------------- Если будет непонятно, то поясню дополнительно.
Сдвиговые регистры, циклические массивы. Экономим память
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 10:03:45
Добрый день, В этой теме я расскажу кратко что такое сдвиговые регистры и циклические массивы. И покажу как на Lua экономить память при создании роботов. ---------------------- При торговле на бирже приходит много информации, такой , как новости, результаты сделок, значения индикаторов, например свечей. эта информация записывается в массивы и в файлы и может составлять очень большой объем. ------------------ Однако, при реальной торговле, для принятия решения, нет надобности не только во всей накопленной информации в файлах, но и порою нужна лишь информация за последние например 60 минут, свечей с интервалом 1 минута. ================= Чтобы массивы с данными не разбухали до безумных размеров я реализую временное окно, в пределах которого храню текущую информацию. ------------------- Например, храним только 1024 последних отсчета. Для этого необходимо выделить массив всего в 1024 элемента. Для каждого нового отсчета необходимо сдвинуть содержимое массив влево на один отсчет, а в освободившейся место записать принятое значение. -------------------- Возникает вопрос как реализовать этот сдвиг элементов массива, чтобы было быстро. --------------------- Один из приемов - циклические массивы. ------------------- В таком массиве элементы не двигаются, а двигается указатель на место удаляемого первого элемента . Это же место является местом размещения принятого элемента. --------------- Еще одним способом является использование многобитовых регистров процессора, с помощью которых можно реализовать многобитовые сдвиги данных за одну операцию. =================== В луа есть операции сдвига >>m (<<m). Они позволяют сдвинуть целое число на m разрядов влево ( вправо), что соответствует делению(умножению) этого числа на 2 в степени m. Такая операция сдвига числа выполняется в регистре сдвига ( в процессоре это АЛУ+регистры) ------------------ В современных процессорах Intel есть регистры в 256 бит (в последних 512 бит) ------------------------------ Так как число double занимает 64 бита, а long(integer в lua) 32 бита, то с помощью этих регистров можно сдвигать не одно число, а массив из 4,8,16 чисел одной командой. Для простоты будем называть эти регистры 256(512) ,битовыми тоже сдвиговыми регистрами. ------------------ Очевидно, что с помощью этих регистров можно сдвигать массивы чисел. ======================= Если не использовать С for lua, то в скрипте на луа можно реализовать два способа работы с такими временными окнами. ------------------------------ Либо циклический массив, либо сдвиг элементов массива. -------------------------------------- Так как данный ликбез в основном для начинающих, то покажу наиболее простой способ, но при этом достаточно быстродействующий. ------------------------------- Вот скрипт функций, которые реализуют механизм такого временного окна данных, где N - размер временного окна
Код
local function newCA(N) local t={}; for j=1,N do t[j]=0; end; return t; end --вставка нового элемента
local function setCA(t,X) table.remove(t,1); t[#t+1]=X; end --вставка нового элемента
Посмотрим, что сохраняется в таком массиве Организуем цикл записи номеров отсчетов которые изменяются от 1 до M и какие из отсчетов будут сохраняться в массиве фиксированной длины 32 элемента
Код
local M=1000000
local t=newCA(32)
for j=1,M do setCA(t,j)
print("j="..j..",t="..table.concat(t,","));
end
Оценим быстродействие такого метода для массива в 1024 элемента
Код
local M=1000000
local t=newCA(1024)
--nklib.startA();
local tim=os.clock();
for j=1,M do setCA(t,j) end
--local tim=0.1*nklib.stopA()/M
tim=os.clock()-tim
print(1000000.*tim/M.." мкс" )
Т .е. на сохранение одного нового элемента в таком массиве затрачивается примерно 10 мкс. --------------------- Таким образом, с помощью приведенных выше двух простых функций, Вы можете управлять расходом оперативной памяти в своем роботе, исходя из требуемого временного окна обработки поступающих данных.
CalcBuySell. Что не так?
Пользователь
Сообщений: Регистрация: 30.01.2015
23.01.2024 07:58:38
Сейчас все работает.
Мой робот
Пользователь
Сообщений: Регистрация: 30.01.2015
22.01.2024 17:36:20
В этой теме
я подробно рассказал как просто сделать очередь событий в роботе и для чего это нужно. При этом использование функции sleep не приводит к потере событий на рынке. ----------------------------- Однако, такое решение имеет недостаток в том, что ядро процессора простаивает, когда в очереди есть события. ----------------------- Может показаться, что простаивание ядра на 10 ms это мелочь. Но у нас ядро работает на частоте 3ГГц и более. За 10ms процессор может выполнить более 100 тысяч команд. Стоит ли их терять? --------------------- Я использую другой способ остановки процессора на время отсутствия событий. Рассказываю о нем лишь в самом упрощенном виде. Кто пожелает его реализовать, рекомендую книгу Дж.Рихтера. -------------------- Этот механизм можно реализовать на СИ. Для этого создается специальный флаг, называемый event - событие. Для обнаружения события используется функция ожидания события. С учетом этого у меня колбеки записаны иначе, чем в указанной выше теме. В них добавлена функция управления событием. А в функцию main добавлена функция ожидания, которая дополнительно реализует функцию "сторожевого пса" Вот фрагменты этих участков скрипта:
Код
function OnParam(c,s) _N=_N+1; tpr[_N]={14,c,s}; nkevent.Set(event);end
Код
----
local w=nkevent.wait(); --ждем события
if w~=0 then Log:write(w..",прошло 30 секунд\n"); Log:flush(); end
while _N>0 do
----
Kolossi написал: Пардон, это я про то, что просто вывести message(tostring(qty).." "..tostring(com))
Цитата
Kolossi написал: local s=c..","..s..","..tostring(client)..","..tostring(price)..","..tostring(acc)..", qty="..tostring(qty);
так там так и стоим:
Код
", qty="..tostring(qty);
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 16:46:02
Цитата
Glukator написал: , объясняльщик ты х**в, понятие "сдвиговый регистр" пришло в ЦОС из схемотехники, где оно материализуется в виде законченного устройства, в виде микросхемы, естественно, с ограниченным числом ячеек. А "очередь" - понятие чисто алгоритмическое, подразумевающее добавление элементов с одного конца, а извлечение с другого, вот и все. И по барабану, с какого там конца программист индексы нумерует. И то, что ему захотелось длину очереди ограничить - с алгоритмической точки зрения тоже ниего не меняет, кто раньше вошел - тот раньше вышел. Называй как хочешь, суть не меняется. Терминологии он тут решил поучить, ага.
А ты тогда просто мудак. Объясняю для тебя специально. В цифровой обработке сигналов есть понятие элементы задержки. Эти понятия есть даже в ИИ. И это вполне алгоритмическое понятие в настоящее время, так как большинство разработчиков ИИ понятия не имеют о схемотехнике. Так вот , то что хочет автор этой темы реализуется не очередями и не стеками, а циклическими массивами. ----------------------- Да и еще Даже в луа есть операция сдвига вправо и влево - а это и есть сдвиговый регистр . можешь придумать другое название Мне по... А то что Вы здесь херней занимаетесь это факт.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
написал: При перезаписи, если нет других ссылок на область памяти, то она будет удалена (почищена) мусорщиком.
Это значит, что память расти не будет.
Херня это все У вас очередь - это массив. Если в массиве хранятся числа, то для них не отводится дополнительной памяти. Но даже если Вы храните указатель, то сам элемент массива останется в памяти. Запись nil - это запись 0 в тип элемента массива. Элементы массива никуда не денутся пока Вы не уничтожите весь массив путем записи nil в его имя. а не в его элементы.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 16:34:53
, Вам тут Виктор засрал мозги своей "гениальной" программой очереди. Вот Вам тест, который доказывает, что ничего это творение не экономит. Объясняю что делает тест. Сначала в цикле загоняются push числа в очередь и очередь увеличивается Потом все числа выгоняются из очереди функцией pop и очередь становится вообще пустая ---------------- В процессе этого измеряем расход памяти до и после и запускаем сборщик чтобы собрать все что освободилось вот сам тест:
Код
local M=10000000
local count1 = collectgarbage("count") -- получаем текущий размер памяти
print("начальный объем занятой памяти",count1);
--------------------------
local list=List.new()
for i=1, M do List.pushlast(list,i) end
print("число элементов в очереди list после "..M.." циклов функции push="..#list)
local count1 = collectgarbage("count")
print("объем занятой памяти",count1);
--------------------------------
for i=1, M do List.popfirst(list) end
print("число элементов в очереди list после "..M.." циклов pop="..#list)
local count1 = collectgarbage("count")
print("объем занятой памяти после сборщика мусора",count1);
collectgarbage("collect")
local count1 = collectgarbage("count") -- получаем текущий размер памяти
print("объем занятой памяти после pop",count1);
------------------------------
collectgarbage("collect") -- выполняем сбор мусора
local count2 = collectgarbage("count") -- получаем размер памяти после сбора
print("объем занятой памяти после сборщика мусора",count1);
а это результат:
Код
>D:/lua53/lua53.exe -e "io.stdout:setvbuf 'no'" "Test_List.lua"
начальный объем занятой памяти 63.69921875
число жлементов в очереди list после 10000000 циклов функции push=9999999
объем занятой памяти 262202.31738281
число элементов в очереди list после 10000000 циклов pop=0
объем занятой памяти после сборщика мусора 262202.51953125
объем занятой памяти после pop 262202.12792969
объем занятой памяти после сборщика мусора 262202.12792969
>Exit code: 0
Как видим, ничего не освободилось. НОЛЬ. При этом элементов в очереди тоже ноль. ============================ Ты не поверь, Карл, такую чушь обсуждают целую неделю.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 11:03:26
Учите терминологию, а не придумывайте
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 11:02:39
В очереди нет синхронизации извлечения первого и добавления последнего. Такая синхронизация в сдвиговых регистрах.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 11:00:42
опечатка .. Если Вы будете удалять первый при добавлении последнего, то это называется СДВИГОВЫЙ РЕГИСТР, а не очередь.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 10:59:39
Если Вы будете удалять первый при удалении последнего, то это называется СДВИГОВЫЙ РЕГИСТР, а не очередь.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 10:38:21
Объясняю медленно . ----------------------- Для экономии памяти очередь вообще не причем. В цифровой обработке сигналов нет даже такого понятия. Для этой цели применяются сдвиговые регистры (массивы, вектора) -------------------- Это КЛАССИКА в цифровой обработке сигналов. ------------------- Все фильтры и индикаторы строятся на циклических массивах. ------------------
CalcBuySell. Что не так?
Пользователь
Сообщений: Регистрация: 30.01.2015
21.01.2024 10:29:44
Функция выдает нули. Что не так? ------------- Тест:
Код
function main()
while fconnect do
if getInfoParam("SERVERTIME") then fconnect=2; end
while fconnect==2 do
c="QJSIM"; s="SBER" client="10326"; acc="NL0011100043"; price=275.74;
qty,com=CalcBuySell(c,s,client,acc,price,true,false);
local s=c..","..s..","..tostring(client)..","..tostring(price)..","..tostring(acc)..", qty="..tostring(qty);
message(s,1);
sleep(10000); end
end
end
function OnInit(pfile) fconnect=isConnected(); end
Результат:
os.sysdate() . Что-то в ней не так..
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 21:01:22
Добрый день, Вопрос к разработчикам В документации на библиотеку QLua заявлено, что os.sysdate() возвращает системное время с точность до микросекунды. ------------------------ Это означает, как я понимаю, что если я получу с помощью этой функции время в двух точках скрипта, то разница даст мне время исполнения этого участка с точностью до микросекунды. ------------------ Я написал такой тест:
Код
paths = "D:/nkarray/"
package.cpath =paths.."?.dll";
require "nkarray"
event=nkevent.Create("event");
---------------------
name="bot"; -- имя робота
path = "D:/QUIK_SCRIPT/nk_bot/" --папка где разместим лог файл
Log=io.open(path..name..".log","w") -- создаем лог файл для записи
------------
_N=0; _tN={};
----------------------
function main()
-----------------------
while fconnect do
if getInfoParam("SERVERTIME") then fconnect=2; end
------------------------------
while fconnect==2 do
w=nkevent.wait(event); --ждем события
while _N>0 do
t=_tN[_N]; _N=_N-1
----------------------
tim2=0.1*nklib.stopA();
T=os.sysdate();
local _,_,_,t3=nkvm.D(); --HMS,YMD,dHMS,dt,ns
t1=60.*(60.*T.hour+T.min)+T.sec+0.001*(T.ms+0.001*T.mcs);
local x1=1000000.*(t1-t[1])//1;
local x2=1000000.*(t3-t[2])//1;
Log:write("os.sysdate OnParam(сек)="..t[1]..", os.sysdate main(сек)="..t1..",разность 1(мкс)=="..(t1-t[1]).."\n");Log:flush();
Log:write("nkvm.D OnParam(мкс)="..t[2]..", nkvm.D main(мкс)="..t3..", разность 2(мкс)="..(t3-t[2]).."\n");Log:flush();
Log:write("разность 3 по высокоточному таймеру OC(мкс)="..tim2.."\n\n");Log:flush();
end
end
end
end
----------------------------
function OnInit(pfile) fconnect=isConnected(); end
----------------
function OnParam(c,s)
local T=os.sysdate(); local tim=60.*(60.*T.hour+T.min)+T.sec+0.001*(T.ms+0.001*T.mcs)
nklib.startA(); local _,_,_,tim1=nkvm.D(); _N=_N+1; _tN[_N]={tim,tim1};
nkevent.Set(event);
end
В котором я замеряю системное время в колбеке on Param в строке
Код
local T=os.sysdate(); local tim=60.*(60.*T.hour+T.min)+T.sec+0.001*(T.ms+0.001*T.mcs)
и передаю его в функцию main в функции main я снова получаю системное время в строках
и все три значения вывожу в лог файл, который покажу ниже. ---------------------- кроме того, для сравнения я делаю тоже самое на основе собственной функции времени а также своего таймера который реализован на высокоточном таймере процессора. Но это так, чтобы показать, что действительность не такая, как показывает ваша функция. и вот результат :
На основе Вашей функции разность показаний равна НУЛЮ. Мои функции показывают разность от 63 до 24 мкс, что более соответствует реальному процессу, так как процессор у меня далеко не квантовый. -------------------- Вопрос: Что не так с вашей функцией os.sysdate() ?
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 14:37:25
Хвалюсь. На начала сессии 6.39% Сейчас шорт, но не закрыт. Подробности на графике.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 14:34:36
Цитата
VPM написал: , Ну первый вопрос зачем лезть в глобальное окружение, я видел у Вас такой прием?
Поясняю. Основной стек VMLua в КВИКЕ - это то, что вне функции main. Функция main - создана как coroutines (вы это уже знаете) , но только в отдельном потоке. -------------------- У main, как у coroutines , есть доступ к переменных основной VMLua. Этот доступ через глобальные функции. Все библиотеки в том числе QLUA содержатся в глобальной таблице, поэтому к ним есть доступ из main, но лишь как к глобальным. -------------------
Схема торговой программы
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 14:16:58
Цитата
Serge123 написал: Кто-то может рассказать об удачной схеме работы торговой программы (без дорогих сердцу торговых стратегий), чтобы потом не переделывать своё изобретение? Я пока не знаю, как это всё в сумме организовывать и с какой стороны подходить... Торговать лучше по индикаторам или как-то ещё?
Очередь -элементарно и полезно, Как сделать очередь в роботе и зачем.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 14:15:15
Примечательно то, что наличие очереди дает нам возможность получить и обработать все события, которые принимают колбеки вне зависимости от величины времени бездействия функции sleep. ---------------- Если бы я не использовал очередь, то в случае sleep(1000) - 1 секунда, в каждом цикле терялись несколько десятков событий. Если посмотрите тему "мой робот", то там видно что за 5 секунд приходит до 3000 событий, которые без организации очереди просто потеряются. ===================== А теперь я объясню как в моем скрипте организована очередь и почему она такая простая. --------------- Очередь реализована так. строка:
Код
_N=0; _tN={};
в ней задается счетчик элементов очереди _N и таблица для этих элементов ------------------- запись элемента в очередь производится в колбеках всегда одинаково просто:
Код
_N=_N+1; _tN[_N]={1,t};
а для колбека onParam так:
Код
_N=_N+1; _tN[_N]={99,c,s,tim};
т е увеличиваем счетчик элементов и записываем в таблицу по значению счетчика ключ и передаваемые параметры. ----------------------- При записи не требуется никакой синхронизации, так как запись лишь в колбеках, а они в одном потоке. ---------------------- Чтение и удаление элемента из очереди реализована в функции main так:
Код
t=_tN[_N]; _N=_N-1
Элемент не удаляется, а уменьшается лишь счетчик. Удаление элемента произойдет лишь, если на его место будет записан новый элемент в колбеке. ===================== Вот и вся очередь. ----------------------- Все просто , но весьма эффективно. --------------------- Далее я расскажу как сделать обработку еще быстрее, но не сложнее. ----------------- Продолжение возможно следует..
Очередь -элементарно и полезно, Как сделать очередь в роботе и зачем.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 13:47:51
В данном варианте скрипта у нас нет информации о времени исполнения каких-либо фрагментов. изменим скрипт и добавим измерения времени исполнения. кроме того, начнем процесс изучения с классической рекомендации разработчиков - поставить sleep на 1 секунду вот такой скрипт:
Код
name="bot"; -- имя робота
path = "D:/QUIK_SCRIPT/nk_bot/" --папка где разместим лог файл
Log=io.open(path..name..".log","w") -- создаем лог файл для записи
------------
_N=0; _tN={};
----------------------
function main()
-----------------------
while fconnect do
if getInfoParam("SERVERTIME") then
DT=getInfoParam("TRADEDATE"); DT=tonumber(string.sub (DT,7,10)..string.sub (DT,4,5)..string.sub (DT,1,2));
fconnect=2;
Log:write("DT="..tostring(DT)..",fconnect="..fconnect.."\n");Log:flush();
end
------------------------------
local clas,sec,ncb,t,_time,tim1,tim2,T;
local tim0,tim1,tim2,T;
-----------------------------
while fconnect==2 do
while _N>0 do
t=_tN[_N]; _N=_N-1 ncb=t[1];
----------------------
if ncb==99 then
clas,sec=t[2],t[3]; tim1=t[4];
else
t=t[2];
if ncb==1 then
clas=t.class_code; sec=t.sec_code; --может не быть
elseif ncb==2 then
clas=t.class_code; sec=t.sec_code;
end
end
T=os.sysdate(); tim=60.*(60.*T.hour+T.min)+T.sec+0.001*(T.ms+0.001*T.mcs);
tim=(1000000.*(tim-tim1))//1;
Log:write(ncb..",tim="..tim..",clas="..tostring(clas)..",sec="..tostring(sec)..",_N=".._N.."\n");Log:flush();
end
sleep(1000);
end
end
end
----------------------------
function OnInit(pfile) fconnect=isConnected(); end
----------------
function OnParam(c,s)
local T=os.sysdate(); local tim=60.*(60.*T.hour+T.min)+T.sec+0.001*(T.ms+0.001*T.mcs)
_N=_N+1; _tN[_N]={99,c,s,tim};
end
function OnTransReply(t) _N=_N+1; _tN[_N]={1,t}; end
function OnOrder(t) _N=_N+1; _tN[_N]={2,t}; end
В лог файле есть два значения времени tim, - задержка исполнения колбека onParam в main Как видно из лог файла , Как видим из лог файла очередь на обработку никогда не бывает пустой. Задержка составляет от 0.3 до 0.8 сек. В лог файле она в мкс. -------------------------- функция sleep установлена чтобы уменьшить загрузку ядра процессора холостыми циклами. Поэтому посмотрим в диспетчере задач эту загрузку. Она составляет:
Примерно 8.5% теперь давайте уменьшим эту величину до 1 ms в результате получим:
Задержка составляет 1998 мкс примерно 2 ms. Очередь бывает пустой. Смотрим загрузку ядра: Примерно 10%. Что вполне допустимо ------------------ Продолжение следует...
Очередь -элементарно и полезно, Как сделать очередь в роботе и зачем.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 12:45:19
Тем, кто хотел бы практически разобраться в данном вопросе, рекомендую установить демо КВИК и запускать скрипты, которые я буду выкладывать и пояснять. Итак начнем. Вот исходный скрипт, в нем закомментированы некоторые операторы, которые демонстрируют однотипность записи колбеков и их обработку в функции main. В первых трех строчках скрипта создаемся лог файл, куда скрипт выводит информацию о своей работе. Вам надо исправить 2-ю строку, записав в ней путь, где Вы хотите создать этот файл
Код
name="bot"; -- имя робота
path = "D:/QUIK_SCRIPT/nk_bot/" --папка где разместим лог файл
Log=io.open(path..name..".log","w") -- создаем лог файл для записи
------------
_N=0; _tN={};
----------------------
function main()
-----------------------
while fconnect do
if getInfoParam("SERVERTIME") then
DT=getInfoParam("TRADEDATE"); DT=tonumber(string.sub (DT,7,10)..string.sub (DT,4,5)..string.sub (DT,1,2));
fconnect=2;
Log:write("DT="..tostring(DT)..",fconnect="..fconnect.."\n");Log:flush();
end
------------------------------
local clas,sec,ncb,t,_time;
-----------------------------
while fconnect==2 do
while _N>0 do
t=_tN[_N]; _N=_N-1 ncb=t[1];
----------------------
if ncb==99 then
clas,sec=t[2],t[3];
else
t=t[2];
if ncb==1 then
clas=t.class_code; sec=t.sec_code; --может не быть
elseif ncb==2 then
clas=t.class_code; sec=t.sec_code;
-- elseif ncb==3 then
-- elseif ncb==4 then
-- elseif ncb==5 then
-- elseif ncb==6 then
-- elseif ncb==7 then
-- elseif ncb==8 then
-- elseif ncb==9 then
-- elseif ncb==10 then
-- elseif ncb==11 then
-- elseif ncb==12 then
end
end
Log:write(ncb..",clas="..tostring(clas)..",sec="..tostring(sec)..",_N=".._N.."\n");Log:flush();
_time=0;
end
sleep(1);
end
end
end
----------------------------
function OnInit(pfile) fconnect=isConnected(); end
----------------
function OnParam(c,s) _N=_N+1; _tN[_N]={99,c,s,tim};end
---------------------
function OnTransReply(t) _N=_N+1; _tN[_N]={1,t}; end
function OnOrder(t) _N=_N+1; _tN[_N]={2,t}; end
--function OnStopOrder(t) _N=_N+1; _tN[_N]={3,t}; end
--function OnTrade(t) _N=_N+1; _tN[_N]={4,t}; end
--function OnQuote(c,s) _N=_N+1; _tN[_N]={5,t}; end
--function OnAllTrade(t) _N=_N+1; _tN[_N]={6,t}; end
--function OnDepoLimit(t) _N=_N+1; _tN[_N]={7,t}; end
--function OnAccountBalance(t) _N=_N+1; _tN[_N]={8,t}; end-- изменение позиции по счету
--function OnAccountPosition(t) _N=_N+1; _tN[_N]={9,t}; end-- изменение позиции по счету
--function OnDepoLimit(t) _N=_N+1; _tN[_N]={10,t}; end -- изменение позиции по инструментам
--function OnFuturesClientHolding(t) _N=_N+1; _tN[_N]={11,t}; end -- изменение позиции по срочному рынку
--function OnMoneyLimit(t) _N=_N+1; _tN[_N]={12,t}; end -- изменение денежной позиции
--function OnClose() fconnect=nil end
--function OnConnected(flag) fconnect=1; end
--function OnDisconnected() fconnect=1 end
--function OnStop(flag) fconnect=nil; return 2000 end
--function OnCleanUp() end -- смена торговой сессии
--function OnDepoLimitDelete(t) end -- удаление позиции по инструментам
--function OnFirm(t) end -- получение описания новой фирмы
--function OnFuturesLimitChange(t) end -- изменение ограничений по срочному рынку
--function OnFuturesLimitDelete(t) end -- удаление лимита по срочному рынку
--function OnMoneyLimitDelete(t) end -- удаление денежной позиции
--function OnNegDeal end-- новая заявка на внебиржевую сделку или изменение параметров существующей заявки на внебиржевую сделку
--function OnNegTrade end-- новая сделка для исполнения или изменение существующей сделки для исполнения
для наглядности уберем эти комментарии:
Код
name="bot"; -- имя робота
path = "D:/QUIK_SCRIPT/nk_bot/" --папка где разместим лог файл
Log=io.open(path..name..".log","w") -- создаем лог файл для записи
------------
_N=0; _tN={};
----------------------
function main()
-----------------------
while fconnect do
if getInfoParam("SERVERTIME") then
DT=getInfoParam("TRADEDATE"); DT=tonumber(string.sub (DT,7,10)..string.sub (DT,4,5)..string.sub (DT,1,2));
fconnect=2;
Log:write("DT="..tostring(DT)..",fconnect="..fconnect.."\n");Log:flush();
end
------------------------------
local clas,sec,ncb,t,_time;
-----------------------------
while fconnect==2 do
while _N>0 do
t=_tN[_N]; _N=_N-1 ncb=t[1];
----------------------
if ncb==99 then
clas,sec=t[2],t[3];
else
t=t[2];
if ncb==1 then
clas=t.class_code; sec=t.sec_code; --может не быть
elseif ncb==2 then
clas=t.class_code; sec=t.sec_code;
end
end
Log:write(ncb..",clas="..tostring(clas)..",sec="..tostring(sec)..",_N=".._N.."\n");Log:flush();
_time=0;
end
sleep(1);
end
end
end
----------------------------
function OnInit(pfile) fconnect=isConnected(); end
----------------
function OnParam(c,s) _N=_N+1; _tN[_N]={99,c,s,tim};end
---------------------
function OnTransReply(t) _N=_N+1; _tN[_N]={1,t}; end
function OnOrder(t) _N=_N+1; _tN[_N]={2,t}; end
Запустим этот скрипт на исполнение и получим следующий результат в лог файле
Последним значением в строке переменная _N - длина очереди. -------------- Пояснение следует...
Очередь -элементарно и полезно, Как сделать очередь в роботе и зачем.
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 09:22:18
Добрый день, Хочу поделиться некоторыми приемами, которые я использую при построении своих роботов. См. тему -мой робот. ----------------- В структуре спинного мозга робота , реализуемого в QUIK, условно можно выделить колбеки, в которые приходят сообщения о событиях и функцию main, работающую в отдельном потоке, которая обрабатывает эти события. ------------------- Как правило, в main делается бесконечный цикл, в котором и осуществляется обработка. ------------------------ Если обрабатывать нечего, то рекомендуют ставить sleep(time) , где time - число миллисекундах, на которое Вы заморозите работу main. =============== Но проблема в том, что пока Main не работает, в колбеки поступают события , которые надо обрабатывать либо как-то сохранить иначе они потеряются. ------------------------------ Если обрабатывать события в колбеках, то на время обработки будет остановлен терминал QUIK, так как колбеки работают в основном потоке термина. ------------------ Проблема решается путем сохранения сообщений из колбеков в массиве, из которого потом main сможет обработать все сохраненные сообщения. Такой список (массив,таблица и т д) сообщений называется очередью. =================== Вопрос лишь в том, как организовать эту очередь , чтобы было просто и быстро. --------------- Есть несколько вариантов, ------------ Вариант 1: классический - это сделать универсальные списки, очереди. Алгоритмов и их реализаций много можно найти в интернете. Сложно, малопонятно не спецам . Большая нагрузка на сборщик мусора, что замедляет исполнение скрипта. -------------------- Вариант 2: -рекомендуемый в документации QLUA - использовать потоко безопасные функции записи и удаления из массива. Просто, но относительно медленно. ------------------- Вариант 3: это мой, тот который я расскажу далее. просто и быстро. Объяснять буду на рабочем примере. ------------------- Продолжение следует...
Lua таблицу в файл и обратно
Пользователь
Сообщений: Регистрация: 30.01.2015
19.01.2024 08:04:35
еще вариант преобразования таблицы в скрипт Lua
Код
function t2s(t,s) -- преобразование таблицы в скрипт Lua
for z,v in pairs(t) do
if s~="" then s=s.."," end
if type(z)~="number" then s=s.."["..z.."]=" end
m=type(v);
if m=="table" then x=t2s(v,"")
elseif m=="number" then x=v;
else x='"'..v..'"'; end
s=s..x;
end
return "{"..s.."}";
end
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
18.01.2024 13:35:49
а теперь хвалюсь. На сегодня 5.98%. Подробности на картинке.
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 30.01.2015
18.01.2024 13:32:09
Выложенный скрипт очереди Владимира - это просто ужас какой-то. Сборщик мусора сойдет с ума. Берем такой два варианта :
Код
--сравнительный тест размер массива
local M=1000000
local list=List.new()
local tnk=nkcc.new(32);
nklib.startA(); for i=1, M do push(tnk,i); end tim1=nklib.stopA();
print("замер массива после"..M.." циклов push="..#tnk)
nklib.startA(); for i=1, M do local x=pop(tnk); end tim2=nklib.stopA();
print("замер массива после"..M.." циклов pop="..#tnk)
nklib.startA(); for i=1, M do local x=get(tnk,i); end tim3=nklib.stopA();
print("замер массива после"..M.." циклов pop="..#tnk)
print(tim0,tim01,tim1,tim2,tim3,tim0/tim1,tim01/tim2,tim01/tim3);
написал: Да хрен его знает, этого прохвоссора, о чем он толкует. У вас какое-то конкретное практическое приложение намечено для этих структур?
Да уж куда еще конкретней. Попробую сформировать свою Задачу.
Эта тема лежит в начале обсуждения (пост #1) на этой веточки. Но куда то подевались программисты? Все "понты" по отлетали. Лучше месяцами "толочь воду в ступе" про OnInit и тому подобное.
Это делается организацией циклическим массивом. Например, в индикаторах используем не более 32 отсчетом . это тест в нем внешний цикл это поступающие отсчеты А внутренний цикла печатает какие отсчеты сейчас внутри массива
Код
local M=1000000
local tnk=newV(32);
for i=1, M do push(tnk,i);
local t1={}
for i=1,32 do t1[i]=get(tnk,i); end
print(table.concat(t1,","));
end
и вот результат: Массив содержит всегда последние 32 элемента . Сборщик мусора отдыхает. Могу показать как работает стек с фиксированной длинной и очередь с циклическим массивом. А ту очередь, которую Вам гуру по прогаммированию написалчто Вам раноше