Athanor .at DSL Reference

The Athanor .at language defines scalar factors over market data sources. A file is a sequence of factor declarations. Each declaration gives a public factor name and an expression that computes its value.

First Factor

factor spread :=
    Bar.close - Bar.open

The name after factor is the factor identifier. The expression after := describes the value computed for each source update.

Factor Declarations

factor name :=
    expression

Factor names use ordinary identifiers:

factor book_spread :=
    Book.ask[1] - Book.bid[1]

factor spread_abs :=
    ABS spread

Declarations may reference factors declared elsewhere in the same input set. The compiler resolves those references before code generation.

Bar Fields

Bar fields read the current bar payload:

Bar.open
Bar.high
Bar.low
Bar.close
Bar.volume

Example:

factor typical_price :=
    (Bar.high + Bar.low + Bar.close) / 3

Book Fields

Book fields read one positive order-book level:

Book.bid[1]
Book.ask[1]
Book.bid_qty[1]
Book.ask_qty[1]

bid and ask read prices. bid_qty and ask_qty read quantities. The bracket value is the visible book level.

Example:

factor book_mid :=
    (Book.bid[1] + Book.ask[1]) / 2

factor book_spread :=
    Book.ask[1] - Book.bid[1]

Numbers

Numeric literals are scalar values:

2
2.
0.5
-1

Arithmetic

Arithmetic expressions combine scalar values:

a + b
a - b
a * b
a / b

Example:

factor bar_return :=
    (Bar.close - Bar.open) / Bar.open

Comparison

Comparison expressions produce numeric conditions:

a > b
a >= b
a < b
a <= b
a == b

Comparisons are most often used inside conditional expressions.

Conditional Expressions

IF condition THEN true_expr ELSE false_expr

Example:

factor spread_sign :=
    IF spread > 0 THEN
        1
    ELSE
        -1

When the condition evaluates away from zero, the true branch is used. When the condition evaluates to zero, the false branch is used.

Pure Operators

Pure operators transform the current expression value:

Operator

Meaning

Example

ABS x

Absolute value

ABS spread

SQRT x

Square root

SQRT variance

POW x n

Power with a numeric exponent

POW spread 2

Parentheses group compound arguments:

factor spread_sqrt :=
    SQRT (ABS spread)

Window Operators

Window operators evaluate over the factor’s active time window:

Operator

Meaning

Example

SUM x

Rolling sum

SUM spread

MEAN x

Rolling mean

MEAN spread

STD x

Rolling standard deviation

STD spread

NORM x

Rolling z-score

NORM spread

MIN x

Rolling minimum

MIN spread

MAX x

Rolling maximum

MAX spread

RANK x

Rolling rank percentile

RANK spread

Example:

factor spread_mean :=
    MEAN spread

Lag Operators

Lag operators keep a short scalar history:

Operator

Meaning

Example

LAG x n

Value from n updates ago

LAG spread 1

DIFF x

Current value minus previous value

DIFF spread

Example:

factor return_1 :=
    (Bar.close - LAG Bar.close 1) / LAG Bar.close 1

Windows

A windowed factor may receive its window from the attachment site:

factor spread_mean :=
    MEAN spread

A fixed window is declared with ~window:

factor spread_mean12 := ~window:12
    MEAN spread

The window belongs to the factor declaration. Window operators inside that factor use the declaration’s active window.

Function-Style Calls

Operators can also use function-style calls with adjacent parentheses:

LAG(spread, 1)
POW(spread, 2)

Space-call style is the canonical form for ordinary formulas:

LAG spread 1
POW spread 2

Source Families

Each factor is evaluated on one source family. Bar factors run from bar updates; Book factors run from book updates.

Bar factor:

factor hl_range :=
    Bar.high - Bar.low

Book factor:

factor top_spread :=
    Book.ask[1] - Book.bid[1]

Book Examples

Top-of-book mid price:

factor book_mid :=
    (Book.bid[1] + Book.ask[1]) / 2

Smart price:

factor smart_price :=
    (Book.bid[1] * Book.ask_qty[1] + Book.ask[1] * Book.bid_qty[1])
    / (Book.bid_qty[1] + Book.ask_qty[1])

Visible depth imbalance:

factor depth_bid :=
    Book.bid_qty[1] + Book.bid_qty[2] + Book.bid_qty[3]

factor depth_ask :=
    Book.ask_qty[1] + Book.ask_qty[2] + Book.ask_qty[3]

factor depth_imb :=
    IF depth_bid + depth_ask > 0 THEN
        (depth_bid - depth_ask) / (depth_bid + depth_ask)
    ELSE
        0

Bar Examples

Typical price:

factor typical_price :=
    (Bar.high + Bar.low + Bar.close) / 3

Rolling volatility:

factor return_1 :=
    (Bar.close - LAG Bar.close 1) / LAG Bar.close 1

factor volatility := ~window:20
    STD return_1

Directional volume flow:

factor obv_flow :=
    IF return_1 > 0 THEN
        Bar.volume
    ELSE
        -Bar.volume

Style

Use snake_case factor names:

factor spread_std :=
    STD spread

Use full Bar field names:

Bar.close
Bar.volume

Use bracketed Book levels:

Book.bid[1]
Book.ask_qty[1]

Use uppercase operators:

ABS spread
MEAN spread
LAG spread 1

Use multiline conditionals for branch formulas:

factor spread_std_or_zero :=
    IF spread > 0 THEN
        STD spread
    ELSE
        0

Generated output

Athanor applies semantics-preserving optimization before it emits C++. The generated implementation can therefore be reordered or structurally simpler than the source formula. Do not depend on a one-to-one mapping between .at syntax and generated statements.

The header includes generated documentation for each factor, including its source family, window behavior, implementation shape, readiness, and estimated complexity. Treat the header as a build artifact: regenerate it from the .at inputs instead of editing it.