Владимир написал: И я ещё в четвёртом своём комментарии на этом форуме 29.09.2020 10:31:16 писал: "В общем, с языком почти всё ясно: граф (точнее, дерево) объектов построить можно, а простейшую таблицу или даже массив - нельзя. Остаётся разобраться со строковыми переменными: способна ли эта loadstring интерпретировать строки как операторы языка (или, скажем, функции), то есть имеется ли здесь техническая возможность программирования данными."
Ну я все таки приведу цитаты из книги, повторюсь, возможно кому то еще будут полезны и понятны подходы:
"Таблицы в Lua — это не одна из структур данных, — это единственная структура данных. Все структуры, которые предлагают другие языки, — массивы, записи, списки, очереди, множества — могут быть представлены в Lua при помощи таблиц. Главное, таблицы Lua эффективно реализуют все эти структуры."
"Хотя мы можем реализовать массивы и списки при помощи таблиц Lua (и иногда мы это делаем), таблицы гораздо мощнее массивов и списков; многие алгоритмы с использованием таблиц становятся до банальности простым"
Последняя цитата хорошо подходит к примеру про индексацию trans_id.
Владимир написал: Да, я прекрасно слышу и себя, и других. В названии темы нет ни слова про таблицы, там только про очереди.
Не понял, а очереди где создаются? Там не только названия, там выложен пример, и в место того чтоб показать опытным товарищам , какие варианты можно собрать, где в каких случаях можно использовать, на простых примерах, получаешь вот это все!
Цитата
Владимир написал: Даже его подход с ключами-айдишками в стеке активных заявок заслуживает внимания, хоть я его и не принимаю.
У Фреймворк про который я здесь рассказывал не однократно, это одна из ключевых идей, более того показывал! Да и любой может сам посмотреть. Вот этот прием, но прежде чем им пользоваться trans_id создаются при инициализации.
Код
for trans_id, smartorder in pairs(SmartOrder.pool) do
smartorder:process()
Владимир написал: Тема: Очереди и двойные очереди в луаОтвет: Ни то, ни другое для решения задач торговли не нужны и должны быть отправлены на помойку.Всё, тема исчерпана, вопрос закрыт.
Вы сами то себя слышите, если все работают с таблицами как она может быть не нужна или закрыта?
Владимир, Я уже говорил, чтоб говорить о великом нужно понятия сделать общими (говорить на одном языке и понимать о чем разговор).
Начну с начала. Вот из последнего от великих:
Цитата
Glukator написал: что именно мне станет понятно? Базовые вещи вроде стеков и очередей? =) Так я их с закрытыми глазами напишу на любом языке, а извращаться в lua, прикручивая "объектно-ориентированность" туда, где можно обойтись тремя функциями, точно не стану. Вам нравится - на здоровье.
Вас тут ничего не смущает?
Попробую пояснить что меня смущает. Уже неоднократно говорилось и разбиралось, что в луа единственная структура данных это таблица, таблица это половина ОПП, а утверждение что этим не буду пользоваться, равно утверждению не понимаю как писать на луа!
или вот
Цитата
Glukator написал: вы так говорите "модуль", как будто это какая-то волшебная таблетка. А это не более чем куча функций, вынесенная в отдельный файл.
Мне можно ошибаться я пришел разбираться, а тем кто тут самоутверждается с закрытыми глазами, стоит глаза открыть!
Владимир написал: ЧЕМ "лично для Вас ветка полезна"?
Ответ: Обсуждаю вопросы для меня не очень понятные. А есть которые самоутверждаются.
Цитата
Владимир написал: Вы ХОТЬ ЧТО-НИБУДЬ сделали в своём коде полезного по материалам этой ветки?
Ответ: Да.
Цитата
Владимир написал: Если собрать в кучу всё полезное, что было высказано в этой тысяче с лишним постов, наберётся ли материала хотя бы на один?
Ответ: Я бы сильно не доверял статистике на сайте, цена ей три копейки. А считать Вы сами умеете, да и вопрос из области полезности, а она индивидуальна.
Цитата
Владимир написал: Для чего написан, скажем, вот этот последний Ваш коммент?
Ответ: Пытаюсь объяснить, что "наделав кучу на голове у оппонента, сидеть на ней, как на горе Эверест, со значимым видом" затея так себе.
PS: Манипуляция - это такой прием, "Перевод с больной головы на здоровую"
Владимир, Лично для меня ветка полезна, а если бы отдельные члены дискуссии не занимались манипуляциями, а прямо отвечали на поставленные вопросы, то пустых постов было бы поменьше. Хочется напомнить, что знак вопроса (?) в конце предложения означает, что задан вопрос, на который требуется ответ, иначе дурной тон. Но хамство это похоже какая - то профессиональная черта.
VPM написал: сделать очередь ФИФО, для управления, передачи и обработки заданного количества элементов
Берете обычную очередь, и если добавление в нее очередного элемента должно привести к превышению заданной длины, то после добавления (или перед ним - как нравится) выбрасываете первый элемент.
Владимир написал: Эта "универсальность" не только нахрен не нужна, но и вредна. Прерывания OnTrade приходят "крест-накрест собаьим шагом", а потому АБСОЛЮТНО по барабану, в какой последовательности их обрабатывать - тем более, события уже произошли. Соответственно, берём самое простое - обычный стек. Чтобы поставить новый элемент на вершину стека или взять его оттуда, никаких фунций не требуется - обычное присвоение. Со стеком заявок чуть сложнее - некторые из них у меня подаются "вне очереди". И со стеком активных заявок тоже: какая из них исполнится, а какая снимется - одному Богу известно. Наконец, поддерживать постоянный размер очереди или стека есть просто идиотизм: страшно переполнение, а не рост. А переполнить Lua-таблицу - это надо ОЧЕНЬ постараться! У меня и при тысяче тикеров размеры стеков будут исчисляться десятками элементов -плюнуть и растереть.
Владимир, Вы сами кого хотите запутаете, то что Вы описали я пользуюсь, веду таблицу ордеров, сделок, позиции, результатов, оценок ... Сделал с Вашего примера опубликованного на этом форуме, за что Вам все скажем, спасибо!
Но здесь речь шла абсолютно о другом, сделать очередь ФИФО, для управления, передачи и обработки заданного количества элементов, а про универсальность пусть каждый сам решает, тем более примеры есть разные, на любой вкус!
Glukator написал: VPM, я вам пытаюсь донести то, что "универсальность" нахрен не нужна. Нужна эффективность на _конкретных_ задачах, а она чаще достигается через отказ от универсальности. Это вообще зачастую две противоположности.
Вы упускаете важную вещь, Вы владеете несколькими языками программирования, закрытыми глазами пишите примеры , а у нас 2 класса образования и те не полные, для меня и думаю 90% процентов здесь таких, важней будет универсальность. Да с эффективность нужно еще посмотреть?
Glukator, У нас с Вами и с другими кто нас читает, абсолютно разные программы, и все что мы можем обсуждать это возможности решения каких то узких задач. Об этом я и говорю нравится это кому то или нет. На Ваши Вопросы я с полна как умею ответил, я уже не понимаю что Вам не понятно в данном примере. Что он универсальней Вашего?
Glukator, Так что же Вы мне тут, целый час голову морочите, это я у Вас должен спрашивать. Мне кажется я Вам уже отвечал что я пишу про возможности, а как Вам делать, что Вам делать разберитесь сами!
Glukator написал: вы так говорите "модуль", как будто это какая-то волшебная таблетка. А это не более чем куча функций, вынесенная в отдельный файл.
Это прежде всего таблица. В которой в одном месте можно хранить функции, значения, строки .... Это просто удобно. А я говорю что еще можно представить как конструктор, такое хранилище элементов конструктор.
Из нашего примера: Можно записать так List.pushlast(list, value) List.popfirst (list) А можно другой function List.poplast (list) удалить последний List.pushlast (list, value) добавить последний
Glukator, Вы напишите не большой пример и попробуйте, это будет более понятно и все встанет на свои места.
Вот мой небольшой
Код
local list=List.new()
local ds={10,20,30}; local value=40;
for i=1, #ds do
List.pushlast(list, value)
print( 'Вставил в конец',list.last, list[first] )
if i>1 then
print( 'Удалил первого', List.popfirst (list) , type(list), #list)
end
end
print(list[first],list[last])
Это и ежу понятно. А вот что конкретно вы имели в виду, говоря о какой-то "матрице" и прочем, понятнее не стало.
Алгоритм хранит 2 переменных, начало и конец, 2 функции на добавление элемента, 2 функции на удаление элемента, т.е. всего можно собрать 4 варианта. 1; 0 --------- 1 | 11; 10 0 | 01; 00
"Кольцевой буфер" - круг, окружность, коло, понятие замкнутости. Определили технологический запас, и его поддерживаем, если полочка пустая (в нашем случае nil), не означает изменения структуры (количество полочек прежнее) или не так?
Цитата
Владимир написал: Во-первых, я знал всё о стеках и очередях за много лет до того, как Вики вообще появилась.
Владимир написал: Никакое ФИФО не "держит размер массива постоянным".
"Кольцевой буфер, или циклический буфер (англ. ring-buffer) — это структура данных, использующая единственный буфер фиксированного размера таким образом, как будто бы после последнего элемента сразу же снова идет первый. Такая структура легко предоставляет возможность буферизации потоков данных".
"Кольцевой буфер находит очень широкое применение в том числе при программировании микроконтроллеров. Данные структуры часто используют для организации различных очередей сообщений и буферов приёма-передачи различных коммуникационных интерфейсов. Популярность КБ обусловлена тем, что это один из самых простых и эффективных способов организовать FIFO (англ. first in — first out, «первым пришёл — первым вышел») без использования динамической памяти. Существует множество разновидностей КБ." https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D1%8C%D1%86%D0%B5%D0%B2%D0%BE%D0%B9_%D0%B1%D1%83%D1....
nikolz написал: а теперь хвалюсь. На сегодня 5.98%. Подробности на картинке.
Торгую руками 3 тикера промежуточный результат 5,6 % к текущему капиталу. А у Вас нейросеть. Не видно даже цены на графике, уберите индикаторы они кроме Вас ни кому не нужны и добавьте сделки (стрелочки на цену) так будет более информативно. Да на результаты выведите подписи линий, тогда достаточно одного взгляда, чтоб понять что хотели сказать графиком.
Glukator, У вас частный случай, а в примере из книги можно собрать любой вариант (матрица 2*2).
Про демонстрирован вот этот прием: "Поскольку окружение — это обычная таблица, то вы можете просто индексировать ее нужным ключом (именем переменной). Похожим образом можно присвоить значение глобальной переменной, чье имя вычисляется динамически, если написать _G[varname] = value."
Плюс модуль, один раз написал и забыл, подключаешь модуль где нужно, собираешь что требуется. Ну ведь классно, согласитесь!
Ну Nikolay, Спасибо Вам, все поставили на свои места, мои подозрения не верны, нужно смотреть что еще может критично накапливаться в таблицах.
У меня сейчас в работе 4 тикера 4 тайм фрейма 4 индикатора рассчитываю на момент запуска примерно 1М на конец дня 25М, и мне это не нравится, так как планирую увеличить и количество тикеров.
ds,Error = CreateDataSource(class,symbol,interval) type (ds) = таблица , т.е. там только методы получения , а сами данные на сервере или в хранилище рабочего места?
Тогда такая запись передача только методов доступа к данным? function f() -- индикатор local Filt,Price={},{}; -- таблицы для хранения данных return function(I,FSettings,ds )
Nikolay, Да мы это обсуждали , массивы в индикаторах подчищаю, этого мало, ведь передается ds, Хочу попробовать очередь! т.е. данные уменьшить до определённого количества необходимого для расчета, а за основу возьму пример из книги. Что скажите?
nikolz, Не все понял, нужно поискать, посмотреть подход, Спасибо. Но Вроде я нашел решение свей задачи, попробую будет ясно. Но в любом случае спасибо за новую идею.
В общем все как люблю, это модуль, написано на чистом луа, написано элегантно загляденье, Размер таблицы задается пользователем, количество элементов поддерживается постоянным, реализовать 4 функциями можно различные варианты (возможности). Вердикт немедленно в работу!
Сделал не большой пример Эта запись list.last = last; list[last] = value; в начале кажется что идет пере присвоение, но когда понимаешь что это две переменные, два разных элемента таблицы , вот из моего примера list.last=0; list[last]=40 Доходит как все элегантно написано! Вот уже полчаса не могу глаз оторвать
Код
local List = {};
---- Теперь мы можем вставлять и удалять элементы с обоих концов за постоянное время:
function List.new()
return {first = 0, last = -1}
end
---- Операции вставки -- table.insert
function List.pushlast (list, value)
local last = list.last + 1;
list.last = last;
list[last] = value;
print('List.pushlast: ' ..'; '..type(list.last)..'; '..'; last='..tostring(list.last)..'; '..type(list[last])..'; '.. tostring(list[last]))
end
---- Операции удаления -- table.remove
function List.popfirst (list)
local first = list.first;
if first > list.last then
--error("list is empty")
return nil
end
local value = list[first]
list[first] = nil -- чтобы разрешить сборку мусора
list.first = first + 1
return value
end
local list=List.new()
local ds={10,20,30}; local value=40;
for i=1, #ds do
List.pushlast(list, value)
print( 'Вставил в конец',list.last, value )
if i>1 then
print( 'Удалил первого', List.popfirst (list) , type(list), #list)
end
end
List.pushlast: ; number; ; list.last=0; number; list[last]=40
Владимир написал: Растёт, если он не обрабатывается. Но стек ведь не только LI, но и FO.
Ну вот, а если миллионы сделок на 1000 тикерах и множестве тайм фреймах -- это уже проблемы с памятью.
"Но стек ведь не только LI, но и FO". - Не большие примеры можете на кидать чтоб всем стало понятно! Не обязательно как у Вас, а принципиально чтоб понять как можно обрабатывать, чтоб держать размер постоянным?
Владимир, Ну тогда прежде чем рассуждать о великом, нужно определиться с понятиями
Вот local i=sdelka[0]; i=i+1; ---- новый размер стека сделок из прерывания sdelka[0]=i; ---- записываем изменение стека: ---- сохраняем новую сделку; sdelka[i]={}; -- заводим новый элемент стека sdelka[i][0]=sdelka[0]; sdelka[i][1]=trade.trans_id; -- ID транзакции sdelka[i][2]=get_date(trade.datetime) sdelka[i][3]=get_time(trade.datetime)
sdelka[i]={}; таблица растет с увеличением размера стека?
Владимир, С автором по аккуратней, если еще его удалить, то что вообще останется Ну Вы же говорите стеки растут?
Вроде до меня доходит, о чем написал профессор. Описан метод FIFO (реализации стека с использованием таблиц, вызывая только pushlast - вставляем в конец и popfirst - удаляем первого ), а эффективность достигается, поскольку элементы не нужно сдвигать после операций вставки и удаления. А размер таблицы всегда постоянен. Попробую в решении своей задачи!!!
Владимир написал: С КАКОГО БОДУНА "эти массивы растут"? У меня почему-то ничего не растёт, кроме лога.
Растут, и у Вас растут просто не критично. А все кто использует ds,Error = CreateDataSource(class,symbol,interval) сталкиваются с этой проблемой!
Цитата
Владимир написал: А если есть какой-то внешний софт, в котором что-то там растёт, так выбросить его на помойку! Зачем пользоваться поделиями криворуких бездарей?
Вы не поняли, внешнего софта нет, есть отдельно написанные небольшие программы (см. пример организации ниже) на луа, для совместного использования в виде индикатора с отображением на графике, так и в main(). В этом случае тот самый бездарь я, так как написаны мной.
1) Передал огромный ds 2) Filt,Price={},{} массивы при такой индексации нарастают с приходом нового индекса.
Код
function f() -- индикатор
local Filt,Price={},{}; -- таблицы для хранения данных
return function(I,FSettings,ds )
local I = I or 1; --индекс бара
local ds = ds or nil; -- передача (ds,Error = CreateDataSource(class,symbol,interval))
local FSettings = FSettings or {};
local v_t = FSettings.v_t or 'C';
local P = FSettings.period or 48;
--------------------------------------
local price = x or Value(I, v_t, ds) or 0;
--------------------------------------
if I == 1 then
Price,Filt={},{};
Price[I],Filt[I]=p0,p0;
end
--------------------------------------
local p1=Price[I-1] or price;
local p2=Price[I-2] or p1;
local pn=Price[I-n] or p2;
Price[I] = price;
.... что то считаем
Filt[I] = filt; --сохраняем промежуточный результат
return filt1,filt выводим
end
end
Glukator написал: Да хрен его знает, этого прохвоссора, о чем он толкует. У вас какое-то конкретное практическое приложение намечено для этих структур?
Да уж куда еще конкретней. Попробую сформировать свою Задачу.
Как было показано в организации структуры данных, программа получает внешние данные из ds по нескольким тикерам на нескольких тайм фреймах. От начало торгов до закрытия торгов, эти массивы растут. Для расчета самописных индикаторов, используемых торговой стратегией (в среднем ~<5), это массив ds передается в качестве входного параметра в алгоритм расчета индикатора. Все они написаны с использованием замыкания, т.е. имеют внутренние таблицы для хранения данных, и все это дело с ходом торгов разрастается.
Изначально такой подход в организации стратегии, принят по тому что у меня много таких индикаторов, и простой заменой (присвоением) одного на другой меняется сама стратегия. Этот подход проходит без проблем на одном инструменте, а при использовании портфеля возникают проблемы с памятью.
Решения вижу два: 1) Организовать расчет индикаторов по другому, но это не решает коренным образом проблему. 2) В организации и хранении структуры данных, ведь как правило не нужен весь массив значений хранящихся в ds, достаточно чтоб сохранялось 5 или 20 (Period=X задается пользователем) последних значений. Пример профессора, это на мой взгляд, ключ к пониманию и решению этой проблемы, правильной организации структуры данных использованию этих данных и хранению.
Эта тема лежит в начале обсуждения (пост #1) на этой веточки. Но куда то подевались программисты? Все "понты" по отлетали. Лучше месяцами "толочь воду в ступе" про OnInit и тому подобное.
VPM написал: local List = {}; function List.new() return {first = 0, last = -1} end --Теперь мы можем вставлять и удалять элементы с обоих концов за постоянное время: function List.pushfirst (list, value) local first = list.first - 1 list.first = first list[first] = value end function List.pushlast (list, value) local last = list.last + 1; list.last = last; list[last] = value; --message('List.pushlast: ' ..'; '..tostring(last)..'; '.. tostring(value.price)..'; '.. tostring(value.qty)) end function List.popfirst (list) local first = list.first; if first > list.last then --error("list is empty") return nil end local value = list[first] list[first] = nil -- чтобы разрешить сборку мусора list.first = first + 1 return value end function List.poplast (list) local last = list.last if list.first > last then error("list is empty") end local value = list[last] list[last] = nil -- чтобы разрешить сборку мусора list.last = last - 1 return val ue end
Если вы будете использовать эту структуру для обслуживания в порядке поступления, вызывая только pushlast и popfirst, то и first, и last будут постоянно расти. Однако, так как мы представляем массивы в Lua при помощи таблиц, вы можете индексировать их как с 1 до 20, так и с 16 777 216 до 16 777 236. Поскольку Lua использует для представления чисел двойную точность, ваша программа можем выполняться на протяжении двухсот лет, делая по миллиону вставок в секунду, прежде чем возникнет проблема с переполнением.
Кто то может сказать, как собрать ФИФО, как собрать ЛИФО, возможно есть еще варианты, и вообще о чем толкует профессор? Кто понимает?
Владимир написал: VPM, Очередь, как и стек, понятия чисто алгоритмические. Но если со стеком всё просто с доступом - обрабатывается всегда последний элемент, то с очередью всё хуже: обрабатывается первый, а потом первым становится уже второй, и вообще вся очередь сдвигается. Это затратно по времени. Если ничего не сдвигать, то первым элементом всегда будет "условно первый" - доступ мгновенный, как и в случае со стеком, но массив данных постоянно растёт. Это затратно по памяти. Наконец, если данные организовать в виде циклической очереди, как, например, организован буфер событий от клавиатуры, затрат почти нет ни по скорости, ни по памяти, но появляется риск переполнения буфера. Других вариантов, как я понимаю, в природе не существует. Вернее, можно очень эффективно реализовать очередь через список, но, строго говоря, это уже и будет список, т.е. другой тип организации данных. А про все эти insert и remove лучше сразу же забыть, как страшный сон.
Вы можете дать пояснения вот этому моменту
Цитата
Если ничего не сдвигать, то первым элементом всегда будет "условно первый" - доступ мгновенный, как и в случае со стеком, но массив данных постоянно растёт. Это затратно по памяти.
Glukator, Это было предположение, что одномоментно дадут сигнал 226 инструментов, но я упустил что Вы алгоритмически ранжируете сделки. С памятью я примерно понимаю проблему, от куда "ноги растут", не очень понимаю как ее элегантно решить. Но всему свое время.
Цитата
Владимир написал: VPM , Не вижу ни малейшего отношения к нашему разговору.
Ну как же не имеет это хороший пример, инвестиционного подхода крупного игрока!