Lesson 5: Values that remember
Read earlier bars with [n], keep a value from bar to bar with state, restart it every day, and count the bars since something happened.
Lesson 5 of 18. A script runs once for every bar, from the top of the file to the bottom, and forgets what it worked out when the bar ends. This lesson shows the two ways a script remembers: reading the history of a value, and keeping a value with state.
Earlier bars#
close[1] is the close of the bar before, close[5] the close five bars back. Any name works the same way, also one you made yourself.
indicator "Change over a few bars"
edition = 1
display = pane
input back: int = 5, name = "Bars back", min = 1, max = 100
let change = close - close[back]
plot(
change,
name = "Change",
style = histogram,
color = if change >= 0 then color.green else color.red,
)
level(0, name = "Zero", color = color.gray)On the first back bars there is no bar that far back, so close[back] is na (no value), the change is na too, and nothing is drawn there. The input has a max: the engine wants to know how far back a script can read.
A value kept from bar to bar#
A name made with let is made again on every bar. A name made with state is set once, on the first bar, and then kept: each bar starts with the value the bar before ended with.
indicator "Up streak"
edition = 1
display = pane
state streak = 0
if close > close[1]
streak += 1
else
streak = 0
plot(streak, name = "Bars up in a row", style = columns, color = color.teal)streak += 1 adds one to the kept value. On the first bar close[1] is na, the comparison is false, and the streak starts at 0.
A value for one bar, and a value for one day#
mut is a name you may change, but only during the run of one bar: it starts again on the next. state day is kept like state, but starts again on the first bar of every trading day.
indicator "Largest body today"
edition = 1
display = pane
mut body = close - open
if body < 0
body = -body
state day largest = 0.0
if body > largest
largest = body
plot(body, name = "Body", style = columns, color = color.gray)
plot(largest, name = "Largest body today", color = color.orange)body is the size of this bar's body, worked out again on every bar. largest keeps the biggest body seen so far today and goes back to 0 when a new trading day starts. Use it on an intraday chart; on a daily chart every bar is a new day.
Bars since something happened#
A kept value can count bars since an event. Here it starts as na, so nothing is drawn until the first crossing:
indicator "Bars since the last cross"
edition = 1
display = pane
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
let up = tech.crosses_above(fast, slow)
let down = tech.crosses_below(fast, slow)
state since: int = na
if up or down
since = 0
else if not is_na(since)
since += 1
plot(since, name = "Bars since the last cross", style = columns, color = color.blue)The two crossing tests are worked out on lines of their own, on every bar, and only then combined with or. A function such as tech.crosses_above remembers the bars it has seen; written directly on the right side of or it would skip bars, and the checker refuses it (Reading the editor's messages shows that message).
Try changing#
- In "Change over a few bars", set Bars back to 1: the histogram becomes the change from one bar to the next.
- In "Up streak", replace
close > close[1]withclose > open: the streak now counts green bars in a row. - In "Largest body today", change
state daytostate: the orange line never goes back down, because it keeps the largest body of the whole chart. - In "Bars since the last cross", remove
or down: the count restarts only on crossings upwards.
Checkpoint#
- You can read the value of a name a number of bars back with
[n], and you know it isnaat the start of the chart. - You can keep a value from one bar to the next with
state, and restart it each day withstate day. - You know when to use
let,mutandstate. - You can count the bars since an event.