Pine Script conditional logic

Pine Script if else and ternary conditions: na in v5 and v6

In Pine Script v5, condition ? A : B returns B when condition is false or boolean na. In v6, a bool can only be true or false, and a numeric value cannot serve as a condition without an explicit conversion. For missing numeric data, use na(value) to test it and nz(value, replacement) only when you intend to substitute a value. Use if/else for blocks of statements and a ternary expression to select a value.

Review conditional logic with AI

Ternary condition truth table: v5 versus v6

Read condition ? A : B as a choice between two expressions. The table distinguishes an unavailable boolean from an unavailable number. A v5 boolean na selects B, but it remains a distinct value that na(condition) can detect. Do not translate that rule into a claim that every na expression is an accepted v6 condition.

Condition or inputPine v5Pine v6
trueSelects ASelects A
falseSelects BSelects B
A bool variable holding naSelects BCannot declare or assign this state
A numeric variable holding na, used directly as conditionImplicit conversion selects BRequires an explicit bool conversion or a boolean test
A numeric zero, used directly as conditionImplicit conversion selects BRequires an explicit bool conversion or a boolean test
A nonzero number, used directly as conditionImplicit conversion selects ARequires an explicit bool conversion or a boolean test
na(value), where value is a missing floattrue: selects Atrue: selects A
condition[1] on the first dataset bar, where condition is boolBoolean na: selects Bfalse: selects B

A complete v5 example: distinguish na from false

This diagnostic gives the first dataset bar an unknown condition, the second bar false, and all later bars true. Expected outputs are documented below the code; they are a reproducible chart check, not a claim that chart execution was measured here. The explicit na(condition) test belongs to v5 and cannot be copied into v6.

  • At bar_index 0: selectedBranch is 0, while explicitState is -1.
  • At bar_index 1: both outputs are 0.
  • At bar_index 2 and later: both outputs are 1.
  • To preserve all three states in v6, use a separate readiness flag or an integer/enum state instead of bool na.
Complete Pine v5 indicator: unknown, false, and true branchespinescript
//@version=5
indicator("v5 ternary na diagnostic", overlay = false)

bool condition = bar_index == 0 ? na : bar_index > 1
int selectedBranch = condition ? 1 : 0
int explicitState = na(condition) ? -1 : condition ? 1 : 0

plot(selectedBranch, "Ternary: true 1, otherwise 0", color = color.blue)
plot(explicitState, "State: unknown -1, false 0, true 1", color = color.orange)

if, else if, nested conditions, and reassignment

Indent each local block by four spaces or one tab. An if/else-if chain uses the first matching branch; separate if statements can both execute. Use = to declare a variable and := to update an existing one. Variables declared inside a block belong to that local scope. An if expression can also return its final expression as a value.

TaskPatternConstraint
Choose one valuecondition ? A : BThe selected expressions must have compatible types
Run several statementsif condition followed by an indented blockUse := when updating a variable declared outside the block
Choose among ordered casesif ... else if ... elsePut the most specific condition before a broader matching condition
Require multiple conditionsisReady and isRisingParenthesize mixed and/or expressions when grouping is not obvious
Nest a dependent operationA second if inside the first blockIndent the inner body one additional level
Plot conditionallyplot(condition ? value : na)Keep plot() in global scope; select its argument conditionally

A complete v6 example: keep missing data separate

The example supplies missing data for the first five dataset bars. It then separates readiness from the above-open comparison, assigns a value through if/else, and uses a chained ternary for a status color. Returning na from a numeric branch is valid in v6 even though a boolean cannot be na. The fallback output deliberately substitutes zero; choose a replacement that makes sense for your calculation.

  • On bars 0 through 4, state is -1, selectedValue is na, and both fallback values are zero.
  • From bar 5 onward, state is 1 when close is above open and 0 otherwise, provided the chart has a valid close.
  • In the Data Window, compare the two fallback plots. They should agree for this numeric source and constant replacement.
  • These expected values follow from the example. Syntax validation does not verify chart output or trading behavior.
Complete Pine v6 indicator: readiness, if/else, and a ternary fallbackpinescript
//@version=6
indicator("v6 conditional readiness diagnostic", overlay = false)

float sourceValue = bar_index < 5 ? na : close
bool isReady = not na(sourceValue)
bool isAboveOpen = isReady and sourceValue > open

int state = if not isReady
    -1
else if isAboveOpen
    1
else
    0

float selectedValue = na
if isReady
    selectedValue := sourceValue

float fallbackValue = na(sourceValue) ? 0.0 : sourceValue
float nzValue = nz(sourceValue, 0.0)
color stateColor = state == -1 ? color.gray : state == 1 ? color.green : color.red

plot(state, "State: missing -1, above 1, otherwise 0", color = stateColor)
plot(selectedValue, "Available source", display = display.data_window)
plot(fallbackValue, "Ternary fallback", display = display.data_window)
plot(nzValue, "nz fallback", display = display.data_window)

Why value == na is not a missing-value test

Use na(value) or not na(value). The current v6 type-system documentation says a literal na operand in a comparison causes a compilation error. If an operand is instead a variable holding na, v6 comparisons return false, including !=. That still does not test whether data exists. The v5 diagnostic above uses na(condition) explicitly to distinguish unknown from false.

  • For a float input, na(value) ? replacement : value selects a fallback when data is missing.
  • nz(value, replacement) is a concise replacement operation for supported types. It does not report whether a replacement occurred.
  • Do not replace all missing prices with zero by default. A substituted zero changes comparisons, averages, and plotted ranges.
  • In v6, na(), nz(), and fixnan() do not accept bool arguments. If readiness matters, test the underlying numeric data.

Branch types and evaluation order

A numeric ternary can combine int and float values through numeric conversion. A price and a color cannot form one result type. Numeric and color outputs may use na as their missing branch, but v6 bool and unique types such as plot styles cannot. Type compatibility and evaluation timing are separate checks.

  • For a bool condition, condition ? close : na is a numeric result. Its missing false branch is legal in v6.
  • A declaration initialized only with na needs a type, as in float selectedValue = na in the v6 example.
  • Ternary expressions select a branch in both versions. v6 also makes and/or lazy; v5 evaluates both operands.
  • Calculate history-dependent functions such as ta.rsi() on every bar before using their results in conditional branches. A skipped call can change the calculation history.
  • Use switch or if/else when a ternary chain becomes difficult to audit. There is no fixed nesting count that makes a chain incorrect.

Migration checks to run in TradingView

Compile each diagnostic under its stated version and inspect its outputs on the first dataset bars. For your own script, compare v5 and v6 on the same symbol, timeframe, inputs, and loaded history. This is a verification procedure; no chart comparison or performance test is claimed for this page.

CheckExpected v5 behaviorv6 action
Unknown boolean stateA bool can hold naReplace the third state with readiness plus bool, or an explicit state value
First-bar boolean historyA prior bool can be naExpect false; confirm that unknown and false may be merged
Numeric conditionZero and na act as falseUse a comparison or explicit bool() conversion that matches the intended rule
Missing-data detectionna() can inspect a boolInspect the source data; bool overloads are unavailable
and/or expressionsBoth operands executeMove calculations that require every bar outside the condition
Unselected resultA ternary skips its unselected expressionCheck calculations in both branches; this concern already exists in v5
Where Pineify fits

Pine Script AI Coding Agent

Share your script version, compiler message, and expected branch behavior with the coding agent, then review the proposed changes in TradingView.

Also useful: Visual Pine Script Editor. Use visual conditions to assemble supported indicator and strategy rules, then inspect the generated Pine Script.

Review conditional logic with AI

Frequently asked questions

Programming examples are for education. Compile the script and inspect its behavior on the relevant chart before using it in a trading workflow. The examples are not trading recommendations.

Sources and verification