WhitmanTrading

How to Write a Pine Script

To write a Pine script, state the rule in plain English first, then declare the script as an indicator or a strategy. Compute each value as a named variable and plot it, so the output can be checked against the chart by eye. Nothing acts until its marks match your reading.

The language is deliberately small, which means the constraint is almost never syntax. It is having a rule specific enough to code, and most scripts that never work were never that.

Before you start

One rule stated in plain English before any code is written. “Mark every bar that closes above the highest close of the previous twenty bars.” If you cannot write that sentence, the script has nothing to express.

A decision about whether you are building an indicator or a strategy, because they are different objects. An indicator draws on the chart; a strategy simulates entries and exits.

A chart you already understand, so the output can be checked by eye. The first test of any script is whether its marks land where you expected on bars you can see.

The steps

1. Write the rule as a sentence, then translate it

A slow-moving stretch of price with entry marks.
The sentence is the specification. Illustrative chart - not real market data.

Every condition in the sentence becomes one line. If a condition has no clear translation, the sentence was vaguer than it looked, which is worth finding out before coding.

2. Declare the script type on the first line

The first half of a price series with marked bars.
Indicator or strategy is the first decision. Illustrative chart - not real market data.

An indicator can overlay price or sit in its own pane. A strategy carries entries, exits and a simulated account. Converting between them later means rewriting most of the file.

3. Compute your values as named variables

A long-horizon price series with computed levels marked.
Named intermediates make faults findable. Illustrative chart - not real market data.

Give every step a name rather than nesting four calls into one line. The compiler does not care and you will, the first time a value comes out wrong.

4. Plot everything, including the intermediates

The first half of a price series with several plotted lines.
A plotted intermediate finds the fault in one glance. Illustrative chart - not real market data.

While developing, plot each computed value. Remove the extra plots at the end. Debugging a script whose internals are invisible is guessing.

5. Check the marks against bars you can see

A range-bound stretch with signals at boundaries.
Your eye is the first test. Illustrative chart - not real market data.

Scroll to a section you understand and confirm the script marks the bars you would have marked. A script that disagrees with you there disagrees everywhere.

6. Make every condition read a closed bar

A slice of price data with a single confirmed signal.
An unclosed bar can change its mind. Illustrative chart - not real market data.

A condition evaluated on the current, still-moving bar can be true now and false at the close. That is where repainting comes from, and it makes a backtest describe a history that never happened.

7. Add costs before believing any strategy output

A long-horizon view of a tested rule.
A costless test is not a test. Illustrative chart - not real market data.

Commission and slippage go in the strategy declaration. On this site’s shared series a round trip measures about 2% of the median bar range of 0.493, and a frequent rule pays that on every trade.

How to tell it worked

The rule exists as 1 written sentence, and every line of code maps to part of it.

Every condition reads a closed bar, so the script cannot change its marks retrospectively.

The marks match your own reading on at least 20 bars you checked by eye.

And any strategy declaration includes costs, so its output is comparable to a real account.

What the language cannot do for you

A candlestick chart annotated with the round-trip cost of a switch.
Costs are a setting, and they are off unless you set them. Illustrative chart - not real market data.

It does not know what a good rule is. The compiler will happily accept a rule fitted to one stretch of history, and it produces exactly the same green checkmark as one that generalises.

A section of a price series drawn without volume context.
And a simulated fill is not a fill. Illustrative chart - not real market data.

Simulated orders always fill. In a thin instrument the price your script transacted at is a price nobody was offering, and the equity curve is built entirely out of those.

The two bugs everyone writes

Reading the current bar. Any condition on a bar still in progress can flip before the close. The chart then redraws its own history, which is why a script can look excellent and produce nothing.

Comparing a value to itself one bar late. Off-by-one on the historical reference is the second most common fault, and it usually looks like a rule that is almost right — signals in the correct places, one bar early or late throughout.

Both are invisible without plotted intermediates, which is the whole argument for step 4.

The original data

Of the 24,971 unique videos in research/search-study-corpus.jsonl, 225 mention this language in the title, at a median of 504 views across 103 channels, and 66% of those titles are instruction-shaped. Automated trading appears in 24 at 20,062 and trading bots in 30 at 51,459. The counts come from site/corpus_count.py and site/rank_howto.py.

A candlestick series with several gaps, the largest of them marked.
A gap breaks a rule written for continuous bars. Illustrative chart - not real market data.

225 videos at a 504 median — the lowest of any subject in this entire ranking. Coding a rule has substantial coverage and almost no audience, while the promise of an automated result has a fraction of the coverage and a hundred times the audience per video.

A stretch of price bars cut short at a decision point.
The backtest returned a smooth curve. Trust it? Illustrative chart - not real market data.

The answer to the question on that chart is that smoothness is a warning rather than a result. On this site’s series 95% of bars sit below a prior peak and the longest recovery took 73 bars. A simulated curve without that texture is usually describing fills that were never available, costs that were never charged, or a rule fitted to the bars it was tested on.

When it fails

The failure is a script that repaints, and it is convincing right up until it is traded. The historical chart shows the signal at the ideal bar every time, because the condition was evaluated on a bar that had not finished moving. Live, the same script marks a bar and then unmarks it. Nothing in the editor warns about this and the backtest reports it as a success.

The second failure is coding before stating the rule. The code then becomes the search.

A third is nesting everything into one expression. A fault in it has nowhere to be seen.

A fourth is a strategy declared without costs. The result is not comparable to an account.

A fifth is trusting simulated fills in a thin instrument. They were never offered.

And a sixth is fixing a script by adding conditions until the curve improves. That is fitting, and it has no stopping rule.

Pine Script covers the language itself and what it can express. Strategy tester is how the output gets read. And backtesting is the discipline that decides whether the result means anything.

What I actually do

The habit that saved me time was plotting every intermediate value, not just the final signal. When a script does something odd, the fault is almost always three lines before the part I was looking at, and a plotted intermediate makes that visible in one glance instead of an afternoon.

— Michael Whitman

This page is educational, not financial advice. Test every idea on your own charts before risking money.