Pine Script tables: build a mini dashboard on your chart
Some numbers don't belong on the candles. The bigger trend, the average range, the timeframe. A Pine Script table puts them in one small box in the corner, so you can read them at a glance.
What a table is
A table is a grid of boxes, fixed to one corner of the chart. It doesn't move when you scroll.
Each box is a cell. Each cell holds a bit of text, with its own color.
Tables suit numbers you want to read, not see as a line. For example: "Close vs average: Above". Or "Average range: 1.85".
New to Pine Script? Start with Pine Script for beginners.
2 steps: make it, then fill it
Every table works the same way:
- table.new() makes the empty grid and says where it sits and how many rows and columns it has.
- table.cell() writes into one cell. You call it once per cell.
The table doesn't show until at least one cell has something in it.
A full example
This draws a 50-candle average and a 3-row dashboard in the top right corner:
//@version=6
indicator("Mini dashboard", overlay=true)
emaLen = input.int(50, "Average length", minval=1)
ema = ta.ema(close, emaLen)
atr = ta.atr(14)
above = close > ema
plot(ema, "Average", color=color.orange)
var table dash = table.new(position.top_right, 2, 3, bgcolor=color.new(color.black, 15), border_color=color.gray, border_width=1)
if barstate.islast
table.cell(dash, 0, 0, "Close vs average", text_color=color.white, text_size=size.small)
table.cell(dash, 1, 0, above ? "Above" : "Below", text_color=above ? color.lime : color.red, text_size=size.small)
table.cell(dash, 0, 1, "Average range (14)", text_color=color.white, text_size=size.small)
table.cell(dash, 1, 1, str.tostring(atr, format.mintick), text_color=color.white, text_size=size.small)
table.cell(dash, 0, 2, "Timeframe", text_color=color.white, text_size=size.small)
table.cell(dash, 1, 2, timeframe.period, text_color=color.white, text_size=size.small)
Every line, in plain words
- Line 1 says this is Pine Script version 6.
- Line 2 names the script and puts it on the price chart.
- Line 3 makes the average length a setting. See Pine Script inputs.
- Line 4 works out an EMA, an average that leans toward the newest candles.
- Line 5 works out the ATR: the average size of a candle's full range over the last 14 candles.
- Line 6 is true when the close is above the average.
- Line 7 draws the average in orange.
- Line 8 makes the table. More on its parts below. var means it's made once and kept.
- Line 9 says "only on the newest candle".
- Lines 10 to 15 fill the 6 cells. Each row has a name on the left and a value on the right.
The parts of table.new()
| Part | In the example | What it means |
|---|---|---|
| position | position.top_right | Which corner or edge it sits in |
| columns | 2 | How many columns |
| rows | 3 | How many rows |
| bgcolor | color.new(color.black, 15) | Background. 15 means 15% see-through |
| border_color | color.gray | The color of the lines between cells |
| border_width | 1 | How thick those lines are |
Other positions follow the same pattern: position.top_left, position.middle_right, position.bottom_center and so on.
The parts of table.cell()
table.cell(dash, 1, 0, …) reads as: "in the table called dash, column 1, row 0, write this".
Counting starts at 0, not 1. So a 2-column table has columns 0 and 1. Ask for column 2 and the script stops with an error.
The rest are optional:
- text_color sets the words' color.
- text_size can be size.tiny, size.small, size.normal, size.large or size.huge.
- bgcolor colors one cell, on top of the table's background.
- tooltip shows a hint when you hover over the cell.
Line 11 shows a handy trick. The text and its color both change with above. Green "Above" or red "Below".
Why fill it only on the last candle?
A table shows one set of values: the latest. It has no history.
If you fill it on every candle, the script writes thousands of cells that are wiped a moment later. That's slow. if barstate.islast writes only once, on the newest candle.
On a live chart, the newest candle keeps updating. So the table updates too, every time price moves.
The live-candle catch
Because the table always shows the current candle, its values move until that candle closes. "Above" can flip to "Below" and back within one candle.
If you want the table to show only what the last finished candle said, use [1]. For example, close[1] > ema[1] means "the previous candle closed above the average". It won't change until the next candle closes.
That fits a rule we use: only a candle body closing past a level counts.
Let people choose the corner
A table can cover something important. Make its corner a setting:
where = input.string("Top right", "Table position", options=["Top right", "Bottom right", "Bottom left"])
pos = switch where
"Top right" => position.top_right
"Bottom right" => position.bottom_right
=> position.bottom_left
- Line 1 is a drop-down with 3 choices.
- Line 2 starts a switch: "pick a value based on what was chosen".
- Lines 3 and 4 match each choice to a position.
- Line 5 is the fallback for anything else.
Then use pos instead of position.top_right in table.new().
What to put in it
A table is a good home for your pre-trade checklist numbers. A few ideas:
- The bigger chart's direction. See Pine Script higher-timeframe trend.
- The average range, to judge how wide a sensible stop might be.
- Your trade size for a given stop. See Pine Script position size.
- The session: open or closed.
Keep it to 3 to 6 rows. More than that and you'll stop reading it.
A dashboard can't make the call. It shows facts in one place. You still decide if the setup fits your plan, where the stop goes and how much to risk.
Try it today
- Paste the full example into the Pine Editor on a computer. Save and add it to a chart.
- Find the table in the top right.
- Switch the chart from 1-hour to daily. Watch the Timeframe row change.
- Add a 4th row with your own number. Remember to change 3 rows to 4 in table.new().
Phone-friendly. Once saved, the script works in the TradingView phone app too. Use size.small text so the table doesn't cover the candles on a small screen.
Learning from a real script
Our course includes the full source code of the StructureX chart tool to learn from and customize, for example adding your own dashboard. It's source code, not a ready-made trading bot.
Common mistakes
- Counting from 1. Rows and columns start at 0.
- Too few rows in table.new(). Writing to a row that doesn't exist stops the script.
- Filling it on every candle. Wrap the cells in if barstate.islast.
- Forgetting var. The table should be made once.
- Cramming it full. A big table hides the chart it's meant to help with.
Questions
How do I make a table in Pine Script?
Make it once with var t = table.new(position.top_right, columns, rows), then fill each cell with table.cell(t, column, row, "text") inside if barstate.islast.
Why is my Pine Script table not showing?
Usually no cell has been filled yet, or the code writes to a column or row that doesn't exist. Check that counting starts at 0.
Can a Pine Script table show past values?
A table shows one set of values at a time, normally the newest candle's. To show the last finished candle, use values with [1].
How many tables can one script have?
A few, one per position is the usual habit. Most dashboards need only one.
Want the next step? We'll walk you through it.
Four free lessons by email, one every few days — each with a 10-minute exercise on a real chart.
Send Me the Free Lessons 4 short emails · No spam · Unsubscribe anytimeOr see the whole method, step by step:
See What’s Inside the Course Try everything free first. Decide when you're ready. · Open the free chart tool (works in the TradingView phone app)One chart idea a day, in plain English. Follow along: