Language reference · live
MuseScript
A small, honest language for describing trading strategies — legible enough to hand-write, structured enough for an evolution engine to discover. Every example on this page is editable and runs in your browser on the same three-backend engine the desktop app ships. Nothing is uploaded; runs are seeded and reproducible.
01
Anatomy of a strategy
A strategy declares params (tunable inputs with a type and a default), then a strategy block with event handlers. onBar runs once per bar with open, high, low, close, and volume in scope. You emit orders with long(), flat(), and short(); a guard fires with when condition: { … }.
The canonical dual-SMA crossover. Edit `fast`/`slow` in the params and re-run — the numbers change live. On a driftless random walk with no planted edge, expect an honest NO-GO.
02
Signals & control flow
Conditions are boolean expressions. The stateful edge-detectors — crossover(a, b), crossunder(a, b), rising(x, n), falling(x, n)— fire only on the bar the event happens, so a guard doesn't re-trigger every bar the condition stays true. Combine gates with &&/||, or the variadic all_of(…) / any_of(…).
A trend-plus-momentum gate: only go long when price is above its slow average AND RSI is rising. Exit when price loses the trend line.
03
Indicators
The usual toolbox is built in and incrementally computed (no O(n²) refolds): sma, ema, wma, rma, rsi, atr, mom, roc, stdev, highest, lowest, vwap. Multi-output indicators return a struct you read by field: macd(close).macd, bbands(close, 20, 2).upper, stoch(14, 3, 3).k, donchian(20).mid.
A Bollinger-band mean-reversion sketch: buy the lower band, exit at the midline. Reads two struct fields off one `bbands` call.
04
The candle-pattern DSL
A small vocabulary for describing candle shapes — designed to read cleanly by hand and to be discoverable by the evolution engine. Each takes i bars back (0 = current): candle_body(i), candle_body_abs(i), candle_upper_wick(i), candle_lower_wick(i), candle_dir(i) (+1/−1), and the ATR-normalized candle_range_atr(i, n) and candle_gap(i, n). Count how many recent bars satisfy a condition with count_true(…); measure recency with bars_since(cond).
A hammer-ish reversal: a long lower wick relative to a small body, after a run of down bars. Scale-free (wick vs body), so it transfers across instruments.
There's a whole candle-pattern cookbook — hammer, engulfing, doji, marubozu, pin bar, three soldiers and more, each runnable.
05
Position & risk
Inside onBar (and the optional onPosition handler) you can read live position state: position(), entry_price(), bars_in_trade(), return_since_entry(), unrealized_pnl_pct(). For exits, trail(dist) is a peak-following ratchet stop — pair it with atr for a volatility-scaled trail that follows a winner up and only exits on a real pullback.
Enter on a breakout of the 20-bar high; exit on a 2·ATR trailing stop or after a time limit. `trail()` is inert while flat, so it's safe to leave in an unconditional exit guard.
06
Multi-asset & portfolios
The same language scales to a universe. Gate per-instrument with asset_is("BTC") / symbol_is(…); read another symbol's series with close_of(sym, n), rsi_of(sym, n), sma_of(sym, n). Rank the universe with scan_top / scan_bottom or the composable bag_* family, then express a target book with rebalance_equal(…), target_weight(sym, w), or portfolio_apply(bag). These need a panel of symbols, so they run in the Studio and the desktop app rather than the single-tape sandbox here.
strategy XSMomentum {
onBar {
// rank the universe by 60-bar momentum, hold the top 5 equally
winners = bag_rank_mom(60, 5, "mom60")
rebalance_equal(bag_symbols(winners))
}
}07
The honesty layer
Every run comes back with a truthReport, and the reference deliberately shows it above the naked Sharpe. A high in-sample Sharpe is easy and usually a lie; the engine reports a verdict after a deflated Sharpe ratio (DSR), a null-Sharpe baseline (what a coin-flip on the same tape scores), a probability of backtest overfitting (PBO), and a minimum-trades gate. On a no-edge random walk the honest answer is NO-GO — and the tool says so.
Same crossover as §1, run longer. Watch the verdict and DSR, not the Sharpe. If you can edit this into a GO on a driftless walk without more trials, you've found a bug — tell us.
This is the whole posture of the product: the language and the engine make it easy to be honest and hard to fool yourself. That's what the verifier and the certified-calibration receipts are built on.
08
Builtin index
The core surface, grouped. This is the hand-writing and evolution vocabulary; the full runtime also ships numeric (np_*), dataframe (pd_*), graph, and program-synthesis (tune, walkforward, distill) families for advanced work in the Studio.
Indicators
- sma(src, n)
- Simple moving average.
- ema(src, n)
- Exponential moving average.
- wma(src, n)
- Weighted moving average.
- rma(src, n)
- Wilder's smoothing (RSI/ATR base).
- rsi(src, n)
- Relative strength index.
- atr(src, n)
- Average true range; atr(n) also accepts implicit OHLC.
- mom(src, n)
- Momentum: src − src[n].
- roc(src, n)
- Rate of change (%).
- stdev(src, n)
- Rolling standard deviation.
- highest(src, n)
- Highest value over n bars.
- lowest(src, n)
- Lowest value over n bars.
- vwap()
- Volume-weighted average price.
- slope(src, n)
- OLS per-bar slope — signed trend strength.
- zscore_roll(src, n)
- Rolling z-score of src vs its window.
- percent_rank(src, n)
- Percentile rank in [0,1] over n bars.
Multi-output indicators
Return a struct — read by field.
- macd(src, f, s, sig).macd | .signal | .hist
- MACD line, signal, histogram.
- bbands(src, n, k).upper | .mid | .lower
- Bollinger bands.
- stoch(k, d, sm).k | .d
- Stochastic oscillator.
- donchian(n).upper | .mid | .lower
- Donchian channel (`.middle` aliases `.mid`).
Signals & control flow
- crossover(a, b)
- True on the bar a crosses above b.
- crossunder(a, b)
- True on the bar a crosses below b.
- rising(x, n)
- x has risen for n bars.
- falling(x, n)
- x has fallen for n bars.
- all_of(…) / any_of(…)
- Variadic AND / OR over booleans.
- count_true(…)
- How many of the given conditions are true.
- bars_since(cond)
- Bars since cond was last true (0 = now).
Candle-pattern DSL
i = bars back (0 = current bar).
- candle_body(i)
- Signed close − open.
- candle_body_abs(i)
- Absolute body size.
- candle_upper_wick(i)
- Upper shadow length.
- candle_lower_wick(i)
- Lower shadow length.
- candle_dir(i)
- +1 up bar, −1 down bar.
- candle_range_atr(i, n)
- Bar range normalized by ATR(n).
- candle_gap(i, n)
- Open-vs-prior-close gap, ATR-normalized.
Orders
- long() / short() / flat()
- Go long, short, or close. Optional tag: flat("stop").
- orders_pending()
- Count of unfilled orders.
- orders_cancel_all()
- Cancel pending orders.
Position & risk
- position()
- Signed position size (0 = flat).
- entry_price()
- Average entry price of the open position.
- bars_in_trade()
- Bars since entry.
- return_since_entry()
- Return since entry.
- unrealized_pnl() / _pct()
- Open P&L, absolute or percent.
- highest_since_entry(f) / lowest_since_entry(f)
- Extreme of field f since entry.
- trail(dist)
- Peak-following ratchet stop; inert while flat.
- cash() / equity()
- Available cash / total equity.
Multi-asset
Panel/universe strategies (run in Studio & desktop).
- asset_is(sym) / symbol_is(sym)
- Gate logic to one instrument.
- symbols() / sym_available(sym)
- The live universe / membership test.
- close_of / open_of / high_of / low_of / volume_of (sym, n)
- Another symbol's OHLCV.
- sma_of / ema_of / mom_of / rsi_of (sym, n)
- Another symbol's indicators.
- fund_of(sym, field, n)
- Fundamental field lookup.
- scan_top(dict, n) / scan_bottom(dict, n)
- Top/bottom-n symbols by a scored dict.
Portfolio & bags
Composable target-book algebra.
- bag_rank_mom / bag_rank_rsi / bag_rank_field
- Rank the universe into a weighted bag.
- bag_add / bag_sub / bag_mask / bag_scale / bag_norm
- Combine and reshape bags.
- rebalance_equal(syms)
- Equal-weight a symbol list.
- target_weight(sym, w)
- Set a target weight for one symbol.
- portfolio_apply / portfolio_add / portfolio_sub
- Apply a bag as the target book.
- pos(sym) / weight_of(sym) / holdings()
- Inspect the current book.
Math & utility
- min(…) / max(…)
- Arity-aware: 1 arg reduces an iterable, 2+ is element-wise.
- sum(xs) / avg(xs) / count(xs)
- Reductions over an iterable.
- clamp(x, lo, hi)
- Constrain x to [lo, hi].
- nz(x, fallback) / na(x)
- Null-coalesce / is-not-available test.
- window(src, n) / ohlcv_window(n)
- Materialize the last n bars as a vector.
Honesty & diagnostics
- truthReport
- Per-run verdict, DSR, null-Sharpe, PBO, gates — returned by every run.
- sharpe / sortino / max_drawdown (equity)
- Risk-adjusted stats over an equity curve.
- diag_drawdown / diag_underwater / diag_acf
- Drawdown, underwater, autocorrelation diagnostics.
- plot / plotshape / hline / bgcolor
- Chart overlays for the Studio.
Keep going
- Strategy Studio — a full IDE with a persistent library, backtests across three backends, tuning, and ensembles.
- Getting started — install the desktop app and bring up a local node.
- Tour the engine — watch each stage run and explain itself.