Система принятия решений и/или Нечеткая логика(FuzzyLogic) ==================================================
"Системы поддержки принятия решения (СППР) (Decision Support System, DSS) - это интерактивные автоматизированные системы, помогающие лицу, принимающему решения, использовать данные и модели для решения слабо структурированных проблем".
В этой ветке предлагаю обсудить область применения Fuzzy Logic в задачах трейдинга. реализации систем правил в задачах принятии управленческих решений, управление риском (риск менеджмент), управление позицией (мани менеджмент), построение торговых стратегий.
В общем случае, область применения нечеткой логики не знает границ. В любом алгоритме, в любой системе правил, где используются четкие выводы (истина и ложь, 1 или 0), можно пробовать заменить их на степень истинности (степень принадлежности), для более точного отражения реальности. Нечеткая логика - равно расширенная логика, полностью совместимая с классической логикой в предельных случаях, обладающая невероятной мощью и простотой. Наш мир, фундаментально нечеток.
"LuaFuzzy простая библиотека, полностью написана на Lua, для решения проблем с применением нечеткой логики. Она была разработана на основе нечеткой логики арсенале Matlab, поэтому она очень похожа легко понять и использовать его. Она реализует систему логического вывода Mamdani".
Предлагаю Вашему вниманию luafuzzy.lua (библиотека не большая для удобства выкладываю сюда)
Код
---------------------------------
-- Fuzzy Operations
---------------------------------
-------------------------------------------------------------------------------
-- Tmin
-------------------------------------------------------------------------------
function tmin(a1,a2)
if a2 < a1 then
return a2
else
return a1
end
end
-------------------------------------------------------------------------------
-- Tmax
-------------------------------------------------------------------------------
function tmax(a1,a2)
if a2 < a1 then
return a1
else
return a2
end
end
-------------------------------------------------------------------------------
-- Tsum
-------------------------------------------------------------------------------
function tsum(a1,a2)
--local y = a1 + a2
return a1 + a2--y -- stop in one(limit)?
end
-------------------------------------------------------------------------------
-- Tprod
-------------------------------------------------------------------------------
function prod(a1,a2)
return a1*a2
end
---------------------------------
-- Membership Functions (членство)
---------------------------------
-------------------------------------------------------------------------------
--[[-- Gaussian membership function
-- @param x Input value
-- @param params Table of parameters:
-- - params[1] = standard deviation
-- - params[2] = mean
-- @return The value of the pertinence
Гауссова функция принадлежности
- @ Параметров х Входное значение
- @ Параметров ПАРАМЕТРЫ Таблица параметров:
--- ПАРАМЕТРЫ [1] = стандартное отклонение
--- ПАРАМЕТРЫ [2] = средняя
- @ Возвращать значение уместности]]
-------------------------------------------------------------------------------
function gaussmf( x, params )
return math.exp( -((x - params[2])^2)/(2*params[1]^2))
end
-------------------------------------------------------------------------------
--[[-- Trapezoidal membership function
-- @param x Input value
-- @param params Table of parameters(see chart below)
-- @return The value of the pertinence
--
-- pertinency
- Функция принадлежности трапецеидальной
- @ Параметров х Входное значение
- @ Параметров ПАРАМЕТРЫ Таблица параметров (см. таблицу ниже)
- @ Возвращать значение уместности
- уместность]]
-- ^
-- |
-- | /2+++3\
-- | / \
-- -|1---------4-->x
-------------------------------------------------------------------------------
function trapmf( x, params)
if x > params[1] and x < params[2] then
return (x-params[1])/(params[2]-params[1])
elseif x >= params[2] and x < params[3] then
return 1
elseif x >= params[3] and x < params[4] then
return (params[4]-x)/(params[4]-params[3])
else
return 0
end
end
-------------------------------------------------------------------------------
--[[-- Triangular membership function
-- @param x Input value
-- @param params Table of parameters(see chart below)
-- @return The value of the pertinence
--
-- pertinency
- Треугольные функции принадлежности
- @ Параметров х Входное значение
- @ Параметров ПАРАМЕТРЫ Таблица параметров (см. таблицу ниже)
- @ Возвращать значение уместности
- уместность]]
-- ^
-- |
-- | /2\
-- | / \
-- -|1-----3-->x
-------------------------------------------------------------------------------
function trimf( x, params )
if x > params[1] and x < params[2] then
return (x-params[1])/(params[2]-params[1])
elseif x >= params[2] and x < params[3] then
return (params[3]-x)/(params[3]-params[2])
else
return 0
end
end
---------------------------------
-- Deffuzification Functions
---------------------------------
-------------------------------------------------------------------------------
-- Centroid deffuzyfication method
-- @param fs A fuzzyset with pairs of x and y like: fs[1].x, fs[1].y
-- @returm Return the geometric center value
-------------------------------------------------------------------------------
function centroid( fs )
if #fs <= 1 then
error('invalid number of fuzzyset entries')
end
local accxy = 0
local accy = 0
for i,v in ipairs(fs) do
if v.y > 0 then
accxy = accxy + v.x*v.y
accy = accy + v.y
end
end
if accy > 0 then
return accxy/accy
else
return (fs[1].y-fs[#fs].y)/2
end
end
---------------------------------
-- Fuzzy Inference System
---------------------------------
-------------------------------------------------------------------------------
--[[-- Method to solve a fuzzy system
-- @param self The fuzzy system
-- @param ... A vararg list of input values
-- @return A vararg list of output values
Метод решить нечеткой системы
- @ Параметр self нечеткая система
- @ Параметр ... Список переменных аргументов входных значений
- @ Возвращать список VARARG выходных значений]]
-------------------------------------------------------------------------------
local function solvefuzzy( self, ... )
local fuzzy = self
local inpvals = {...}
-- error check
if #fuzzy.inps <= 0 then error('invalid number of inputs') end
if #fuzzy.outs <= 0 then error('invalid number of outputs') end
if #fuzzy.rules <= 0 then error('invalid number of rules') end
-- solve each input
for i,inp in ipairs(fuzzy.inps) do
-- current input value
local x = inpvals[i]
-- error check
if x > inp.mx or x < inp.mn then
error('value ' .. x .. ' out of range for input \'' .. inp.name .. '\'')
end
-- save the current value of the function for each lingvar
for _,lg in pairs(inp.lingvars) do
lg.value = lg.mf( x, lg.params )
end
end
-- for each rule...
for ri,r in ipairs(fuzzy.rules) do
--
-- Errors Check
--
-- range errors check
if #r.pres <= 0 then error('invalid number of premises') end
if #r.imps <= 0 then error('invalid number of implications') end
-- premises errors check
for pi=1,#r.pres do
if not fuzzy.inps[r.pres[pi].ifpart] then
error('invalid \'if part = '..r.pres[pi].ifpart..'\' for premise '..pi..' of rule ' .. ri)
end
if not fuzzy.inps[r.pres[pi].ifpart].lingvars[r.pres[pi].ispart] then
error('invalid \'is part = '..r.pres[pi].ispart..'\' for premise '..pi..' of rule ' .. ri)
end
end
-- implications errors check
for ii,imp in ipairs(r.imps) do
if not fuzzy.outs[imp.thenpart] then
error('invalid \'then part = '..imp.thenpart..'\' for implication '..ii..' of rule ' .. ri)
end
if not fuzzy.outs[imp.thenpart].lingvars[imp.ispart] then
error('invalid \'is part = '..imp.ispart..'\' for implication '..ii..' of rule ' .. ri)
end
end
-- connection function error check
if not fuzzy[r.connmethod] then
error('invalid \'connection method = '..r.connmethod..'\' for rule '..ri..'. (must be \'andmethod\' or \'ormethod\')')
end
--
-- Calculate the result value for a rule...
--
-- retrive the connection function
local conn = fuzzy[r.connmethod]
-- result value of premises
r.value = fuzzy.inps[r.pres[1].ifpart].lingvars[r.pres[1].ispart].value
-- for each premise...
for pi=2,#r.pres do
local v = fuzzy.inps[r.pres[pi].ifpart].lingvars[r.pres[pi].ispart].value
r.value = conn(v, r.value)
end
--
-- Calculate the resulting fuzzyset for each implication...
--
for _,imp in ipairs(r.imps) do
-- retrive the out's table
local out = fuzzy.outs[imp.thenpart]
-- retrive the lingvar fr om the out table
local lg = out.lingvars[imp.ispart]
-- save the fuzzyset for each implication
imp.fuzzyset = {}
-- compute the step
local step = (out.mx - out.mn)*fuzzy.step
-- calculate the resulting fuzzyset
for i=out.mn,out.mx,step do
-- computes the mf value for i
local lgval = lg.mf( i, lg.params )
-- compute the implication result
local v = fuzzy.implicmethod( lgval , r.value )
-- add the result to the fuzzy set
table.insert( imp.fuzzyset, { x=i, y=v } )
end
end -- end implications
end -- end rules
--
-- Computes output...
--
-- result table
local outvals = {}
-- solve each output
for i,out in ipairs(fuzzy.outs) do
-- clear previews fuzzyset
out.fuzzyset = nil
-- for each rule...
for _,r in ipairs(fuzzy.rules) do
--
-- Aggregation
--
-- for each implication
for _,imp in ipairs(r.imps) do
if out.name == imp.thenpart then
if not out.fuzzyset then
out.fuzzyset = {}
-- copy the first implication fuzzyset
for k,v in ipairs(imp.fuzzyset) do
out.fuzzyset[k] = { x=v.x, y=v.y }
end
else
-- calculate the resulting fuzzyset with aggregation method
for i,v in ipairs(out.fuzzyset) do
-- computes the new value
out.fuzzyset[i] = { x=v.x, y = fuzzy.aggregmethod( v.y, imp.fuzzyset[i].y ) }
end
end
end
end
end
--
-- Defuzzification...
--
-- call deffuzyfication method
out.value = fuzzy.defuzzmethod( out.fuzzyset )
-- add output value to result table
table.insert( outvals, out.value )
end
return unpack( outvals )
end
---------------------------------
-- Fuzzy System
---------------------------------
--
-------------------------------------------------------------------------------
--[[-- Method to add a new linguistic variable to a fuzzy input or output
-- @param self The variable's table
-- @param name Name of the variable
-- @param mf The membership function
-- @param params Table of parameters of the membership function
-- @return The lingvar's table
Метод для добавления нового языкового переменной нечеткой входа или выхода
- @ Параметров самостоятельно таблице переменной
- @ Параметров имя Имя переменной
- @ Параметров MF функция принадлежности
- @ Параметров ПАРАМЕТРЫ Таблица параметров функции принадлежности
- @ Вернуться таблицу в lingvar в]]
-------------------------------------------------------------------------------
local function addlingvar( self, name, mf, params )
local var = self
local lg = {}
lg.name = name
lg.mf = mf
lg.params = params
var.lingvars[lg.name] = lg
return lg
end
-------------------------------------------------------------------------------
--[[-- Method to add a new input variable to a fuzzy system
-- @param self The fuzzy system table
-- @param name Name of the variable
-- @param mn Lower lim it of values
-- @param mx Upper limit of values
-- @return The variable's table
- Метод, чтобы добавить новую переменную ввода на нечеткой системы
- @ Параметров самостоятельно нечеткой системной таблицы
- @ Параметров имя Имя переменной
- @ Параметров млн. Нижний предел значений
- @ Параметров м Верхний предел значений
- @ Вернуться таблицу переменной]]
-------------------------------------------------------------------------------
local function addinp( self, name, mn, mx )
local fis = self
local inp = {}
inp.name = name
inp.mn = mn
inp.mx = mx
inp.lingvars = {}
inp.addlingvar = addlingvar
table.insert( fis.inps, inp )
fis.inps[inp.name] = inp
return inp
end
-------------------------------------------------------------------------------
--[[-- Method to add a new output variable to a fuzzy system
-- @param self The fuzzy system table
-- @param name Name of the variable
-- @param mn Lower limit of values
-- @param mx Upper limit of values
-- @return The variable's table
Метод для добавления нового выходной переменной к нечеткой системы
- @ Параметров самостоятельно нечеткой системной таблицы
- @ Параметров имя Имя переменной
- @ Параметров млн. Нижний предел значений
- @ Параметров м Верхний предел значений
- @ Вернуться таблицу переменной]]
-------------------------------------------------------------------------------
local function addout( self, name, mn, mx )
local fis = self
local out = {}
out.name = name
out.mn = mn
out.mx = mx
out.lingvars = {}
out.addlingvar = addlingvar
table.insert( fis.outs, out )
fis.outs[out.name] = out
return out
end
-------------------------------------------------------------------------------
--[[-- Method to add a new premise to a rule
-- @param self The rule's table
-- @param neg Flag to informe if the implication output should be negated
-- @param ifpart Name of the input variable
-- @param ispart Name of the linguistic variable of the input
-- @return The premises table
- Метод, чтобы добавить новое помещение, чтобы правило
- @ Параметров самостоятельно таблице в правиле
- @ Параметров нег Флаг, Informe если выход вывод следует быть сведены на нет
- @ Параметров ifpart Имя входной величины
- @ Параметров ispart Название лингвистической переменной входа
- @ Вернуть таблицу помещения]]
-------------------------------------------------------------------------------
local function addpremise( self, neg, ifpart, ispart )
local rule = self
local prem = {}
prem.neg = neg
prem.ifpart = ifpart
prem.ispart = ispart
table.insert( rule.pres, prem )
return prem
end
-------------------------------------------------------------------------------
--[[-- Method to add a new implication to a rule
-- @param self The rule's table
-- @param neg Flag to informe if the implication output should be negated
-- @param thenpart Name of the output variable
-- @param ispart Name of the linguistic variable of the ouput
-- @return The implication's table--]]
-------------------------------------------------------------------------------
local function addimplic( self, neg, thenpart, ispart )
local rule = self
local impl = {}
impl.neg = neg
impl.thenpart = thenpart
impl.ispart = ispart
table.insert( rule.imps, impl )
return impl
end
-------------------------------------------------------------------------------
--[[-- Method to add a new rule to a fuzzy sistem
-- @param self The fuzzy system
-- @param weight The weight of the rule
-- @param connmethod The connection method. (must be: 'andmethod' or 'ormethod')
-- @return The rule's table--]]
-------------------------------------------------------------------------------
local function addrule( self, weight, connmethod )
local fis = self
local rule = {}
rule.weight = weight
rule.connmethod = connmethod
rule.pres = {}
rule.imps = {}
rule.addpremise = addpremise
rule.addimplic = addimplic
table.insert( fis.rules, rule )
return rule
end
-------------------------------------------------------------------------------
-- Create a new fuzzy system
-- @return A new table with the fuzzy system
-------------------------------------------------------------------------------
function luafuzzy()
-- create new table(создать новую таблицу)
local fuzzy = {}
-- and method
fuzzy.andmethod = tmin
-- or method
fuzzy.ormethod = tmax
-- implication method(метод Смысл)
fuzzy.implicmethod = tmin
-- aggregation method()
fuzzy.aggregmethod = tmax
-- deffuzification method
fuzzy.defuzzmethod = centroid
-- step used to compute a discrete fuzzyset(Шаг используется для вычисления дискретного fuzzyset)
fuzzy.step = 0.01
-- table os rules
fuzzy.rules = {}
-- table of inputs
fuzzy.inps = {}
-- tabla of outputs
fuzzy.outs = {}
-- method to add a new input
fuzzy.addinp = addinp
-- method to add a new output
fuzzy.addout = addout
-- method to add a new rule
fuzzy.addrule = addrule
-- method to solve the fuzzy inferece system
fuzzy.solve = solvefuzzy
return fuzzy
end
1) В дельнейшем не копируйте из интернета, а дайте ссылку например, так: https://github.com/ajsher/luafuzzy ============================== 2) здесь можно сначала почитать, чтобы потом предметно обсуждать. https://habr.com/ru/articles/113020/ ================== 3) А Вы базу знаний откуда будете брать для DSS? ================== Метод нечетких множеств - это всего лишь инструмент. -------------- Подобно мясорубке. На выходе всегда фарш. А вот сможете его есть или нет, зависит от того, что на входе т е от базы знаний.
Хочу заметить про один недостаток данной библиотеки нет в ней Сигмовидной функции принадлежности, если кто допишет библиотеку выложите. Так как nikolz, дал ссылку на автора, то тем кому тема незнакома, может перейти по ссылке и там лежит пример показывающий как этим пользоваться. Это классический пример из букваря, суть рассчитать комиссионные официанту в зависимости от двух параметров.
Прежде чем говорить о базах знаний, я хочу предложить Вашему вниманию другую ссылку по нашей теме.
Цитата
В современном трейдинге все чаще используются системы автоматической торговли, чаще именуемые торговыми экспертами или роботами. Суть их работы в том, что они имеют четкую, жестко заданную систему, а именно торговую стратегию и систему управления финансами (мани-менеджмент).Преимущества таких систем в том, что они исключают человеческий фактор, строго действуют по определенному алгоритму. Недостатки автоматической торговли заключаются в отсутствии гибкости применяемой торговой стратегии, она всегда будет работать в одних и тех же рамках, с одними и теми же жестко разбитыми на категории параметрами. Проще говоря, система будет груба: средний тренд — входит одним лотом, сильный тренд — двойным и точка!
Как бы торговал человек, которому как раз присуща нечеткость категорий, различное мнение при схожих сигналах на вход? Он бы пытался оценить тренд, задаваться вопросом: а насколько он средний, или, может быть, он ближе к сильному, или сильный, но не настолько, чтобы входить двойным лотом по стратегии?
Все это может описать нечеткая логика. Она не ставит жестких границ между категориями, она их как бы размывает и тем самым делает торговую систему более гибкой, сочетая в себе дисциплину робота и гибкость человеческого мышления.
Просматривая материалы по теме, мне захотелось пропеть дифирамб луа, судите сами, как относительно просто, элегантно, интуитивно понятно написана библиотека (Все познается в сравнении!) Все что на страницах данного сайта обсуждается, в конечном итоге с водится к одному - принятию торгового решения, в той или иной рыночной ситуации. И нечеткая логика нам в этом помогает. Для огромного количества технических задач создаются AI с использованием нечеткой логике, вот и я переделывая свою программу, подошел на конец к этапу - "бэктестинга". При котором нужно создовать правила решения управенческих задач, всповнил про нечеткую логику, решил поделиться свими соображениями. Пользоваться этим или не пользоваться решать Вам. Могу сказать одно, я у себя собираю комбинированный подход эксперт + нечеткая логика.
Выкладываю совсем простой пример (собрал "на коленке"), но от этого не менее мощный. Определяем силу тренда при помощи алгоритма ADX (J. Welles Wilder) устанавливая четкие правила, ответ индикатора являются входным сигналом для нечеткого индикатора. Выходной сигнал нечеткого индикатора, будет корректировать нашу позицию на рынке с учетом нечеткой переменной силы тренда, в стратегии это ТП и СЛ; можно задать размер лота; значение процента риска депозита относительно нечеткой переменной или еще чего то там ... Делитесь идеями, выкладывайте примеры! Хорошей алго торговли!
Скрытый текст
-- Выходной сигнал, который будет корректировать нашу позицию на рынке с учетом нечеткой переменной силы тренда, function mamdani_adx( v ) ---- Mamdani Fuzzy System require 'luafuzzy' local fuzzy = luafuzzy() ----- 1). Задаем 4 категории силы тренда: слабый (low), умеренный (moderate),средний (medium) и сильный (high). ----- создать все нечеткие входные переменные, задав имя переменной, её значения:
---- 2) четыре категории для значений целей прибыли: -- первая и четвертая категории(10-20 и 40-50 пунктов) — трапециевидными функциями, а две оставшиеся (20-30 и 30-40 пунктов) — треугольными. -- Так будет выглядеть описание нашего выходного сигнала.
----- 3) составляем базу правил Mamdani (fuzzy rules)
-- Правило R1 если , то local r1 = fuzzy:addrule( 1, 'andmethod' ) r1:addpremise( false, 'trend', 'low' ) r1:addimplic ( false, 'target', 'low' )
-- Правило R2 если , то local r2 = fuzzy:addrule( 1, 'andmethod' ) r2:addpremise( false, 'trend', 'moderate' ) r2:addimplic ( false, 'target', 'moderate' )
-- Правило R3 если , то local r3 = fuzzy:addrule( 1, 'andmethod' ) r3:addpremise( false, 'trend', 'medium' ) r3:addimplic ( false, 'target', 'medium' )
-- Правило R3 если , то local r4 = fuzzy:addrule( 1, 'andmethod' ) r4:addpremise( false, 'trend', 'high' ) r4:addimplic ( false, 'target', 'high' )
-----4) Set input value local res = fuzzy:solve( v ) or 0 --print('res = '..res ,1) return res; end
Имитация: print('системa рекомендаций;') for adx = 30,60, 5 do print('cилы тренда: ADX = ', adx, 'выходной сигнал, с учетом силы тренда корректировать позицию на ',math.floor(mamdani_adx( adx ) ), 'пунктов') end Ответы: системa рекомендаций; cилы тренда: ADX = 30 выходной сигнал, с учетом силы тренда корректировать позицию на 14 пунктов cилы тренда: ADX = 35 выходной сигнал, с учетом силы тренда корректировать позицию на 14 пунктов cилы тренда: ADX = 40 выходной сигнал, с учетом силы тренда корректировать позицию на 14 пунктов cилы тренда: ADX = 45 выходной сигнал, с учетом силы тренда корректировать позицию на 25 пунктов cилы тренда: ADX = 50 выходной сигнал, с учетом силы тренда корректировать позицию на 25 пунктов cилы тренда: ADX = 55 выходной сигнал, с учетом силы тренда корректировать позицию на 30 пунктов cилы тренда: ADX = 60 выходной сигнал, с учетом силы тренда корректировать позицию на 35 пунктов
VPM, Петь дифирамбы луа может лишь тот, кто никогда не видел ни одного другого языка программирования. Мне доводилось писать где-то на полутора-двух десятках языков, и большего дерьма, чем луа я что-то не могу припомнить. За каким хреном нужна нечёткая логика - тем более, для такой примитивной задачи как принятие торгового решения, я тоже без понятия. AI пытаются использовать лишь те, у кого начисто отсутствует NI. Определять силу тренда - задача столь же простая, сколь и бесполезная: во-первых, на разных таймфреймах тренды могут быть разными, вплоть до диаметрально противоположных. Во-вторых, если у нас, скажем, высокая волатильность, то какая, в жопу, разница, куда направлен тренд? В третьих, наша позиция на рынке зависит не только (и даже не столько) от поведения рынка, сколько от состояния портфеля и кошелька. В-четвёртых, портфель обычно состоит из достаточно большого количества тикеров, которые ведут себя по-разному, и управлять надо всем этим конгломератом, а не каким-то сраным тикером, лежащим в каком-то сраном тренде какого-то сраного таймфрейма.
Владимир, Дифирамб мой в отношении луа, как раз и заключается в том что увидел, как эта задача реализуется на языке программирования mql. Относительно ADX, это просто упрощенный пример, хорошо известный широкой публике, для понимания вопроса как этим можно пользоваться а нашем контексте. Про нечеткую логику можно легко "погуглить" (на пример, мне нравится пример управление автомобилем). Обращу внимание лишь на главное. Пример, задали четкую пороговую границу TREND = ADX>30 or false, что получается 30.1 тренд а 29.9 нет. Что же предлагает нечеткая логика. Происходит размытие четко заданных границ, они становятся нечеткими. То есть в приграничных зонах жестко заданных категорий появляется двойственность — сила тренда относится сразу к двум понятиям, но с разной степенью принадлежности.
Относительно трендов согласен с Вами, скажу про свой подход гоняю 5 тайм фреймов это минимум (легко могу увеличить только пока не вижу задачи зачем это делать), 3 тайм фрейма это торговые, я про это писал на страницах "двойной очереди". Главный старший определяет тренд, Затем торговый для поиска сигналов на удержание длительной позиции, и младший на котором все уточняется. Два остальных технические(1 минута и 1 секунда). В своем подходе, выделяю не только тренд, но циклическую компоненту и флат, то есть строю гипотезы о состоянии рынка, от этого зависит, какая стратегия торгует в данный момент, и здесь тоже нечеткая логика.
Волатильность имеет важное значение у меня отвечает за торговые цели, установку параметров sl, tp, но это совершенно другие задачи, определяя направлен тренда - определяем куда наиболее вероятно двигается цена за определенный промежуток времени (если хотите это мера смещения центра, хорошо характеризует альфа в линейной регрессии).
Что касается портфеля, а что мешает Вам написать так: ADX={} ADX[i]=function ADX().
VPM, Не знаю - может, mql ещё хуже, чем lua, но тогда в автоматизации торговли работают самые выдающиеся дебилы в мире. Что такое ADX я не знаю и знать не хочу, а что такое нечёткая логика знаю прекрасню, и не вижу ни малейшего смысла в её применении здесь. Решения здесь принимаются очень даже чёткие: либо я подаю заявку либо нет.
Я гоняю 8 таймфреймов, торгую на трёх, и задача распределения бумаг между таймфреймами, хоть и нетривиальная, но вполне себе чёткая. Задача балансировки портфеля (какие тикеры туда закупать, какие выводить, долю каких увеличивать или уменьшать) ещё более нетривиальная, но тоже очень даже чёткая.
Для того что бы понять нужна ли вам такая логика достаточно вставить в скрипт использующий эту библиотеку функцию выставления заявок и дать доступ к деньгам. Своим деньгам ;)
Kolossi, Прежде чем, что - то куда - то вставлять, неплохо бы вначале, разработать лингвистические переменные для входящих данных, для выхода, создать правила, разработать алгоритм использования ответов. И это задача далеко не простая. Ну прежде чем встраивать в реал, нужно от тестировать. (Алгоритм создания есть в примере).
VPM написал: Kolossi, Прежде чем, что - то куда - то вставлять, неплохо бы вначале, разработать лингвистические переменные для входящих данных, для выхода, создать правила, разработать алгоритм использования ответов. И это задача далеко не простая. Ну прежде чем встраивать в реал, нужно от тестировать. (Алгоритм создания есть в примере).
А Вас не смущает, что теория нечетких множеств разработана 50 лет назад. И кроме пиара компаний продающих софт для принятия решений , вы никаких достижений в этой области не найдете. ---------------- Для полноты понимания вы еще посмотрите скрытую марковскую модель. Это уж точно применяется уже давно в подобных задачах.
nikolz, Ползает робот - пылесос и меня это совсем не смущает, стиральная машина стирает и меня это не смущает. В быту куда не ткнись наткнешься на Fuzzy Logic, и это ни кого не смущает. Срок говорит о проверке временем, и подтверждает тот факт, что решать задачи управления лучше простыми методами. Хотя при проектировании Fuzzy System легко наделать ошибок.
VPM написал: nikolz, Ползает робот - пылесос и меня это совсем не смущает, стиральная машина стирает и меня это не смущает. В быту куда не ткнись наткнешься на Fuzzy Logic, и это ни кого не смущает. Срок говорит о проверке временем, и подтверждает тот факт, что решать задачи управления лучше простыми методами. Хотя при проектировании Fuzzy System легко наделать ошибок.
Вы ошибаетесь. В этих устройствах нет нечетких множеств. Но Вы можете верить, что там оно есть. Блажен, кто верует,...
VPM написал: Нечеткая логика - равно расширенная логика, полностью совместимая с классической логикой в предельных случаях, обладающая невероятной мощью и простотой.
Попытка быстро собрать нечеткий апgроксиматор на основе двух готовых lua библиотек (luafuzzy, luann) - застряла? Виновник тому - библиотекa, luann, не проходит обучение если порог err < 0.42. Вот уже который день не могу разобраться почему? Если кто то в теме посмотрите, вот сам модуль
Скрытый текст
Код
local write, writeIndent, writers, refCount;
persistence =
{
store = function (path, ...)
local file, e = io.open(path, "w")
if not file then return error(e) end
local n = sel ect("#", ...)
local objRefCount = {} -- Stores reference that will be exported
for i = 1, n do refCount(objRefCount, (sel ect(i,...))) end
local objRefNames = {}
local objRefIdx = 0;
file:write("-- Persistent Data\n");
file:write("local multiRefObjects = {\n");
for obj, count in pairs(objRefCount) do
if count > 1 then
objRefIdx = objRefIdx + 1;
objRefNames[obj] = objRefIdx;
file:write("{};"); -- table objRefIdx
end;
end;
file:write("\n} -- multiRefObjects\n");
for obj, idx in pairs(objRefNames) do
for k, v in pairs(obj) do
file:write("multiRefObjects["..idx.."][");
write(file, k, 0, objRefNames);
file:write("] = ");
write(file, v, 0, objRefNames);
file:write(";\n");
end;
end;
for i = 1, n do
file:write("local ".."obj"..i.." = ");
write(file, (select(i,...)), 0, objRefNames);
file:write("\n");
end
if n > 0 then
file:write("return obj1");
for i = 2, n do
file:write(" ,obj"..i);
end;
file:write("\n");
else
file:write("return\n");
end;
file:close();
end;
load = function (path)
local f, e = loadfile(path);
if f then
return f();
else
return nil, e;
end;
end;
}
write = function (file, item, level, objRefNames)
writers[type(item)](file, item, level, objRefNames);
end;
writeIndent = function (file, level)
for i = 1, level do
file:write("\t");
end;
end;
refCount = function (objRefCount, item)
if type(item) == "table" then
if objRefCount[item] then
objRefCount[item] = objRefCount[item] + 1;
else
objRefCount[item] = 1;
for k, v in pairs(item) do
refCount(objRefCount, k);
refCount(objRefCount, v);
end;
end;
end;
end;
writers = {
["nil"] = function (file, item) file:write("nil") end;
["number"] = function (file, item)
file:write(tostring(item));
end;
["string"] = function (file, item)
file:write(string.format("%q", item));
end;
["boolean"] = function (file, item)
if item then
file:write("true");
else
file:write("false");
end
end;
["table"] = function (file, item, level, objRefNames)
local refIdx = objRefNames[item];
if refIdx then
file:write("multiRefObjects["..refIdx.."]");
else
file:write("{\n");
for k, v in pairs(item) do
writeIndent(file, level+1);
file:write("[");
write(file, k, level+1, objRefNames);
file:write("] = ");
write(file, v, level+1, objRefNames);
file:write(";\n");
end
writeIndent(file, level);
file:write("}");
end;
end;
["function"] = function (file, item)
local dInfo = debug.getinfo(item, "uS");
if dInfo.nups > 0 then
file:write("nil --[[functions with upvalue not supported]]");
elseif dInfo.what ~= "Lua" then
file:write("nil --[[non-lua function not supported]]");
else
local r, s = pcall(string.dump,item);
if r then
file:write(string.format("loadstring(%q)", s));
else
file:write("nil --[[function could not be dumped]]");
end
end
end;
["thread"] = function (file, item)
file:write("nil --[[thread]]\n");
end;
["userdata"] = function (file, item)
file:write("nil --[[userdata]]\n");
end;
}
local luann = {}
local Layer = {}
local Cell = {}
---local exp = math.exp
local Activation = {}
--Define the activation functions
Activation["sigmoid"] = function(signalSum)
return 1 / (1 + math.exp(-1*signalSum))
end
Activation["relu"] = function(signalSum)
return math.max(0, signalSum)
end
Activation["leakyrelu"] = function(signalSum)
return math.max(0.01*signalSum, signalSum)
end
--// Cell:new(numInputs)
-- numInputs -> The number of inputs to the new cell
-- Note: The cell has a structure containing weights that modify the input fr om the previous layer.
-- Each cell also has a signal, or output.
function Cell:new(numInputs)
local cell = {delta = 0, weights = {}, signal = 0}
for i = 1, numInputs do
cell.weights[i] = math.random() * 0.1
end
setmetatable(cell, self)
self.__index = self
return cell
end
--// Cell:activate(inputs, bias, actFuncName)
-- inputs -> The collection of inputs to the cell
-- bias -> The bias input to the cell
-- actFuncName -> The name of the activation function (see luann:new)
function Cell:activate(inputs, bias, actFuncName)
local signalSum = bias
local weights = self.weights
for i = 1, #weights do
signalSum = signalSum + (weights[i] * inputs[i])
end
---self.signal = 1 / (1 + exp((signalSum * -1) / threshold))
res = Activation[actFuncName](signalSum)
self.signal = res
end
--// Layer:new([numCells [, numInputs]])
-- numCells -> Optional (default: 1). Number of cells in this layer
-- numInputs -> Optional (default: 1). Number of inputs to this layer
-- Note: The layer is a table of cells.
function Layer:new(numCells, numInputs)
numCells = numCells or 1
numInputs = numInputs or 1
local cells = {}
---for i = 1, numCells do cells[i] = Cell:new(numInputs) end
---local layer = {cells = cells, bias = math.random()}
---setmetatable(layer, self)
---self.__index = self
for i = 1, numCells do
cells[i] = Cell:new(numInputs)
end
local layer = {cells = cells, bias = math.random()}
setmetatable(layer, self)
self.__index = self
return layer
end
--// luann:new(layers, learningRate [, actiFuncName])
-- layers -> Table of layer sizes fr om input to output
-- actiFuncName -> Optional (default: 'sigmoid'). Defines the NAME of the function (in the Activation table) to use in for activation.
-- Note: For actiFuncName, the function itself cannot be passed due to issues with table persistence.
-- This is currently considered a workaround..
function luann:new(layers, learningRate, actiFuncName)
local network = {learningRate = learningRate, actiFuncName = actiFuncName or 'sigmoid'}
--initialize the input layer
network[1] = Layer:new(layers[1], layers[1])
---initialize the hidden layers and output layer
for i = 2, #layers do
--initialize the hidden layers and output layer
network[i] = Layer:new(layers[i], layers[i-1])
end
setmetatable(network, self)
self.__index = self
return network
end
--// luann:train(inputs, expectedOutput, rmseThreshold)
-- inputs = collection of a collection of inputs to train on
-- expectedOutput = collection of a collection of expected outputs for the given inputs
-- rmseThreshold = train until RMSE falls below this value
function luann:train(inputs, expectedOutput, rmseThreshold)
local out = {}
local count = 0
repeat
for i=1, #inputs do
-- for each set of inputs
self:bp(inputs[i], expectedOutput[i])
out[i] = self:getOutputs()
end
local rmse = self:getRMSE(out, expectedOutput)
if count>50000 then
print("Current RMSE: " .. rmse)
count = 0
end
count = count + 1
until(rmse < rmseThreshold)
end
---function luann:decode(hiddenSignal)
--// luann:forwardPropagate(inputs)
-- propagates the inputs and returns the outputs, a convience function
function luann:forwardPropagate(inputs)
self:activate(inputs)
return self:getOutputs()
end
--// luann:getOutputs()
-- gets the set of previous outputs
function luann:getOutputs()
local out = {}
for o=1, #self[#self].cells do
out[o] = self[#self].cells[o].signal
end
return out
end
--// luann:getRMSE(predictions, expected)
-- predictions = a collection of a collection of predictions
-- expected = a collection of a collection of expected outputs
function luann:getRMSE(predictions, expected)
assert(#predictions == #expected, "ERR: #predictions ~= #expected")
local numElements = 0
local sum = 0
for i=1, #predictions do
-- for each set of predictions
for j=1, #predictions[i] do
-- for each output node
numElements = numElements+1
sum = sum + math.pow(expected[i][j]-predictions[i][j],2)
end
end
local mse = sum/numElements
return math.sqrt(mse)
end
--// luann:activate(inputs)
-- inputs -> The collection of inputs to be forward propagated through the network
function luann:activate(inputs)
for i = 1, #inputs do
self[1].cells[i].signal = inputs[i]
end
for i = 2, #self do
local passInputs = {}
local cells = self[i].cells
local prevCells = self[i-1].cells
for m = 1, #prevCells do
passInputs[m] = prevCells[m].signal
end
local passBias = self[i].bias
for j = 1, #cells do
--activate each cell
cells[j]:activate(passInputs, passBias, self.actiFuncName)
end
end
end
--// luann:bp(inputs, expectedOutputs)
-- inputs -> The collection of training inputs for backpropagation
-- expectedOutputs -> The collection of expected outputs for the given training inputs
-- Note: Contains some debug info for when cell weights become inf and cell deltas become NaN
function luann:bp(inputs, expectedOutputs)
self:activate(inputs) --update the internal inputs and outputs
local numLayers = #self
local learningRate = self.learningRate
for i = numLayers, 2, -1 do --iterate backwards (nothing to calculate for input layer)
local numCells = #self[i].cells
local cells = self[i].cells
for j = 1, numCells do
-- for each cell in the current layer
local cellOutput = cells[j].signal
if i ~= numLayers then
local weightDelta = 0
local nextLayerCells = self[i+1].cells
for k = 1, #nextLayerCells do
-- for each cell in the next layer
weightDelta = weightDelta + nextLayerCells[k].weights[j] * nextLayerCells[k].delta
-- ensure weightDelta does not become inf
assert(weightDelta ~= math.huge, "weightDelta: INF!\nnextLayerCells["..k.."].weights["..j.."]="..nextLayerCells[k].weights[j]..", \nnextLayerCells["..k.."].delta="..nextLayerCells[k].delta)
end
cells[j].delta = cellOutput * (1 - cellOutput) * weightDelta
-- ensure cell delta does not become NaN
assert(cells[j].delta == cells[j].delta, "cells["..j.."].delta: NaN!\n" .. "cellOutput="..cellOutput..",\nweightDelta="..weightDelta)
else --special calculations for output layer
cells[j].delta = (expectedOutputs[j] - cellOutput) * cellOutput * (1 - cellOutput)
-- ensure cell delta does not become NaN
assert(cells[j].delta == cells[j].delta, "cells["..j.."].delta: NaN! OUTPUT\nexpectedOutputs["..j.."]="..expectedOutputs[j]..",\ncellOutput="..cellOutput)
end
end
end
for i = 2, numLayers do
-- update the bias
self[i].bias = self[i].bias + learningRate * self[i].cells[#self[i].cells].delta
for j = 1, #self[i].cells do
for k = 1, #self[i].cells[j].weights do
-- update the weights
local weights = self[i].cells[j].weights
weights[k] = weights[k] + learningRate * self[i].cells[j].delta * self[i-1].cells[k].signal
end
end
end
end
--// luann:saveNetwork(network, savefile)
-- network -> The luann network to be saved
-- path -> The path of the output file
function luann:saveNetwork(network, path)
print("Saving network to: " .. path)
persistence.store(path, network)
end
--// luann:loadNetwork(path)
-- path -> The path of the file to load
function luann:loadNetwork(path)
local ann = persistence.load(path)
ann.bp = luann.bp
ann.activate = luann.activate
for i = 1, #ann do
for j = 1, #ann[i].cells do
ann[i].cells[j].activate = Cell.activate
end
end
return(ann)
end
--// luann:loadTrainingDataFromFile(path)
-- path -> The path of the file containing the training data
function luann:loadTrainingDataFromFile(path)
local trainingData = {}
local fileLines = {}
local f = io.open(path, "rb")
for line in f:lines() do
table.insert (fileLines, line);
end
f:close()
for i = 1, #fileLines do
if i%2 == 0 then
local tempInputs = {}
for input in fileLines[i]:gmatch("%S+") do
table.insert(tempInputs, tonumber(input))
end
local tempOutputs = {}
for output in fileLines[i+1]:gmatch("%S+") do
table.insert(tempOutputs, tonumber(input))
end
table.insert(trainingData, {tempInputs, tempOutputs})
end
end
return(trainingData)
end
return(luann)
local luann = require("luann2")
math.randomseed(89890)
learningRate = 0.2; ---- set between 0, 1
local err = 0.42--01 ---- train until RMSE < 0.01
--------------------
---- create a network with 2 inputs, 3 hidden cells, and 1 output
myNetwork = luann:new({2, 3, 1}, learningRate, 'sigmoid')
local inputs = {
{0,0}, {1,0}, {0,1}, {1,1}
};
local expectedOutputs = {
{0}, {1}, {1}, {0}
};
---- train the network
myNetwork:train(inputs, expectedOutputs, err)
---- print the signal of the single output cell when :activated with different inputs
print("Results:")
print("0 0 | " .. myNetwork:forwardPropagate({0,0})[1])
print("0 1 | " .. myNetwork:forwardPropagate({0,1})[1])
print("1 0 | " .. myNetwork:forwardPropagate({1,0})[1])
print("1 1 | " .. myNetwork:forwardPropagate({1,1})[1])
---- Save the network to a file
luann:saveNetwork(myNetwork, "demoNetwork.dump")
--Load the network from a file
newNetwork = luann:loadNetwork("demoNetwork.dump")
---- run the loaded network
print("Results:")
print("Output of 0,0: " .. myNetwork:forwardPropagate({0,0})[1])
print("Output of 0,1: " .. myNetwork:forwardPropagate({0,1})[1])
print("Output of 1,0: " .. myNetwork:forwardPropagate({1,0})[1])
print("Output of 1,1: " .. myNetwork:forwardPropagate({1,1})[1])
Если err = 0.42
Results:
0 0 | 0.087963877174929
0 1 | 0.65479578845313
1 0 | 0.65514033859186
1 1 | 0.67301633908636
Saving network to: demoNetwork.dump
Results:
Output of 0,0: 0.087963877174929
Output of 0,1: 0.65479578845313
Output of 1,0: 0.65514033859186
Output of 1,1: 0.67301633908636
>Exit code: 0 Time: 1.544
Если err = 0.41 и ниже
Current RMSE: 0.41082711758809
Current RMSE: 0.41051673305992
Current RMSE: 0.4104241333885
Current RMSE: 0.41037984366439
Current RMSE: 0.41035393431294
Current RMSE: 0.41033694994401
Current RMSE: 0.41032496576157
Current RMSE: 0.41031606177729
Current RMSE: 0.41030918840836
Current RMSE: 0.41030372375712
Current RMSE: 0.41029927605292
Current RMSE: 0.41029558629415
Current RMSE: 0.41029247643831
Current RMSE: 0.41028982008542
Current RMSE: 0.41028752503411
Current RMSE: 0.41028552245745
Current RMSE: 0.41028375994307
Current RMSE: 0.41028219687901
Current RMSE: 0.41028080131238
Current RMSE: 0.41027954776023
Current RMSE: 0.41027841565222
Current RMSE: 0.41027738820225
Current RMSE: 0.41027645157721
Current RMSE: 0.41027559427552
Current RMSE: 0.41027480665622
Current RMSE: 0.41027408057764
Current RMSE: 0.41027340911714
Current RMSE: 0.41027278635136
Current RMSE: 0.41027220718234
Current RMSE: 0.41027166719876
Current RMSE: 0.41027116256414
Current RMSE: 0.41027068992629
Current RMSE: 0.41027024634327
Current RMSE: 0.41026982922256
Current RMSE: 0.41026943627071
Current RMSE: 0.41026906545149
Current RMSE: 0.41026871495082
Current RMSE: 0.4102683831473
Current RMSE: 0.41026806858733
Current RMSE: 0.41026776996397
Current RMSE: 0.41026748609891
Current RMSE: 0.41026721592702
Current RMSE: 0.41026695848313
Current RMSE: 0.41026671289054
Current RMSE: 0.41026647835116
Current RMSE: 0.41026625413687
Current RMSE: 0.41026603958203
Current RMSE: 0.41026583407693
Current RMSE: 0.41026563706206
Current RMSE: 0.41026544802301
Current RMSE: 0.41026526648604
Current RMSE: 0.41026509201416
Current RMSE: 0.41026492420362
Current RMSE: 0.4102647626808
Current RMSE: 0.41026460709947
Current RMSE: 0.41026445713833
Current RMSE: 0.4102643124988
Current RMSE: 0.41026417290304
Current RMSE: 0.41026403809221
Current RMSE: 0.41026390782484
Current RMSE: 0.41026378187541
Current RMSE: 0.41026366003308
Current RMSE: 0.41026354210048
Current RMSE: 0.41026342789266
Current RMSE: 0.41026331723616
Current RMSE: 0.41026320996809
Current RMSE: 0.41026310593536
Current RMSE: 0.41026300499395
Current RMSE: 0.41026290700826
Current RMSE: 0.41026281185048
Current RMSE: 0.41026271940006
Current RMSE: 0.41026262954319
Current RMSE: 0.41026254217235
Current RMSE: 0.41026245718585
Current RMSE: 0.4102623744875
Current RMSE: 0.41026229398616
Current RMSE: 0.4102622155955
Current RMSE: 0.41026213923363
Current RMSE: 0.41026206482282
Current RMSE: 0.41026199228929
Current RMSE: 0.41026192156289
Current RMSE: 0.41026185257695
Current RMSE: 0.410261785268
Current RMSE: 0.41026171957563
Current RMSE: 0.4102616554423
Current RMSE: 0.41026159281316
VPM написал: Nikolay, Вы уже не первый кто меня хочет в чем то уличить, а я даже не понимаю в чем?
Это не попытка в чем-то уличить. В среде разработчиков принято оставлять ссылки на исходный код автора. Также как и в цитировании научных трудов, да и просто цитировании. Да и зачем сюда помещать весь текст когда есть репозитарий автора с удобным просмотром кода. Если необходимо видоизменять код, сделайте fork репозитария и изменяйте.
Nikolay, Помещаю я сюда для удобства использования, код не большой полностью функционален, меня берут сильные сомнения, что по ссылке, кто куда то пойдет искать ошибку. Написан на луа 5.1, нужно убедиться на соответствие 5.4. А лишнее я убрал для экономии места, кому нужно всегда можно вернуться к исходникам (в моих все сохранено). Ваше замечание учту.
Сделал исправление
Код
function luann:getRMSE(predictions, expected)
assert(#predictions == #expected, "ERR: #predictions ~= #expected")
local numElements = 0
local sum = 0
for i=1, #predictions do
-- for each set of predictions
for j=1, #predictions[i] do
-- for each output node
numElements = numElements+1
sum = sum + (expected[i][j]-predictions[i][j])^2--math.pow(expected[i][j]-predictions[i][j],2)
end
end
local mse = sum/numElements
return mse^0.5--math.sqrt(mse)
end
Ну, не работает в этой версии обратное распределение, ошибка уменьшается нормально до 0.42, а при достижении менее 0.41 в разы увеличиваются вычислительные мощности. Не удалось дождаться 0.1 уже не говоря про 0.01. Почему так происходит не разобрался, не могу понять, вроде все верно с точки зрения вычислений? А как красиво модуль написан! Какой пассаж!
Интересная ситуация сложилась на рынке ПРИРОДНОГО ГАЗА (NG) , всю прошлую неделю даже раньше, шли мощные продажи, казалось что уже совсем на этих уровнях нет покупателей. И вот вчера 21.02.24г., в работе маркет - мейкер, во всей своей красе. С утра гэпом улучшает свою логовую позицию, разворачивает рынок в рост, мощное пробитие уровня 1.692, запирает "шортистов" на уровне 1.790, и целый день работает от этого диапазона видимо, разворачиваются и набирают лонговые позиции. А как вы хотели маркет - мейкера обижать! А что дальше? Я предполагаю откат в зону 1.750 и в рост. Ну вовсяком случае я в логе.
VPM написал: Ну, не работает в этой версии обратное распределение, ошибка уменьшается нормально до 0.42, а при достижении менее 0.41 в разы увеличиваются вычислительные мощности. Не удалось дождаться 0.1 уже не говоря про 0.01. Почему так происходит не разобрался, не могу понять, вроде все верно с точки зрения вычислений? А как красиво модуль написан! Какой пассаж!
А что вы хотите от простейшей сигмоидной функции. В тех же алгоритмах EM кластеризации, например Gaussian Mixture Model все намного точнее. Правда требуется подготовка данных и может долго производится подготовка модели. После расчета уже все быстрее - по входным данным находится кластер, размеченный тем или иным образом.
Nikolay, А что неужели нет методов улучшения обучения? Этих персептронов на писано на разных языках, и все годами ждут обучения? Ну если даже нет ошибки в luann2, то и решением это точно ни назовёшь, ответ через год это ни кому ненужный ответ, ну по крайней мере в нашей сфере.
luann1 меня конечно смущает, более привлекательно выглядит базовый пример с чего все началось (но сайт нынче не открывается, а Вы говорите ссылки, нужно у себя поискать, что имеем то храним)
Методы есть. Просто для каждой задачи необходимо выбирать корректный инструмент. Где-то регрессионный анализ, где-то кластеризация и т.д. В конечном итоге - задача оценить вероятности разных событий и уже на основе этого принимать решения.
Что касается ссылок, то всегда можно клонировать репозитарий локально.
VPM написал: Nikolay, А что неужели нет методов улучшения обучения? Этих персептронов на писано на разных языках, и все годами ждут обучения? Ну если даже нет ошибки в luann2, то и решением это точно ни назовёшь, ответ через год это ни кому ненужный ответ, ну по крайней мере в нашей сфере.
luann1 меня конечно смущает, более привлекательно выглядит базовый пример с чего все началось (но сайт нынче не открывается, а Вы говорите ссылки, нужно у себя поискать, что имеем то храним)
нейросеть подобна мясорубке. Если железо мощное как у гугла то и мясорубка мощная. На выходе всегда фарш, но из чего он ,зависит от продукта на входе. Если мясо -то мясной, говно, то и на выходе оно же.
От функции активации ничего практически не зависит. Зависит лишь от объема статистики на входе. Если в интернете набралось миллиарды фото и текста , то и удалось обучить GPT.
Ну что тут скажешь, быстро не получилось, а медленно и нам не нужно. Вернулся в тему, нечеткая логика, на мой взгляд может пригодиться нам, в определении стратегии, т.е. пытаемся определить каким методом предпочтительней в данный момент на данном инструменте торговать. Речь идет о краткосрочной торговле, торговле по тренду и флете, И вообще возможно ли алгоритмически условно делить рынок на сегменты?
VPM написал: Ну что тут скажешь, быстро не получилось, а медленно и нам не нужно. Вернулся в тему, нечеткая логика, на мой взгляд может пригодиться нам, в определении стратегии, т.е. пытаемся определить каким методом предпочтительней в данный момент на данном инструменте торговать. Речь идет о краткосрочной торговле, торговле по тренду и флете, И вообще возможно ли алгоритмически условно делить рынок на сегменты?
Полагаю, Вы немного не поняли эту логику. Она фактически определяет вариант булевой алгебры, когда вместо 1 используется значение от 0 до 1. ------------------ Я например использую бинарные нейронные сети, но и в них затык с оптимизацией (это булева алгебра). ----------------------------- Пока не встречал, чтобы кто-то реализовал бинарную сеть с нечеткими бинарными правилами. --------------------- Есть хорошо известная и давно успешно применяемая альтернатива нечеткой логике - это Байесовский метод принятия решений. --------------- Полагаю Вы о нем слышали. Можно начать с него. Это проще.
nikolz, Не понял, а что Вас не устраивает в LuaFuzzy простая библиотека, полностью написана на Lua, без всяких костылей, прекрасно работает на практике. Отвечает на вопрос о двойственности насколько объект принадлежит к то или иной области (например лингвистическая переменная тренд равна 0.65, а флет = 0.35 (в диапазоне 0/1) ну и торгуем тренд. Байесовский метод принятия решений не пользовался, если есть готовые библиотеки приведите, или хотя бы пример на луа. Про функции распределения вероятностей я уже трогал чуть - чуть вопрос. Разные способы нормировки приводят к различным PDF, а значить нужно строить стратегии с учетом этих функций. Классический пример это стохастик и RSI. Я выкладывал ссылку на небольшую статью John Ehlers, где он это прекрасно показал.
VPM написал: Интересная ситуация сложилась на рынке ПРИРОДНОГО ГАЗА (NG) , всю прошлую неделю даже раньше, шли мощные продажи, казалось что уже совсем на этих уровнях нет покупателей. И вот вчера 21.02.24г., в работе маркет - мейкер, во всей своей красе. С утра гэпом улучшает свою логовую позицию, разворачивает рынок в рост, мощное пробитие уровня 1.692, запирает "шортистов" на уровне 1.790, и целый день работает от этого диапазона видимо, разворачиваются и набирают лонговые позиции. А как вы хотели маркет - мейкера обижать!
Проведу ликбез небольшой, а то вы так далеко от реальности удалились, что читать больно: NG на МБ это расчетный контракт, цена исполнения которого привязана к значению расчетной цены соответствующего фьючерса Henry Hub Natural Gas Futures, которая определяется биржей NYMEX и публикуется на сайте CME Group. То есть это "зеркало" - цена на МБ ходит за ценой на CME. Оригинальный фьючерс торгуется круглосуточно, 20 февраля в 16-00 по Eastern Time, когда МБ не работает, вышел отчет известной газовой компании Chesapeake Energy Corporation. На этом отчете газ сильно вырос, естественно без всякого гэпа, просто за несколько свечей. Тут график посмотрите. NG на МБ с утра, естественно, открывается гэпом, так как он привязан. Вот и всё. пс. Забудьте вы про кукловодство маркет-мейкеров - это всё конспирология для недалёких.
Добавлю к предыдущему ликбезу. Маркет-мейкер (у него контракт с биржей на эту должность) никогда не наращивает позиции, так как это не его цель и за это ему не платят. Его задача как майкет-мейкера как раз обратная, чтобы рынок не двигался . Т е чтобы была малая волатильность и малый спред. ================== Позиции наращивают игроки и они двигают рынок.
Так как маркет-мейкер как правило крупный игрок, то он может быть и в роли такого игрока. -------------------- Не все крупные игроки являются маркет-мейкерами. =============== Т е если маркет-мейкер это такой игрок, которому за покупки-продажи акций платит биржа.
и еще.. Когда на рынок приходит крупный игрок, т е рынок начинает мощно двигаться, то маркет-мейкер перестает играть свою роль, а присоединяется к этому игроку т к на этом он заработает больше бабла чем если будет сдерживать рынок. Вот тогда рынок буквально улетает так как его никто не держит.
Игорь М, Спасибо, за отличный ликбез, сразу видно знание вопроса, прослеживается стройный, четкий анализ в установление причины для РАЗВОРОТА. Только что это отменяет?
1) Институт маркет - мейкера на ММВБ? 2) или маркет - мейкеру не нужно обеспечивать ликвидность на своем рынке? 3) а может не нужно следить за меж рыночным спредом (арбитраж)? 4) или он умеет, без финансовых вложений двигать цену?
Вы не понимая сами,
Цитата
для недалёких
описали только что автоматическую, высокочастотную торговлю "с поводырем". А причины определяемые, как триггер, бывают разные. Важно, что цену сильно опустили, и нужна была причина для разворота рынка. А я лишь указал на графике, где можно наблюдать классическую работу маркет - мейкера, я ее наблюдал на "ленте", увлекся, просто давненько не торговал такое сильное движение.
Просто к слову, торговля любым commoditie подразумевает анализ фундаментальных показателей, сезонности. Если задача - это элементарные краткосрочные спекуляции то да, можете торговать что угодно, выбирая любой метод принятия решений. Но даже в таком случае не удастся избежать элементарного понимая причин. Например, отрицательная цена на нефть в 2020 имела вполне себе логические причины. Надо было просто анализировать информацию о заключенных контрактах участников, не имеющих возможности произвести поставку, обработку физического товара, что приводит к закрытию позиций при экспирации. А если нет спроса, то об кого закрывать? ММ на товарном рынке не будет принимать такой контракт, т.к. что он будет делать с ним, где хранить. А прокси биржи, типа ММВБ, просто следуют за этим. При этом на ММВБ еще нет торговли ночью, что приводит к неприятным последствиям. Не учитывая все это и перенося позиции через ночь - это верх смелости. И жаловаться после всего этого на прокси, который, по сути, ни на что не влияет - это верх идиотизма.
Но куда более важный момент хочется обсудить вот он:
Цитата
VPM написал: Про функции распределения вероятностей я уже трогал чуть - чуть вопрос. Разные способы нормировки приводят к различным PDF, а значить нужно строить стратегии с учетом этих функций. Классический пример это стохастик и RSI. Я выкладывал ссылку на небольшую статью John Ehlers, где он это прекрасно показал.