Charts
Concepts

Coordinates

How a script places shapes: pane px, time in epoch ms, raw prices, and converting between them.

Pane px

Everywhere a script sees x and y, they are pane px: CSS px from the top-left corner of its pane's data area. The pane spans 0 to frame.width and 0 to frame.height. This holds for g calls, hit shapes, pointer events and widget Rect placement, on every surface, so a script moves between surfaces unchanged.

y grows downward: a higher price has a smaller y.

Time and price

  • Time is epoch ms (Date.now() style). A bar's time is its open time.
  • Price is the raw instrument price, e.g. 5012.25.

Converting (chart surfaces)

CallReturnsNote
frame.timeToX(time)number | nullthe center of the bar slot at time, extrapolated beyond the loaded bars. null without bars.
frame.xToTime(x)number | nullnull without bars
frame.barTimeAt(time)number | nullopen time of the bar that holds time
frame.priceToY(price)numberon this pane's price scale
frame.yToPrice(y)number
frame.formatPrice(price)stringas the price axis shows it

Always check timeToX for null:

const x = frame.timeToX(p.time);

if (x === null) continue;

What is in view

  • frame.visibleTime.from / .to: epoch ms at the left and right edge. Skip everything outside, it costs draw time and is clipped anyway.
  • frame.visiblePrice.from / .to: price at the bottom and top edge.
  • frame.barSpacing: px between neighboring bar centers. A bar is barSpacing wide around its x.

The first visible bar starts half a bar left of its center. To not miss it, start from frame.barTimeAt(frame.visibleTime.from).

Crisp lines

frame.dpr is the device pixel ratio. To put an edge on a device pixel: Math.round(y * frame.dpr) / frame.dpr.

On this page