Pine Script v6 language guide

Pine Script Enums: Typed Modes and Input Choices

A Pine Script enum defines a named type with a fixed set of members. Use enum to declare the type, input.enum() to select a member, and switch to choose its behavior. An optional string title controls the dropdown label; the value used by your code remains the enum member. This separates readable settings from the string spellings used in your logic.

Refactor Pine Script Modes

A complete enum, input, and switch example

Paste this v6 indicator into Pine Editor. The default Exponential choice plots a 20-bar EMA; Simple plots the SMA; Hidden removes the line. Both averages are calculated on every bar before the switch selects the output. The table shows the selected title through str.tostring(). The title is useful for display, while dispatch uses AverageMode members.

Complete v6 indicator: named modes with readable input titlespinescript
//@version=6
indicator("Enum average modes", overlay=true)

enum AverageMode
    sma = "Simple"
    ema = "Exponential"
    hidden = "Hidden"

AverageMode mode = input.enum(AverageMode.ema, "Average mode")
int length = input.int(20, "Length", minval=1)
float smaValue = ta.sma(close, length)
float emaValue = ta.ema(close, length)

float selected = switch mode
    AverageMode.sma => smaValue
    AverageMode.ema => emaValue
    AverageMode.hidden => float(na)
    => float(na)

plot(selected, "Selected average", color=color.blue, linewidth=2)
var table status = table.new(position.top_right, 1, 1)
if barstate.islast
    table.cell(status, 0, 0, str.tostring(mode), text_color=color.white, bgcolor=color.blue)

Keep the type, member, and title separate

The declaration assigns a label to a member, not a string value to an ordinary variable. Without an explicit title, the member name becomes the displayed text. Each enum declaration creates its own type: two separately declared enums are incompatible even if their member names and titles match. Enum variables can also contain na, so helper functions receiving enum values still need a missing-value policy.

ElementIn the examplePurpose
TypeAverageModeRestricts a variable or function parameter to this enum
MemberAverageMode.emaSelects a branch without matching a string label
Member titleExponentialText displayed for the EMA choice
Input titleAverage modeLabel beside the whole dropdown
String conversionstr.tostring(mode)Retrieves the selected member title for display

Restrict options and repair an invalid default

The next script intentionally hides the Hidden member from the dropdown. Its default is AverageMode.ema, which is in the options list. The commented lines are deliberately invalid examples, each followed by the valid assignment. Keep those comments disabled when copying the script. Removing a choice from the input does not remove that member from the enum type.

Corrected v6 script: invalid examples are comments, not executable codepinescript
//@version=6
indicator("Enum option defaults", overlay=true)

enum AverageMode
    sma = "Simple"
    ema = "Exponential"
    hidden = "Hidden"

// INVALID: the default is a title string, not an AverageMode member.
// mode = input.enum("Exponential", "Average mode")
// INVALID: the default is absent from the explicit options list.
// mode = input.enum(AverageMode.hidden, "Average mode", options=[AverageMode.sma, AverageMode.ema])
AverageMode mode = input.enum(AverageMode.ema, "Average mode", options=[AverageMode.sma, AverageMode.ema])

// INVALID: an enum member cannot be assigned to a string variable.
// string title = mode
string title = str.tostring(mode)
float smaValue = ta.sma(close, 20)
float emaValue = ta.ema(close, 20)
float selected = switch mode
    AverageMode.sma => smaValue
    AverageMode.ema => emaValue
    => float(na)

plot(selected, "Selected average", color=color.orange)
var table status = table.new(position.top_right, 1, 1)
if barstate.islast
    table.cell(status, 0, 0, title, text_color=color.white, bgcolor=color.blue)

What changes when string options become an enum?

A string input with options already restricts what users can select. Its weak point is repeated string literals in the source. For example, an EMA choice and an Ema switch case are different strings, yet that comparison can compile and miss the branch. A misspelled enum member reference is rejected. Neither approach detects a valid branch that was accidentally wired to the wrong average.

Concerninput.string with optionsinput.enum
Dropdown choicesExplicit stringsAll members, or an explicit subset
DefaultA string from the optionsA member from the allowed enum choices
Branch matchingRepeated string spelling must agreeUse qualified member names
Rename visible textUpdate matching literals wherever usedChange the member title; member references stay the same
Outside text formatsAlready a stringConvert or map explicitly at the boundary
Correct calculationRequires branch testsStill requires branch tests

Migrate with a branch parity check

Start by mapping existing choices to members without changing their calculations. This transitional script retains the old string dropdown and translates its value to AverageMode. It plots the old and migrated calculations in the Data Window and their difference in a pane. With the same mode and length, the difference should be zero wherever both values exist; Off intentionally yields no value. This is a reproducible check to run, not a claim that a chart test has already been performed.

  • Run SMA, EMA, and Off with the same chart, length, and history. Check both missing values and numeric values.
  • After parity holds, replace the legacy input and translation block with input.enum(), as in the first complete example.
  • Preserve the intended default: the old EMA string corresponds to AverageMode.ema, not the first declared member.
  • Review saved chart settings and existing alerts after replacing an input. Do not assume the platform will migrate stored selections automatically.
  • If alert text or another external format needs stable machine values, keep an explicit mapping for those values. A display-title edit also changes str.tostring() output.
Complete v6 migration check: string boundary, typed dispatch, numeric paritypinescript
//@version=6
indicator("String to enum migration check")

enum AverageMode
    sma = "Simple"
    ema = "Exponential"
    hidden = "Hidden"

string legacyMode = input.string("EMA", "Legacy mode", options=["SMA", "EMA", "Off"])
int length = input.int(20, "Length", minval=1)
float smaValue = ta.sma(close, length)
float emaValue = ta.ema(close, length)

float legacyValue = switch legacyMode
    "SMA" => smaValue
    "EMA" => emaValue
    => float(na)

AverageMode typedMode = switch legacyMode
    "SMA" => AverageMode.sma
    "EMA" => AverageMode.ema
    => AverageMode.hidden

float migratedValue = switch typedMode
    AverageMode.sma => smaValue
    AverageMode.ema => emaValue
    AverageMode.hidden => float(na)
    => float(na)

bool missingMismatch = na(legacyValue) != na(migratedValue)
bool valueMismatch = not na(legacyValue) and not na(migratedValue) and math.abs(legacyValue - migratedValue) > 1e-10
if missingMismatch or valueMismatch
    runtime.error("Migration changed the selected output")

plot(legacyValue, "Legacy value", display=display.data_window)
plot(migratedValue, "Enum value", display=display.data_window)
plot(migratedValue - legacyValue, "Expected difference: zero", color=color.blue)

What the compiler cannot verify for you

An enum limits the values used to select behavior. It does not verify the behavior itself. Keep calculation tests separate from syntax checks, and test the full script after changing a declaration or adding a member.

  • A new member can reach an existing fallback if its switch branch is missing. Recheck dispatch whenever the enum grows.
  • A matching branch can still return na because price history is unavailable. The fallback only handles an unmatched selection.
  • Changing a title can change exported text even when member-based calculations stay the same.
  • The examples use current close values, which can change during the open bar. Enum selection does not establish confirmed signals or prevent repainting.
  • These indicators demonstrate programming behavior and place no orders. They are not tested trading strategies.
Where Pineify fits

Pine Script AI Coding Agent

Give Pineify your complete script and a mapping from each existing string choice to its intended enum member. Ask the Pine Script AI Coding Agent to refactor the modes and explicitly request a syntax check. Review the returned source, then compare every branch in TradingView before replacing the original.

Refactor Pine Script Modes

Frequently asked questions

Programming examples for education, not investment advice. Syntax checks do not verify chart behavior or trading results. Test each mode, default, and missing-value case in the complete script.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.