pine script - How can I reliably access timeseries values in user-defined functions? - Stack Overflow

admin2025-04-17  3

Can someone help me understand the current pine script behavior with my custom indicator? I declare what I believe is a normal timeseries global variable "a" to store the closing price. Yet if I try to access this value from a user-defined function, past values are not correct if the user-defined function is not called on every single bar. THe value of the built-in "close" variable works correctly though. How can I declare a variable to behave like the built-in ones? (i.e. to reliably return past values even if the user-defined function is executed inside a conditional statement)

Here is my code:

//@version=6
indicator("My script")
plot(close)

float a = close

f() =>
    log.info("f: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], a[1], close[1])

g() => 
    log.info("g: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], a[1], close[1])

f()
if bar_index % 2 == 0
    g()

here is the outcome:

[2025-01-30T21:00:00.000-05:00]: f: barIndex=23,682, a[0]=2,848.4, close[0]=2,848.4, a[1]=2,849.3, close[1]=2,849.3
[2025-01-30T21:00:00.000-05:00]: g: barIndex=23,682, a[0]=2,848.4, close[0]=2,848.4, a[1]=2,852.6, close[1]=2,849.3
[2025-01-30T22:00:00.000-05:00]: f: barIndex=23,683, a[0]=2,851.2, close[0]=2,851.2, a[1]=2,848.4, close[1]=2,848.4
[2025-01-30T23:00:00.000-05:00]: f: barIndex=23,684, a[0]=2,848.9, close[0]=2,848.9, a[1]=2,851.2, close[1]=2,851.2
[2025-01-30T23:00:00.000-05:00]: g: barIndex=23,684, a[0]=2,848.9, close[0]=2,848.9, a[1]=2,848.4, close[1]=2,851.2
[2025-01-31T00:00:00.000-05:00]: f: barIndex=23,685, a[0]=2,847.1, close[0]=2,847.1, a[1]=2,848.9, close[1]=2,848.9
[2025-01-31T01:00:00.000-05:00]: f: barIndex=23,686, a[0]=2,845.8, close[0]=2,845.8, a[1]=2,847.1, close[1]=2,847.1
[2025-01-31T01:00:00.000-05:00]: g: barIndex=23,686, a[0]=2,845.8, close[0]=2,845.8, a[1]=2,848.9, close[1]=2,847.1
[2025-01-31T02:00:00.000-05:00]: f: barIndex=23,687, a[0]=2,849.8, close[0]=2,849.8, a[1]=2,845.8, close[1]=2,845.8
[2025-01-31T03:00:00.000-05:00]: f: barIndex=23,688, a[0]=2,844.9, close[0]=2,844.9, a[1]=2,849.8, close[1]=2,849.8
[2025-01-31T03:00:00.000-05:00]: g: barIndex=23,688, a[0]=2,844.9, close[0]=2,844.9, a[1]=2,845.8, close[1]=2,849.8

I would expect a[1] to be the same as close[1] in both f() and g() calls since variable "a" is a global variable (and not a local one).

Can someone help me understand the current pine script behavior with my custom indicator? I declare what I believe is a normal timeseries global variable "a" to store the closing price. Yet if I try to access this value from a user-defined function, past values are not correct if the user-defined function is not called on every single bar. THe value of the built-in "close" variable works correctly though. How can I declare a variable to behave like the built-in ones? (i.e. to reliably return past values even if the user-defined function is executed inside a conditional statement)

Here is my code:

//@version=6
indicator("My script")
plot(close)

float a = close

f() =>
    log.info("f: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], a[1], close[1])

g() => 
    log.info("g: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], a[1], close[1])

f()
if bar_index % 2 == 0
    g()

here is the outcome:

[2025-01-30T21:00:00.000-05:00]: f: barIndex=23,682, a[0]=2,848.4, close[0]=2,848.4, a[1]=2,849.3, close[1]=2,849.3
[2025-01-30T21:00:00.000-05:00]: g: barIndex=23,682, a[0]=2,848.4, close[0]=2,848.4, a[1]=2,852.6, close[1]=2,849.3
[2025-01-30T22:00:00.000-05:00]: f: barIndex=23,683, a[0]=2,851.2, close[0]=2,851.2, a[1]=2,848.4, close[1]=2,848.4
[2025-01-30T23:00:00.000-05:00]: f: barIndex=23,684, a[0]=2,848.9, close[0]=2,848.9, a[1]=2,851.2, close[1]=2,851.2
[2025-01-30T23:00:00.000-05:00]: g: barIndex=23,684, a[0]=2,848.9, close[0]=2,848.9, a[1]=2,848.4, close[1]=2,851.2
[2025-01-31T00:00:00.000-05:00]: f: barIndex=23,685, a[0]=2,847.1, close[0]=2,847.1, a[1]=2,848.9, close[1]=2,848.9
[2025-01-31T01:00:00.000-05:00]: f: barIndex=23,686, a[0]=2,845.8, close[0]=2,845.8, a[1]=2,847.1, close[1]=2,847.1
[2025-01-31T01:00:00.000-05:00]: g: barIndex=23,686, a[0]=2,845.8, close[0]=2,845.8, a[1]=2,848.9, close[1]=2,847.1
[2025-01-31T02:00:00.000-05:00]: f: barIndex=23,687, a[0]=2,849.8, close[0]=2,849.8, a[1]=2,845.8, close[1]=2,845.8
[2025-01-31T03:00:00.000-05:00]: f: barIndex=23,688, a[0]=2,844.9, close[0]=2,844.9, a[1]=2,849.8, close[1]=2,849.8
[2025-01-31T03:00:00.000-05:00]: g: barIndex=23,688, a[0]=2,844.9, close[0]=2,844.9, a[1]=2,845.8, close[1]=2,849.8

I would expect a[1] to be the same as close[1] in both f() and g() calls since variable "a" is a global variable (and not a local one).

Share Improve this question edited Feb 6 at 22:23 isherwood 61.2k16 gold badges121 silver badges170 bronze badges asked Jan 31 at 19:30 user2282460user2282460 112 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Interesting question, did some research on it. The way how PineScipt handles historical data can introduce weird results, as you have experienced. The solution lies within the execution model of PineScript.

As the docs says:

The result of function calls on successive bars leaves a succession of values in a time series that scripts can reference using the [] history-referencing operator.

This means, that if you execute g() on every second bar, it will record half the amount of historical data then f(), since it executes half the time. More on that here. With the built-in variables (like close, open, ohlc4, etc) this is not a problem, since they are implemented in a way, such a problems cannot arise.

Luckily, there is a workaround. You have to evaluate a[1] globally, then use that value locally. Just like this:

//@version=6
indicator("My script")
plot(close)

float a = close
aBefore = a[1]

f() =>
    log.info("f: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], a[1], close[1])

g() => 
    log.info("g: barIndex={0}, a[0]={1}, close[0]={2}, a[1]={3}, close[1]={4}", bar_index, a[0], close[0], aBefore, close[1])

f()
if bar_index % 2 == 0
    g()

Notice the aBefore = a[1] line. This will be calculated on every bar, and you can use the value in your function - g() -. A similar problem is presented on the linked docs site.

转载请注明原文地址:http://anycun.com/QandA/1744849499a88482.html