Enums arrived with Pine Script v6 in November 2024. They are one of the smaller additions in the v6 feature list, and they do not unlock anything you could not technically do before. What they do is make code you already write far cleaner and safer, which matters more than it sounds once your scripts grow past a few dozen lines.
The problem enums solve
Before enums, if your strategy had states like waiting, long, and short, you tracked them with strings or integers. Strings are easy to typo, and a typo does not error, it just silently never matches. Integers are worse: state == 2 tells a reader nothing about what 2 means. Both approaches let invalid values slip in, and the compiler cannot help you because it has no idea which values are legal.
//@version=6
strategy("Magic strings, the old way", overlay = true)
// Fragile: a typo like "lng" never matches and never errors
var string state = "flat"
if state == "flat" and ta.crossover(close, ta.sma(close, 50))
state := "long"
strategy.entry("L", strategy.long)
else if state == "long" and ta.crossunder(close, ta.sma(close, 50))
state := "flat"
strategy.close("L")The same logic with an enum
You declare an enum with a name and a set of members, then use the members wherever you used strings. Now a typo is a compile error, the reader knows exactly which states exist, and your editor can help you complete them.
//@version=6
strategy("Enum state machine", overlay = true)
enum State
flat
long
var State state = State.flat
if state == State.flat and ta.crossover(close, ta.sma(close, 50))
state := State.long
strategy.entry("L", strategy.long)
else if state == State.long and ta.crossunder(close, ta.sma(close, 50))
state := State.flat
strategy.close("L")The logic is identical, but State.long cannot be misspelled without the compiler catching it, and there is no ambiguity about what the value means. For a multi-state machine, this is the difference between code you can trust and code you have to reread constantly. The persistence here relies on var, covered in the var and varip guide.
Type-safe dropdown inputs
The other place enums shine is inputs. If you want a settings dropdown for, say, the moving-average type, you can back it with an enum so the input can only ever hold a valid choice. This removes a whole class of bugs where a user setting is compared against a string that was spelled slightly differently in the code.
//@version=6
indicator("Enum-backed input", overlay = true)
enum MaType
sma
ema
wma
maChoice = input.enum(MaType.ema, "MA type")
len = input.int(20, "Length")
maValue = switch maChoice
MaType.sma => ta.sma(close, len)
MaType.ema => ta.ema(close, len)
MaType.wma => ta.wma(close, len)
plot(maValue)The switch over an enum is exhaustive and readable, and because the input is enum-backed there is no way for maChoice to hold a value the switch does not handle. Compare that to matching input strings by hand, which is a classic source of the silent mismatches described in our type system guide.
When to bother
Enums are worth reaching for whenever you have a fixed set of named options: strategy states, mode selectors, categories of signal. For a one-off boolean or a value with no natural name, they are overkill. The rule of thumb is that if you catch yourself writing the same string literal in more than one place, or comparing against an integer whose meaning you have to remember, an enum will make the code clearer and let the compiler watch your back.
If you would rather not memorize the exact enum and input.enum syntax, PineScripter writes it for you from a plain description and keeps to current v6 constructs, so your generated code uses enums where they help rather than falling back on the fragile magic-string patterns older AI models default to. Try it free at PineScripter.
Disclaimer: PineScripter is a coding tool for Pine Script development. It does not provide financial advice and does not guarantee trading profits. Always backtest strategies thoroughly and understand the risks before live trading.