Expression Language Reference

This page is here to teach you how to actually write expressions for Axiom Strategy Lab Pro.

Written By AxiomCharts

Last updated About 2 hours ago

Expression Language Reference

This page is here to teach you how to actually write expressions for Axiom Strategy Lab Pro. If you are a first-time buyer, the practical question is usually not "what parser rules exist in theory?" The practical question is: "How do I write logic the strategy can understand?" That is the job of this page.

What An Expression Is

An expression is a piece of logic the strategy reads and evaluates. Sometimes the expression answers a yes-or-no question: - should this setup become active? - should this entry trigger now? - should this working order cancel? Sometimes the expression calculates a number: - what price should this limit order use? - what price should this stop use? - how far is price from the average fill? That gives you two big expression families:

Expression familyWhat it producesTypical strategy use
boolean expressiontrue or falsesetup gates, triggers, cancels, confirmations
numeric expressiona numberlimit prices, stop prices, calculations

The Two Most Important Ideas First

1. Tokens are the words your expression uses

Tokens are the named values the strategy exposes.

  • PRICE_CLOSE
  • BARSTATE_ISCONFIRMED
  • POSITION_ACTIVE
  • POSITION_AVG_PRICE

If you need the full token catalog, read Default Token Reference.

2. Operators and functions are how you do something with those tokens

An operator is a symbol like: - > - && - + - *

A function is a named tool like: - CROSSOVER(...) - HIGHEST(...) - ABS(...) - SAFE_DIV(...)

Put simply: - tokens are the ingredients - operators connect or compare them - functions do a named job with them

Where Expressions Are Used In The Strategy

This matters because the field tells you what kind of expression you need to write.

Field typeWhat the strategy expectsExample
setup, entry, and exit conditionsyes-or-no logicBARSTATE_ISCONFIRMED && PRICE_CLOSE > PRICE_HLC3
limit-price and stop-price fieldsa numberPOSITION_AVG_PRICE * 1.01

That means one of the first questions to ask is: "Am I writing a yes-or-no expression, or am I calculating a number?"

The Fastest Way To Build A Good Expression

Use this order:

  1. Decide what the field needs. If the field is a condition field, write a yes-or-no expression. If the field is a price field, write a number expression.
  2. Pick the tokens you need.
  3. Choose the operator or function that expresses the idea.
  4. Keep the first version small.
  5. Verify it on the chart before you make it more clever.

A Few Expressions In Plain English

ExpressionPlain-English meaning
PRICE_CLOSE > PRICE_HLC3close is above HLC3
BARSTATE_ISCONFIRMED && PRICE_CLOSE > PRICE_HLC3the bar is confirmed and close is above HLC3
CROSSOVER(PRICE_CLOSE, PRICE_HLC3)close crossed up through HLC3
POSITION_ACTIVE ? POSITION_AVG_PRICE * 1.01 : PRICE_CLOSEif a position is active, use 1% above average price, otherwise use current close
HIGHEST(PRICE_HIGH, 20)highest high seen across the last 20 bars

If you can read expressions like short sentences, this page is doing its job.

Operators: What They Are And How To Use Them

Operators are the symbols that compare, combine, or calculate.

Comparison Operators

Use these when the job is to ask whether one number is above, below, equal to, or different from another.

OperatorWhat it meansExampleReads like
>greater thanPRICE_CLOSE > PRICE_HLC3close is above HLC3
<less thanPRICE_CLOSE < PRICE_LOW[1]close is below the prior low
>=greater than or equal toPRICE_CLOSE >= POSITION_AVG_PRICEclose is at or above average entry price
<=less than or equal toPRICE_CLOSE <= PRICE_HL2close is at or below HL2
==equal toPRICE_CLOSE == POSITION_AVG_PRICEclose is effectively equal to average entry price
!=not equal toPRICE_CLOSE != POSITION_AVG_PRICEclose is not effectively equal to average entry price

One important note about ==

In this expression engine, numeric equality is not treated as raw bit-for-bit equality. It uses the symbol's minimum tick size as a tolerance. In trader terms, that means: - == means "close enough to count as equal" - != means "far enough apart to count as different" That is usually much more useful for chart logic than exact machine-style equality. Also because of the execution speed of TradingView scripts you may miss equality if not massaged just a little bit.

Logical Operators

Use these when you want to combine yes-or-no conditions.

OperatorWhat it meansExampleReads like
&&andBARSTATE_ISCONFIRMED && PRICE_CLOSE > PRICE_HLC3both things must be true
||orPOSITION_ACTIVE || POSITION_READYeither thing can be true
!not!POSITION_ACTIVEposition is not active

Good mental model

- && narrows the condition - || widens the condition - ! flips a condition

Arithmetic Operators

Use these when you want to calculate a number.

OperatorWhat it meansExampleReads like
+addPOSITION_AVG_PRICE + 10average price plus 10
-subtractPRICE_CLOSE - PRICE_HLC3close minus HLC3
*multiplyPOSITION_AVG_PRICE * 1.011% above average price
/dividePRICE_CLOSE / PRICE_HLC3close divided by HLC3
%remainderBAR_INDEX % 2remainder after dividing by 2

Arithmetic is most often used in price expressions and numeric calculations.

Unary Operators

These are the one-input versions of an operator.

OperatorWhat it doesExample
unary -turns a number negative-PRICE_CLOSE
unary +keeps the number positive+PRICE_CLOSE
!flips a boolean!POSITION_ACTIVE

Most traders will mainly use unary - and !.

The Ternary Operator

This is the "if this, then that, otherwise something else" operator.

Shape: condition ? value_if_true : value_if_false

Example: POSITION_ACTIVE ? POSITION_AVG_PRICE * 1.01 : PRICE_CLOSE

Reads like: "If a position is active, use 1% above average price. Otherwise, use current close."

When ternary is useful

- choosing one price formula or another - switching behavior based on whether a position exists - creating one compact expression instead of repeating the same field in two places

Two rules to remember

- the condition must be yes-or-no - both result branches must be the same kind of thing - both numbers or both booleans

Token History: Looking Back

You can ask for an older value of a token by adding [number] after it.

ExpressionMeaning
PRICE_CLOSE[1]prior bar close
PRICE_HIGH[5]high from 5 bars ago
BARSTATE_ISCONFIRMED[1]whether the prior bar was confirmed

Rules for token history

- write it with no spaces: PRICE_CLOSE[1] - use a non-negative whole number - the base token has to exist

Good: PRICE_CLOSE[1] POSITION_ACTIVE[3]

Not good: PRICE_CLOSE [1] PRICE_CLOSE[-1] PRICE_CLOSE[1.5]

Order Of Operations In Plain English

You do not need to memorize parser theory to use this well.

The practical reading order is: 1. math happens first 2. comparisons happen after the math 3. && and || combine the results 4. ternary chooses between the final branches

If you ever feel unsure, use parentheses. That is the cleanest habit anyway because it makes your intent obvious to both you and the next time you read the expression.

Example: BARSTATE_ISCONFIRMED && (PRICE_CLOSE > PRICE_HLC3 || PRICE_CLOSE > PRICE_HIGH[1]) The parentheses make the grouping obvious without needing to think about operator tables.

Functions: What They Are And What They Do

Functions are named tools. They let you do jobs that would be awkward or repetitive with operators alone. The most useful way to learn them is by job, not by parser category.

Function Group 1: Check Or Clean Values

These help you test, convert, or clean values before using them.

FunctionWhat it doesExampleWhen to use it
NA(x)checks whether a numeric value is naNA(PRICE_CLOSE)check whether a number is missing
NZ(x)replaces na with 0NZ(PRICE_CLOSE)avoid na breaking a numeric calculation
NZ(x, replacement)replaces na with your chosen numberNZ(PRICE_CLOSE, PRICE_HLC3)use a fallback number you trust more
BOOL(x)turns a number or bool into a booleanBOOL(PRICE_CLOSE - PRICE_HLC3)convert numeric output into yes-or-no logic
INT(x)converts a number to an integer-style numeric valueINT(PRICE_CLOSE)truncate decimals when needed
FLOAT(x)returns a numeric float valueFLOAT(PRICE_CLOSE)rarely needed, but useful when being explicit helps

What BOOL(...) really does

- non-zero numbers become true - zero becomes false - na becomes false - booleans stay boolean

Function Group 2: Compare Or Measure Numbers

These are everyday workhorse functions.

FunctionWhat it doesExampleGood use
ABS(x)absolute valueABS(PRICE_CLOSE - PRICE_HLC3)measure distance without caring about direction
AVG(a, b, ...)average of two or more valuesAVG(PRICE_HIGH, PRICE_LOW, PRICE_CLOSE)combine several values into one average
MAX(a, b, ...)largest valueMAX(PRICE_CLOSE, PRICE_HIGH[1])keep the higher of several values
MIN(a, b, ...)smallest valueMIN(PRICE_LOW, PRICE_LOW[1])keep the lower of several values
DIST(a, b)absolute distance between two valuesDIST(PRICE_CLOSE, POSITION_AVG_PRICE)simpler distance comparison
NEAR(a, b, epsilon)checks whether two numbers are closeNEAR(PRICE_CLOSE, POSITION_AVG_PRICE, MINTICK * 2)test "close enough" behavior
CLAMP(x, lo, hi)keeps a value inside a rangeCLAMP(PRICE_CLOSE, PRICE_LOW, PRICE_HIGH)restrict a number to a range
BETWEEN(x, lo, hi)checks whether a value sits inside a rangeBETWEEN(PRICE_CLOSE, PRICE_LOW[1], PRICE_HIGH[1])yes-or-no range test

Function Group 3: Work With Percentages And Safer Math

These are very useful in strategy authoring.

FunctionWhat it doesExampleGood use
SAFE_DIV(numerator, denominator, fallback)divide, but use a fallback if the denominator is unusableSAFE_DIV(PRICE_CLOSE - PRICE_HLC3, PRICE_HLC3, 0)avoid divide-by-zero problems
PCT_FROM(base, value)percent distance from a base valuePCT_FROM(POSITION_AVG_PRICE, PRICE_CLOSE)measure how far current price is from average entry
PCT_CHANGE(current, previous)percent change from old value to new valuePCT_CHANGE(PRICE_CLOSE, PRICE_CLOSE[1])measure one-bar or multi-bar percent change
ROUND(x)round to a whole numberROUND(PRICE_CLOSE)simplify a number
ROUND(x, precision)round to a chosen precisionROUND(PRICE_CLOSE, 2)tidy output to chosen decimals
ROUND_TO_MINTICK(x)round to the symbol's minimum tickROUND_TO_MINTICK(POSITION_AVG_PRICE * 1.01)clean order prices to tradable tick spacing
ROUND_STEP(x, step)round to a custom step sizeROUND_STEP(PRICE_CLOSE, 0.25)force values onto a known increment

Function Group 4: Detect Events And Timing

These are often the most useful functions for setup and entry logic.

FunctionWhat it doesExampleGood use
CROSS(a, b)checks whether a crossed b in either directionCROSS(PRICE_CLOSE, PRICE_HLC3)any cross
CROSSOVER(a, b)checks for an upward crossCROSSOVER(PRICE_CLOSE, PRICE_HLC3)bullish cross logic
CROSSUNDER(a, b)checks for a downward crossCROSSUNDER(PRICE_CLOSE, PRICE_HLC3)bearish cross logic
CHANGE(x)checks or measures change from the prior barCHANGE(PRICE_CLOSE)one-bar change
CHANGE(x, length)change from farther backCHANGE(PRICE_CLOSE, 5)multi-bar change
BARSSINCE(condition)bars since the condition was last trueBARSSINCE(CROSSOVER(PRICE_CLOSE, PRICE_HLC3))timing windows after an event

CHANGE(...) behaves differently depending on the input

- if you pass a number, it returns a number - if you pass a boolean, it returns a boolean That makes it flexible, but it also means you should know what kind of value you are feeding into it.

Function Group 5: Work With Trends, Ranges, And Lookbacks

These help you look across a window of bars instead of only the current bar.

FunctionWhat it doesExampleGood use
HIGHEST(source, length)highest value in the lookback windowHIGHEST(PRICE_HIGH, 20)top of a recent range
LOWEST(source, length)lowest value in the lookback windowLOWEST(PRICE_LOW, 20)bottom of a recent range
HIGHESTBARS(source, length)how many bars ago the highest value occurredHIGHESTBARS(PRICE_HIGH, 20)timing around recent highs
LOWESTBARS(source, length)how many bars ago the lowest value occurredLOWESTBARS(PRICE_LOW, 20)timing around recent lows
RANGE(source, length)range across the windowRANGE(PRICE_CLOSE, 20)compact volatility-style reading
MOM(source, length)momentum over the windowMOM(PRICE_CLOSE, 10)directional numeric momentum
ROC(source, length)rate of change over the windowROC(PRICE_CLOSE, 10)percent-style momentum reading
FALLING(source, length)checks whether a series is fallingFALLING(PRICE_CLOSE, 3)falling condition
RISING(source, length)checks whether a series is risingRISING(PRICE_CLOSE, 3)rising condition
ALL_TIME_HIGH(source)all-time high of the sourceALL_TIME_HIGH(PRICE_HIGH)historical extreme check
ALL_TIME_LOW(source)all-time low of the sourceALL_TIME_LOW(PRICE_LOW)historical extreme check

Function Group 6: Advanced Math Tools

These are available, but they are not where most first strategy authors need to start.

FunctionWhat it does
POW(base, exponent)power function
SQRT(x)square root
SIGN(x)sign of the number
SUM(source, length)rolling math sum
CEIL(x)round upward
FLOOR(x)round downward
LOG(x)natural log
LOG10(x)base-10 log
EXP(x)exponential
SIN(x) COS(x) TAN(x)trig functions
ASIN(x) ACOS(x) ATAN(x)inverse trig functions
TODEGREES(x)radians to degrees
TORADIANS(x)degrees to radians

They are part of the current engine, but most strategy authoring starts with the earlier groups first.

Expressions You Can Actually Use

These are much more helpful than abstract syntax on their own.

Example 1: Wait for a confirmed bullish condition

BARSTATE_ISCONFIRMED && PRICE_CLOSE > PRICE_HLC3

Good use: - setup gates - entry gates - basic confirmed-bar filters

Example 2: Trigger only when price crosses up

CROSSOVER(PRICE_CLOSE, PRICE_HLC3)

Good use: - setup activation - entry trigger logic

Example 3: Only manage exits when a position exists

POSITION_ACTIVE

Good use: - exit gate conditions

Example 4: Place a take-profit 1% above average entry price

POSITION_AVG_PRICE * 1.01

Good use: - take-profit limit price

Example 5: Place a stop 1% below average entry price

POSITION_AVG_PRICE * 0.99

Good use: - stop-loss stop price

Example 6: Choose one price when in a trade and another when flat

POSITION_ACTIVE ? POSITION_AVG_PRICE * 1.01 : PRICE_CLOSE

Good use: - dynamic price formulas

What The Strategy Expects In Real Fields

This is one of the most useful sections on the page.

Fields that want yes-or-no logic

These want a boolean result:

  • setup_gate_condition
  • setup_active_when
  • setup_cancel_when
  • setup_reset_when
  • entry_gate_condition
  • entry_trigger_when
  • entry_cancel_when
  • take_profit_gate_condition
  • take_profit_trigger_when
  • take_profit_cancel_when
  • stop_loss_gate_condition
  • stop_loss_trigger_when
  • stop_loss_cancel_when

Good examples:

BARSTATE_ISCONFIRMED PRICE_CLOSE > PRICE_HLC3 POSITION_ACTIVE && BARSTATE_ISCONFIRMED

Fields that want a number

These want a numeric result:

  • entry_limit_price
  • entry_stop_price
  • take_profit_limit_price
  • take_profit_stop_price
  • stop_loss_limit_price
  • stop_loss_stop_price

Good examples:

PRICE_LOW POSITION_AVG_PRICE * 1.01 ROUND_TO_MINTICK(PRICE_HLC3)

What Makes An Expression Feel "Wrong" Even When It Looks Close

Most of the time, it is one of these:

ProblemWhat it usually looks likeBetter move
wrong token nameprice_close or a typo in a custom tokenuse the exact token name
wrong kind of resultwriting math in a yes-or-no fieldturn it into a comparison like PRICE_CLOSE > PRICE_HLC3
unsupported Pine habitwriting ta.ema(...) or math.abs(...)use the supported function style shown on this page
unsupported helperassuming every Pine helper exists herechoose from the supported helper groups instead
malformed history syntaxPRICE_CLOSE [1]write PRICE_CLOSE[1]
mixed ternary branch typesnumber on one side, bool on the othermake both branches the same kind of result

Use Parentheses Liberally

You do not need to memorize parser theory to write strong expressions. If the reading order feels even slightly unclear, add parentheses.

Example: BARSTATE_ISCONFIRMED && (PRICE_CLOSE > PRICE_HLC3 || CROSSOVER(PRICE_CLOSE, PRICE_HLC3)) That makes your intent clearer immediately.

A Good Verification Habit

After you write an expression: 1. say it out loud in plain English 2. make sure it reads like what you intended 3. check that the field wants a bool or a number 4. verify it on the chart with the expression value label if needed

That one habit usually catches a lot before the strategy ever feels "mysterious."

What To Read Next