What “production ready” can mean
The phrase is used constantly and almost never defined, which makes it unfalsifiable. Here is a definition narrow enough to check.
A production-ready Pine strategy is one where the file does what you intended and the backtest measures something possible. That is all. It is a property of the artefact, not a prediction about the market.
The four claims it does make
| Claim | How you check it |
|---|---|
| it is a strategy, not an indicator | line two says strategy( |
| costs are declared and realistic | commission_value, commission_type, slippage are set [1] |
| every control affects behaviour | move each input, confirm the trade count changes |
| the fills were possible | three trades spot-checked against the chart's high-low range |
A file passing all four is one you can reason about. A file failing any of them produces numbers that describe nothing, and no amount of further analysis recovers that.
The four claims it explicitly does not make
This is the part that makes the term usable:
It does not claim the strategy is profitable. A clean implementation of a bad idea is still a bad idea, correctly implemented.
It does not claim the result will repeat. A curve-fitted strategy passes every check above — the code is clean, the costs are honest, the fills are real, and the parameters happen to be the ones that suited this stretch of history. That failure leaves no trace in the file at all.
It does not claim the strategy will trade by itself. A Pine strategy raises alerts; an alert is a notification, not an order, and alerts only fire on the realtime bar. Getting from alert to fill needs a broker integration that is not part of the file.
It does not claim the backtest is reproducible by anybody else. How much history you tested depends on your TradingView account plan [4], and your input values live with the chart rather than in the file. Two people with the same file can legitimately get different reports.
Why the narrow definition is more useful
Because it is achievable and checkable in about five minutes, and because it separates two questions that are constantly conflated:
- Is this file correct? — answerable today, by inspection
- Is this strategy any good? — answerable only with out-of-sample evidence, and never with certainty
Most disappointment in this field comes from treating a yes on the first as a yes on the second. The checks in the next section are all for the first question, which is the only one a tool can help with.
Migrating a v5 strategy to v6
A v5 strategy you wrote or inherited is the clearest case of a file that can fail the definition above while looking finished. Some v6 changes stop the script, and cost ten minutes. Others let it compile and run and change what it returns, and cost a backtest you believe. All of them are in TradingView's migration guide [6]; they are grouped here by consequence, and the full language surface is in the v6 reference [3].
The changes that run and return different numbers
| What changed [6] | v5 | v6 | Consequence |
|---|---|---|---|
and / or evaluation | both sides always evaluated | short-circuits | an indicator call after a false condition is skipped, corrupting its history |
margin_long / margin_short default | 0 — no margin checking | 100 — strict enforcement | margin calls where there were none |
strategy.exit() with both relative and absolute levels | absolute won, relative ignored | whichever triggers first | profit = 0, limit = price now exits at entry |
| Orders beyond 9,000 | runtime error, execution halted | oldest orders silently trimmed | trimmed trades return na from strategy.closedtrades.* |
timeframe.period on a daily chart | "D" | "1D" | timeframe.period == "D" is now always false |
5 / 2 with two const ints | 2 | 2.5 | thresholds and lookback lengths shift |
| A bool referenced before it exists | na | false | first-bar logic takes the other branch |
for i = 0 to expr | expr evaluated once | re-evaluated every iteration | a loop whose bound mutates can run indefinitely |
array.get(-1) | runtime error | returns the last element | an off-by-one that used to shout now returns a plausible wrong value |
Lazy evaluation is the worst of them, because it corrupts an indicator's internal state and the damage is invisible in the code. In v5 an indicator inside a condition was called on every bar; in v6 the call is skipped on bars where the first condition is false [6]:
// v6: ta.rsi() is skipped whenever close <= open
if close > open and ta.rsi(close, 14) > 50
signal := true
// the fix: call it at global scope, where it runs on every bar
rsiVal = ta.rsi(close, 14)
if close > open and rsiVal > 50
signal := true
Check every converted script that calls a ta.* function inside an if, a
switch or the right-hand side of an and. Nothing warns you, and the
backtest still produces a curve.
The margin default catches leveraged strategies. A v5 strategy that was
quietly overleveraged is now stopped out by margin calls [6]. Setting
margin_long = 0, margin_short = 0 restores the old behaviour, but that is a
choice about realism, not a fix: a strategy that only worked without margin
enforcement was never going to survive live.
The changes the compiler catches
These cost time rather than money, and every one has a mechanical fix [6]:
whenwas removed fromstrategy.entry()and the other order calls. It was the standard v5 way to place a conditional order, so a large share of published v5 strategies need theif condrewrite.- Numbers no longer cast to bool:
if someNumberbecomesif someNumber != 0, and a bool can no longer bena. - A mutated variable is
series, and functions such asta.ema()accept onlysimplefor their length. It was never sound — a length that changes bar to bar has no consistent history — so v6 refuses something that was silently wrong. - Smaller removals: no
[]history on literals or built-in constants,transpreplaced bycolor.new(), no repeated parameters,linewidthat least 1. The colour constants also changed value (color.redis now#F23645), which surprises people comparing screenshots.
Use the converter, then check the silent list yourself
The Pine Editor's own converter handles most of the mechanical changes [6], so
use it before migrating anything by hand. Its documented limits [6]: a script
that does not compile cleanly as v5 cannot be auto-converted; rare cases still
need a manual fix; and request.*() calls are now dynamic by default, so nested
requests can behave differently and restoring v5 behaviour can need
dynamic_requests = false.
The converter rewrites syntax. It does not know that your ta.rsi() inside an
and no longer runs on every bar, or that your strategy now enforces margin:
after converting, the table above is still yours to check.
A strategy built in the builder has nothing to migrate: it is kept as a strategy document, and re-exporting writes the file again as Pine Script v6. The generated code uses no platform indicator built-ins — every indicator is written out in the file you download, so you can read it.
The evidence to hold before risking money
The previous section is about whether the file is correct. This is about whether you have grounds to run it. Different question, different tests, and no tool can do these for you.
Five things you either have or do not have
| Evidence | Why it is the one that matters |
|---|---|
| a result on a date range you did not tune on | the only test of whether you found an edge or fitted a sample |
| a result on a second instrument | a strategy that works on one symbol may be a description of that symbol |
| more than a hundred trades | below that, the statistics describe a handful of events |
| the result on fixed position size | percent-of-equity compounds and flatters a weak edge [1] |
| the number of variations you tried | the best of ten is a biased estimate, and the count belongs with the result |
The last row is the one nobody records and the one that changes the interpretation most. If you tested ten parameter sets and kept the best, that best result is upward-biased by the search itself — the reasoning, with the literature, is in testing variations honestly.
The cost sensitivity test
One measurement, rarely done, that tells you more than another month of backtesting: double your commission and slippage, and re-run.
| What happens | What it means |
|---|---|
| the edge survives | costs are not carrying the result |
| the edge halves | you are close to the margin; small execution differences will decide the outcome |
| the edge disappears | the strategy was a rounding error on transaction costs |
The third case is common and worth finding before live trading rather than after. The surveyed academic evidence on technical trading rules weakens sharply once transaction costs are included [5], so a strategy whose result is cost-sensitive is the expected case, not the surprising one.
What to write down
Not the equity curve. This:
Instrument, timeframe, date range, account plan, position sizing, the input values used, the trade count, maximum drawdown, and how many variations were tested before this one.
Ten lines. They make the result reproducible by you in six months and checkable by anyone else — and their absence is why almost no published backtest can be verified. If you quote a number without the plan and the variation count, you have published something nobody can check, including you.
The honest last step
Paper first, and for long enough to see the strategy be wrong. A strategy you have only seen win has not shown you the thing that decides whether you will keep running it: what it looks like during the drawdown. The maximum drawdown figure in the tester is a number; living through it is a different experience, and it is the reason strategies get abandoned at the worst possible moment.

