Loops
for and while repeat a block on the current bar. They are for walking rows: the price rows of the footprint ladder, the prints of the tape, the levels of the book, the order events of a bar, or a fixed set of offsets into history. Every loop is bounded, so a mistake stops the script with one line instead of freezing the chart.
var heavy_rows: float = 0
heavy_rows := 0
for i = 0 to cell.count() - 1 by 1 {
if nz(cell.volume(i), 0) < cell.max_volume() * 0.6 {
continue
}
heavy_rows += 1
plot.box(true, cell.price(i) + chart.tick_size(), cell.price(i), color.teal, 0.35, 0, 0)
}
plot.label(str.concat("HEAVY ROWS ", format.compact(heavy_rows)), "#E5E7EB")| Form | Meaning |
|---|---|
| for i = a to b { } | Runs with i = a, then each whole number up to and including b. When a is above b it counts down instead. |
| for i = a to b by s { } | The same with step s, which may be fractional or negative. A step of 0 stops the script. |
| while condition { } | Repeats while the bool condition is true, checked before every pass. |
| break | Leaves the innermost loop. |
| continue | Skips to the next pass of the innermost loop. |
- a, b and the step are computed once, before the first pass, and must be numbers. i is read only inside the loop; copy it into a local to change it.
- Write by 1 when the end can fall below the start. for i = 0 to cell.count() - 1 counts DOWN on a bar with no rows and runs with i = 0 and i = -1; with by 1 it runs zero times. Every row accessor answers nan for -1, so the first form draws nothing wrong, but the second says what you mean. A script that has such a loop keeps running exactly as before, and the settings under the editor point it out with its line: A "for … to n - 1" loop without "by 1" counts down (0, then -1) when n is 0; add "by 1".
- A bound or step that is nan, such as a count from data the chart does not have, runs the loop zero times.
- let inside a loop body declares a local for that pass. A top level var may be assigned inside a loop.
- break and continue must be written inside the loop itself, not in a function called from it.
- A loop at the top level runs once per bar, on every bar. History reads with the loop variable, such as close[k], are allowed.
What a loop body may call
Anything that keeps one value per bar, or declares something once, is refused inside a loop body, including inside a function called from one: ta.*, mtf.*, session.* except session.in, input.*, indicator, and the per bar drawings plot.line, plot.histogram, plot.band, plot.hline, plot.label, plot.candle_color, plot.panel_line, plot.panel_area, plot.panel_hline, plot.panel_range and the short form of plot.zone. Compute those once per bar outside the loop and use the result inside.
Drawings that make one object each time they run belong in loops: plot.marker, plot.text, plot.box, plot.dot, plot.segment, plot.panel_segment, plot.vline, plot.position, the event form of plot.zone, plot.rect, plot.polygon, plot.cell, plot.hbar, plot.table, profile.fold and profile.row_color.
Budgets
- At most 100,000 passes of all loops together on one bar.
- At most 25,000,000 steps in one run, a step being one statement or expression inside a loop body, once per pass.
- A script with a loop may draw at most 250,000 markers, texts, boxes, dots, segments, event zones and vertical lines in one run. A script without a loop draws at most one per call site per bar and has no such cap.
- Statements inside a loop body do not count toward the 10,000 statements per bar.
var ups: float = 0
ups := 0
for k = 0 to 9 {
if close[k] > open[k] {
ups += 1
}
}
plot.histogram(ups - 5, "#22C55E", "#EF4444")