Nikolay написал: Если речь была про задержку потока main, то да она должна быть.
Как раз хотел спросить: какую задержку выставлять в main после цикла обработки очереди от OnAllTrade и OnQuote? Я сделал 10 мс, может, есть более правильная задержка?
Все добрый день! Попалась хорошая ссылка на то что здесь пытались обсудить https://blog.amd-nick.me/understanding-lua-coroutines Второе - перечитывая последнюю тему, заметил еще одно расхождение в рассуждениях и понятиях. Обработчики событий и коллбэки - это два механизма для вызова функций в ответ на определенное событие. Не смотря на то, что механизмы очень похожи, но есть существенное отличие. Обработчики событий обычно регистрируются на объектах, коллбэки передаются функциям в качестве аргументов. Ну в общем лучше взглянуть на примеры.
В продолжении темы асинхронности, собрал не большой пример для себя, такую "напоминалочку" Вот код:
Код
-- 1) Запуск программы main в потоке терминала QUIK
-- 2) Запуск сопрограммы в потоке терминала main
local working = true -- Флаг для продолжения цикла
function Robot()
local events = {} -- Таблица для хранения событий
local routine = coroutine.create(function()-- Создание сопрограммы для отслеживания событий
while working do -- Отслеживание событий и создание итераций
-- ... (реализация отслеживания событий)
local conect = coroutine.create(function()-- реализация отслеживания события соединения с сервером
while working do
local event_conect = math.random(1,10) -- print("event_conect",event_conect)
-- Добавление события в таблицу
--table.insert(events, { event }) -- Добавляем данные события
-- Если соединение установлено делаю Паузу до следующей итерации, Если нет соединение ждем.
if event_conect >= 5 then coroutine.yield() else print("No conect?",event_conect) end
end
end)
coroutine.resume(conect)
-- ... (реализация отслеживания событий)
local WorkTime = coroutine.create(function()-- реализация отслеживания события Рабочего времени
while working do
local event_WorkTime = math.random(1,10)
--print("event_WorkTime",event_WorkTime)
-- Добавление события в таблицу
--table.insert(events, { event }) -- Добавляем данные события
-- Пауза для отслеживания новых событий
if event_conect >= 5 then coroutine.yield() else print("No WorkTime?",event_conect) end
end
end)
coroutine.resume(WorkTime)
-- реализация создания итераций для получения рыночной информации и ее обработки
local event = math.random(1,10) print("event",event)
-- Добавление события в таблицу
table.insert(events, { event }) -- Добавляем данные события
-- Пауза для отслеживания новых рыночных событий
coroutine.yield()
end
end)
-- Запуск сопрограммы coroutine.resume(routine)
while working do -- Главный цикл для обработки событий (поток main)
coroutine.resume(routine)-- Заход в сопрограмму для отслеживания событий
if coroutine.status(routine) == "dead" then -- Проверка статуса сопрограммы
print("Robot routine finished")
break
end
for _, event in ipairs(events) do-- Обработка событий из таблицы
-- ... (реализация обработки событий)
print("event",event[#event],#event)
if event[#event] >= 5 then print("Buy") else print("Sell") end
end
events = {} -- Очистка таблицы событий
-- Заход в сопрограмму для дальнейшего отслеживания событий
--coroutine.resume(routine)
end
working = false
end
Пример рабочий для этого добавлены случайные входа - это просто некий макет. Запуск функции Robot - print( Robot() ) в среде луа, запустит бесконечный цикл имитируя работу сопрограммы в потоке main() запущенного в терминала QUIK. В чем смысл данного примера: Можно просто в main() написать логику работы программы и последовательно исполнять код. Данный код демонстрирует асинхронный подход к воспроизведению кода программы. Сопрограмма запускается до основного цикла main() выполняется необходимая работа идет приостановка, выполняется работа в цикле main() по окончании идет возврат в сопрограмму, добавлены для примера еще 2 ниточки отслеживающие соединение и рабочее время для примера. Хотел подробней описать, но смысла особого нет, сложно просто без запуска разобраться. Кому интересен подход запустит, и где нужно добавит комментариев. Почему это лучше лучше почитать букварь. Всем хорошего кода.
Всем добрый день! И вот оно, торговая программа нашла себе все таки проблематику. Проблема лежит в прямой плоскости озвученной в заголовке данной ветки - системе принятия решений. В чем смысл, если двумя словами то в масштабах, проблема чисто на мой взгляд математическая, давно известная человечеству, да и мне, просто откладывал ее решения на потом, видимо настал тот потом. Дело в том, что я в своих программах использую такой показатель как HPR (Holding Period Return) представляет собой изменение актива за определенный период времени - отношение. То есть отвечает на вопрос "как ты ко мне относишься". В таком подходе, во всей своей красе, возникает маcштаб или фрактальность, всё б ни чего когда котировки цены разных инструментов одинаковы или близки.
Но программа засекает их уже, ну к примеру актив GD (золото) котируется значениями pricce[1] = 2349.3 pricce[2] = 2349.6 шаг изменения 0.1, и есть другой BR (нефть) котируется значениями pricce[1] = 77.33 pricce[2] = 77.49, шаг изменения 0.01, необходимо найти их отношения и сравнить изменения для принятия решений, и вот он во все красе масштаб. В первом случае ни одного сигнала, во втором на ура вылетают.
Кто незнаком с проблематикой, хорошо описана в работах Мандельброта. Вот я и подумал наверняка кто - то уже решал эту задачу. Первое что приходит: нормализация к диапазону [0, 1], логарифмическое преобразование - лог доходности, приведение к общему масштабу, ну даже тяжело представить с чего тут начать. В общем если кто занимался, будем признательны, думаю все сообществом.
дайте определение, что вы под этим понимаете? ================ "необходимо найти их отношения и сравнить изменения для принятия решений" напоминает классический арбитраж, ------------------- можете пояснить Вы о чем говорите?
VPM написал: Проблема лежит в прямой плоскости озвученной в заголовке данной ветки - системе принятия решений.
Ну, надо же. какая глубокая мысль . Глаза нам открыли.
Цитата
VPM написал: проблема чисто на мой взгляд математическая, давно известная человечеству, да и мне, просто откладывал ее решения на потом, видимо настал тот потом.
Зачем откладывали? Ждем вашего решения и запасаемся поп-корном .
Цитата
nikolz написал: возникает маcштаб или фрактальность, всё б ни чего когда котировки цены разных инструментов одинаковы или близки.
nikolz, Ни чего нового. Фрактальность, концепция, используется для описания сложных объектов (процессов), которые имеют повторяющуюся структуру на разных масштабах. В контексте анализа временных рядов, проблема сравнения данных разных масштабов имеет значение для корректного анализа и принятия решений. Классическая задача демонстрирующая данную проблематику, измерение длины береговой линии на разных масштабах (можно на гугл картах по экспериментировать).
TGB, Ну очень остроумно, чтобы Вас хотя бы начали понимать окружающие, научитесь мысли формировать понятно, а предложений я жду от Вас, или страна напрасно Вас учила?.
В мире финансов принято приводить к единой шкале, в частности к пунктам. Логарифмическая шкала тоже, конечно. Но пункт более универсален и удобен, т.к. это целое число.
Nikolay, Я просто подумал что, за то время когда я последний раз открывал букварь по математике, человечество могло что - то придумать нового, новые подходы. Поиск ни чего не дал, да и поисковики последнее время странно себя ведут, впечатление что идет не поиск, а навязывание какого то мнения в вперемежку с рекламой. Нет нормализация как способ приведения данных к единому масштабу, мне конечно известен использую, от логарифмической шкалы отказался, теперь уже не могу сказать почему. Но ведь есть инструменты котируемые к примеру 10000 и втб котировка 0.022957, разве тут уже чисто арифметически нет проблемы?
VPM написал: Nikolay, Я просто подумал что, за то время когда я последний раз открывал букварь по математике, человечество могло что - то придумать нового, новые подходы. Поиск ни чего не дал, да и поисковики последнее время странно себя ведут, впечатление что идет не поиск, а навязывание какого то мнения в вперемежку с рекламой. Нет нормализация как способ приведения данных к единому масштабу, мне конечно известен использую, от логарифмической шкалы отказался, теперь уже не могу сказать почему. Но ведь есть инструменты котируемые к примеру 10000 и втб котировка 0.022957, разве тут уже чисто арифметически нет проблемы?
втб котировка 0.022957
Это 22957 пунктов. И когда инструмент расчет, то говорят - вырос на 10, 100 пунктов. Можно уже пункты отнормировать, чтобы цифры были близкие, как это делают при подготовке данных для моделей, например.
Nikolay написал: Можно уже пункты отнормировать, чтобы цифры были близкие, как это делают при подготовке данных для моделей, например.
Поясните.
Вообще я про универсальный подход, который можно применять в своих алгоритмах не задумываясь, о разрядности чисел. Вот это я использую, но чаще забываю
Код
-- Функция для нормализации цен
local function normalize_prices(prices, step)
local normalized_prices = {}
for i, price in ipairs(prices) do
normalized_prices[i] = price / step
end
return normalized_prices
end
Отлично работают еще способы приведения к нормальному распределению, но хочется универсальности.
VPM написал: nikolz, Ни чего нового. Фрактальность, концепция, используется для описания сложных объектов (процессов), которые имеют повторяющуюся структуру на разных масштабах. В контексте анализа временных рядов, проблема сравнения данных разных масштабов имеет значение для корректного анализа и принятия решений. Классическая задача демонстрирующая данную проблематику, измерение длины береговой линии на разных масштабах (можно на гугл картах по экспериментировать).
TGB, Ну очень остроумно, чтобы Вас хотя бы начали понимать окружающие, научитесь мысли формировать понятно, а предложений я жду от Вас, или страна напрасно Вас учила?.
Понятно, но повторяемость картинки на рынках в различных масштабах есть у Эллиотта (почти 100 лет тому назад).. а термин «фрактал» введён Бенуа Мандельбротом в 1975 году т е примерно через пол века, Причем этот термин к рынкам никто не применяет. Полагаю, что Вы зря притянули Мандельброта и понятие фрактальность. Так как похожесть рынков это не тоже самое что подобие самому себе в фрактальности. --------------- Но если Вам нравится это слово применяйте. Важно то, как Вы его реально используете в форме алгоритмов и чем ваши алгоритмы отличаются от описанных в популярных книжках? Можете пояснить?
nikolz, Термин на рынок подтянули за долго до моего появления на этом рынке, Билл Вильямс целую книжку выпустил, есть индикаторы. Позволяющие оценивать ее. Ни чего нового здесь нет. Графики ценового временного ряда на различных временных интервалах (минутные, часовые, дневные, недельные графики) помогает увидеть, как паттерны повторяются на разных временных масштабах. Вложенность мелкого тайм фрейма в старший, именно это свойство я имел ввиду. Почему мои алгоритмы должны чем то отличаться? Ни чего нового все давно известно, разве входные данные. Проблема которую я описал возникла в алгоритме рассчитывающем функцию роста, входными данными которой являются hpr, но Nikolay, прав нужно уйти в один масштаб, торговать пунктиками, тогда и оценка эффективности становится на место, логарифмическая школа скорее больше подходит для инвестиционных горизонтов, а с горизонтом 1 день - пунктики. Хотя подниму старое по экспериментирую и то и другое.
Хотел остановиться на освещении этой проблематики, так как собственно решение озвучено, но есть некая не досказанность. Сама десятичная система счисления, обладает фрактальными свойствами, благодаря их само подобной структуре и итеративным процессам. 0,1,2...9 10,11,12...19 Что само по себе при использовании функции доходности (отношение) уже может приводить не к однозначной оценке, когда цены находится в разных разрядах, нет, доходность которая поднимается с 10 до 11, эквивалентна доходности которая выросла со 100 до 110. Проблема возникает когда инвестор отвечает на вопрос "на сколько цены изменились за интервал времени".
В финансовой математике обычно расчеты ведут в процентах (доходность). Приращение цены в процентах обычно считается как (P2-P1)/P1, однако, данный способ имеет этот недостаток, т.е. если цена уменьшилась на 5%, а затем увеличилась на 5% мы не получим первоначальное значение. И здесь на помощь приходит оценка относительного изменения цен за период (интервал) времени.
Логарифм цены позволяет уйти от этого искажения, связанного с абсолютными значениями цены и перейти к относительной оценке. Для инвестора имеет значение не столько, сколько стоит в настоящий момент инструмент, а на(во) сколько произошло относительное изменение цен за период (интервал) времени. Здесь смысл логарифма нужно озвучить: "инвесторы и трейдеры мыслят в терминологии «выросло в х раз», и не важно от каких уровней. Чтобы уровнять рост в х раз от разных уровней и используют логарифм".
Логарифмированные ценовые ряды обладают свойствами log(b)-log(a)=log(b/a), разница логарифмов двух цен a и b = логарифму относительного приращения b/a, то есть логарифму доходности. Математически логарифмирование заменяет умножение сложением, то есть с помощью логарифма можно суммировать доходности за разные промежутки времени, функции роста изменяет свой темп (характер) от экспонетциального на линейный. Ну и еще одно, с точки зрения теории случайных процессов, логарифмы приращений цен Гауссовы (нормальны). Чем пользоваться, как пользоваться решайте сами, надеюсь и любители попкорна чуть-чуть вспомнили финансовую математику, хороших алгоритмов.
Не очень понятно зачем писать очевидные вещи. Логарифмы как способ изменить шкалу используются очень-очень давно. И финансах в частности. Достаточно вспомнить любой расчет волатильности.
Вот на первую в скидку взял из букваря по финансовой математике.
Экспоненциальный рост описывается дифференциальным уравнением: dx/dt=kx, Решение этого дифференциального уравнения — экспонента x=ae^kt. примером экспоненциального роста являются, сложные проценты, Общая сумма, которую получит вкладчик, при расчёте по сложному проценту будет равна x*(1+a)^n, Где x — начальная сумма вложенных средств, a — годовая процентная ставка, n— срок вклада в годах.
При вкладе по ставке s% годовых, после первого года хранения капитал составил бы x плюс s% от неё, то есть возрос бы в (1+s/100) раза. На второй год s% рассчитывались бы уже не от одной копейки, а от величины, большей её в (1 + s/100) раза. И, в свою очередь, данная величина увеличилась бы тоже за год в (1 + s/100) раза. Значит, по сравнению с первичной суммой вклад К году N первичный вклад вырос бы до величины в n раз больше первоначальной. (1 + s/100)^n
В применении к ежемесячной капитализации формула сложного процента имеет вид: (1 + s/100)^m/12, где x — начальная сумма вклада, s — годовая ставка в процентах, m — срок вклада в месяцах.
Разве ни чего не напоминает? И таких примеров Вы сами сколько угодно найдете, все дело в прикладном характере.
Nikolay написал: Не очень понятно зачем писать очевидные вещи. Логарифмы как способ изменить шкалу используются очень-очень давно. И финансах в частности. Достаточно вспомнить любой расчет волатильности.
Америку то и не открываю, лишь на поминаю эти очевидные вещи, тем кто их подзабыл, в том числе и себе, для чего все это нужно. Если посмотреть алгоритмы столь именитых здесь программистов, то думаю 90% этих алгоритмов не учитывают обстоятельство со размерности. Нет когда робот работает с одним инструментом то и ладно, а когда портфель, то есть проблема. Именно это обстоятельство я озвучил. А подробно, на мой взгляд полезно, не все кто пишет подкованы как Вы, да и просто вспомнить.
Nikolay, Спасибо, пробежал бегло, ну в общем тоже известный подход, расчет исторической волатильности, терминология несколько отличается а смысл один, у себя я так и считаю терминология другая, 1) в случае моделирования сделки; 2) при оценки результатов торговой стратегии если достаточно статистики. Отсутствие строгой терминологии привносит свою лепту и путаницу. Для себя, установил как бы два термина, Доходность - это % приращения, а HPR - когда средняя = 1, это удобно, позволяет переходить из одно системы в другую измеряю по сути одно и тоже используя разные размерности. HPR = Р2/Р1; относительная доходность = Р2 / Р1 - 1; доходность% = ( Р2 / Р1 - 1) * 100 Сейчас поясню, минмаксная нормировка дает нам размерность [0,1] , где 0 предел (самое маленькое значение), 1 предел (самое большое значение), умножая на 100 уже в процентах, делая перевод [-1,0,1] средняя = 0, получили осциллятор с нормальным распределением. Надеюсь ни кого не запутал?
VPM написал: Отсутствие строгой терминологии привносит свою лепту и путаницу.
Т.к. это не точная наука, то есть некая девиация. Но все же зарубежные термины уже давно устоялись, рынок там давно живет. Вот когда начинают творческим переводом заниматься, то и возникает путаница. Справедливости ради, почти все приходит не из русскоязычного сегмента, так что и не стоит пытаться что-то искать по-русски - это будет творческое переосмысление. Правда всегда можно уйти в область обработки сигналов, мат. теории. рядов. Там уже достаточно отечественных материалов по теме.
Посмотрел внимательней. Нет все таки есть существенная неточность в моих суждениях. В своих расчетах (использую абсолютные значения), расчеты в статье (применяют натуральный логарифм цены), а это более чем существенное отличие. Хотя даже не знаю что лучше использовать, ведь в стать тоже делается допущение "Когда доходность мала, например, всего несколько процентов, мы имеем: г ≈ Ln (1 + г)", когда делаешь расчет с горизонтом год и один день?
VPM написал: Отсутствие строгой терминологии привносит свою лепту и путаницу.
Т.к. это не точная наука, то есть некая девиация. Но все же зарубежные термины уже давно устоялись, рынок там давно живет. Вот когда начинают творческим переводом заниматься, то и возникает путаница. Справедливости ради, почти все приходит не из русскоязычного сегмента, так что и не стоит пытаться что-то искать по-русски - это будет творческое переосмысление. Правда всегда можно уйти в область обработки сигналов, мат. теории. рядов. Там уже достаточно отечественных материалов по теме.
Но ведь и слег не добавляет точности, волатильность широко вошла в обиход, и под этим названием скрываются несколько смыслов, так как расчеты различны. Один из способов это расчет стандартного отклонения, если вместо волатильности произнесли стандартное отклонение, то ту появляется смыслы, сигма, нулевая средняя, нормальное распределение с вероятностями исходов. Родной язык позволяет эти смыслы поддерживать, ну к примеру русский язык строится от корня, корень несет смысл, что уже по себе существенно (отклонился, уклонился приклонился...). В то время как применяя термин на иностранном, он превращается в некую новую переменную, теряя или привнося новые смыслы. Так что и переосмысление бывает полезным. Но лучше с оригинала самому.
VPM написал: Но ведь и слег не добавляет точности, волатильность широко вошла в обиход, и под этим названием скрываются несколько смыслов, так как расчеты различны. Один из способов это расчет стандартного отклонения, если вместо волатильности произнесли стандартное отклонение, то ту появляется смыслы, сигма, нулевая средняя, нормальное распределение с вероятностями исходов. Родной язык позволяет эти смыслы поддерживать, ну к примеру русский язык строится от корня, корень несет смысл, что уже по себе существенно (отклонился, уклонился приклонился...). В то время как применяя термин на иностранном, он превращается в некую новую переменную, теряя или привнося новые смыслы. Так что и переосмысление бывает полезным. Но лучше с оригинала самому.
Не соглашусь. Один из способов это расчет стандартного отклонения - это обработка набора данных, чтобы определить его характеристику, в данном случае волатильность как концепция. Но сам по себе метод применяется, в первую очередь, в статистике. А вот какой набор данных будет - это важно. Логарифм применяют не просто так, а в связи с концепцией непрерывно начисляемой доходностью и логнормальным распределением приращений цен.
nikolz, Подобные аргументы слышны на этом форуме, чуть ли не через пост. Вы напрасно обижаетесь, назвать подобное ахиней, согласитесь относительно мягко, здесь ни статьи не помогут ни Шекспир.
Цитата
nikolz написал: 'Математически логарифмирование заменяет умножение сложением" -------- тогда исходя из этого правила получается, что 2*2=2*log(2) Круто!
1) Одно из основных фундаментальных свойств логарифмов заключается в том, что они заменяют умножение сложением, нет здесь ни какого моего правила - это свойство логарифмов, возможно забыли? ln(a⋅b)=ln(a)+ln(b) Это свойство позволяет заменить умножение сложением, что особенно удобно при анализе временных рядов. 2) Где в Вашем примере хоть что то напоминает операцию сложения 2*2=2*log(2) , вообще что этим хотели сказать???
Nikolay написал: Логарифм применяют не просто так, а в связи с концепцией непрерывно начисляемой доходностью и логнормальным распределением приращений цен.
Наверняка при моделировании будет удобней пользовать концепцией непрерывно начисляемой доходностей, не совсем уверен что нужно применять при анализе работы торговой системы, и уж точно не стоит отражать в финансовых отчетах?
Вроде нашел, Логнормальное распределение приращений цен. Предполагается, что приращения логарифмических цен (логарифмические доходности) распределены нормально. Это означает, что если цены актива P(t) следуют логнормальному распределению, то логарифм цен ln(P(t)) следует нормальному распределению. Это предположение основано на наблюдениях, что логарифмы цен часто лучше подходят для нормального распределения и что цены акций и других финансовых активов не могут быть отрицательными. И здесь нужно вспомнить, не столь далекие события ценообразованию нефти, когда к товару добавляли премию.
Переписал Все! и продолжаю переписывать! Добрался до индикаторов, написанных ранее используя принцип замыкания, все перевожу в класс луа. а иногда и OPP, в чем суть ниже покажу пример. А если в двух словах, всему основа структура языка луа - таблица. Таблица - это объект, то есть для примера как бы описывали автомобиль, начали бы перечислять его свойствами (цвет = красный, мотор = бензиновый и так далее), возможную скорость, расход топлива, уже не описать свойствами нужны методы = функции. Так и при описании позиции, бара, тренда ... Если еще проще говорить, таблица позволяет оперировать (говорить) смыслами, создавать паттерны. Это позволяет перейти, от элементарной арифметике к векторному счислению и управлению объектами. "Аз. Буки , Ведай, Глаголь, Добро, ..." - это остатки от языка на котором все создавалось и описывалось - это смыслы. Луа нас возвращает к возможности этим оперировать, об этом автор языка нам рассказывает.
Эта страничка начиналась с примера нечеткой логики с использованием алгоритма, даже можно назвать программы ADX. Этот индикатор всегда нравился мне своими правильными смысла, мощью, если бы не одно но. В таком виде "классическом" он подходит для инвестирования, то есть для использования на больших тайм фреймах, и виной тому заложенное отставание в расчетах этого алгоритма. Для примера вот так его реализовали разработчики
Код
[/CODE][SPOILER=][CODE]------------------------------------------------------------------
----Moving Average SMA, MMA, EMA, WMA, SMMA, VMA
------------------------------------------------------------------
local SMA,MMA,EMA,WMA,SMMA,VMA = "SMA","MMA","EMA","WMA","SMMA","VMA"
local OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = "O","H","L","C","V","M","T","W","D","A"
--[[Simple Moving Average (SMA)
SMA = sum(Pi) / n]]
local function F_SMA()
local sum = {}
local it = {p=0, l=0}
return function (I, P, VT, ds)
if I == 1 then
sum = {}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then it={p=I, l=it.l+1} end
local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
if it.l >= P then
return (sum[Ip] - (sum[Ippp] or 0)) / P
end
end
return nil
end
end
--[[Modified Moving Average (MMA)
MMA = (MMAi-1*(n-1) + Pi) / n]]
local function F_MMA()
local sum = {}
local tmp = {pp=nil, p=nil}
local it = {p=0, l=0}
return function(I, P, VT, ds)
if I == 1 then
sum = {}
tmp = {pp=nil, p=nil}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then
it = {p=I, l=it.l+1}
tmp.pp = tmp.p
end
local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
if it.l <= P + 1 then
sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
if (it.l == P) or (it.l == P + 1) then
tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
end
else
tmp.p = (tmp.pp*(P-1) + GetValueEX(it.p,VT,ds)) / P
end
if it.l >= P then
return tmp.p
end
end
return nil
end
end
--[[Exponential Moving Average (EMA)
EMAi = (EMAi-1*(n-1)+2*Pi) / (n+1)]]
local function F_EMA()
local tmp = {pp=nil, p=nil}
local it = {p=0, l=0}
return function(I, P, VT, ds)
if I == 1 then
tmp = {pp=nil, p=nil}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then
it = {p=I, l=it.l+1}
tmp.pp = tmp.p
end
if it.l == 1 then
tmp.p = GetValueEX(it.p,VT,ds)
else
tmp.p = (tmp.pp*(P-1) + 2*GetValueEX(it.p,VT,ds)) / (P+1)
end
if it.l >= P then
return tmp.p
end
end
return nil
end
end
--[[William Moving Average (WMA)
( Previous WILLMA * ( Period - 1 ) + Data ) / Period]]
local function F_WMA()
local tmp = {pp=nil, p=nil}
local it = {p=0, l=0}
return function(I, P, VT, ds)
if I == 1 then
tmp = {pp=nil, p=nil}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then
it={p=I, l=it.l+1}
tmp.pp = tmp.p
end
if it.l == 1 then
tmp.p = GetValueEX(it.p,VT,ds)
else
tmp.p = (tmp.pp * (P-1) + GetValueEX(it.p,VT,ds)) / P
end
if it.l >= P then
return tmp.p
end
end
return nil
end
end
--[[Volume Adjusted Moving Average (VMA)
VMA = sum(Pi*Vi) / sum(Vi)]]
local function F_VMA()
local sum = {}
local sum2 = {}
local it = {p=0, l=0}
return function(I, P, VT, ds)
if I == 1 then
sum = {}
sum2 = {}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then it={p=I, l=it.l+1} end
local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds) * GetValueEX(it.p,VOLUME,ds)
sum2[Ip] = (sum2[Ipp] or 0) + GetValueEX(it.p,VOLUME,ds)
if it.l >= P then
return (sum[Ip] - (sum[Ippp] or 0)) / (sum2[Ip] - (sum2[Ippp] or 0))
end
end
return nil
end
end
--[[Smoothed Moving Average (SMMA)
SMMAi = (sum(Pi) - SMMAi-1 + Pi) / n]]
local function F_SMMA()
local sum = {}
local sum2 = {}
local it = {p=0, l=0}
return function(I, P, VT, ds)
if I == 1 then
sum = {}
sum2 = {}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then it={p=I, l=it.l+1} end
local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
if it.l >= P then
if it.l == P then
sum2[Ip] = (sum[Ip] - (sum[Ippp] or 0)) / P
else
sum2[Ip] = ((sum[Ip] - (sum[Ippp] or 0)) - (sum2[Ipp] or 0)+ GetValueEX(it.p,VT,ds)) / P
end
return sum2[Ip]
end
end
return nil
end
end
local function CandleExist(I,ds)
return (type(C)=="function" and C(I)~=nil) or
(type(ds)=="table" and (ds[I]~=nil or (type(ds.Size)=="function" and (I>0) and (I<=ds:Size()))))
end
local function Squeeze(I,P)
return math.fmod(I-1,P+1)
end
local function ConvertValue(T,...)
local function r(V, R)
if R and string.upper(R)== "ON" then R=0 end
if V and tonumber(R) then
if V >= 0 then return math.floor(V * 10^R + 0.5) / 10^R
else return math.ceil(V * 10^R - 0.5) / 10^R end
else return V end
end
local arg = {...}
arg.n = select('#', ...)
if arg.n > 0 then
for i = 1, arg.n do
arg[i]=arg[i] and r(arg[i] * ((T and T.Multiply) or 1), (T and T.Round) or "off")
end
return unpack(arg)
else return nil end
end
local function GetValueEX(I,VT,ds)
VT=(VT and string.upper(string.sub(VT,1,1))) or ANY
if VT == OPEN then --Open
return (O and O(I)) or (ds and ds:O(I))
elseif VT == HIGH then --High
return (H and H(I)) or (ds and ds:H(I))
elseif VT == LOW then --Low
return (L and L(I)) or (ds and ds:L(I))
elseif VT == CLOSE then --Close
return (C and C(I)) or (ds and ds:C(I))
elseif VT == VOLUME then --Volume
return (V and V(I)) or (ds and ds:V(I))
elseif VT == MEDIAN then --Median
return ((GetValueEX(I,HIGH,ds) + GetValueEX(I,LOW,ds)) / 2)
elseif VT == TYPICAL then --Typical
return ((GetValueEX(I,MEDIAN,ds) * 2 + GetValueEX(I,CLOSE,ds))/3)
elseif VT == WEIGHTED then --Weighted
return ((GetValueEX(I,TYPICAL,ds) * 3 + GetValueEX(I,OPEN,ds))/4)
elseif VT == DIFFERENCE then --Difference
return (GetValueEX(I,HIGH,ds) - GetValueEX(I,LOW,ds))
else --Any
return (ds and ds[I])
end
return nil
end
local function MA() --Moving Average ("MA")
local T_MA = {[SMA]=F_SMA(),[MMA]=F_MMA(),[EMA]=F_EMA(),[VMA]=F_VMA(),[SMMA]=F_SMMA(),[WMA]=F_WMA()}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
if (P > 0) then
return T_MA[string.upper(Fsettings.Metod or EMA)](I, P, (Fsettings.VType or CLOSE), ds)
end
return nil
end
end
local function TR() --True Range ("TR")
local it = {pp=0, p=0, l=0}
return function (I, ds)
if I == 1 then
it = {pp=0, p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then it={pp=it.p, p=I, l=it.l+1} end
if it.l == 1 then
return math.abs(GetValueEX(it.p,DIFFERENCE, ds))
else
return math.max(math.abs(GetValueEX(it.p,DIFFERENCE, ds)),
math.abs(GetValueEX(it.p,HIGH,ds) - GetValueEX(it.pp,CLOSE,ds)),
math.abs(GetValueEX(it.pp,CLOSE,ds)-GetValueEX(it.p,LOW,ds)))
end
end
return nil
end
end
function ADX() --Average Directional Movement Index ("ADX")
local pDI_MA=MA()
local mDI_MA=MA()
local ADX_MA=MA()
local f_TR=TR()
local it = {pp=0, p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local M = (Fsettings.Metod or EMA)
if (P>0) then
if I == 1 then
if (M==VMA) then M=SMA end
it = {pp=0, p=0, l=0}
end
local i_TR = f_TR(I,ds)
if CandleExist(I,ds) then
if I~=it.p then it={pp=it.p, p=I, l=it.l+1} end
if it.l > 1 then
if GetValueEX(it.p,HIGH,ds) > GetValueEX(it.pp,HIGH,ds) then
pDM = math.abs(GetValueEX(it.p,HIGH,ds)-GetValueEX(it.pp,HIGH,ds))
else pDM = 0 end
if GetValueEX(it.p,LOW,ds) < GetValueEX(it.pp,LOW,ds) then
mDM = math.abs(GetValueEX(it.pp,LOW,ds)-GetValueEX(it.p,LOW,ds))
else mDM = 0 end
if pDM > mDM then mDM=0 end
if mDM > pDM then pDM=0 end
if pDM == mDM then pDM=0 mDM = 0 end
if i_TR~=0 then pSDI = pDM / i_TR * 100 else pSDI = 0 end
if i_TR~=0 then mSDI = mDM / i_TR * 100 else mSDI = 0 end
local pDI = pDI_MA(it.l-1, {Period=P, Metod=M, VType=ANY}, {[it.l-1] = pSDI})
local mDI = mDI_MA(it.l-1, {Period=P, Metod=M, VType=ANY}, {[it.l-1] = mSDI})
if it.l>P and pDI and mDI then
return ADX_MA(it.l-P, {Period=P, Metod=M, VType=ANY}, {[it.l-P]=math.abs(pDI-mDI)/(pDI+mDI)*100}),pDI,mDI
else
return nil,pDI,mDI
end
end
end
end
return nil,nil,nil
end
end
Settings = {
Name = "*ADX (Average Directional Movement Index)",
Period = 14,
Metod = "EMA", --(SMA, MMA, EMA, WMA, SMMA, VMA)
line = {{
Name = "Horizontal line",
Type = TYPE_LINE,
Color = RGB(140, 140, 140)
},
{
Name = "ADX",
Type = TYPE_LINE,
Color = RGB(0, 162, 232)
},
{
Name = "ADX +DI",
Type = TYPE_LINE,
Color = RGB(0, 206, 0)
},
{
Name = "ADX -DI",
Type = TYPE_LINE,
Color = RGB(221, 44, 44)
}
},
Round = "off",
Multiply = 1,
Horizontal_line="off"
}
local func
function Init()
func = ADX()
return #Settings.line
end
function OnCalculate(Index)
return tonumber(Settings.Horizontal_line),ConvertValue(Settings,func(Index, Settings))
end
[/SPOILER]Вот так переписываюlocal ADX = {} ADX.__index = ADX
function ADX:new(settings) local instance = setmetatable({}, ADX) instance.settings = settings or { Name = "*ADX (Average Directional Movement Index)", Period = 14, Method = "EMA", line = { {Name = "Horizontal line", Type = TYPE_LINE, Color = RGB(140, 140, 140)}, {Name = "ADX", Type = TYPE_LINE, Color = RGB(0, 162, 232)}, {Name = "ADX +DI", Type = TYPE_LINE, Color = RGB(0, 206, 0)}, {Name = "ADX -DI", Type = TYPE_LINE, Color = RGB(221, 44, 44)} }, Round = "off", Multiply = 1, Horizontal_line = "off" } instance:initialize() return instance end
function ADX:initialize() self.pDI_MA = self:createMovingAverage() self.mDI_MA = self:createMovingAverage() self.ADX_MA = self:createMovingAverage() self.f_TR = self:createTrueRange() self.it = {pp = 0, p = 0, l = 0} end function ADX:createMovingAverage() local T_MA = { [SMA] = self.F_SMA(), [MMA] = self.F_MMA(), [EMA] = self.F_EMA(), [VMA] = self.F_VMA(), [SMMA] = self.F_SMMA(), [WMA] = self.F_WMA() } return function(I, settings, ds) local settings = settings or {} local P = settings.Period or 14 if P > 0 then return T_MA[string.upper(settings.Method or EMA)](I, P, settings.VType or CLOSE, ds) end return nil end end function ADX:createTrueRange() local it = {pp = 0, p = 0, l = 0} return function(I, ds) if I == 1 then it = {pp = 0, p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {pp = it.p, p = I, l = it.l + 1} end if it.l == 1 then return math.abs(self:GetValueEX(it.p, DIFFERENCE, ds)) else return math.max(math.abs(self:GetValueEX(it.p, DIFFERENCE, ds)), math.abs(self:GetValueEX(it.p, HIGH, ds) - self:GetValueEX(it.pp, CLOSE, ds)), math.abs(self:GetValueEX(it.pp, CLOSE, ds) - self:GetValueEX(it.p, LOW, ds))) end end return nil end end function ADX:calculate(I, settings, ds) local P = settings.Period or 14 local M = settings.Method or EMA if P > 0 then if I == 1 then if M == VMA then M = SMA end self.it = {pp = 0, p = 0, l = 0} end local i_TR = self.f_TR(I, ds) if self:CandleExist(I, ds) then if I ~= self.it.p then self.it = {pp = self.it.p, p = I, l = self.it.l + 1} end if self.it.l > 1 then local pDM, mDM if self:GetValueEX(self.it.p, HIGH, ds) > self:GetValueEX(self.it.pp, HIGH, ds) then pDM = math.abs(self:GetValueEX(self.it.p, HIGH, ds) - self:GetValueEX(self.it.pp, HIGH, ds)) else pDM = 0 end if self:GetValueEX(self.it.p, LOW, ds) < self:GetValueEX(self.it.pp, LOW, ds) then mDM = math.abs(self:GetValueEX(self.it.pp, LOW, ds) - self:GetValueEX(self.it.p, LOW, ds)) else mDM = 0 end if pDM > mDM then mDM = 0 end if mDM > pDM then pDM = 0 end if pDM == mDM then pDM = 0 mDM = 0 end local pSDI = (i_TR ~= 0) and (pDM / i_TR * 100) or 0 local mSDI = (i_TR ~= 0) and (mDM / i_TR * 100) or 0 local pDI = self.pDI_MA(self.it.l - 1, {Period = P, Method = M, VType = ANY}, {[self.it.l - 1] = pSDI}) local mDI = self.mDI_MA(self.it.l - 1, {Period = P, Method = M, VType = ANY}, {[self.it.l - 1] = mSDI}) if self.it.l > P and pDI and mDI then return self.ADX_MA(self.it.l - P, {Period = P, Method = M, VType = ANY}, {[self.it.l - P] = math.abs(pDI - mDI) / (pDI + mDI) * 100}), pDI, mDI else return nil, pDI, mDI end end end end return nil, nil, nil end
-- Methods for different Moving Averages (SMA, MMA, EMA, WMA, SMMA, VMA) function ADX:F_SMA() local sum = {} local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then sum = {} it = {p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} end local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P) sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds) if it.l >= P then return (sum[Ip] - (sum[Ippp] or 0)) / P end end return nil end end function ADX:F_MMA() local sum = {} local tmp = {pp = nil, p = nil} local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then sum = {} tmp = {pp = nil, p = nil} it = {p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} tmp.pp = tmp.p end local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P) if it.l <= P + 1 then sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds) if (it.l == P) or (it.l == P + 1) then tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P end else tmp.p = (tmp.pp * (P - 1) + self:GetValueEX(it.p, VT, ds)) / P end if it.l >= P then return tmp.p end end return nil end end function ADX:F_EMA() local tmp = {pp = nil, p = nil} local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then tmp = {pp = nil, p = nil} it = {p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} tmp.pp = tmp.p end if it.l == 1 then tmp.p = self:GetValueEX(it.p, VT, ds) else tmp.p = (tmp.pp * (P - 1) + 2 * self:GetValueEX(it.p, VT, ds)) / (P + 1) end if it.l >= 1 then return tmp.p end end return nil end end function ADX:F_VMA() local sum = {} local tmp = {pp = nil, p = nil} local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then sum = {} tmp = {pp = nil, p = nil} it = {p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} tmp.pp = tmp.p end local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P) sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds) if it.l >= P then tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P return tmp.p end end return nil end end function ADX:F_SMMA() local sum = {} local tmp = {pp = nil, p = nil} local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then sum = {} tmp = {pp = nil, p = nil} it = {p = 0, l = 0} end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} tmp.pp = tmp.p end if it.l == P then sum[P] = sum[P - 1] + self:GetValueEX(it.p, VT, ds) tmp.p = sum[P] / P elseif it.l < P then sum[it.l] = (sum[it.l - 1] or 0) + self:GetValueEX(it.p, VT, ds) else tmp.p = (tmp.pp * (P - 1) + self:GetValueEX(it.p, VT, ds)) / P end if it.l >= P then return tmp.p end end return nil end end function ADX:F_WMA() local sum = {} local weight_sum = 0 local it = {p = 0, l = 0} return function(I, P, VT, ds) if I == 1 then sum = {} weight_sum = 0 it = {p = 0, l = 0} for i = 1, P do weight_sum = weight_sum + i end end if self:CandleExist(I, ds) then if I ~= it.p then it = {p = I, l = it.l + 1} end local sum_weights = 0 for i = 1, P do if self:CandleExist(it.p - i + 1, ds) then sum_weights = sum_weights + self:GetValueEX(it.p - i + 1, VT, ds) * (P - i + 1) end end if it.l >= P then return sum_weights / weight_sum end end return nil end end
-- Helper functions function ADX:CandleExist(I, ds) return ds:C(I) ~= nil end function ADX:GetValueEX(I, VT, ds) return ds[VT](ds, I) end function ADX:Squeeze(I, P) return (I - 1) % P + 1 end return ADX
В продолжение темы хочется "пропеть пару дифирамб - корутинам" хотя бы и в собственном исполнении. Реализация сопрограмм в луа, на мой взгляд на сколько простая на столько классная. Мало одной модульности нужен еще хороший процессинг. Что позволяет делать корутина, как и функции делить программу по функциональности, на отдельно исполняемые кусочки. Но в отличии от функции исполнение идет в собственном потоке, низко затратам, без использования задержек и блокировки основного потока, может приостанавливать исполнение и возобновлять впоследствии. Подход, в котором каждая стратегия работает в своей корутине, позволяет молниеносно обрабатывать ее, практически не влияя на производительность. Асинхронность позволяет расставлять приоритеты при принятии решений. Как то странно, на ветке посвященной программированию на луа, совсем, ну почти совсем это не обсуждается. А ведь сколько полезных вещей можно написать упрощая себе и продлевая программе жизнь. Например вот уже из букваря, реализованных у себя. Итераторы, Конечный автомат, Обработка ошибок, Многопоточность, и даже рисование линий (и видимо можно и объектов ведь рисуют анимации). Вот тут все классно "разжевано" https://fingercomp.gitlab.io/lua-coroutines/#code-1.3
Нечетка логика (библиотека LuaFuzzy), хорошо подходит для оценки различных рыночных условий, особенно удобно получать зоны: перекупленность / перепроданность, накопление / распределение, сопротивление / поддержка, зоны высокой ликвидности. Все это можно получить используя выше предоставленную библиотеку нечеткой логики, сохраняя высокую степень автоматизации.
Вот простой алгоритм ее применения, подход следующий, 1) определяем тренды разных интервалов, 2) рассчитываем стандартное отклонение, приняв его за волатильность, 3) используем правило 3 сигм при составлении нечетких правил и выводов.
Использование стандартного отклонения для оценки волатильности и правило трех сигм поможет более точно определить границы для зон. Установив зависимости Волатильность = sigma = стандартное отклонение цен. Тогда Зоны: Высокая волатильность: если цена выходит за пределы ±3 * sigma (верояное событие) Умеренная волатильность: если цена находится в пределах ± 3 * sigma.
Это дает нам четкие критерии для определения трендов при формирования нечетких правил. Метод еще и универсален так как данные нормированы.
Другой важный аспект. Учёт свойства вложенности в колебательных процессах и определение локальных максимумов и минимумов на различных временных масштабах — это ключ к более точному анализу временного ряда. Также важно учитывать лаг, который смещает фазы колебаний, чему виной часто, сам мат. аппарат применяемый в расчетах. Уже важно само понимание того, что отображение цены за интервал времени в формате свечи, это тоже отражение колебаний, которые являются следствием закона спроса и предложения, заложенного в ценообразовании на бирже. Колебательный процесс приводит к пониманию возможности применения со всей строгостью фазаво - частотных характеристик в описании этих данных. Точное определение фазы - вот наша цель! И здесь нужно вспомнить задачу Коши, зная функциональный закон и определяя начальные условия, можем формировать прогноз системы любой природы. Тема обширна и наверно выходит за рамки данного форума, но не сказать про нее нельзя. Если кто то заинтересовался могу предложить алгоритм подобного подхода, он отличается от академических, но на мой взгляд так же строг и значительно прост в понимании.
VPM написал: Но в отличии от функции исполнение идет в собственном потоке, низко затратам, без использования задержек и блокировки основного потока, может приостанавливать исполнение и возобновлять впоследствии. Подход, в котором каждая стратегия работает в своей корутине, позволяет молниеносно обрабатывать ее, практически не влияя на производительность
Вы опять ошибаетесь . корутина выполняется не в отдельном потоке , а в отдельном стеке . Но поток в смысле многопоточность ОС будет один Т е все корутины , которые вы создадите будут исполняться на одном ядре и последовательно. они не мешают друг другу так как при их создании выделяется отдельный стек. ------------------ Но Вы можете верить что у вас все параллельно.
Добрый день nikolz, ну вот, а то можно подумать что что то случилось? Не знаю флуд это или Ваши заблуждения, Вы по прежнему не читаете сообщения, кроме своих. Чисто из уважения к Вашему возрасту в сотый уже раз повторю, тема давно разобрана по винтикам на данном сайте и не только, вот ссылка, где очень подробно простым языком разыскано о сопрограммах https://fingercomp.gitlab.io/lua-coroutines/#code-1.3. От себя лишь добавлю если еще и этого не достаточно, создайте корутину и возьмите type(). Логика Вашего высказывания тоже не выдерживает критики, Вы привели цитату, ткните пальцем, где есть слово "ОС", или "параллельно". Сопрограмма нужна для создания асинхронности исполнения кода, нет другого варианта в луа уйти от примитивов. Вы писали что пользуетесь таблицей состояний для прерываний. Так воспользуйтесь еще раз, добавьте состояние которое будет отслеживать допустим подключение к серверу, оберните в корутину, и попробуйте, это пример элементарной асинхронности исполнения кода. Я не рассуждаю об ОС, их потоках языках от личных от луа и прочем, меня интересует эффективное использование прикладной программы на луа. На деюсь не чем Вас не обидел.
Стояла задача оценить финансово хозяйственную деятельность инвестора, ничего лучше придумать не мог и взял за основу модели, финансово хозяйственную деятельность предприятия. Покопался, нашел подход описанный М. Беляев "Милогия", собрал ккласс на Lua для управления портфелем инвестора, основанного на предложенном подходе. Этот класс будет включать методы для добавления и удаления активов, расчета общей стоимости портфеля, а также получения информации о доходах и обязательствах. Создается новый портфель, добавляются активы и обязательства, рассчитываются доходы и расходы, после чего выводится сводка о состоянии портфеля.
Этот класс можно расширять, добавляя новые методы и функциональность, например, для анализа доходности активов, отслеживания динамики портфеля или интеграции с внешними API для получения рыночных данных. Создается новый портфель, добавляются активы и обязательства, рассчитываются доходы и расходы, после чего выводится сводка о состоянии портфеля. Концепция бухгалтерского учета, перенесена на учет и анализ финансово-хозяйственной деятельности (ФХД) инвестора, применяя аналогию с "весами монады" для управления активами и пассивами. Но главное, это универсальность анализа структуры. Все тут не расскажешь, но как классно все легло по образу и подобию на деятельность Инвестора. Нет предала совершенству.
Дальнейшее развитие концепции М.И. Беляева. (Прикладной характер Структурного Анализа рыночных отношений).
Если рассматривать рынок как сложную систему, применяя структурный анализ с учетом иерархических и мульти двойственных отношений, можно организовать рынок в виде сети взаимодействий различных элементов (агентов) и факторов. Основной монадой рыночных отношений, является взаимосвязь спроса и предложения, выраженная в ценах. Как можно построить структурный анализ рынка, учитывая его сложность. Иерархическая структура рынка. Рынок можно рассматривать как многоуровневую систему, где разные уровни отражают различные аспекты его функционирования. Например: а) Макроуровень — глобальные экономические и политические факторы (центральные банки, международные соглашения, денежно-кредитная политика, торговые блоки). б) Мезоуровень — отрасли и сектора экономики, которые взаимодействуют друг с другом через спрос и предложение, производственные и логистические цепочки. с) Микроуровень — отдельные участники рынка: компании, покупатели, продавцы, биржи, банки и т.д. Каждый уровень этой иерархии взаимодействует с соседними уровнями через механизмы координации и субординации.
Начнем с микроуровеня. Биржевой анализ. На финансовых рынках структурный анализ может помочь понять, как взаимодействие участников рынка (инвесторов, маркет-мейкеров, регуляторов) на различных уровнях иерархии определяет динамику цен акций, облигаций и деривативов. При анализе финансовых рынков на микроуровне важно рассматривать рыночные структуры и отношения между различными участниками, такими как инвесторы, маркет-мейкеры и регуляторы, и как их действия влияют на динамику цен финансовых инструментов (акций, облигаций, деривативов). Микроуровневый биржевой анализ в этом контексте помогает понять краткосрочные ценовые колебания, ликвидность и распределение капитала на рынке.
Микроуровень под микроскоп. Микроструктура. Применим концепцию структурного анализа в комбинации с монадой рыночных отношений, которая включает взаимодействие таких параметров, как цена, количество заявок, открытый интерес, и других данных, поступающих с биржи. На микроуровне структурный анализ позволяет рассматривать рынок как сложную систему, состоящую из взаимосвязанных элементов, каждый из которых оказывает влияние на общий рыночный баланс.
Монада рыночных отношений. Монада в этом контексте — это абстрактное представление взаимосвязанного взаимодействия между всеми рыночными параметрами, которые формируют динамику актива. Монада рыночных отношений включает: Цена актива (в виде баров) — отражает баланс спроса и предложения за определенный период. Количество заявок на покупку и продажу — индикатор текущего рыночного настроения и ликвидности. Открытый интерес — объем открытых позиций, отражающий интерес участников к активу. Объем торгов — подтверждение силы движения цены. Волатильность — оценка уровня неопределенности и риска. Объём ликвидности по ценовым уровням (Level 2) — распределение ликвидности на разных уровнях цены. Эти элементы можно рассматривать как взаимосвязанные части единой системы, где каждый параметр влияет на другой. Их совместное изучение может привести к более глубокой оценке текущей рыночной ситуации.
Если рассматривать монаду рыночных отношений как двойственные отношения между покупателями и продавцами, можно интерпретировать ее как систему, стремящуюся к равновесию, где две противоположные силы находятся в постоянном взаимодействии. В нашем случае это спрос и предложение, отраженные через рыночные данные. Основная задача в этом контексте — двигаться от микроуровневого анализа данных к нахождению баланса, который можно назвать монадой или состоянием рынка. Спин монады в данном случае можно представить как динамическое смещение рыночного баланса, которое отражает, в чью сторону идет движение: к покупателям (росту) или к продавцам (падению).
Движение от микроуровня к монаде (алгоритм). 1. Исходные рыночные данные (нижний уровень). Мы начинаем с анализа микроуровневых данных, таких как:
Заявки на покупку и продажу — количество и объем. Цены сделок — отражение фактического взаимодействия между покупателями и продавцами. Открытый интерес — количество открытых позиций (как фьючерсов, так и опционов). Объемы торгов — подтверждение активности на рынке. Ликвидность — плотность заявок на разных уровнях цены. Каждый из этих показателей может быть рассмотрен с точки зрения "весов" или структурных долей покупателей и продавцов.
2. Оценка относительной силы покупателей и продавцов (средний уровень) На этом этапе происходит расчет весов каждой из сторон. Например, Баланс заявок на покупку и продажу: если на рынке преобладают покупатели, то их доля может быть, скажем, 0.6, а продавцов 0.4. Этот баланс может быть выражен как, Впокупатели=0.6, Впродавцы=0.4
Аналогично мы можем рассчитать и другие пропорции:
Объемы сделок: насколько активны покупатели и продавцы в конкретный момент. Открытый интерес: сколько позиций принадлежит каждой из сторон. Ликвидность на уровнях: где сосредоточена ликвидность и что это говорит о готовности покупателей и продавцов действовать на определенных уровнях цен. Эти весовые коэффициенты могут динамически меняться в зависимости от рыночных условий.
3. Поиск баланса или монады (верхний уровень) После того как мы оценили силу участников (покупателей и продавцов) через микроуровневые данные, мы можем определить, как эти отношения формируют общую структуру рынка и стремятся к состоянию баланса. Этот баланс можно представить как целостную систему — монаду: M = Bпокупатели + Bпродавцы = 1 Здесь B — это доли участия каждой стороны. Например, если Покупатели занимают 60% рынка (0.6), а Продавцы — 40% (0.4), то монада равна 1, что означает, что все силы учтены. Таким образом, монада рыночных отношений — это итоговая оценка, показывающая, как сильно смещены силы в сторону покупателей или продавцов.
4. Движение от обратного (снизу вверх) Когда мы говорим о движении от обратного, мы имеем в виду постепенное построение монады, начиная с самого низкого уровня данных. Мы берем микроуровневые показатели (баланс заявок, объемы, ликвидность и т.д.), оцениваем их относительные силы, а затем объединяем эти оценки для получения целостного представления о состоянии рынка.
Если покупатели активны, их доля возрастает, и рыночные данные показывают это через: Превышение объема заявок на покупку. Увеличение объема сделок по покупкам. Рост открытого интереса в сторону длинных позиций. Если же продавцы доминируют, эти показатели начинают смещаться в их пользу: Превышение объема заявок на продажу. Снижение объемов покупок. Увеличение коротких позиций.
5. Применение структурного анализа для баланса. Построение монады из рыночных данных и оценка баланса покупателей и продавцов через структурный анализ дает нам возможность понимать, где рынок находится относительно равновесия.
Если баланс смещен в сторону покупателей (например, 0.7 покупатели и 0.3 продавцы), это может говорить о бычьем настроении, и трейдеры могут ожидать продолжения роста цен. Если баланс смещен в сторону продавцов (например, 0.4 покупатели и 0.6 продавцы), это может указывать на медвежьи настроения, и цены, скорее всего, пойдут вниз.
Заключение Поиск монады рыночных отношений через микроуровневые данные — это по сути построение целостной картины рынка, начиная с отдельных элементов и заканчивая общей структурой взаимодействия покупателей и продавцов. Это движение "снизу вверх" — от микроуровневого анализа данных к глобальному пониманию баланса на рынке — позволяет принимать более точные торговые решения, основанные на реальном положении дел. Спин монады в данном случае можно представить как динамическое смещение рыночного баланса, которое отражает, в чью сторону идет движение: к покупателям (росту) или к продавцам (падению).
"Смесь бульдога с носорогом" или на стыке предметов. На основе идеи двойственности, можно создать класс для управления инвестиционным портфелем, который учитывает баланс между доходами и обязательствами, активами и пассивами, а также принцип двойственности - "Всякой твари по паре". Двойственные отношения через базисные экспоненциальные функции и их связь с множественными концепциями, включая спиральность, фазовые сдвиги и принципы симметрии. Этот подход не только затрагивает математические аспекты, такие как ряды Тейлора для экспоненциальных функций, но и более широкие концепции, относящиеся к философии, физике, и даже управлению. Этот пример класса опирается на концепции представленные М.И. Беляевым, его задача показать как помочь инвестору управлять портфелем через балансировку пар, нахождение баланса между активами, обязательствами, доходами и расходами, это своего рода такие математические весы.
Пояснения к классу: 1. Фактор двойственности. Этот фактор отражает дисбаланс между активами и обязательствами. Когда активов больше, чем обязательств, этот фактор увеличивается, показывая, что инвестор находится в более устойчивой позиции. Если обязательств больше, то фактор будет отражать "долговую нагрузку". 2. Метод `balanceDuality. Он рассчитывает баланс между активами и обязательствами, регулируя фактор двойственности в зависимости от текущего состояния портфеля. 3. Методы для добавления и удаления активов и обязательств. После каждой операции система автоматически пересчитывает баланс. 4. Самонормировка. Вдохновленный идеей о "самонормировке экспоненциальных функций", портфель сам настраивается через фактор двойственности, который балансирует активы и обязательства.
Этот пример, подсвечивает как элегантно, автоматически проходит Самонормировка.
Код
-- Класс для управления портфелем инвестора на основе двойственного подхода
local DualityPortfolioManager = {}
DualityPortfolioManager.__index = DualityPortfolioManager
-- Конструктор
function DualityPortfolioManager:new()
local instance = {
assets = {}, -- Активы
liabilities = {}, -- Обязательства
income = 0, -- Доходы
expenses = 0, -- Расходы
dualityFactor = 1 -- Фактор двойственности (влияет на баланс активов и обязательств)
}
setmetatable(instance, DualityPortfolioManager)
return instance
end
-- Метод для добавления актива
function DualityPortfolioManager:addAsset(name, value)
self.assets[name] = (self.assets[name] or 0) + value
self:balanceDuality()
end
-- Метод для удаления актива
function DualityPortfolioManager:removeAsset(name, value)
if self.assets[name] then
self.assets[name] = self.assets[name] - value
if self.assets[name] <= 0 then
self.assets[name] = nil
end
end
self:balanceDuality()
end
-- Метод для добавления обязательства
function DualityPortfolioManager:addLiability(name, value)
self.liabilities[name] = (self.liabilities[name] or 0) + value
self:balanceDuality()
end
-- Метод для удаления обязательства
function DualityPortfolioManager:removeLiability(name, value)
if self.liabilities[name] then
self.liabilities[name] = self.liabilities[name] - value
if self.liabilities[name] <= 0 then
self.liabilities[name] = nil
end
end
self:balanceDuality()
end
-- Метод для добавления дохода
function DualityPortfolioManager:addIncome(value)
self.income = self.income + value
end
-- Метод для добавления расхода
function DualityPortfolioManager:addExpense(value)
self.expenses = self.expenses + value
end
-- Метод для баланса двойственности (самонормировка)
function DualityPortfolioManager:balanceDuality()
-- Рассчитываем соотношение активов и обязательств
local totalAssets = self:getTotal(self.assets)
local totalLiabilities = self:getTotal(self.liabilities)
-- Применяем фактор двойственности для поддержания баланса
if totalAssets > totalLiabilities then
self.dualityFactor = totalAssets / totalLiabilities
elseif totalLiabilities > totalAssets then
self.dualityFactor = totalLiabilities / totalAssets
else
self.dualityFactor = 1
end
end
-- Метод для получения общей стоимости активов или обязательств
function DualityPortfolioManager:getTotal(t)
local total = 0
for _, value in pairs(t) do
total = total + value
end
return total
end
-- Метод для расчета чистой стоимости портфеля
function DualityPortfolioManager:calculateNetWorth()
local totalAssets = self:getTotal(self.assets)
local totalLiabilities = self:getTotal(self.liabilities)
-- Рассчитываем с учетом фактора двойственности
return (totalAssets - totalLiabilities) * self.dualityFactor
end
-- Метод для получения общей информации о портфеле
function DualityPortfolioManager:getPortfolioSummary()
return {
assets = self.assets,
liabilities = self.liabilities,
income = self.income,
expenses = self.expenses,
netWorth = self:calculateNetWorth(),
dualityFactor = self.dualityFactor
}
end
-- Пример использования класса
local investor = DualityPortfolioManager:new()
investor:addAsset("Stock A", 10000)
investor:addAsset("Real Estate", 25000)
investor:addLiability("Mortgage", 15000)
investor:addIncome(5000)
investor:addExpense(2000)
local summary = investor:getPortfolioSummary()
for k, v in pairs(summary) do
if type(v) == "table" then
print(k .. ":")
for asset, value in pairs(v) do
print(" " .. asset .. ": " .. value)
end
else
print(k .. ": " .. v)
end
end
Рычажные весы как символ баланса (смысл который автор закладывает)
Рычажные весы смысла и бессмыслицы отображают баланс между этими двумя крайностями. Статическая уравновешенность этих весов отражает статический баланс между порядком и хаосом. В рамках этого баланса действует закон сохранения, который гласит, что изменение одного элемента компенсируется изменением другого: "Что от одного тела убудет, то присовокупится к другому".
Баланс (S1 / S2 = 1): Смысл и бессмыслица уравновешены, что отражает статическую гармонию системы.
Дисбаланс (S1 / S2 > 1): Преобладание смысла над бессмыслицей, что символизирует порядок и структурированность.
Дисбаланс (S1 / S2 < 1): Преобладание бессмыслицы, указывающее на рост энтропии и хаоса.
Таким образом, рычажные весы смысла и бессмыслицы являются мощной метафорой для описания динамических процессов самоорганизации и деградации в системах, отражающих вечную борьбу между порядком и хаосом, смыслом и бессмыслицей.
О чудеса чудесные или Создание и Использование хук-функции. Что такое хуки простыми словами? Хуки — это технология перехвата вызовов функций в чужих процессах, в моем случае механизм, позволяющий зарегистрировать действия, которые должны быть выполнены при завершении программы. Идея состоит в том, чтобы установить определенный код, который выполнится автоматически перед завершением работы робота или программы, независимо от того, завершилась ли программа корректно или аварийно. Это механизм позволяет регистрировать действия, которые будут выполнены в конце работы программы, когда все процессы будут завершены. Это полезно для "корректного завершения" программы — закрытия всех активных ордеров или выполнения другой важной логики. Вынос в отдельную функцию позволяет аккуратно и централизованно завершать работу с ордерами, упрощая управление состояниями. В моем случае это просто анонимная функция.
Добрый день! Решил разбавить свой портфель разными активами, остановил выбор на ОФЗ, дописал под них свой класс. В общем не чего особенного, ОФЗ котируют трех типов поэтому в основу легло три стратегии, которые при одной и той же ситуации ведут себя по разному. Но столкнулся с проблемой автоматического обновления показателей инфляции и ключевой ставки, то есть с необходимость подключить внешние данные? Возможно уже решали подобную задачу или есть идеи. В основу создания универсального класса положена простая идея, класс который способен давать однозначные рекомендации по облигациям с указанием, на каких показателях основывается рекомендация. Сейчас это выглядит примерно так
Код
-- Вывод рекомендаций
function Bond:print_recommendations(inflation_rate, expected_rate_change)
local strategies = self:recommend_strategy(inflation_rate, expected_rate_change)
print("Рекомендации для облигации:", self.name)
for _, strategy in ipairs(strategies) do
print(string.format("- Стратегия: %s", strategy.strategy))
print(string.format(" Применима: %s", strategy.applicable and "Да" or "Нет"))
print(string.format(" Рекомендация: %s", strategy.message))
end
end
-- Пример использования
local myBond = Bond:new("ОФЗ 26207", "ОФЗ-ПД", 1000, 0.07, 950, 5)
local inflation_rate = 0.06 -- Текущая инфляция 6%
local expected_rate_change = -0.01 -- Ожидаемое снижение ставки на 1%
myBond:print_recommendations(inflation_rate, expected_rate_change)
Это ответ
Код
modules\Bond.lua" 1
Рекомендации для облигации: ОФЗ 26207
- Стратегия: Сохранение капитала
Применима: Да
Рекомендация: Облигация сохраняет капитал при текущей инфляции.
- Стратегия: Стабильный доход
Применима: Да
Рекомендация: ОФЗ-ПД подходят для стабильного дохода благодаря фиксированным купонам.
- Стратегия: Заработок на ставках
Применима: Нет
Рекомендация: Для заработка на ставках подходят долгосрочные ОФЗ-ПД.
>Exit code: 0 Time: 0.8326