function takes for example rsi and from declared for me historical bar 1 to 12 finds me maximum value ( integer or '00,0') of rsi.
//#version=5
indicator("loop", shorttitle="loop")
len = input.int(14, title="RSI Length")
src = input.source(close, "RSI Source")
Rsi = ta.rsi(src, len)
plot(Rsi*10, "RSI", color=#673ed8)
hline(65,linestyle= hline.style_dashed , color=color.new(color.red, 0))
minF = 1, maxF = 12, RsiFunction = Rsi
ff_loopMax(RsiFunction,minF, maxF) =>
var float Max = na
var float MaxOdpCena = na
var int MaxNrBar = na
for i=minF to maxF
if i == minF
Max := RsiFunction[i]
//MaxOdpCena := high[i]
//MaxNrBar := i
else
//MaxOdpCena := Max > RsiFunction[i] ? MaxOdpCena : high[i]
//MaxNrBar := Max > RsiFunction[i] ? MaxNrBar : i
Max := math.max(Max,RsiFunction[i])
// I want Max result from function
plot(Max, "rsiMax", color=#b63253)
Result = ff_loopMax(Rsi,5,15)
The code extracted from function should work alone. But I can't cope with function.
A function in pine script return the value of the last expression. In your case, the last expression is Max, but you can't access this directly. You call the function, and set this return to a variable.
You should change the last two lines to:
Result = ff_loopMax(Rsi,5,15) // Result is now equal to Max
plot(Result, "rsiMax", color=#b63253)
I run the following code, but Lua keeps giving me "attempt to call a nil value". When I change the _G[fi] to _G.fi it gives me "attempt to call a string value".
i = "0"
j = "0"
k = "0"
fi = "f"..i
fj = "f"..j
fk= "f"..k
functions = {
f1 = function(next, v)
for t = 1, 1, 4 do
v[t] = v[t] + 1
v[t] = v[t] % 3
end
if (next == "0") then return v
else return functions[next](0, v) end
end,
f2 = function(next, v)
for t = 1, 1, 4 do
v[t] = v[t] + 2
v[t] = v[t] % 3
end
if (next == "0") then return v
else return functions[next](0, v) end
end,
f3 = function(next, v)
if (next == "0") then return v
else return functions[next](0, v) end
end,
f4 = function(next, v)
swap(v[2], v[3])
if (next == "0") then return v
else return functions[next](0, v) end
end,
f5 = function(next, v)
swap(v[1], v[3])
if (next == "0") then return v
else return functions[next](0, v) end
end,
f6 = function(next, v)
swap(v[1], v[2])
if (next == "0") then return v
else return functions[next](0, v) end
end,
}
for i = 0, 1, 6 do
for j = 0, 1, 6 do
for k = 0, 1, 6 do
if _G[fi](fj, {1,2,0}) == _G[fj](fk, {1,2,0}) and not _G[fi](-1, {1,2,0}) == _G[fk](-1, {1,2,0}) then
print(i + " " + j + " " + k)
end
end
end
end
The problem is you set fi = "f"..i at the start, which sets fi == "f0", and that never changes for the rest of the program until you later invoke _G[fi]. The value of fi does not automatically change just because you changed the value of i.
You probably want to expand i (and j and k) at the call point, with something more like:
_G["f"..i]("f"..j, {1,2,0})... etc
I want to be able to plot a linear regression line(fixed interval straight trend line, not a continuous curve) from any two start and end price bars on a stock chart. Tradingview has a regression TREND tool that allows you to draw it on the chart, instead of entering the dates manually. This tool is easier, but I cant find the code for it, so a manual date entry box is also fine. I would like that regression trendline to appear on the chart, then state the standard error of each bar, making it easy to note the most extreme outliers. If possible, having r-squared added to this line as a readout would also be an excellent comparative tool (to help determine weakest r-squared). Lastly, I want some type of ANGLE measurement of the linear regression trendline; Angle of line, or Slope? Attached is tradingview's built-in Linear regression Channel indicator code as a starting point. Any help with this would be greatly appreciated. Thank you
```
//#version=5
indicator("Linear Regression Channel", shorttitle="LinReg", overlay=true)
lengthInput = input.int(100, title="Length", minval = 1, maxval = 5000)
sourceInput = input.source(close, title="Source")
group1 = "Channel Settings"
useUpperDevInput = input.bool(true, title="Upper Deviation", inline = "Upper Deviation", group = group1)
upperMultInput = input.float(2.0, title="", inline = "Upper Deviation", group = group1)
useLowerDevInput = input.bool(true, title="Lower Deviation", inline = "Lower Deviation", group = group1)
lowerMultInput = input.float(2.0, title="", inline = "Lower Deviation", group = group1)
group2 = "Display Settings"
showPearsonInput = input.bool(true, "Show Pearson's R", group = group2)
extendLeftInput = input.bool(false, "Extend Lines Left", group = group2)
extendRightInput = input.bool(true, "Extend Lines Right", group = group2)
extendStyle = switch
extendLeftInput and extendRightInput => extend.both
extendLeftInput => extend.left
extendRightInput => extend.right
=> extend.none
group3 = "Color Settings"
colorUpper = input.color(color.new(color.blue, 85), "", inline = group3, group = group3)
colorLower = input.color(color.new(color.red, 85), "", inline = group3, group = group3)
calcSlope(source, length) =>
max_bars_back(source, 5000)
if not barstate.islast or length <= 1
[float(na), float(na), float(na)]
else
sumX = 0.0
sumY = 0.0
sumXSqr = 0.0
sumXY = 0.0
for i = 0 to length - 1 by 1
val = source[i]
per = i + 1.0
sumX += per
sumY += val
sumXSqr += per * per
sumXY += val * per
slope = (length * sumXY - sumX * sumY) / (length * sumXSqr - sumX * sumX)
average = sumY / length
intercept = average - slope * sumX / length + slope
[slope, average, intercept]
[s, a, i] = calcSlope(sourceInput, lengthInput)
startPrice = i + s * (lengthInput - 1)
endPrice = i
var line baseLine = na
if na(baseLine) and not na(startPrice)
baseLine := line.new(bar_index - lengthInput + 1, startPrice, bar_index, endPrice, width=1, extend=extendStyle, color=color.new(colorLower, 0))
else
line.set_xy1(baseLine, bar_index - lengthInput + 1, startPrice)
line.set_xy2(baseLine, bar_index, endPrice)
na
calcDev(source, length, slope, average, intercept) =>
upDev = 0.0
dnDev = 0.0
stdDevAcc = 0.0
dsxx = 0.0
dsyy = 0.0
dsxy = 0.0
periods = length - 1
daY = intercept + slope * periods / 2
val = intercept
for j = 0 to periods by 1
price = high[j] - val
if price > upDev
upDev := price
price := val - low[j]
if price > dnDev
dnDev := price
price := source[j]
dxt = price - average
dyt = val - daY
price -= val
stdDevAcc += price * price
dsxx += dxt * dxt
dsyy += dyt * dyt
dsxy += dxt * dyt
val += slope
stdDev = math.sqrt(stdDevAcc / (periods == 0 ? 1 : periods))
pearsonR = dsxx == 0 or dsyy == 0 ? 0 : dsxy / math.sqrt(dsxx * dsyy)
[stdDev, pearsonR, upDev, dnDev]
[stdDev, pearsonR, upDev, dnDev] = calcDev(sourceInput, lengthInput, s, a, i)
upperStartPrice = startPrice + (useUpperDevInput ? upperMultInput * stdDev : upDev)
upperEndPrice = endPrice + (useUpperDevInput ? upperMultInput * stdDev : upDev)
var line upper = na
lowerStartPrice = startPrice + (useLowerDevInput ? -lowerMultInput * stdDev : -dnDev)
lowerEndPrice = endPrice + (useLowerDevInput ? -lowerMultInput * stdDev : -dnDev)
var line lower = na
if na(upper) and not na(upperStartPrice)
upper := line.new(bar_index - lengthInput + 1, upperStartPrice, bar_index, upperEndPrice, width=1, extend=extendStyle, color=color.new(colorUpper, 0))
else
line.set_xy1(upper, bar_index - lengthInput + 1, upperStartPrice)
line.set_xy2(upper, bar_index, upperEndPrice)
na
if na(lower) and not na(lowerStartPrice)
lower := line.new(bar_index - lengthInput + 1, lowerStartPrice, bar_index, lowerEndPrice, width=1, extend=extendStyle, color=color.new(colorUpper, 0))
else
line.set_xy1(lower, bar_index - lengthInput + 1, lowerStartPrice)
line.set_xy2(lower, bar_index, lowerEndPrice)
na
linefill.new(upper, baseLine, color = colorUpper)
linefill.new(baseLine, lower, color = colorLower)
// Pearson's R
var label r = na
label.delete(r[1])
if showPearsonInput and not na(pearsonR)
r := label.new(bar_index - lengthInput + 1, lowerStartPrice, str.tostring(pearsonR, "#.################"), color = color.new(color.white, 100), textcolor=color.new(colorUpper, 0), size=size.normal, style=label.style_label_up)
```
You can use the confirm = true argument with input.time() in order to manually click start and end points.
Since we have to render something like the individual errors historically, we have to use the label functions to do so. There is a 500 label limit, so if the regression contains more than 500 bars, then you will have to define "extreme outliers" in this context in order to limit outliers to 500 labelled bars or less.
//#version=5
indicator("point to point linreg", overlay = true, max_lines_count = 500, max_labels_count = 500)
start_time = input.time(timestamp("20 Jul 2022 00:00 +000"), title = "Start time", confirm = true)
end_time = input.time(timestamp("21 Jul 2022 00:00 +000"), title = "End time", confirm = true)
src = input.source(close, title = "Source")
devmult = input.float(1.000, title = "Dev mult")
reg_line_col = input.color(color.blue, title = "Reg line color")
up_line_col = input.color(color.green, title = "Upper Dev line color")
dn_line_col = input.color(color.red, title = "Lower Dev line color")
reg_line_width = input.int(2, title = "Line width")
f_linreg_from_arrays(_x_array, _y_array) =>
_size_x = array.size(_x_array)
_size_y = array.size(_y_array)
float _sum_x = array.sum(_x_array)
float _sum_y = array.sum(_y_array)
float _sum_xy = 0.0
float _sum_x2 = 0.0
float _sum_y2 = 0.0
if _size_y == _size_x
for _i = 0 to _size_y - 1
float _x_i = nz(array.get(_x_array, _i))
float _y_i = nz(array.get(_y_array, _i))
_sum_xy := _sum_xy + _x_i * _y_i
_sum_x2 := _sum_x2 + math.pow(_x_i, 2)
_sum_y2 := _sum_y2 + math.pow(_y_i, 2)
_sum_y2
float _a = (_sum_y * _sum_x2 - _sum_x * _sum_xy) / (_size_x * _sum_x2 - math.pow(_sum_x, 2))
float _b = (_size_x * _sum_xy - _sum_x * _sum_y) / (_size_x * _sum_x2 - math.pow(_sum_x, 2))
float[] _f = array.new_float()
for _i = 0 to _size_y - 1
float _vector = _a + _b * array.get(_x_array, _i)
array.push(_f, _vector)
_slope = (array.get(_f, 0) - array.get(_f, _size_y - 1)) / (array.get(_x_array, 0) - array.get(_x_array, _size_x - 1))
_y_mean = array.avg(_y_array)
float _SS_res = 0.0
float _SS_tot = 0.0
for _i = 0 to _size_y - 1
float _f_i = array.get(_f, _i)
float _y_i = array.get(_y_array, _i)
_SS_res := _SS_res + math.pow(_f_i - _y_i, 2)
_SS_tot := _SS_tot + math.pow(_y_mean - _y_i, 2)
_SS_tot
_r_sq = 1 - _SS_res / _SS_tot
float _sq_err_sum = 0
for _i = 0 to _size_y - 1
_sq_err_sum += math.pow(array.get(_f, _i) - array.get(_y_array, _i), 2)
_dev = math.sqrt(_sq_err_sum / _size_y)
[_f, _slope, _r_sq, _dev]
var int[] time_vals = array.new_int()
var float[] price_vals = array.new_float()
var line[] reg_lines = array.new_line()
var line[] up_lines = array.new_line()
var line[] dn_lines = array.new_line()
var label reg_label = label.new(x = na, y = na, xloc = xloc.bar_time, style = label.style_label_upper_left, textcolor = color.white, textalign = text.align_left)
is_last_bar = time >= end_time and time[1] < end_time
is_in_time_range = time >= start_time and time <= end_time
if is_in_time_range
array.unshift(time_vals, time)
array.unshift(price_vals, src)
if barstate.isfirst
for i = 0 to 165
array.push(reg_lines, line.new(x1 = na, y1 = na, x2 = na, y2 = na, xloc = xloc.bar_time, color = reg_line_col, width = reg_line_width))
array.push(up_lines, line.new(x1 = na, y1 = na, x2 = na, y2 = na, xloc = xloc.bar_time, color = up_line_col, width = reg_line_width))
array.push(dn_lines, line.new(x1 = na, y1 = na, x2 = na, y2 = na, xloc = xloc.bar_time, color = dn_line_col, width = reg_line_width))
if is_last_bar
[f, slope, r_sq, dev] = f_linreg_from_arrays(time_vals, price_vals)
size = array.size(time_vals)
if size > 0
if size <= 167
for i = 0 to size - 2
start_x = array.get(time_vals, i)
start_y = array.get(f, i)
end_x = array.get(time_vals, i + 1)
end_y = array.get(f, i + 1)
reg_line = array.get(reg_lines, i)
up_line = array.get(up_lines, i)
dn_line = array.get(dn_lines, i)
line.set_xy1(reg_line, x = start_x, y = start_y)
line.set_xy2(reg_line, x = end_x, y = end_y)
else
interval = math.ceil(size / 166)
line_index = 0
for i = 0 to size - math.floor(interval / 2) - 2 by interval
index2 = i + math.floor(interval / 2)
start_x = array.get(time_vals, i)
start_y = array.get(f, i)
end_x = array.get(time_vals, index2)
end_y = array.get(f, index2)
reg_line = array.get(reg_lines, line_index)
up_line = array.get(up_lines, line_index)
dn_line = array.get(dn_lines, line_index)
line.set_xy1(reg_line, x = start_x, y = start_y)
line.set_xy2(reg_line, x = end_x, y = end_y)
line.set_xy1(up_line, x = start_x, y = start_y + devmult * dev)
line.set_xy2(up_line, x = end_x, y = end_y + devmult * dev)
line.set_xy1(dn_line, x = start_x, y = start_y - devmult * dev)
line.set_xy2(dn_line, x = end_x, y = end_y - devmult * dev)
line_index += 1
reg_info = "Slope : " + str.tostring(slope) + "\nR² : " + str.tostring(r_sq) + "\ndev : " + str.tostring(dev)
label_x = array.get(time_vals, 0)
label_y = array.get(f, 0) - devmult * dev
label.set_xy(reg_label, x = label_x, y = label_y)
label.set_text(reg_label, text = reg_info)```
I'm making an indicator that plots the last 5 candles of each user-selected timeframe. Everything else is working (i think lol) besides my scaling/normalize function (it's messing up the wicks/high and low values) and my _lastDiffValue function.
I'm trying to create a function (_lastDiffValue) that runs a while loop and returns a specific integer for a history reference. The integer would be how many times the while loop ran. This way I can find the history reference for a specific condition. The reason I'm trying to do this is because the series I am working with has a lot of repetitive values and I want to find the last different value and assign it to a variable. This is one piece of a very involved indicator (at least for my experience lol).
Here's the code:
// © pipjitsu
//#version=5
indicator("Multi-TF Candles", overlay = false, explicit_plot_zorder = true)
group1 = "Timeframes"
bull_col = input.color(color.blue, "Bullish")
bear_col = input.color(color.new(color.red, 0), "Bearish")
wick_color = input.color(#000000, "Wick Color")
lookback = input.int(6, "Candles per Timeframe")
space = 3
tf1 = input.timeframe("1D", title = "", inline = "Column 1", group = group1)
tf2 = input.timeframe("240", title = "", inline = "Column 1", group = group1)
tf3 = input.timeframe("60", title = "", inline = "Column 1", group = group1)
tf4 = input.timeframe("15", title = "", inline = "Column 1", group = group1)
tf5 = input.timeframe("5", title = "", inline = "Column 1", group = group1)
tf6 = input.timeframe("1", title = "", inline = "Column 1", group = group1)
_makeCandle(_open, _high, _low, _close, _group) =>
if barstate.islast
for i = 1 to lookback
_bias = _close[i] > _open[i] ? bull_col : bear_col
_shift = (i * space) + ((_group - 1) * (space * lookback + 4))
line1 = line.new(bar_index - _shift, _high[i], bar_index - _shift, _low[i], color = wick_color)
line.delete(line1[1])
box1 = box.new((bar_index - 1) - _shift, _open[i], (bar_index + 1) - _shift, _close[i], bgcolor = _bias, border_color = color.black)
box.delete(box1[1])
_lastDiffVal(_val) =>
var float _newVal = _val + 1
var int counter = na
while _val == _newVal
counter := counter + 1
_newVal := _val[counter]
counter
_normalize(_src) =>
_min = 0
_max = 100
var _historicMin = 10e10
var _historicMax = -10e10
_historicMin := math.min(nz(_src, _historicMin), _historicMin)
_historicMax := math.max(nz(_src, _historicMax), _historicMax)
_min + (_max - _min) * (_src - _historicMin) / math.max(_historicMax - _historicMin, 10e-10)
_getData(_tf) =>
[_open, _high, _low, _close] = request.security("", _tf, [open[_lastDiffVal(open)], high[_lastDiffVal(high)], low[_lastDiffVal(low)], close[_lastDiffVal(close)]])
_open := _normalize(_open)
_high := _normalize(_high)
_low := _normalize(_low)
_close := _normalize(_close)
[_open, _high, _low, _close]
_masterFun(_tf, _group) =>
[_open, _high, _low, _close] = _getData(_tf)
_makeCandle(_open, _high, _low, _close, _group)
_masterFun(tf1, 1)
_masterFun(tf2, 2)
_masterFun(tf3, 3)
_masterFun(tf4, 4)
_masterFun(tf5, 5)
_masterFun(tf6, 6)