Pine Script Tables: table.cell() Syntax & Dashboard Examples
table.cell populates a cell in an existing Pine table. The table is a display object, not a trading strategy or a historical performance report. This example uses one persistent table to show the latest price, RSI, MACD line, and ATR.
Create once, calculate every bar, display the last bar
TradingView's tables documentation separates table creation from cell population. Coordinates are zero-based and must fit the allocated dimensions. Border and frame properties belong to the table; cell properties include text, alignment, size, and colors. Repeating table.cell on a cell replaces its properties; use a cell setter when changing only one property.
The example allocates two columns and five rows with var. Its numeric calculations run on every bar so their histories are available. The display calls run on the last bar, including realtime updates. This avoids unnecessary historical display work but does not establish a measured speed improvement.
//@version=6
indicator("Current values table", overlay=true)
float rsiValue = ta.rsi(close, 14)
[macdLine, signalLine, macdHistogram] = ta.macd(close, 12, 26, 9)
float atrValue = ta.atr(14)
formatValue(float value, string pattern) =>
na(value) ? "N/A" : str.tostring(value, pattern)
var table dashboard = table.new(position.top_right, 2, 5, bgcolor=color.navy, border_width=1, border_color=color.gray)
if barstate.islast
table.cell(dashboard, 0, 0, "Metric", text_color=color.aqua)
table.cell(dashboard, 1, 0, "Value", text_color=color.aqua)
table.cell(dashboard, 0, 1, "Price", text_color=color.white)
table.cell(dashboard, 1, 1, formatValue(close, format.mintick), text_color=color.white)
table.cell(dashboard, 0, 2, "RSI (14)", text_color=color.white)
color rsiColor = na(rsiValue) ? color.gray : rsiValue > 70 ? color.red : rsiValue < 30 ? color.lime : color.white
table.cell(dashboard, 1, 2, formatValue(rsiValue, "0.00"), text_color=rsiColor)
table.cell(dashboard, 0, 3, "MACD line", text_color=color.white)
table.cell(dashboard, 1, 3, formatValue(macdLine, "0.0000"), text_color=color.white)
table.cell(dashboard, 0, 4, "ATR (14)", text_color=color.white)
table.cell(dashboard, 1, 4, formatValue(atrValue, format.mintick), text_color=color.orange)
The MACD row labels the line value accurately; it is not the signal line or a crossover. The RSI color is only a threshold display. Neither row submits an order or establishes a reversal forecast. N/A identifies unavailable data during warmup instead of displaying a false zero.
Diagnose a table problem
| Symptom | Check in this example |
|---|---|
| Blank table | Confirm that cell calls execute and the indicator is loaded |
| Index error | Valid columns are 0 and 1; valid rows are 0 through 4 |
| Unexpected price precision | Price uses the current symbol's minimum tick |
| Missing early values | The indicators need historical inputs |
| Value changes before close | The last bar can update while it is open |
| Wrong MACD label | Line, signal, and histogram are separate tuple members |
The table displays its current state rather than following the crosshair across earlier bars. Use plots or explicit historical logic if that is the behavior you need. barstate.isconfirmed is not an equivalent performance shortcut: it is true on historical bars as well as the closing update of a realtime bar.
Extend the display deliberately
Adding a row requires allocating enough rows and keeping every cell coordinate in bounds. Repeatedly creating a new table as volatility changes is not a resizing operation on the existing object. For a small dashboard, allocate the required capacity and control the displayed cells explicitly.
A higher-timeframe row also needs a defined data and confirmation policy. Adding a table does not remove repainting concerns from the underlying request. Test the calculations and units separately from the visual layout.
Pineify's Coding Agent can help draft a dashboard. Review the generated source, compile it, and check known values on a chart. A successful compiler check does not prove that labels, units, or trading interpretations are correct.
Does table.cell create a table?
No. Create the table first with table.new, then populate cells using its ID and valid column and row indices.
Does the table prove a strategy is profitable?
No. This example only displays indicator values and contains no simulated orders or return calculation.
Why keep RSI outside the last-bar block?
It needs a consistent series calculation across bars. Restrict the display updates, not the historical calculations the display depends on.

