I do not know how to make this example shorter so here is the full code so you can replicate.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AVAndronov
//@version=5
indicator("Tradingview TF Bug", overlay = true)
// 1. Two values, one will be assigned when condition is true, one when condition is false
pivLenTrue = input.int(3, "pivLenTrue", minval = 0)
pivLenFalse = input.int(1, "pivLenFalse", minval = 0)
// 2. Four booleans, one for each case
curTFLessD = timeframe.in_seconds() < timeframe.in_seconds("1D") //shape.cross
curTFLessW = timeframe.in_seconds() < timeframe.in_seconds("1W") //shape.label
curTFEqual4H = timeframe.in_seconds() == timeframe.in_seconds("240") //shape.xcross
curTFEqualD = timeframe.in_seconds() == timeframe.in_seconds("1D") //shape.diamond
// 3. One default pivot length and four based on booleans
pivPer = pivLenTrue
pivcurTFLessD = curTFLessD ? pivLenTrue : pivLenFalse
pivcurTFLessW = curTFLessW ? pivLenTrue : pivLenFalse
pivcurTFEqual4H = curTFEqual4H ? pivLenTrue : pivLenFalse
pivcurTFEqualD = curTFEqualD ? pivLenTrue : pivLenFalse
// 4. Label to demonstrate results
if (bar_index == 0)
label.new(0,0,"[ <D ] [ <W ] [ =4H ] [ =D ]\n"+
str.tostring(curTFLessD) + " "+str.tostring(curTFLessW) + " "+str.tostring(curTFEqual4H) + " "+str.tostring(curTFEqualD)+"\n"+
str.tostring(pivcurTFLessD) + " "+str.tostring(pivcurTFLessW) + " "+str.tostring(pivcurTFEqual4H) + " "+str.tostring(pivcurTFEqualD)+"\n"+
"+ \\/ X ⯁", yloc=yloc.abovebar)
// 5. Getting security
[hHigh,hLow,pivotH,pivotL,pivotHLD,pivotLLD,pivotHLW,pivotLLW,pivotHE4H,pivotLE4H,pivotHED,pivotLED] = request.security(syminfo.tickerid, timeframe.in_seconds() == timeframe.in_seconds("240") ? "1D" : "1W",
[high[1+pivPer], low[1+pivPer],
ta.pivothigh(pivPer, pivPer)[1], ta.pivotlow(pivPer, pivPer)[1],
ta.pivothigh(pivcurTFLessD, pivcurTFLessD)[1], ta.pivotlow(pivcurTFLessD, pivcurTFLessD)[1],
ta.pivothigh(pivcurTFLessW, pivcurTFLessW)[1], ta.pivotlow(pivcurTFLessW, pivcurTFLessW)[1],
ta.pivothigh(pivcurTFEqual4H, pivcurTFEqual4H)[1], ta.pivotlow(pivcurTFEqual4H, pivcurTFEqual4H)[1],
ta.pivothigh(pivcurTFEqualD, pivcurTFEqualD)[1], ta.pivotlow(pivcurTFEqualD, pivcurTFEqualD)[1]], gaps = barmerge.gaps_on, lookahead = barmerge.lookahead_on)
// 6. Output
plot(hHigh, linewidth = 1)
plot(hLow, linewidth = 1)
plotshape(pivotH, location = location.absolute, style = shape.circle, size = size.normal)
plotshape(pivotL, location = location.absolute, style = shape.circle, size = size.normal)
plotshape(pivotHLD, location = location.absolute, style = shape.cross, size = size.normal, color = color.green)
plotshape(pivotLLD, location = location.absolute, style = shape.cross, size = size.normal, color = color.green)
plotshape(pivotHLW, location = location.absolute, style = shape.labeldown, size = size.normal, color = color.red)
plotshape(pivotLLW, location = location.absolute, style = shape.labeldown, size = size.normal, color = color.red)
plotshape(pivotHE4H, location = location.absolute, style = shape.xcross, size = size.normal, color = color.green)
plotshape(pivotLE4H, location = location.absolute, style = shape.xcross, size = size.normal, color = color.green)
plotshape(pivotHED, location = location.absolute, style = shape.diamond, size = size.small, color = color.green)
plotshape(pivotLED, location = location.absolute, style = shape.diamond, size = size.small, color = color.green)
So I've spent ages trying to find a bug in my 2000 line code and eventually I figured out that for some reason, timeframe.in_seconds() is giving DIFFERENT values to different functions. I have reduced my code to absolute minimum to reproduce this bug.
Okay so what's going on here?
I am defining two inputs. Two values that are going to be used for ta.pivot function later. We call them TRUE and FALSE.
Now I define four booleans. Whether timeframe.in_seconds(), which supposedly is current chart's timeframe, is lesser than 1D, less than 1W, equal to 4H, or equal to 1D. I am going to run this on 4H timeframe, so it should be TRUE, TRUE, TRUE, FALSE in that case.
Now I calculate four pivot lengths based on these 3 booleans. Naturally, first three should be equal to TRUE one (3 in my example), and last to FALSE one (1 in my example)
Now I output these values in a label so we can confirm everything works correct. For Less than Day, Less than 1W, equal to 4H, boolean is true, pivot length is For equal to 1D, false, and pivot length is 1.
Now I do request.security and request high, low, one pair of ta.pivot functions for comparison sake, and four pairs of ta.pivot functions, one for each boolean-dependant pivot length. I do [1] to have consistent values with lookahead_on.
Now I plot everything. Here, "Less than 1D" plots as + cross, "Less than 1W" plots as a label, "Equal to 4H" plots as X cross, and "Equal to 1D" plots as diamond.
So we should expect all values except one to match with our compare-to value! And one to stand out!
Run this on any 4H timeframe chart. You will get a result like this https://postimg.cc/5YqCZwcN where green ⯁diamond and red / label will match with blue circle, but X and + will not.
What this means is X and + are false, while /label and ⯁diamond is true
What this means is timeframe is not less than day, is less than 1W, is not equal to 4h, but equal to 1D!!!!!
So request.security function is using DIFFERENT values than everything else in the script. More than that, it is using it stealthily, because NOTHING can help determine that. Like, I tried "var"ing, meaning, variable is initialised only once - doesn't help! Nothing helps! Whole script thinks properly except that one where it's inside the request.security!
What the hell?.... What do I do if I want to involve current timeframe in calculation before I call it?...
By the way, notice the comparison inside the request.security. IT WORKS THERE! WTF?! ?
request.security(syminfo.tickerid, timeframe.in_seconds() == timeframe.in_seconds("240") ? "1D" : "1W",
As evident, it correctly compares to 240 and gets data for 1d. So here it works. But before it doesnt!?.....
EDIT: Improved example to make it even more obvious