Placement & Coordinates
A draw call maps a field's columns to bars or timestamps and its rows to a vertical range. Each call returns the Canvas and replaces its previous drawings.
Five ways to place a field
| Call | Horizontal position | Use it when |
|---|---|---|
drawLookback() | Ends at the current bar | The picture follows the latest bar. This is the usual choice. |
draw() | Between two bar indices | The picture belongs to a fixed stretch of bars. |
drawTime() | Between two timestamps | The stretch is far in the past, or defined by time. |
drawGrid() | Explicit bar-index edges | Columns or rows have uneven widths. |
drawTimeGrid() | Explicit timestamp edges | Uneven columns placed by time. |
All five accept a ValueField or a PaletteField. Rolling sources are drawn with their own form of drawLookback().
drawLookback
// field, lookback, bottom, top, rightOffset = 0
canvas.drawLookback(field, 0, bottomPrice, topPrice) // one bar per column
canvas.drawLookback(field, 600, bottomPrice, topPrice) // stretched over 600 bars
canvas.drawLookback(field, 0, bottomPrice, topPrice, 20) // right edge 20 bars aheadlookbackis the width in bars.0means one bar per column. Any other value must be at least the number of columns.rightOffsetmoves the right edge away from the current bar, forward when positive and back when negative.- The left edge sits at
bar_index + rightOffsetminus the width. It cannot be before the first bar, so guard the call until enough bars exist.
if barstate.islast and bar_index >= field.columns
canvas.drawLookback(field, 0, bottomPrice, topPrice)draw
// field, leftIndex, rightIndex, bottom, top
canvas.draw(field, bar_index - 300, bar_index - 100, bottomPrice, topPrice)The span between the two indices must be at least the number of columns, so that every column is at least one bar wide.
drawTime
// field, leftTime, rightTime, bottom, top (UNIX time in milliseconds)
canvas.drawTime(field, sessionOpenTime, time, bottomPrice, topPrice)Time placement is not limited to 10,000 bars of history. Use it for distant pictures, and whenever the edges come from session or event times.
Explicit grid edges
drawGrid() and drawTimeGrid() take the position of every cell edge, which allows columns and rows of different sizes. An edge array has one more entry than the field has cells in that direction, and its values must strictly increase.
array<int> columnEdges = array.from(bar_index - 40, bar_index - 30, bar_index - 15, bar_index - 5, bar_index)
array<float> rowEdges = array.from(100.0, 101.0, 103.0, 106.0)
canvas.drawGrid(field, columnEdges, rowEdges)drawTimeGrid(field, timeEdges, rowEdges) is the same with timestamps in milliseconds as the horizontal edges.
Vertical bounds
On the price chart
bottom and top are prices. Row 0 starts at bottom and the last row ends at top, with rows of equal height between them. A value at a given price belongs to the row at int(math.floor((price - bottom) / rowHeight)), where rowHeight is (top - bottom) / rows.
In a separate pane
The bounds are any numbers. Using the row count as top and 0 as bottom makes each row one unit tall, which keeps the pane's scale readable.
Logarithmic rows
With logarithmicY() set on the Canvas, the rows between bottom and top are spaced logarithmically. Both bounds must be positive. This matches a chart on a log price scale.
top at or below bottom, or with either bound na, stops the script. Check the range before drawing when it is computed from data.Bounds and history limits
- 10,000 bars back: a bar-index placement cannot start further back than that. Use
drawTime()ordrawTimeGrid()instead. - 500 bars forward: a bar-index placement cannot end further ahead than that.
- Not before the first bar: the left edge cannot be a negative bar index.
- 2 by 2 at least: a field needs at least 2 rows and 2 columns to be drawn.
Framing a separate pane
A pane scales itself to its plots, not to its drawings. Two invisible plots at the picture's vertical bounds keep the whole picture in view.
plot(0.0, "Frame low", color = color.new(color.white, 100), editable = false)
plot(float(field.rows), "Frame high", color = color.new(color.white, 100), editable = false)