millionchart
فارسی

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.

Cuprel
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.

Cuprel
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.

Cuprel
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:

Cuprel
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] with close > open: the streak now counts green bars in a row.
  • In "Largest body today", change state day to state: 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 is na at the start of the chart.
  • You can keep a value from one bar to the next with state, and restart it each day with state day.
  • You know when to use let, mut and state.
  • You can count the bars since an event.

Next: Lesson 6: Your own functions