Settings= { Name = "AT-obl_can", -- название индикатора delta=2.0, -- параметр индикатора rep=5, shif=0, wt=1, line= { { Name = "ln1", Type =TYPE_LINE, Width = 2, Color = RGB(255, 0, 0) }, { Name = "ln2", Type =TYPE_LINE, Width = 2, Color = RGB(255, 0, 0) } } } function Init() vMin = 0 vMax = 0 vMinindex = 0 vMaxindex = 0 voldMinindex = 0 voldMaxindex = 0 return 2 end function OnCalculate(index) rep = Settings.rep shif = Settings.shif wt = Settings.wt sz = Size()-shif if index <= sz then if index <= 1 then vMin = C(index) vMax = C(index) vMinindex = index vMaxindex = index voldMinindex = index voldMaxindex = index v = C(index) else if voldMaxindex >= voldMinindex then --if vMin~=nil then if C(index) > (1 + Settings.delta/100)*vMin then vMin = C(index) vMax = C(index) vMaxindex = index voldMinindex = vMinindex vFrom = vMinindex else if vMin > C(index) then vMin = C(index) vMinindex = index vFrom = voldMaxindex else vFrom = vMinindex end end --end else if voldMaxindex <= voldMinindex then --if vMax~=nil then if C(index) < (1 - Settings.delta/100)*vMax then vMax = C(index) vMin = C(index) vMinindex = index voldMaxindex = vMaxindex vFrom = vMaxindex else if vMax < C(index) then vMax = C(index) vMaxindex = index vFrom = voldMinindex else vFrom = vMaxindex end end --end end end --if vFrom~=nil then --[[ for i = vFrom, index do k = (C(index)- C(vFrom))/(index- vFrom); v = i*k + C(index) - index*k SetValue(i, 1, v) end --]] --end if index == sz then for k = 1, 2 do vf = 1 vs = 0 if k == 1 then if vMinindex < vMaxindex then vf = vMinindex vs = vMaxindex up = 0 elseif vMinindex > vMaxindex then vs = vMinindex vf = vMaxindex up = 1 end elseif k == 2 then if voldMinindex < voldMaxindex then vf = voldMinindex vs = voldMaxindex up = 0 elseif voldMinindex > voldMaxindex then vs = voldMinindex vf = voldMaxindex up = 1 end end n = 0 xy = 0 x = 0 y = 0 xx = 0 m = 0 for i = vf, vs do m = m +1 n = n + 1*(1+wt*m) xy = xy + i*C(i)*(1+wt*m) x = x + i*(1+wt*m) y = y + C(i)*(1+wt*m) xx = xx + i*i*(1+wt*m) end if (n*xx - x*x) ~= 0 and n ~= 0 then a = (n*xy - x*y)/(n*xx - x*x) b = (y - a*x)/n for j = 1, rep do n = 0 xy = 0 x = 0 y = 0 xx = 0 m = 0 for i = vf, vs do v = a*i + b clc = 0 if up == 1 and C(i) > v then clc = 1 end if up == 0 and C(i) < v then clc = 1 end if clc == 1 then m = m + 1 n = n + 1*(1+wt*m) xy = xy + i*C(i)*(1+wt*m) x = x + i*(1+wt*m) y = y + C(i)*(1+wt*m) xx = xx + i*i*(1+wt*m) end end --[[--]] if (n*xx - x*x) ~= 0 and n ~= 0 and n > 2 then a = (n*xy - x*y)/(n*xx - x*x) b = (y - a*x)/n --[[ --]] end end for i = vf, sz do v = a*i + b if up == 1 and v >= C(vs) or up == 0 and v <= C(vs) then SetValue(i, k, v) end end end end end end end end
Бывает очень полезно искать локальные экстремумы. С точки зрения математического моделирования на ценовых рядах, это не такая тривиальная задача. Я пробовал разные методы, и на удивление, весьма неплохими оказались достаточно известные всем — фракталы Вильямса. Те самые которые ищут максимум или минимум цен среди N+1 значений по простому условию –центральное из них было выше, или ниже тех, которое идут до неё, и после. Особенно хорошо фракталам удается находить такие экстремумы на больших временных интервалах и с большим количеством N (График 1, Фаркталы Вильямса N=30 Days)
Однако, самый большой недостаток фракталов Вильямса, это скорость их появления. То есть существенное запаздывание появление, что делает их абсолютно непригодным с точки зрения проведения хоть каких-нибудь значимых динамических исследований. Они прекрасно отображают историю, но и только. Думаю, я не ошибусь, если скажу, что и в ТА его редко используют. Помнится в 2017 году мы с другом написали робота, который должен был торговать от уровней, которые показывал последний известный фрактал (График 2. Пример построения фрактального уровня).
--[[ AutoTrade target indicator shows target growth/fall varsion 3 line gr shows real growth line tgr_up shows target growth line tgr_dwn shows target fall line ln_up shows target growth history line ln_dwn shows target fall history --]] Settings= { Name = "AT-target_v3", -- indicator name per=20, -- period growth=1.0, -- growth by % fall=1.0, -- fall by % xshift=0, -- shifth by x axis showln=1, -- 1-show lines 0-do not show line= { { Name = "gr", Type =TYPE_LINE, Width = 1, Color = RGB(0,0,0) -- black }, { Name = "tgr_up", Type =TYPE_LINE, Width = 1, Color = RGB(0,0,255) -- blue }, { Name = "tgr_dwn", Type =TYPE_LINE, Width = 1, Color = RGB(255,0,0) -- red }, { Name = "ln_up", Type =TYPE_LINE, Width = 1, Color = RGB(0,0,255) -- blue }, { Name = "ln_dwn", Type =TYPE_LINE, Width = 1, Color = RGB(255,0,0) -- red } } } function Init() return 5 end function OnCalculate(index) sz = Size() per = Settings.per gr = Settings.growth fl = Settings.growth sh = Settings.xshift sl = Settings.showln if index == sz then for i = 1, sz do -- crearing SetValue(i, 1, nil) SetValue(i, 2, nil) SetValue(i, 3, nil) SetValue(i, 4, nil) SetValue(i, 5, nil) end for i = sz-per-sh, sz-sh do -- paint line v = (C(sz-sh) - C(sz-per-sh+1))*(i-(sz-per-sh+1))/per + C(sz-per-sh+1) v2 = (C(sz-per-sh+1)*(1+gr/100) - C(sz-per-sh+1))*(i-(sz-per-sh+1))/per + C(sz-per-sh+1) v3 = -(C(sz-per-sh+1)*(1+fl/100) - C(sz-per-sh+1))*(i-(sz-per-sh+1))/per + C(sz-per-sh+1) SetValue(i, 1, v) SetValue(i, 2, v2) SetValue(i, 3, v3) end if sl == 1 then for i = per, sz-sh do -- paint line v4 = (C(i-per+1)*(1+gr/100) - C(i-per+1)) + C(i-per+1) v5 = -(C(i-per+1)*(1+fl/100) - C(i-per+1)) + C(i-per+1) SetValue(i, 4, v4) SetValue(i, 5, v5) end end -- last value if sh == 0 then return v, v2, v3, v4, v5 end end end