Negative index caused by undeclared identifier in 'for' statement - for-loop

I'm trying to test my script, and I wanted to plot some of the variables I have on it. The problem is that everything that is being ploted before the 'for' statement works, but nothing comes to work beyond that. I made a test to plot the 'bar' variable, and when I do so, it pops an error: Undeclared identifier 'bar'. This happens when I try to plot the 'bar' variable.
The 'SwingIndex' variable contains the result that I finally want to plot in the indicator, but when I try to plot it, it comes an error on the indicator window that says 'Study Error Negative index -1'. Something is causing a problem somewhere inside the 'for' statement.
Personally, I see that since the 'bar' variable is not working (declared in line 39 of my code), nothing else is. But I don't know why is not working.
Can anyone help me to find where is my mistake? I'll leave the code down here.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TD_DaFen
//#version=5
// Indicator name
indicator("DAF_Swing_Index", shorttitle= 'DAF_SwInd', overlay=false)
// Input
T = input.int(30000, title = 'Ratio de escala', minval = 1000, maxval = 150000)
Shift = input.int(0, title = 'Desplazamiento horizontal', minval = 0, maxval = 100)
// Other variable
var float SwingIndex = 0
var int StartBars = 1
Prev_calculated = bar_index
Rates_total = bar_index + 1
var float SH1 = 0
var float SI = 0
var float R = 0
// Array
Open = array.new_float(Rates_total)
Open1 = array.new_float(Rates_total)
Close = array.new_float(Rates_total)
Close1 = array.new_float(Rates_total)
High = array.new_float(Rates_total)
Low = array.new_float(Rates_total)
// Initial bar verification
if Rates_total < StartBars
SwingIndex := 0
Primero = 1
if Prev_calculated > Rates_total or Prev_calculated <= 0
Primero := 1
else
Primero := Prev_calculated -1
// Main process
for bar= Primero to Rates_total-1
array.push(Open, high[bar])
array.push(Open1, open[bar-1])
array.push(Close, close[bar])
array.push(Close1, close[bar-1])
array.push(High, high[bar])
array.push(Low, low[bar])
K = math.max(math.abs(array.get(High, bar)- array.get(Close1, bar)), math.abs(array.get(Low, bar) - array.get(Close1, bar)))
TR = math.max(math.max(math.abs(array.get(High, bar) - array.get(Close1, bar)), math.abs(array.get(Low, bar) - array.get(Close1, bar))), math.abs(array.get(High, bar) - array.get(Low, bar)))
ER = 0.0
if array.get(Close1, bar) > array.get(High, bar)
ER := math.abs(array.get(High, bar) - array.get(Close1, bar))
if array.get(Close1, bar) < array.get(Low, bar)
ER := math.abs(array.get(Low, bar) - array.get(Close1, bar))
SH1 := math.abs(array.get(Close1, bar) - array.get(Open1, bar))
R := TR - 0.5 * ER + 0.25 * SH1
SI := 0.0
if R != 0
SI := 50 * ((array.get(Close, bar) - array.get(Close1, bar)) + 0.5 * (array.get(Close, bar) - array.get(Open1, bar))) * (K / T) / R
SwingIndex := SI
// ploting partial results to see if its working
plot(SwingIndex, title = 'Swing Index', style = plot.style_line, color = color.rgb(193, 150, 51, 10))

Your problem is in your for loop. Error message tells you that you are trying to access an element at negative index -1.
Following two array.push calls are causing the problem:
for bar= Primero to Rates_total-1
array.push(Open1, open[bar-1])
array.push(Close1, close[bar-1])
That is because at the second bar of the chart, Primero becomes zero, making your for loop start from zero (for bar = Primero). Then you subtract 1 from zero and therefore try to access an element at negative index -1.
How do we know that?
Remember your script will be executed for every bar. Let's analyze the following segments of your code for the very first and second bars.
Prev_calculated = bar_index
Rates_total = bar_index + 1
Primero = 1
if Prev_calculated > Rates_total or Prev_calculated <= 0
Primero := 1
else
Primero := Prev_calculated -1
Very first bar (bar_index = 0)
Prev_calculated = 0
Rates_total = 1
Primero = 1 (if branch -> Prev_calculated <= 0 is true)
Second bar (bar_index = 1)
Prev_calculated = 1
Rates_total = 2
Primero = 0 (else branch)
Also, this Prev_calculated > Rates_total check will always be false.

Related

barstate.islast invalidades series[1]

Original Question
Apparently, when using barstate.islast the values before zero in a series are not returned.
Is this the expected behavior? Or is it a problem?
//#version=5
indicator("barstate.islast invalidades series[1]", max_bars_back=5000)
index = bar_index
countNonNa(indices) =>
count = 0
for i = 0 to 4999 by 1
index = indices[i]
if not(na(index))
count += 1
count
count00 = countNonNa(index)
plot(count00, "count00", color = color.blue) // ok
count01 = barstate.isconfirmed ? countNonNa(index) : 0
plot(count01, "count01", color = color.black) // ok
count02 = barstate.islast ? countNonNa(index) : 0
plot(count02, "count02", color = color.red) // error expected 5000 in the last bar, but gets 1
You should execute your function on every bar, as stated in the console.
This will work:
//#version=5
indicator("barstate.islast invalidades series[1]", max_bars_back=5000)
index = bar_index
countNonNa(indices) =>
count = 0
for i = 0 to 4999 by 1
idx = indices[i]
if not(na(idx))
count += 1
count
c = countNonNa(index)
count00 = c
plot(count00, "count00", color = color.blue) // ok
count01 = barstate.isconfirmed ? c : 0
plot(count01, "count01", color = color.black) // ok
count02 = barstate.islast ? c : 0
plot(count02, "count02", color = color.red) // error expected 5000 in the last bar, but gets 1

How to draw a fan in Pine v5? Lines connecting open/close in a range?

Hello I'm new to pine and i have a question.
I would like to write a script that helps me drawing lines connecting the close of the first candle in a selected range and the close of every other candle in the range.
I think I have some problem understanding pine runtime because using for loops or conditional structures seems bad but I can't find a solution around this.
I tried with if but had no succes, the idea was that
after i select the start/end point, the code should be something like this:
if bar_index > bar_index[barStart] and bar_index < bar_index[barEnd]
line.new(bar_index[barStart], close[barStart], bar_index, close)
else na
After this I tried with a for loop, again with no success:
for i = bar_index[barStart]+1 to bar_index[barEnd]
line.new(bar_index[barStart], close[barStart], bar_index[i], close[i])
The code I use to select the range and count the candles inside it is this one:
//#version=5
indicator("Close", overlay=true)
// Range Start
t0 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
p0 = input.price(defval = 0, confirm = true)
// Range End
t1 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
p1 = input.price(defval = 0, confirm = true)
///////////////////////////////////////////////////////////////////////////////////
// Bar counting
t_bar(_t) =>
var int _bar = na
if time_close[1] <= _t and time >= _t
_bar := bar_index
_bar
start = int(t_bar(t0))
end = int(t_bar(t1))
//Counting bars in the selected range
barStart = bar_index - start
barEnd = bar_index - end
barDelta = end - start
//Print results
plot(barStart, "Range start")
plot(barEnd, "Range end")
plot(barDelta, "Candles in range")
But from here on I don't know how to proceed. This should be pretty easy but I'm stuck.
What I'm trying to draw
Thank you to anyone willing to help!!
You don't need the loop or the input price variables. The lines can be drawn bar by bar as the script's execution enters your time range and the price variables can also be obtained at the same time.
//#version=5
indicator("Close", overlay=true)
// Range Start
t0 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
// Range End
t1 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
///////////////////////////////////////////////////////////////////////////////////
first_bar = time >= t0 and time[1] < t0
in_range = time > t0 and time <= t1
post_bar = time > t1 and time[1] <= t1
var float start_close = na
var int start_index = na
if first_bar
start_close := close
start_index := bar_index
if in_range and not first_bar
line.new(x1 = start_index, y1 = start_close, x2 = bar_index, y2 = close)
if post_bar
num_bars = bar_index[1] - start_index
delta = close[1] - start_close
info_text = "Start Bar : " + str.tostring(start_index) + "\nEnd Bar : " + str.tostring(bar_index[1]) + "\nNumber of bars : " + str.tostring(num_bars) + "\nPrice delta : " + str.tostring(delta)
label.new(x = bar_index[1], y = high[1], style = label.style_label_lower_left, size = size.small, text = info_text)
Follow up question :
To draw the lines on a higher timeframe and have them "persist" once you move to a lower timeframe is a bit trickier. You will have to use an input to manually set the higher timeframe as the script has no way to determine the previous timeframe that it was applied to.
When you set t0 and t1 on the higher timeframe, the timestamp values will correspond to the opening time for those higher time frame bars. This isn't ideal as the lower timeframe candle that starts at this same time isn't the close value we are after.
By using request.security() we can then get the actual closing time of the higher timeframe bar which has the closing value we do want.
So we can use time to determine when we've started the correct higher time frame bars and then use time_close to determine when we are on the lower time frame bar that coincides with the higher timeframe close.
//#version=5
indicator("MTF Close", overlay=true)
// Range Start
t0 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
// Range End
t1 = input.time(timestamp("20 Jul 2021 00:00 +0300"), confirm = true)
///////////////////////////////////////////////////////////////////////////////////
tf = input.timeframe("240", title = "higher timeframe")
htf_close = request.security(syminfo.tickerid, tf, time_close)
is_htf_closing_bar = time_close == htf_close
new_htf = ta.change(time(tf)) != 0
var bool started_first_htf_bar = false
var float start_close = na
var int start_index = na
var bool started_last_htf_bar = false
if time >= t0 and time[1] < t0 and new_htf
started_first_htf_bar := true
else if new_htf
started_first_htf_bar := false
if started_first_htf_bar and is_htf_closing_bar and na(start_close)
start_close := close
start_index := bar_index
else if not started_first_htf_bar and is_htf_closing_bar and time > t0 and time < t1
line.new(x1 = start_index, y1 = start_close, x2 = bar_index, y2 = close)
if time >= t1 and time[1] < t1 and new_htf
started_last_htf_bar := true
else if new_htf
started_last_htf_bar := false
if started_last_htf_bar and is_htf_closing_bar
line.new(x1 = start_index, y1 = start_close, x2 = bar_index, y2 = close)
post_bar = new_htf and started_last_htf_bar[1]
if post_bar
num_bars = bar_index[1] - start_index
delta = close[1] - start_close
info_text = "Start Bar : " + str.tostring(start_index) + "\nEnd Bar : " + str.tostring(bar_index[1]) + "\nNumber of bars : " + str.tostring(num_bars) + "\nPrice delta : " + str.tostring(delta)
label.new(x = bar_index[1], y = high[1], style = label.style_label_lower_left, size = size.small, text = info_text)

Pine Script outputting weird for loop error

Everything works except for loop. It's been outputting weird error:
Script could not be translated from: for i = 1 to 10
study("RSI Below 25.3", overlay=true)
rsiValue = rsi(close, 14)
rsiValLow= rsi(low, 14)
x =low[1]
//for i = 1 to 10
// if x > low[i]
// x := low[i]
isDivergent = abs(x-low[0])/low[0]*100 < .05 and abs(x- rsiValLow[0])>=1.5
isRsiOS = rsiValue <= 25
//plot signals to chart
plotshape(isRsiOS, title="Oversold", location=location.belowbar, transp=0, style=shape.triangleup, text="Buy")
plotshape(isDivergent, title="Divergence", location=location.belowbar, transp=0, style=shape.triangleup, text= "Divergence" )
I have been working on this for a while but cannot figure out why it won't work. Can you help?
Thanks!
If you need to find the minimum value, then it is better to replace the loop with a function lowest.
//#version=4
study("Help (RSI Below 25.3)", overlay=true)
rsiValue = rsi(close, 14)
rsiValLow= rsi(low, 14)
//x = low[1]
// for i = 1 to 10
// if x > low[i]
// x := low[i]
x = lowest(low[1], 10) // to replace the cycle
isDivergent = abs(x-low[0])/low[0]*100 < .05 and abs(x- rsiValLow[0])>=1.5
isRsiOS = rsiValue <= 25
//plot signals to chart
plotshape(isRsiOS, title="Oversold", location=location.belowbar, transp=0, style=shape.triangleup, text="Buy")
plotshape(isDivergent, title="Divergence", location=location.belowbar, transp=0, style=shape.triangleup, text= "Divergence" )
//plot(x)
I was missing:
//#version=4
That's all and nothing else was the problem and there for it concludes this question

Unknown issue with image refinement process

As introduced in this work (code), the following code sould refine an image (i.e. a gray scale saliency map).
Refinement Function:
function sal = Refinement(y, dim)
th_2 = graythresh(y);
if dim == 1
sal = y;
sal(y<th_2) = 10*(y(y < th_2))/th_2 - 10;
sal(y>=th_2) = 10*(y(y >= th_2) - th_2)/(1-th_2);
sal = 1 ./ (1 + exp(-sal)) + y;
sal = normalization(sal, 0);
elseif dim == 2
[r, c] = size(y);
y_col = reshape(y,[1 r*c]);
sal_col = y_col;
sal_col(y_col<th_2) = 10*(y_col(y_col < th_2))/th_2 - 10;
sal_col(y_col>=th_2) = 10*(y_col(y_col >= th_2) - th_2)/(1-th_2);
sal_col = 1 ./ (1 + exp(-sal_col)) + y_col;
sal = reshape(sal_col, [r c]);
end
end
normalization function:
function matrix = normalization(mat, flag)
% INPUT :
% flag: 1 denotes that the mat is a 3-d matrix;
% 0 denotes that the mat is a matrix;
%
if flag ~= 0
dim = size(mat,3);
matrix = mat;
for i = 1:dim
matrix(:,:,i) = ( mat(:,:,i) - min(min(mat(:,:,i)))) / ( max(max(mat(:,:,i))) - min(min( mat(:,:,i))) + eps);
end
else
matrix = ( mat - min(min(mat)))/( max(max(mat)) - min(min(mat)) + eps);
end
However, after applying the function values of the image matrix will be changed, the result remains the same as the image before the refinement.
Is there a conceptual error with that or the implementation failed?
P.S. The input image (saliency map) for refinery is something like below. in the refined saliency map, the foreground (satrfish in this image) should stand out(becomes homogeneously white as possible) and the background noise should be removed (becomes homogenously black as possible):

SpriteKit for loop

Hi I'm trying to follow a tutorial on Ray Wenderlich site
[http://www.raywenderlich.com/76740/make-game-like-space-invaders-sprite-kit-and-swift-tutorial-part-1][1]
so I'm going thru the functions breaking it down so i can get an understanding of how it works I've commented out stuff which i think i understand but this bit has me stumped
thanks for looking
the for loop whats the var row = 1 at the beginning doing ?
I've only ever done for lops like
for Position in 0...9
{
// do something with Position ten times
}
then whats the % in if row %3 mean?
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
hers the rest of the code
func makeInvaderOfType(invaderType: InvaderType) -> (SKNode) // function passes in a enum of atype,btype,ctype and returns sknode
{
var invaderColor: SKColor// variable for the colour
switch(invaderType)// switch statment if we pass in atype we will get red
{
case .AType:
invaderColor = SKColor.redColor()
case .BType:
invaderColor = SKColor.greenColor()
case .CType:
invaderColor = SKColor.blueColor()
default:
invaderColor = SKColor.blueColor()
}
let invader = SKSpriteNode(color: invaderColor, size: kInvaderSize)//variable of a skspritenode with color from switch statement size from vairiabe kinvadersize
invader.name = kInvaderName // name is invader fron let kinvadername
return invader //return the spritenode with color size name
}
func setupInvaders()
{
let baseOrigin = CGPoint(x:size.width/3, y:180) // vairible to hold cgpoint screen size /3 width 180 height
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
{
invaderType = .BType
} else
{
invaderType = .CType
}
let invaderPositionY = CGFloat(row) * (kInvaderSize.height * 2) + baseOrigin.y// varible to hold cgfloat row ? think its the incriment of the for loop times 16 times 2 = 32 plus 180 first time is 212 then 244
/* so if ive got his rightthe sum goes row = 1 kinvadersize.hieght *2 = 32 + baseoringin.y = 180
1 * 32 +180 = 212
2 * 32 + 180 = 392 but its 244
*/
println(row)
var invaderPosition = CGPoint(x:baseOrigin.x, y:invaderPositionY) // varible to hold cgpoint
println(invaderPosition.y)
for var col = 1; col <= kInvaderColCount; col++
{
var invader = makeInvaderOfType(invaderType)// varible that runs function and return the spritenode with color size name????
invader.position = invaderPosition
addChild(invader)
invaderPosition = CGPoint(x: invaderPosition.x + kInvaderSize.width + kInvaderGridSpacing.width, y: invaderPositionY)
}
}
}
If I understand your question correctly, here's the answer. Based on this code:
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
The first line means:
var row = 1: given a new variable, row, with a value of 1
row <= kInvaderRowCount: as long as the variable row is less than or equal to kInvaderRowCount, keep running the for loop
row++: after each time the loop is run, increment (increase) the value of row by 1
As for the "%", that is the modulo operator. It returns the remainder after a division operation on integer values. So if 7 divided by 3 = 2, with a remainder of 1, then
7 / 3 = 2
7 % 3 = 1
The modulus operator results in an integer. While 1 / 3 = 0.33..., 1 % 3 = 1. Because the remainder of 1 divided by 3 is 1.
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
see also: How Does Modulus Divison Work.

Resources