DSL Reference

Complete reference for the .algomln strategy language.

v0.1.0 Stable

AlgoMLN strategies are written in .algomln files — a small, intentionally limited domain-specific language. It is rules-only: no variables, no loops, no state. Just conditions and actions. The simplicity is by design — strategies should be readable at a glance.

The language is case-insensitive for keywords. Blank lines and # comments are allowed anywhere. Indicator periods and quantities must be positive integers.

Strategies compile through a full pipeline: Lexer → Parser → AST → Validator → Runtime Engine → ExecutionTarget. The same compiled strategy runs backtests, paper trading, and live trading — there is no separate live code path.

Grammar

Formal grammar of the .algomln language in EBNF notation:

EBNF
strategy       = rule+

rule           = "WHEN" condition NEWLINE action

condition      = comparison
               | cross_expr
               | not_expr
               | logical_expr
               | position_expr    ← parses, not yet evaluated
               | time_window      ← parses, not yet evaluated

comparison     = expr operator expr
operator       = "<" | ">" | "<=" | ">=" | "==" | "!="

logical_expr   = condition "AND" condition
               | condition "OR" condition

not_expr       = "NOT" "(" condition ")"

cross_expr     = "cross_above" "(" expr "," expr ")"
               | "cross_below" "(" expr "," expr ")"

expr           = indicator_call | price_field | number

indicator_call = indicator "(" integer ")"
indicator      = "ema" | "ma" | "rsi" | "rel_vol" | "atr" | "vwap"
               | "bb_upper" | "bb_lower" | "bb_mid"

price_field    = "close" | "open" | "high" | "low" | "volume"
               | "prev_close" | "prev_open" | "prev_high" | "prev_low"

action         = "BUY" integer
               | "SELL" integer
               | "SELL" "ALL"

Price Fields

These identifiers resolve to values from the current (or previous) candle:

Field Description
closeCurrent candle close price
openCurrent candle open price
highCurrent candle high price
lowCurrent candle low price
volumeCurrent candle volume
prev_closePrevious candle close price
prev_openPrevious candle open price
prev_highPrevious candle high price
prev_lowPrevious candle low price

Indicators

All built-in indicators are pure Rust functions — stateless and deterministic. They use a bounded window provider to stay O(N) regardless of history length. Custom indicators can be registered via the Plugin System.

Indicator calls take the form indicator_name(period) where period must be a positive integer.

ma — Simple Moving Average

Arithmetic mean of the last N close prices.

algomln
WHEN close > ma(50)
BUY 10

ema — Exponential Moving Average

Exponentially weighted moving average, giving more weight to recent candles. Used for crossover strategies.

algomln
WHEN cross_above(ema(20), ema(50))
BUY 10

rsi — Relative Strength Index

Momentum oscillator in the range 0–100. Values below 30 indicate oversold; above 70 indicate overbought. Typical period: 14.

algomln
WHEN rsi(14) < 30
BUY 1

WHEN rsi(14) > 70
SELL ALL

atr — Average True Range

Measures market volatility. The true range is the greatest of: current high−low, |current high−prev close|, |current low−prev close|. ATR averages this over N candles.

algomln
WHEN atr(14) > 50
BUY 5

vwap — Volume Weighted Average Price

Average price weighted by volume over the given period. Commonly used as a dynamic support/resistance level.

algomln
WHEN close > vwap(20)
BUY 5

rel_vol — Relative Volume

Current candle volume relative to the average volume over N candles. A value of 2.0 means twice the average volume — useful for detecting breakouts.

algomln
WHEN rel_vol(20) > 2 AND close > ma(50)
BUY 10

bb_upper / bb_mid / bb_lower — Bollinger Bands

Bollinger Bands consist of a middle band (simple moving average) and upper/lower bands at ±2 standard deviations. All three share the same period parameter and are computed together for efficiency.

IndicatorReturns
bb_upper(period)Middle band + 2 standard deviations
bb_mid(period)Simple moving average (same as ma)
bb_lower(period)Middle band − 2 standard deviations
algomln
WHEN close < bb_lower(20)
BUY 10

WHEN close > bb_upper(20)
SELL ALL

Conditions

Conditions follow the WHEN keyword and determine when a rule fires.

Trigger state machine: A rule only fires on a false → true transition. Once a rule is true, it will not fire again until it first becomes false. This prevents WHEN close > 0 / BUY 1 from firing on every candle.

Comparison

Compare any two expressions using a standard operator:

OperatorMeaning
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal
==Equal
!=Not equal
algomln
WHEN close > ma(50)
BUY 5

WHEN rsi(14) >= 70
SELL ALL

Cross Detection

Crossovers fire on the exact candle where the fast value crosses the slow value. The CrossDetector internally stores the previous candle values for each rule and compares them after evaluation — so all rules within a cycle see consistent previous-candle state.

algomln
# Fires when ema(20) crosses above ema(50)
WHEN cross_above(ema(20), ema(50))
BUY 10

# Fires when ema(20) crosses below ema(50)
WHEN cross_below(ema(20), ema(50))
SELL ALL

Logical — AND / OR / NOT

Combine conditions with AND, OR, or negate with NOT(...).

algomln
# AND — both must be true
WHEN ema(9) > ema(21) AND rsi(14) < 60
BUY 5

# OR — either is sufficient
WHEN rsi(14) > 75 OR close > bb_upper(20)
SELL ALL

# NOT — negation
WHEN NOT (rsi(14) > 70)
BUY 2

NOT requires parentheses around its condition: NOT (condition).

Actions

Actions follow the condition on the next line. They instruct the execution engine to place an order.

ActionDescription
BUY nBuy n units of the strategy symbol at current close price
SELL nSell n units
SELL ALLClose the entire position (sell all held units)

Quantities (n) must be positive integers. Partial sells greater than held units are clamped to the position size by the PaperBroker.

Examples

RSI Oversold / Overbought

algomln
WHEN rsi(14) < 30
BUY 1

WHEN rsi(14) > 70
SELL ALL

EMA Crossover

algomln
WHEN cross_above(ema(20), ema(50))
BUY 10

WHEN cross_below(ema(20), ema(50))
SELL ALL

Compound Condition

algomln
WHEN ema(9) > ema(21) AND rsi(14) < 60
BUY 5

WHEN rsi(14) > 75
SELL ALL

Bollinger Band Breakout

algomln
WHEN close < bb_lower(20)
BUY 10

WHEN close > bb_upper(20)
SELL ALL

VWAP + Volume Filter

algomln
# Only buy if volume is elevated and price is above VWAP
WHEN close > vwap(20) AND rel_vol(20) > 1

BUY 5

WHEN close < vwap(20)
SELL ALL

Limitations

These features parse successfully but are not yet evaluated at runtime. Using them will not cause an error, but they will have no effect:

FeatureStatus
position_expr — position-based conditions (e.g., "if in position")Parses · Not Evaluated
time_window — time-based conditions (e.g., "between 9:30 and 15:30")Parses · Not Evaluated

Additional intentional constraints:

These constraints are intentional. The DSL is designed to be readable at a glance — a strategy should be self-evident from a 5-second read. Complex logic belongs in a plugin, not in the DSL itself.