Price Scale
The price scale is the vertical axis strip beside each pane: tick labels, the last-price label, and the currency/unit header. A pane can carry several strips on either side, each with a stable id, its own mode, and its own assigned sources. That is what makes comparisons, reassigned indicators, ratio geometry, and feed-side currency conversion possible without opening a second chart.
Common tasks first
| Task | Setting or API | Check |
|---|---|---|
| Fit visible data | autoFit / reset price scale | All visible owned sources fit with configured margins |
| Change mode | axisType normal, percent, log, indexed-to-100 | Tick labels and geometry change together |
| Move side | side or scale-slot placement | Axis strip moves without reassigning data |
| Put an indicator on its own scale | updateIndicator(..., { priceScale, priceScaleId }) | Indicator and axis use the same scale ID |
| Convert currency/unit | setPriceScale({ currency, unitId }) | Symbol re-resolves and data reloads through the feed |
Anatomy

BTCUSDT · 15m · dark theme — right price scale captured from the live playground.
Three regions make up the scale column:
- Currency/unit header (
USDT) — visibility isPriceScaleSettings.currencyUnitVisibility. - Tick labels — spacing follows the scale transform; text formatting comes from
SymbolInfo.pricePrecision,pricescale,minMove,tickSize, andpriceFormat. - Last-price label — the highlighted current-price pill (visible in the full-terminal capture on Chart) is
ChartDisplaySettings.showLastPriceLabel.
Ticks and last-value labels belong to one scale transform. Left, right, overlay, and host-defined slots use the same ownership model: every scale owns a set of sources (main series, indicators, comparisons) and its axis strip renders where those sources are assigned.
Appearance and placement
| Need | TradeScript surface |
|---|---|
| Move scale left/right | side in PriceScaleSettings |
| Scale-control visibility | features.priceAxisScaleControls and ChartDisplaySettings.showPriceAxisScaleControls |
| Cropped edge tick labels | ChartDisplaySettings.showCroppedPriceScaleTickMarks. Defaults on so price labels anchored at the top or bottom of the axis can remain visible even when their text is partially cropped. |
| Hide all-hidden source scale | ChartDisplaySettings.hidePriceScaleIfAllSourcesHidden. Defaults to true. Every native scale evaluates the visibility of the main series, indicators, and comparisons that own it, and its axis strip disappears when the last visible source is hidden. |
| Empty/error scale clearing | ChartDisplaySettings.clearPriceScaleOnErrorOrEmptyBars. Defaults on so stale price ranges clear when the main series is empty or an initial main-series load error clears bars. |
Modes and geometry
| Need | TradeScript surface |
|---|---|
| Scale mode | chart.setPriceScale(...) with mode set to 'locked' or 'free' |
| Price-axis type | ChartDisplaySettings.priceAxisType and PriceScaleSettings.axisType use PriceAxisType (normal, percentage, logarithm, indexed-to-100) |
| Autoscale | autoFit in PriceScaleSettings |
| Invert/reverse | reverse in PriceScaleSettings |
| Top/bottom auto-scale margins | topMargin and bottomMargin in PriceScaleSettings |
| Visible price range | visiblePriceRange in PriceScaleSettings |
| Price-to-bar geometry | priceToBarRatio expresses price units per horizontal bar slot. The y range responds to chart height and bar spacing; priceToBarRatioLocked prevents manual y-scale resizing. |
Each mode has a visible result: percentage and indexed-to-100 re-label ticks relative to the comparison base, logarithm compresses large ranges, reverse flips the axis, and locked stops manual y-drag from changing the transform.
Interaction and menus
| Need | TradeScript surface |
|---|---|
| Native price-axis controls | The price-axis menu routes move-left/right, normal/percent/log/indexed-to-100 axis modes, invert, lock/free, currency/unit-label visibility, and reset through chart.setPriceScale(...) / chart.resetPriceScale() |
| Object properties editor | chart.showPropertiesDialog('price-scale:main') opens the native price-scale editor for mode, side, axis type, autoscale, inversion, currency/unit, menu visibility, conversion, pinned object ids, fixed visible range, auto-scale margins, price/bar ratio state, auto-scale scope, default indicator placement, and metadata. chart.showPropertiesDialog('price-scale:slot:<slotId>') opens the native slot editor for label, placement, pane target, order, description, and metadata. |
| Price-axis quick actions | ChartDisplaySettings.showPriceAxisActions controls the plus menu and emits price-axis-action for add-alert, buy-stop, sell-limit, add-order, and horizontal-line actions. |
| Built-in indicator scale picker | The price-axis menu lists active indicators, shows each current scale/slot label, and lets users choose built-in or host-defined scale slots |
Series and indicator assignment
| Need | TradeScript surface |
|---|---|
| Pin sources to scale | pinnedObjectIds in PriceScaleSettings |
| Comparison placement | same-price-scale, same-percent-scale, new-price-scale, new-pane |
| Indicator scale placement | IndicatorDefinition.priceScale, priceScaleId, and paneId attach the source to the main scale, an independent left/right scale, or a hidden scale. |
| Indicator scale reassignment | chart.updateIndicator(indicatorId, { priceScale, priceScaleId, paneId }); the updated source ownership and strip placement apply to the live indicator. |
| Host-defined scale slots | priceScaleSlots define stable scale IDs. Multiple slots and their sources can share one pane while retaining independent transforms and ordered axis strips. |
| Source ownership | chart.getPriceScaleSources(scaleId, paneId?) lists the main series, indicators, and comparisons owned by that scale, including each source's pane, axis placement, and visibility. |
Labels and lines
| Need | TradeScript surface |
|---|---|
| Bar-close countdown | ChartDisplaySettings.showBarCountdown. The price scale consumes MarketDataFeed.getServerTime when the feed advertises supportsServerTime, then ticks locally from that server-time offset. |
| Visible average close line | ChartDisplaySettings.showAverageClosePriceLine, showAverageClosePriceLabel, and StyleOverrideSettings.averageClosePriceLine. The chart computes the average close from the currently visible bars and renders a dashed price line with an optional right-side label. |
| Visible high/low lines | ChartDisplaySettings.showHighLowPriceLines, showHighLowPriceLabels, and StyleOverrideSettings.highLowPriceLine. The chart computes the high and low from currently visible loaded bars. |
| Main-series, bid/ask, session, and indicator last-value labels | ChartDisplaySettings.showLastPriceLabel, showSeriesSymbolLabel, showExchangeInSymbolLabels, seriesLastValueMode, showBidAskLabels, showPrePostMarketPriceLabel, showIndicatorLastValue, and showIndicatorPlotLabels |
| Bid/ask quote lines | ChartDisplaySettings.showBidAskPriceLines plus StyleOverrideSettings.bidAskPriceLine. The chart uses MarketDataFeed.getQuotes / subscribeQuotes and draws only finite Quote.bid / Quote.ask values. |
| Previous-close line | ChartDisplaySettings.showPreviousClosePriceLine, showPreviousClosePriceLabel, and StyleOverrideSettings.previousClosePriceLine. The chart uses MarketDataFeed.getQuotes / subscribeQuotes and draws only finite Quote.previousClose values. |
| Crosshair price/time labels | styleOverrides.crosshair.horizontal.text and .vertical.text |
| Price formatting | SymbolInfo.pricePrecision, pricescale, minMove, tickSize, and priceFormat |
Currency and unit
| Need | TradeScript surface |
|---|---|
| Currency/unit conversion | chart.setPriceScale({ currency, unitId }) re-resolves the current symbol with SymbolResolveContext when the target differs from the current symbol currency/unit, reloads through the normal symbol-change path, and records currency, unitId, and conversion in PriceScaleSettings. The host datafeed supplies the converted symbol metadata and bars; see Datafeeds for cache-key and invalidation rules. |
| Currency/unit menu visibility | currencyMenuVisible and unitMenuVisible in PriceScaleSettings |
| Currency/unit label visibility | currencyUnitVisibility in PriceScaleSettings |
Host-defined scale slots
Use priceScaleSlots when you want product-specific scale names and stable scale targets in the built-in indicator scale picker:
sdk.chart.mount({
mount,
symbol: 'AAPL',
interval: '1D',
datafeed,
priceScaleSlots: [
{ id: 'momentum-left', label: 'Momentum', placement: 'new-left' },
{ id: 'hidden-normalizer', label: 'Hidden', placement: 'no-scale' },
],
});
The slot catalog persists in ChartState.priceScaleSlots and saved layouts. When paneId is omitted, the scale belongs to candle_pane. Give multiple slots the same pane ID to render independent ordered strips around one plot, or provide another pane ID when the scale belongs elsewhere.
Selecting a slot records priceScaleSlotId, applies the slot ID as priceScaleId, and attaches the source to the slot's pane. Multiple indicators assigned to the same slot share its transform and visibility ownership. Updating the slot catalog moves every owned source together. Removing a slot detaches the catalog identity while preserving the source's concrete placement.
Scale slots are first-class chart objects. They appear from chart.listObjects() as price-scale:slot:<slotId> rows with actions.properties and actions.remove; generic object APIs route those rows back through the native slot catalog.
Comparisons use this same scale registry. new-price-scale and same-percent-scale create native scale IDs and native axis strips; they do not paint labels over the main axis rectangle. Candles, comparisons, and indicators contribute visibility and range through one source-ownership model.
Related pages
- Panes and Scales — pane lifecycle around the scales
- Time Scale — the horizontal axis
- Comparisons — comparison scale modes in practice
- Datafeeds — currency/unit conversion ownership