Rule Language Reference

Complete guide to writing deterministic trading rules

A simple, sandboxed language for conditional trading logic with no loops or recursion

Quick Start

Minimal Rule Example

rule simple_routing:
  if action == "BUY" goto buy
  if action == "SELL" goto sell
  goto end

:buy
  place_order(symbol=symbol, side="BUY", quantity=quantity, type="market")
  send_message("Buy order placed")
  goto end

:sell
  place_order(symbol=symbol, side="SELL", quantity=quantity, type="market")
  send_message("Sell order placed")
  goto end

:end
  end

Rule Structure

Declaration

Every rule starts with a rule declaration:

rule rule_name:

Rule names must start with a letter or underscore, followed by letters, numbers, or underscores.

Labels

Labels mark jump targets for goto and if commands:

:label_name

Execution Flow

Rules execute top-to-bottom unless redirected by goto or if commands. All rules must end with the end command.

Comments

# This is a comment

Commands

set - Variable Assignment

Assign a value to a variable:

set stop_price = price * 0.98
set qty = quantity / 2
set message = "Order for " + symbol

if - Conditional Jump

Jump to a label if condition is true:

if action == "BUY" goto buy_logic
if quantity > 10 goto large_order
if price < 50000 goto low_price

goto - Unconditional Jump

goto end

spawn - Execute Another Rule

Execute another rule with a copy of the current context:

spawn risk_check

⚠️ Note: Spawned rules run in isolated contexts - no shared state

end - Terminate Execution

end

Actions

place_order

Place a trading order:

place_order(symbol=symbol, side="BUY", quantity=1.0, type="market")
place_order(symbol="BTCUSDT", side="SELL", quantity=qty, type="limit", price=50000)
  on_error goto error_handler

Parameters:

  • symbol - Trading pair (string)
  • side - "BUY" or "SELL" (string)
  • quantity - Order size (number)
  • type - "market" or "limit" (string)
  • price - Limit price (number, required for limit orders)

Sets: last_order_id variable

send_message

Send a Telegram notification:

send_message("Order placed for " + symbol)
send_message("Buy at " + price + ", qty: " + quantity)

Messages are sent to the user's active Telegram connection.

cancel_order

cancel_order(order_id=last_order_id)

⚠️ Coming in Phase 2 - currently stubbed

Variables & Expressions

Webhook Payload Variables

All webhook fields are available as variables:

  • symbol, action, quantity, price
  • timestamp, user_id, exchange_id
  • Any custom fields from your webhook

System Variables

  • last_order_id - Set after successful place_order
  • last_error - Set when action fails (for on_error handling)

Operators

Arithmetic

+ - * / %

Comparison

== != < > <= >=

Logical

and or not

String

+ (concatenation)

Error Handling

Actions can fail (network errors, invalid parameters, etc.). Use on_error goto label to handle failures:

place_order(symbol=symbol, side="BUY", quantity=qty, type="market")
  on_error goto retry

send_message("Order placed successfully")
goto end

:retry
  send_message("Order failed: " + last_error)
  # Try with different parameters or notify user
  goto end

:end
  end

Example Rules

Example 1: Dynamic Stop Loss

rule buy_with_stop:
  if action != "BUY" goto end

  set stop_price = price * 0.98
  set qty = quantity

  place_order(symbol=symbol, side="BUY", quantity=qty, type="market")
    on_error goto error

  send_message("Buy order placed at " + price + ". Stop: " + stop_price)
  goto end

:error
  send_message("Order failed: " + last_error)
  goto end

:end
  end

Example 2: Multi-Exchange Routing

rule multi_exchange:
  if symbol == "BTC-USD" goto crypto
  if symbol == "EURUSD" goto forex
  goto unsupported

:crypto
  place_order(symbol=symbol, side=action, quantity=1.0, type="market")
  send_message("Crypto order: " + symbol)
  goto end

:forex
  place_order(symbol=symbol, side=action, quantity=0.1, type="market")
  send_message("Forex order: " + symbol)
  goto end

:unsupported
  send_message("Symbol not supported: " + symbol)
  goto end

:end
  end

⚠️ Limitations (By Design)

  • No loops - Backward jumps are forbidden
  • No recursion - Rules cannot spawn themselves
  • No dynamic rule names - spawn targets must be literal strings
  • Max 1000 instructions - Safety limit per execution
  • 30 second timeout - Maximum execution time

These limitations ensure rules are deterministic, predictable, and safe for production trading.

Ready to Create Your First Rule?

Start building custom trading logic in minutes