Node Reference
Full specification of every Strategy Studio node — ports, parameters, and behavior.
Every built-in node, grouped by Library category. Notation: port:type for ports (* = required input); param(kind=default) for parameters.
coin params accept either a literal symbol such as BTC or the special "$CURRENT_MARKET" token, exposed in the Inspector as Current market. Every coin param defaults to Current market: the strategy trades the market you start it on.
Port types
There are 9 port types. They split into two axes of meaning — see Core Concepts for the full model.
| Type | Meaning | |
|---|---|---|
number | A scalar level/state, readable on any tick. | |
`number\ | candle` | Accepts a number or a candle; indicators use this for their value input (a candle is reduced via the source param). |
boolean | A sustained true/false level. | |
candle | One OHLCV bar { t, o, h, l, c, v }. | |
series<candle> | A rolling history of candles ( data.candles → history). | |
orderIntent | An order to be submitted, produced by an exec.* node. | |
signal<boolean> | A momentary boolean event — true for exactly the tick it fires. | |
signal<number> | A momentary numeric event — carries a value only on the tick it fires. | |
any | Untyped escape hatch; connects in either direction. |
Compatibility rule: identical types connect; any connects to anything; a signal<T> may feed the matching level (signal<boolean>→boolean, signal<number>→number/number|candle); but a level may not feed a signal<> input — convert it first with logic.edge. See signal vs level.
Per-node timeframe override
data.candles, clock.bar, ind.crossover, and every indicator carry an optional timeframe param:
- Empty (default) = inherit the graph's global timeframe (the
data.timeframenode). - A non-empty value must be a coarser timeframe and an integer multiple of the base (e.g. a
4hoverride on a1hgraph). The node resamples the base candle stream into higher-timeframe bars locally and only updates on each HTF bar close — it holds its last value between closes (no repaint). A finer or non-aligned override is a validation error.
This is how you read, e.g., a 4h EMA inside a 1h strategy. See Multi-timeframe.
Data
Market data sources: candles, prices, book, position, balance, funding, open interest, liquidations, run statistics.
data.timeframe — Timeframe
Sets the graph's global/base timeframe used by backtest, paper, and live runs. Exactly one allowed per graph.
- Out:
timeframe:any,minutes:number,ms:number - Params:
timeframe(timeframe="1h")
data.candles — Candles
OHLCV stream for a coin at the strategy timeframe (or the optional higher-timeframe override).
- Out:
candle:candle,close:number,high:number,low:number,open:number,volume:number,history:series<candle> - Params:
coin(coin="$CURRENT_MARKET"),timeframe(timeframe="")— empty = inherit graph timeframe; coarser override resamples to HTF bars
data.mid — Mid Price
Live mid from BBO if available; falls back to candle close. coin can be wired (e.g. a ui.coin); spot is true when the coin is a spot pair, and coin echoes the resolved symbol.
- In:
coin:any(optional; falls back to the param) - Out:
mid:number,spot:boolean,coin:any - Params:
coin(coin="$CURRENT_MARKET")
data.orderbook — Order Book BBO
Live best-bid/offer snapshot. Empty in backtest; live data in paper/live.
- Out:
bid:number,ask:number,mid:number,spread:number,bidSize:number,askSize:number,imbalance:number - Params:
coin(coin="$CURRENT_MARKET")
data.position — Position
Current open position for a coin. Paper/live populate liquidationPx, unrealizedPnl, cumFunding from clearinghouseState; backtest only has size + entryPx.
- In:
coin:any(optional; falls back to the param) - Out:
size:number,signedSize:number,side:number,entryPx:number,positionValue:number,unrealizedPnl:number,liquidationPx:number,marginUsed:number,leverage:number,leverageSetting:number,cumFundingSinceOpen:number,cumFundingAllTime:number - Params:
coin(coin="$CURRENT_MARKET")
side is 1 (long), -1 (short), or 0 (flat). leverageSetting is the position's leverage, else the account's leverage setting for the coin (NaN when unknown). Spot pairs (e.g. HYPE/USDC) read the wallet's base-token balance.
data.balance — Account Equity
Live perp account equity (mark-to-market). For spot wallet balances use data.spotBalance.
- Out:
equity:number,available:number(free margin: what open positions don't hold)
data.fundingRate — Funding Rate
Latest per-hour funding rate from Hyperliquid (paper/live). The engine debits/credits this rate against open positions each hour. NaN in backtest (no historical funding series is loaded).
- Out:
rate:number(hourly, e.g.0.0001= 1 bp/hr),annualized:number(rate × 24 × 365 × 100) - Params:
coin(coin="$CURRENT_MARKET")
data.fundingCountdown — Funding Countdown
Time until the next hourly funding settlement. Uses the runner's settlement time in paper/live, else derives the next top-of-hour from the tick clock (works in backtest too).
- Out:
seconds:number,minutes:number,nextMs:number(absolute timestamp of next settlement) - Params:
coin(coin="$CURRENT_MARKET")
data.openInterest — Open Interest
Latest open interest in coin units (paper/live). NaN in backtest — no historical OI series is loaded.
- Out:
oi:number(coin units),notional:number(oi × price, USD) - Params:
coin(coin="$CURRENT_MARKET")
data.takerPressure — Taker Pressure
Aggressor buy vs sell notional (USD) over a rolling window from the trades tape. pressure is the normalized net in [−1, 1] (+1 all buys, −1 all sells). Paper/live only — NaN in backtest.
- Out:
pressure:number,buy:number(USD),sell:number(USD),net:number(buy − sell),total:number(buy + sell) - Params:
coin(coin="$CURRENT_MARKET"),window(select="60")— 15s / 30s / 1m / 2m / 5m
data.liqVolume — Liquidation Volume
Share of taker volume that was liquidations over the rolling window. share is liq/total in [0, 1]; liq/total are notional (USD). Paper/live only — NaN in backtest.
- Out:
share:number,liq:number(USD),total:number(USD) - Params:
coin(coin="$CURRENT_MARKET"),window(select="60")— 15s / 30s / 1m / 2m / 5m
data.spotBalance — Spot Balance
Wallet balance of one spot token (USDC, HYPE, …). available = total − hold (hold = reserved by resting orders). Paper/live only. NaN in backtest.
- In:
token:any(optional; falls back to the param) - Out:
available:number,total:number,hold:number,entryNtl:number - Params:
token(string="USDC")(the token symbol as shown in your Balances tab)
data.prices — Prices
Mid, mark, oracle and last price for a coin, plus basis (mark − oracle) and premium %. Mark/oracle come from the perp asset context in paper/live; in backtest they equal the candle close.
- Out:
mid:number,mark:number,oracle:number,last:number,basis:number,premiumPct:number - Params:
coin(coin="$CURRENT_MARKET")
data.runStats — Run Stats
Trading statistics for this run: fills, entries and closed trades (run and today, UTC), realized PnL, streaks, drawdown from peak equity, day PnL, and time in position for a coin. Backtest counts simulated fills; live counts exchange fills.
- Out:
dayPnl:number,dayPnlPct:number,realizedToday:number,realizedRun:number,entriesToday:number,entriesRun:number,closedTradesToday:number,closedTradesRun:number,consecutiveLosses:number,consecutiveWins:number,lastTradePnl:number,winRate:number,drawdownPct:number,drawdownUsd:number,peakEquity:number,barsInPosition:number,msInPosition:number - Params:
coin(coin="$CURRENT_MARKET")(the coin for the in-position counters)
Indicator
Technical indicators. Most take a value/candle input and a period param. Every indicator carries the per-node timeframe(timeframe="") override param (omitted from the lists below for brevity — empty means inherit the graph timeframe).
Indicators that operate on a numeric value stream accept either a raw number or a full candle on their value input. When a candle is connected, the source param selects close, open, high, low, or volume (close by default).
Every numeric param listed below is also exposed as an optional input port of the same name (period, mult, …) — wire a ui.number / ui.slider to drive it live; unconnected ports fall back to the param.
Info
Warmup: every indicator emits NaN until its lookback is properly seeded — including composite indicators (MACD, ADX, DEMA, TEMA, Keltner, TSI, TRIX, Ichimoku, PSAR), which use TA-lib-style SMA/Wilder seeding instead of emitting finite-but-wrong values from bar 1. ind.highest/ind.lowest emit NaN (never ±Infinity) on an empty window. Downstream logic sees false from any comparison against NaN, so warmup can never fire a trade.
The sampled indicators (roc, momentum, zscore, stdev, highest, lowest) carry a sampleMode param whose default is barClose — one sample per bar close, so "period N" means N bars identically in backtest, paper, and live. change mode (per-tick sampling on live data) is an explicit opt-in.
See the Indicators page for grouping and notes.
ind.sma — SMA
Simple moving average over the connected value stream.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.ema — EMA
Exponential moving average. Seeded with SMA over period bars.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.wma — WMA
Linearly-weighted moving average. Most recent value has the largest weight.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.dema — DEMA
Double EMA. Reduces lag vs single EMA at the cost of overshoot.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.tema — TEMA
Triple EMA. Even less lag than DEMA.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.hma — HMA
Hull Moving Average — fast and smooth.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=16),source(select="close")
ind.kama — KAMA
Kaufman Adaptive Moving Average — adjusts smoothing with volatility.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=10),fast(int=2),slow(int=30),source(select="close")
ind.vwma — VWMA
Volume-weighted moving average: sum(price×vol) / sum(vol) over the last N bars. Needs a candle input for volume. source is close, open, high, low or hlc3; with hlc3 (typical price) it is a rolling VWAP over the last N bars.
- In:
candle:candle* - Out:
out:number - Params:
period(int=20),source(select="close")
ind.vwapSession — Session VWAP
Volume-weighted average price anchored to the start of each UTC day. Resets at the daily boundary. Uses the typical price (h+l+c)/3.
- In:
candle:candle* - Out:
out:number
ind.linreg — Linear Regression
Least-squares line fit over the last N values. value = the regression line's endpoint (current bar); slope = per-bar slope.
- In:
value:number|candle* - Out:
value:number,slope:number - Params:
period(int=20),source(select="close")
ind.macd — MACD
Moving Average Convergence Divergence. Outputs macd, signal, histogram. SMA-seeded EMAs: macd is NaN until the slow EMA is seeded, signal until signal-many macd values exist.
- In:
value:number|candle* - Out:
macd:number,signal:number,histogram:number - Params:
fast(int=12),slow(int=26),signal(int=9),source(select="close")
ind.rsi — RSI
Wilder's RSI on the connected value stream. Exact edge handling: all-gains → 100, all-losses → 0, fully flat (no gains and no losses) → neutral 50.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=14),source(select="close")
ind.stochRsi — Stoch RSI
Stochastic of RSI. Outputs %K and %D.
- In:
value:number|candle* - Out:
k:number,d:number - Params:
rsiPeriod(int=14),stochPeriod(int=14),kSmooth(int=3),dPeriod(int=3),source(select="close")
ind.stoch — Stochastic
Stochastic oscillator. Inputs: candle. Outputs %K and smoothed %D (0–100).
- In:
candle:candle* - Out:
k:number,d:number - Params:
kPeriod(int=14),kSmooth(int=3),dPeriod(int=3)
ind.cci — CCI
Commodity Channel Index over typical price.
- In:
candle:candle* - Out:
out:number - Params:
period(int=20)
ind.willr — Williams %R
Williams %R momentum oscillator (−100 to 0).
- In:
candle:candle* - Out:
out:number - Params:
period(int=14)
ind.mfi — Money Flow Index
Volume-weighted RSI. Inputs: candle.
- In:
candle:candle* - Out:
out:number - Params:
period(int=14)
ind.tsi — TSI
True Strength Index — double-smoothed momentum.
- In:
value:number|candle* - Out:
out:number - Params:
long(int=25),short(int=13),source(select="close")
ind.trix — TRIX
Triple-smoothed EMA rate-of-change (%). Momentum oscillator that filters out short-term noise.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=15),source(select="close")
ind.roc — Rate of Change
Percent change vs N bars ago.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=9),source(select="close"),sampleMode(select="barClose")
ind.momentum — Momentum
Difference vs N bars ago (absolute, not %).
- In:
value:number|candle* - Out:
out:number - Params:
period(int=10),source(select="close"),sampleMode(select="barClose")
ind.zscore — Z-Score
(value − mean) / stdev over N bars.
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close"),sampleMode(select="barClose")
ind.stdev — Stdev
Population standard deviation over N bars (matches Bollinger).
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),source(select="close"),sampleMode(select="barClose")
ind.realizedVol — Realized Volatility
Standard deviation of log returns over N bars, annualized by the bar timeframe (% per year); perBar is the same in % per bar. A regime gauge: size down or stand aside when it spikes, lean in when it compresses.
- In:
value:number|candle* - Out:
annualized:number,perBar:number - Params:
period(int=20),source(select="close")
ind.percentRank — Percent Rank
Where the current value sits inside its own last-N-bar range, 0–100 (100 = highest of the window). Turns any series (volume, ATR, funding, an oscillator) into an adaptive threshold.
- In:
value:number|candle* - Out:
rank:number - Params:
period(int=100),source(select="close")
ind.rvol — Relative Volume
Current bar volume divided by the average volume over the last N bars. >1 means above-average activity.
- In:
candle:candle* - Out:
out:number - Params:
period(int=20)
ind.highest — Highest
Highest value over the last N bars, optionally excluding the most recent offset bars. offset: 1 gives the *prior* N-bar high — what breakout logic needs so close > highest can be true on a new-high bar. Emits NaN on an empty/unfilled window (never ±Infinity).
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),offset(int=0),source(select="close"),sampleMode(select="barClose")
ind.lowest — Lowest
Lowest value over the last N bars, optionally excluding the most recent offset bars (see ind.highest). Emits NaN on an empty/unfilled window (never ±Infinity).
- In:
value:number|candle* - Out:
out:number - Params:
period(int=20),offset(int=0),source(select="close"),sampleMode(select="barClose")
ind.bollinger — Bollinger Bands
SMA basis ± k × stdev. Outputs basis, upper, lower, bandwidth, %b.
- In:
value:number|candle* - Out:
basis:number,upper:number,lower:number,bandwidth:number,percentB:number - Params:
period(int=20),mult(number=2),source(select="close")
ind.keltner — Keltner Channels
EMA basis ± k × ATR. Inputs: candle. Outputs basis, upper, lower. SMA-seeded EMA basis + Wilder-seeded ATR — NaN until period bars.
- In:
candle:candle* - Out:
basis:number,upper:number,lower:number - Params:
period(int=20),mult(number=2)
ind.donchian — Donchian Channels
Rolling high/low over N bars, optionally excluding the most recent offset bars. Inputs: candle. Outputs upper, lower, mid. offset: 1 gives the prior N-bar channel (breakouts); with offset > 0 all outputs are NaN until period + offset bars are buffered.
- In:
candle:candle* - Out:
upper:number,lower:number,mid:number - Params:
period(int=20),offset(int=0)
ind.pivots — Pivots (swing high/low)
Confirmed swing points: a bar is a pivot high when its high tops the left bars before and the right bars after it, so it confirms right bars late (pivot lows likewise). Outputs the last confirmed pivot high/low and a pulse when a new one confirms. Use it for support/resistance and structure breaks.
- In:
candle:candle* - Out:
high:number,low:number,newHigh:signal<boolean>,newLow:signal<boolean> - Params:
left(int=5),right(int=5)
ind.atr — ATR
Average True Range (Wilder smoothing). Seeded with the SMA of the first period true ranges.
- In:
candle:candle* - Out:
out:number - Params:
period(int=14)
ind.adx — ADX
Average Directional Index. Outputs ADX, +DI, −DI (Wilder). Wilder-seeded: DI is NaN until period bars; ADX needs a further period DX samples (first ADX around bar 2 × period).
- In:
candle:candle* - Out:
adx:number,plusDi:number,minusDi:number - Params:
period(int=14)
ind.aroon — Aroon
Aroon up/down/oscillator over N bars.
- In:
candle:candle* - Out:
up:number,down:number,osc:number - Params:
period(int=25)
ind.vortex — Vortex
Vortex Indicator — outputs VI+ and VI− over N bars.
- In:
candle:candle* - Out:
plus:number,minus:number - Params:
period(int=14)
ind.supertrend — Supertrend
Supertrend overlay. Outputs trend (+1 long, −1 short) and line value. Uses the standard final-band logic: a band ratchets only while price stays on its side and resets to the basic band once the previous close breaks through it (matches TradingView et al.).
- In:
candle:candle* - Out:
trend:number,line:number - Params:
period(int=10),mult(number=3)
ind.psar — Parabolic SAR
Welles Wilder PSAR. Outputs sar line + trend (+1/−1). Bar 1 emits NaN/0; the initial trend is derived from the first two closes (Wilder seeding).
- In:
candle:candle* - Out:
sar:number,trend:number - Params:
step(number=0.02),max(number=0.2)
ind.obv — OBV
On-Balance Volume — cumulative signed volume.
- In:
candle:candle* - Out:
out:number
ind.ichimoku — Ichimoku
Ichimoku Cloud — tenkan, kijun, senkouA, senkouB. The senkou outputs are the displaced cloud: the value AT the current bar, computed displacement bars ago (the standard charting definition). They stay NaN until the displacement buffer fills, so no logic runs against a partial cloud.
- In:
candle:candle* - Out:
tenkan:number,kijun:number,senkouA:number,senkouB:number - Params:
tenkan(int=9),kijun(int=26),senkouB(int=52),displacement(int=26)
ind.crossover — Crossover
Emits +1 when A crosses above B, −1 when below, 0 otherwise. cross is a numeric event; above is a sustained level (A > B). The cross steps only on bar-close ticks (intra-bar ticks emit cross: 0 and hold the last above); with an HTF override it fires at most once per HTF bucket.
- In:
a:number*,b:number* - Out:
cross:signal<number>,above:boolean - Params:
timeframe(timeframe="")
> For a clean boolean up/down event, prefer logic.cross (below).
Logic & Math
Comparisons, boolean ops, arithmetic, formulas, clocks, gates, series logic.
Sampling (sampleMode). Nodes that buffer a stream (math.window, state.memory, and the sampled indicators) carry a sampleMode param. The default is barClose: one sample per bar close, so "period N" means N bars identically in backtest, paper, and live. change opts in to per-tick sampling on live data (counts quote ticks, ≈10 Hz).
logic.compare — Compare
Boolean comparison of two numbers. tolerance makes ==/!= compare within an absolute epsilon (0 = exact float equality) — useful for computed prices that never match exactly. NaN input → false for every op (so != is *not* the negation of == under NaN).
- In:
a:number*,b:number* - Out:
out:boolean - Params:
op(select=">")— one of>,>=,<,<=,==,!=—tolerance(number=0)
logic.and — AND
Boolean AND of two inputs.
- In:
a:boolean*,b:boolean* - Out:
out:boolean
logic.or — OR
Boolean OR.
- In:
a:boolean*,b:boolean* - Out:
out:boolean
logic.not — NOT
Boolean negation.
- In:
a:boolean* - Out:
out:boolean
logic.math — Math
Arithmetic between two numbers.
- In:
a:number*,b:number* - Out:
out:number - Params:
op(select="+")— one of+,-,*,/,min,max
logic.constant — Constant
Static numeric constant.
- Out:
out:number - Params:
value(number=0)
logic.text — Text
Outputs a fixed text, e.g. status labels chosen with logic.select and shown with ui.status.
- Out:
out:any - Params:
text(string="")
logic.equals — Equals
True when a equals b: numbers, text (case-insensitive) or booleans. logic.compare is numeric only; use this to compare a side, a coin or a text value. false when either input is missing.
- In:
a:any*,b:any* - Out:
out:boolean
logic.select — Select
Outputs a while cond is true, else b. The building block for symmetric long/short logic (pick +size or −size, entry or exit price, …).
- In:
cond:boolean*,a:any*,b:any* - Out:
out:any
logic.edge — Edge
Pulses true on the tick a boolean rises (or falls) from false. This is the only way to turn a sustained level into a signal<> event.
- In:
in:boolean* - Out:
out:signal<boolean> - Params:
edge(select="rising")—risingorfalling
logic.cross — Cross
Detects A crossing B in either direction. Each output fires only on the bar the cross happens. Evaluated on bar-close ticks only (Pine semantics) — intra-bar live ticks emit false, so paper/live never see crosses a backtest wouldn't.
- In:
a:number*,b:number* - Out:
up:signal<boolean>(crossed above),down:signal<boolean>(crossed below),any:signal<boolean>(either)
logic.barssince — Bars Since
Number of bars since the condition was last true (0 on the bar it is true). NaN until it has been true at least once.
- In:
cond:boolean* - Out:
bars:number
logic.rising — Rising
True when the input has strictly increased over each of the last N bars.
- In:
in:number* - Out:
out:boolean - Params:
length(int=1)
logic.falling — Falling
True when the input has strictly decreased over each of the last N bars.
- In:
in:number* - Out:
out:boolean - Params:
length(int=1)
logic.valuewhen — Value When
The value of source on the Nth most recent bar where cond was true (occurrence 0 = most recent). NaN until enough occurrences seen.
- In:
cond:boolean*,source:number* - Out:
out:number - Params:
occurrence(int=0)
logic.count — Count
How many of the last N bar closes had in true. Use it for N-of-M confirmation (e.g. 3 of the last 5 bars closed above the band) or event frequency. all is true when every bar of a full window was true; any when at least one was.
- In:
in:boolean* - Out:
count:number,all:boolean,any:boolean - Params:
window(int=5)
clock.now — Timestamp
Current tick timestamp + decomposed parts. Use for time-of-day gates and session windows.
- Out:
ms:number,seconds:number(second within the current minute, 0–59),minute:number,hour:number,dayOfWeek:number(0 = Sunday … 6 = Saturday),dayOfMonth:number,month:number(1–12),year:number - Params:
tz(select="utc")—utcorlocal
clock.bar — Bar Close Clock
Fires true exactly once per bar close at the strategy timeframe (or the optional higher-timeframe override); false on intra-bar live ticks.
- Out:
tick:signal<boolean> - Params:
timeframe(timeframe="")— empty = strategy timeframe; coarser override fires once per HTF bar close
clock.boundary — New Hour / Day / Week
Fires one pulse on the first bar close of each new hour, day, week (Monday) or month, on any strategy timeframe. The natural clock for DCA, daily rebalancing or session resets. No pulse on the very first tick of a run or during warmup replay.
- Out:
tick:signal<boolean> - Params:
unit(select="day")(hour,day,week,month),tz(select="utc")(utcorlocal)
clock.everyMs — Every N ms
Fires on the first tick after each N-millisecond due boundary in ctx.now. Drives intra-bar timers / TWAP without drift. Warmup-safe: the schedule never emits during warmup replay and re-anchors at the warmup→live transition, so a run can't fire the instant it goes live.
- Out:
tick:signal<boolean> - Params:
ms(int=5000)
clock.everyN — Every N Bars
Fires true once every N bar closes; false on intra-bar live ticks and during warmup replay. A true reset re-anchors the counter: the resetting tick never fires, the resetting bar doesn't count, and the next fire is N bar closes later. A sustained-true reset holds the counter at zero — hold it while flat to turn this into a bars-since-entry time stop.
- In:
n:number— optional override; falls back to the param —reset:boolean - Out:
tick:signal<boolean> - Params:
n(int=5)
The counter starts fresh when the live run begins — warmup history does not advance it.
clock.session — Session Window
True while the current time is inside a session window [start, end) on the allowed days, at minute resolution. Overnight sessions (start > end) wrap past midnight; the days filter applies to the day the session starts, so a Fri 22:00→04:00 session stays active into Saturday morning.
- Out:
active:boolean,hour:number,dayOfWeek:number - Params:
startHour(int=9),endHour(int=17),startMinute(int=0),endMinute(int=0),days(string="1,2,3,4,5")(comma list, 0 = Sunday; empty = all days),tz(select="utc")—utcorlocal
math.expr — Formula
Arbitrary arithmetic over inputs a, b, c, d (e.g. (a+b)/2, a*b - c). Supports + − × ÷, parentheses, the constants pi and e, and functions min, max, abs, sqrt, pow, log.
- In:
a:number,b:number,c:number,d:number - Out:
out:number - Params:
expr(string="a + b")
math.window — Window Reduce
Rolling reduce (sum/mean/max/min/std/range) over the last N values of a stream.
- In:
in:number* - Out:
out:number - Params:
size(int=20),op(select="mean"),sampleMode(select="barClose")
math.clamp — Clamp
Constrain a number to [lo, hi].
- In:
in:number*,lo:number,hi:number - Out:
out:number - Params:
loFallback(number=0),hiFallback(number=1)
math.abs — Abs
Absolute value.
- In:
in:number* - Out:
out:number
math.batch — Batch
Adds amount on each tick add is true. When the total reaches min (and hold is false) it pulses out with the total in released, then starts over; pending is what's waiting. Typical use: collect the proceeds of each fill and place one order once they clear Hyperliquid's $10 minimum.
- In:
add:boolean*,amount:number*,hold:boolean - Out:
out:boolean,released:number,pending:number - Params:
min(number=12),minIntervalMs(number=0)(least time between two releases; 0 = no limit)
Gates & Timing
Pass-through gating and timing primitives. All are liveStateful — they keep their state across intra-bar ticks (see Core Concepts).
logic.gate — Gate
Pass value through when open is true. When closed, output is the last passed value (hold) or NaN (block).
- In:
value:any*,open:boolean* - Out:
out:any - Params:
mode(select="hold")—holdorblock
logic.latch — Latch (one-shot)
Rising-edge trigger arms the latch. Once armed, the next finite value passes through to out and the latch disarms. armed exposes the current state.
- In:
trigger:boolean*,value:any* - Out:
out:any,armed:boolean,fired:boolean - Params:
edge(select="rising"),passWhen(select="anyValue")
logic.hold — Hold
Outputs the last finite value. Updates only when the input changes to a new finite number; NaN leaves the held value unchanged.
- In:
value:number* - Out:
out:number
logic.sustain — Sustain
Holds the boolean in true for ms milliseconds after it goes false. Re-triggering during the sustain extends the window.
- In:
in:boolean* - Out:
out:boolean,remainingMs:number - Params:
ms(int=1000)
logic.delay — Delay (boolean)
Forwards each true pulse on in after ms milliseconds. The delay can be driven dynamically by the ms input port; the param is the fallback. Warmup-safe: nothing is queued during warmup replay (a historical pulse can never release into the live run).
- In:
in:boolean*,ms:number - Out:
out:boolean,pending:number - Params:
msFallback(int=1000)
logic.delayValue — Delay (number)
Holds a numeric value for ms milliseconds before emitting. Useful for staggering size/price signals. ms input overrides the fallback param. hold (default on) keeps emitting the last released value between releases; off emits it only on the release tick (NaN otherwise — a pulse). Warmup-safe like logic.delay.
- In:
in:number*,ms:number - Out:
out:number,pending:number - Params:
msFallback(int=1000),hold(boolean=true)
logic.toggle — Toggle (SR latch)
Set/Reset latch: a true set turns out on, a true reset turns it off. When both are true on the same tick, reset wins (safe default: a kill condition always beats an arm condition). The level survives warmup replay — it is state, not a pulse. Use it to turn one-bar pulses into a persistent regime level.
- In:
set:boolean,reset:boolean - Out:
out:boolean
logic.cooldown — Cooldown
Pass-through pulse suppressor: passes a pulse, then suppresses further pulses for bars bar closes and/or ms milliseconds (both set = until both expire). Prevents signal machine-gunning (e.g. one entry per RSI dip, then quiet for 12 bars). cooling is true while the suppression window is active.
- In:
in:boolean* - Out:
out:boolean,cooling:boolean - Params:
bars(int=0)(0 = no bar cooldown),ms(number=0)(0 = no time cooldown)
State
Persistent memory across ticks.
state.memory — Memory
Remembers the previous sample of an input. Outputs current + previous (use logic.valuewhen or math.window for deeper history).
- In:
in:number* - Out:
current:number,previous:number - Params:
sampleMode(select="barClose")
state.var — Variable
Stores latest input until overwritten.
- In:
set:number - Out:
out:number - Params:
initial(number=0)
state.extreme — Running High / Low
Highest and lowest value seen since reset was last true (e.g. the peak price since entry, for a trailing stop). A true reset clears both.
- In:
value:number*,reset:boolean - Out:
max:number,min:number
state.first — First Value
Holds the first live value of value (after warmup) for the rest of the run, e.g. the price when the strategy started. A true reset captures again. captured is true once a value is held.
- In:
value:any*,reset:boolean - Out:
out:any,captured:boolean
Risk
Order gating at the submit barrier. See the gating model.
risk.killSwitch — Kill Switch
When trip is true the latch sticks: every order this tick and thereafter is dropped at the submit barrier, managed orders are deactivated, and tracked resting orders are best-effort cancelled — tripping doesn't just block new orders, it pulls existing ones. The run stays alive (monitoring continues) but disarmed until restarted. Strongly recommended for live runs (not required). liveStateful — the trip survives intra-bar ticks.
- In:
trip:boolean - Out:
armed:boolean
risk.stop — Stop Strategy
When trip becomes true the entire run halts. Crucially, this tick's orders still submit first (so a same-tick close fires), then the run ends and any resting orders are cancelled. Use it for hard exits — daily loss limit reached, profit target hit, time's up.
- In:
trip:boolean* - Out:
stopped:boolean
> Distinct from risk.killSwitch: the kill switch disarms trading (drops new intents and cancels resting orders) while keeping the run alive and monitoring; risk.stop ends the run after letting the current tick's orders through.
risk.maxPositionSize — Max Position Size
ok is false when the coin's current position notional has reached maxNotional (USD). Wire ok into risk.preTradeValidate, or read it as a boolean gate. The engine also drops orders on this coin at the submit barrier when they would push the notional past the cap and increase exposure — exposure-reducing and reduce-only orders always pass, so the cap can never trap a position it can't close.
A wired max overrides maxNotional (e.g. an adjustable budget); cap outputs the cap in force. basis picks how the position is measured: mark (size × current price) or cost (size × entry price, for a budget). With thin (Shrink to fit) an order that would pass the cap is shrunk to the part that fits, if that is still a valid order, instead of dropped.
- In:
trigger:boolean,max:number - Out:
ok:boolean,cap:number - Params:
coin(coin="$CURRENT_MARKET"),maxNotional(number=5000),basis(select="mark")(markorcost),thin(boolean=false)
risk.maxFillSize — Max Fill Size
Cap total filled size (coin units) for a market over the run. Each fill accumulates toward maxSize; once reached, no further orders are submitted and the strategy stops (paper/live) or the backtest ends. maxSize 0 means no cap.
- In:
trigger:boolean - Out:
ok:boolean,filled:number,remaining:number - Params:
coin(coin="$CURRENT_MARKET"),maxSize(number=0.01)
risk.maxDailyLoss — Max Daily Loss
Blocks new exposure for the rest of the UTC day once the day's PnL (realized + unrealized, against day-start equity) falls below −limit. Closes and reductions still pass. Set a USD limit, a % of day-start equity, or both (the first hit wins; 0 = off). Enforced by the engine at the submit barrier; a new UTC day re-arms it. Wired inputs override the params.
- In:
limitUsd:number,limitPct:number - Out:
tripped:boolean,dayPnl:number,remaining:number - Params:
limitUsd(number=0),limitPct(number=2)
risk.maxTradesPerDay — Trade Throttle
Blocks new entries once maxEntries position-opening or adding fills have happened this UTC day (closes still pass; 0 = unlimited). With pauseAfterLosses above 0 it also blocks while the losing streak is at least that many trades. Enforced by the engine at the submit barrier. A false enabled turns it off.
- In:
maxEntries:number,enabled:boolean - Out:
blocked:boolean,entriesToday:number,remaining:number - Params:
maxEntries(int=5),pauseAfterLosses(int=0)
risk.preTradeValidate — Pre-Trade Validate
Functional gate. Wire an exec.* node's intent output into intent and a boolean into ok. When ok is false on a tick, the engine drops the intent emitted by that exec node at the submit barrier — not just the forwarded copy. Managed places are gated too. When ok is true (or unwired), the intent passes through unchanged. The engine gates on the node's explicit ok output (a managed exec node's intent port is always empty, so out alone can't distinguish "blocked" from "nothing to forward").
- In:
intent:orderIntent*,ok:boolean - Out:
out:orderIntent,ok:boolean
Execution
Order emission. All exec.* order nodes carry fireOnBarClose(boolean=true) — they no-op on intra-bar ticks unless set false. Size is floored to the market lot, limit price rounded to the tick, and sub-$10 notionals are rejected (paper/live; backtest also enforces lot/tick/min-notional when market metadata is present). Reduce-only orders skip the $10 minimum so dust positions can always be closed.
The size fallback param is now named sizeFallback; older graphs carrying defaultSize/size still read for back-compat.
fireMode (Trigger). Every fire-driven exec node carries fireMode(select="edge") and fireEveryMinutes(number=60):
edge(default, Once when it turns true): fire once per false→true transition offire. A gate that is simply held true (the classic failure mode of condition wiring) fires ONE order instead of stacking a fresh order every bar-close forever.level(Every bar while true): legacy behaviour: fire on every eligible tick whilefireis true. For graphs that pulsefirethemselves.first(First time only): one order for the whole run, the first timefireturns true.every(Every N minutes while true): whilefirestays true, an order at most everyfireEveryMinutes(Repeat every) minutes.
The edge is sampled in the same tick domain the node can fire in (bar-close-gated nodes sample fire only on bar-close ticks, so a pulse that rises intra-bar and holds into the close still fires). The latch survives warmup replay — a signal already true during warmup will not fire at live start. Managed exec.limit is level-driven by design, so fireMode does not apply there.
exec.market — Market Order
Emits a market order intent when fire pulses true. Size it in coins (size) or dollars (notional, converted at the current price); with neither wired, sizeFallback applies. coin can be wired (e.g. a ui.coin). A wired everyMinutes overrides fireEveryMinutes.
Fill outputs. filled is true on the tick a fill of this node's orders lands, with that tick's filledUsd / filledSize; fillSide is +1 (buy) or −1 (sell) of the last fill; filledTotalUsd / filledTotalSize sum the whole run. Other nodes can act on fills, e.g. feed each fill's proceeds into a math.batch that buys another coin.
Retry until filled (retryUnfilled): what didn't fill (a failed or partly filled order, or one that couldn't be sent) is re-sent as a new market order, at most every retryEveryMs, while holdRetries is false. unfilled / unfilledUsd report the fresh shortfall on a tick, retryPendingUsd what is still waiting to be retried; a remainder under the $10 minimum is dropped.
Total cap (maxTotal, coins) / Total cap ($) (maxTotalUsd): stop once this much has filled in total (in-flight orders count); each order is clipped to what's left. 0 = no cap. Wired inputs override the params. capReached turns true once the cap is used up and nothing is in flight.
Use available balance (waitForBalance): each order is sized to what the account can place right now at your Hyperliquid leverage. If that is under the $10 minimum, the node waits instead of failing (waitingBalance is true) and sends as soon as balance frees up, e.g. from profit. Set a large size to always use it all. Reduce-only orders are not affected. inFlight is true while an order of this node is sent and not yet filled or failed.
- In:
fire:boolean*,size:number,side:any,notional:number,coin:any,holdRetries:boolean,maxTotal:number,maxTotalUsd:number,everyMinutes:number - Out:
intent:orderIntent,filled:boolean,filledUsd:number,filledSize:number,fillSide:number,filledTotalUsd:number,filledTotalSize:number,unfilled:boolean,unfilledUsd:number,retryPendingUsd:number,inFlight:boolean,capReached:boolean,waitingBalance:boolean - Params:
coin(coin="$CURRENT_MARKET"),side(select="buy"),sizeFallback(number=0.01),reduceOnly(boolean=false),fireOnBarClose(boolean=true),fireMode(select="edge"),fireEveryMinutes(number=60),waitForBalance(boolean=false),retryUnfilled(boolean=false),maxTotalUsd(number=0),maxTotal(number=0),retryEveryMs(number=5000)
exec.twap — TWAP Order
On fire, executes a total size as a series of equal market-order slices spread evenly over a duration (time-weighted average price). The first slice fires immediately; the rest on schedule. A new fire while a TWAP is running is ignored (no restart, no duplicate schedule); in edge mode a held-true fire starts exactly one TWAP and does not auto-restart. The bar-close gate governs starting only: once running, due slices drain on any tick, and coarse cadence catches up by emitting all due slices at once. A rejected slice (min-notional, lot floor) is retried at the next interval, bounded at 5 attempts before being abandoned.
Slices are sized from what really filled: a slice that comes back unfilled or partly filled is made up by the next one, and up to 3 extra slices after the schedule finish a shortfall. A slice waits while an earlier one is still unanswered. A new run starts only once the previous run's orders have settled.
While pause is true, due slices wait and the schedule resumes where it paused, with no catch-up burst (e.g. while price is past a limit). With Stop when fire turns false (stopWhenFireDrops) the remaining slices are cancelled once fire is false, checked on the same ticks as the start. Outputs: the fill outputs of exec.market, plus active (running), paused, progress (0–1 of the total filled) and done (finished and settled).
- In:
fire:boolean*,size:number,side:any,duration:number,slices:number,reduceOnly:boolean,pause:boolean - Out:
intent:orderIntent,filled:boolean,filledUsd:number,filledSize:number,fillSide:number,filledTotalUsd:number,filledTotalSize:number,active:boolean,paused:boolean,progress:number,done:boolean - Params:
coin(coin="$CURRENT_MARKET"),side(select="buy"),sizeFallback(number=0.06)(TOTAL size),durationMinutes(number=30),slices(int=6),reduceOnly(boolean=false),fireOnBarClose(boolean=true),stopWhenFireDrops(boolean=false),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.limit — Limit Order
Emits a limit order intent. Size floored, price rounded to tick.
Managed mode (managed: true): the node represents ONE standing resting order the engine keeps reconciled — while fire is true it keeps exactly one order resting at the current price/size (re-pricing via cancel+replace, never duplicating); when fire goes false it cancels the order. Level-driven by design (fireMode n/a). When off (default) the node emits a fresh one-shot order each time it fires.
Managed-mode options: After a fill (afterFill) decides what happens once the resting order has filled: replace places a new one while fire stays true (grid refill), retrigger waits until fire turns false and true again, never places no other order this run. Re-price at bar close only (holdBetweenCloses, with fireOnBarClose off) rests the order as soon as fire turns true and re-prices it only at bar close (mid-bar it only shrinks), avoiding a cancel/replace on every tick. One-shot orders support Use available balance (waitForBalance, see exec.market).
- In:
fire:boolean*,price:number*,size:number,side:any - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="buy"),sizeFallback(number=0.01),postOnly(boolean=true),reduceOnly(boolean=false),managed(boolean=false),fireOnBarClose(boolean=true),holdBetweenCloses(boolean=false),afterFill(select="replace")(replace,retrigger,never),fireMode(select="edge"),fireEveryMinutes(number=60),waitForBalance(boolean=false)
exec.closePosition — Close Position
Closes the current position with a reduce-only market order on fire (no-op when flat). Being reduce-only, it skips the $10 minimum, so sub-$10 dust positions are closable. fraction closes only part of it (0.5 = half, for scale-outs); the fraction input overrides the param.
- In:
fire:boolean*,fraction:number - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),fraction(number=1),fireOnBarClose(boolean=true),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.stopMarket — Stop Market
Stop-loss market order. Rests until price crosses stopPx, then fills at market. Reduce-only by default. Whole position (wholePosition) sends Hyperliquid's native entire-position stop: it closes the whole position at trigger time and is cancelled when the position closes (perps only; wire the position size into size for backtest/paper).
- In:
fire:boolean*,stopPx:number*,size:number,side:any - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="sell"),sizeFallback(number=0.01),reduceOnly(boolean=true),fireOnBarClose(boolean=true),wholePosition(boolean=false),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.stopLimit — Stop Limit
Stop-loss that posts a limit order at limitPx once price crosses stopPx. Reduce-only by default.
- In:
fire:boolean*,stopPx:number*,limitPx:number*,size:number,side:any - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="sell"),sizeFallback(number=0.01),reduceOnly(boolean=true),fireOnBarClose(boolean=true),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.takeProfit — Take Profit
Take-profit market order. Rests until price moves favourably to targetPx, then fills at market. Reduce-only by default. Whole position (wholePosition) works as on exec.stopMarket.
- In:
fire:boolean*,targetPx:number*,size:number,side:any - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="sell"),sizeFallback(number=0.01),reduceOnly(boolean=true),fireOnBarClose(boolean=true),wholePosition(boolean=false),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.trailingStop — Trailing Stop
Stop that ratchets to stay trailDistance (price units) from the best price seen, only ever tightening toward the market. Reduce-only. The ratchet is simulated in backtest/paper; live submits a static trigger at the initial offset (Hyperliquid has no native trailing order) — see Backtest Modeling.
- In:
fire:boolean*,trailDistance:number*,size:number,side:any - Out:
intent:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="sell"),sizeFallback(number=0.01),fireOnBarClose(boolean=true),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.bracket — Bracket Order
Entry market order plus a protective stop and take-profit, emitted together. Stop + target are reduce-only triggers on the opposite side. The stopPx / targetPx legs are optional (omitted when their input is unwired or non-positive). In backtest/paper the stop and target are OCO — whichever fires first cancels the sibling; live submits them as independent trigger orders (no native OCO), so the surviving leg must be managed.
- In:
fire:boolean*,size:number,side:any,stopPx:number,targetPx:number - Out:
entry:orderIntent,stop:orderIntent,target:orderIntent - Params:
coin(coin="$CURRENT_MARKET"),side(select="buy"),sizeFallback(number=0.01),fireOnBarClose(boolean=true),fireMode(select="edge"),fireEveryMinutes(number=60)
exec.targetPosition — Target Position
Reconciles the position to a target signed size (+long / −short / 0 flat) with market orders: opens, adds, reduces, closes or flips as needed. Reductions are reduce-only. Fires at most once per cooldownBars bar closes and ignores adjustments below the market lot or minDelta; minDeltaPct also ignores adjustments smaller than that % of the target (flattening always fires). maxStepUsd (Max per order) splits big adjustments into steps, one per cooldown (0 = all at once). A false enabled pauses it. Spot pairs read the wallet's base-token balance as the current size.
- In:
target:number*,enabled:boolean,coin:any,maxStepUsd:number,minDeltaPct:number - Out:
intent:orderIntent,delta:number(target − current),current:number - Params:
coin(coin="$CURRENT_MARKET"),minDelta(number=0),minDeltaPct(number=0),maxStepUsd(number=0),cooldownBars(int=1),fireOnBarClose(boolean=true)
exec.sizeByRisk — Size by Risk
Position size from a fixed dollar risk and a stop distance: size = riskUSD / |entry − stop|. Emits coin-unit size — wire size into an exec node's size input. (Pure compute; no order emitted.)
- In:
riskUSD:number,entryPx:number*,stopPx:number* - Out:
size:number - Params:
riskUSDFallback(number=100)
exec.sizeByEquityPct — Size by Equity %
Position size from a percentage of account equity at the current price: size = (equity × pct/100) / price.
- In:
pct:number,price:number*,equity:number - Out:
size:number,notional:number - Params:
pctFallback(number=10)
exec.notionalToSize — Notional to Size
Convert a USD notional to a coin-unit size at the current price: size = notional / price.
- In:
notional:number,price:number* - Out:
size:number - Params:
notionalFallback(number=100)
Debug
Inspection — probe, log, plot.
debug.probe — Probe
Taps a value; displayed inline and pinned to the bottom panel.
- In:
in:any* - Out:
out:any - Params:
label(string="probe")
debug.plot — Plot
Plots a value over time on the chart or in a separate panel. In an indicator graph each plot becomes one chart line.
- In:
value:number* - Out:
out:number - Params:
series(string="series"),color(select="primary")— primary/green, warn/amber, danger/red, info/sky, violet —placement(select="overlay")— overlay on price chart or separate panel
debug.log — Log
Logs value to the console when the gate is true.
- In:
value:any*,when:boolean - Params:
label(string="log")
note — Note
A free-text comment pinned to the canvas. No ports, never runs — pure annotation.
- Params:
text(code="Note"),color(select="amber")— amber, sky, violet, emerald, slate —width(int=220)
Frontend (UI)
End-user form fields and feedback. See the Strategy Frontends page.
Every ui.* node also carries visibleWhenNode(string="") (Visible when node) and visibleWhenEquals(string="true") (…equals), omitted from the lists below: set the first to the id of another ui.* node (e.g. a Toggle Field) and the field shows only while that node's value equals the second. Empty = always visible.
ui.number — Number Field
End-user numeric input. Outputs the entered number, clamped to [min, max] (out-of-range values from the form or CLI never leak past the field's declared bounds). When rendered as the order-form Size block, the RO toggle's state is exposed on the reduceOnly output — wire it into an exec node's reduceOnly input to make the toggle functional.
- Out:
value:number,reduceOnly:boolean - Params:
label(string="Number"),default(number=0),min(number=0),max(number=1000000),step(number=1),unit(string=""),sizeField(boolean=false)(render as the order form's Size block),order(int=0)
ui.balance — Balance Field
Percent-of-balance slider. Outputs the resolved USD amount: percent × perp account equity (source = equity) or percent × the available wallet balance of a spot token (source = spot). While a spot balance is unknown (backtest, or live before the first wallet sync), value is NaN (not 0), so downstream exec nodes drop the non-finite size instead of silently sizing orders at zero.
- Out:
value:number,percent:number - Params:
label(string="Amount"),default(number=25),source(select="equity")(equityorspot),token(string="USDC"),order(int=0)
ui.boolean — Toggle Field
End-user on/off switch. Outputs a boolean.
- Out:
value:boolean - Params:
label(string="Enabled"),default(boolean=false),order(int=0)
ui.string — Text Field
End-user free-text input. Outputs the entered string (e.g. a label, tag, or note to pipe into ui.status).
- Out:
value:any - Params:
label(string="Text"),default(string=""),placeholder(string=""),order(int=0)
ui.slider — Slider Field
End-user slider over a numeric range. Outputs the selected number, clamped to [min, max].
- Out:
value:number - Params:
label(string="Slider"),default(number=1),min(number=1),max(number=100),step(number=1),order(int=0)
ui.select — Select Field
End-user dropdown over preset options. Outputs the chosen number or text value. The end-user value is validated against the authored options — an unmatched value falls back to the node default, never passing through.
- Out:
value:any - Params:
label(string="Option"),options(string="1,2,5,10" | "1m,5m,1h" | "fast=1,slow=2" | "1 minute=1m,1 hour=1h"),default(string="1"),order(int=0)
ui.coin — Coin Field
End-user market picker. Outputs the chosen coin symbol.
- Out:
coin:any - Params:
label(string="Market"),default(coin="$CURRENT_MARKET"),order(int=0)
ui.side — Side Field
End-user buy/sell or long/short picker. Outputs the chosen order side (buy or sell). Wire into exec.* side input. opposite is the other side (for a hedge or exit leg that should go the other way) and sign is +1 for buy, −1 for sell.
- Out:
side:any,opposite:any,sign:number - Params:
label(string="Side"),default(select="buy"),labels(select="buy-sell" | "long-short"),order(int=0)
ui.button — Action Button
Fires a one-shot true pulse when the end-user clicks. Wire into exec.*. emitOn picks the tick: barClose (default) holds the press until the next bar-close tick (the pulse survives intra-bar ticks unconsumed, and fires exactly once); instant consumes it on the very next tick — pair with fireOnBarClose: false on the exec node for true click-to-trade.
- Out:
pressed:signal<boolean> - Params:
label(string="Run"),tone(select="primary")— primary, success, danger —emitOn(select="barClose")— barClose or instant —order(int=0)
ui.timeframe — Timeframe Field
End-user timeframe picker bound to the strategy's graph timeframe (changing it re-sets the candle subscription). The value lives on the graph itself, not in the form values; the output just echoes the resolved timeframe for optional display wiring.
- Out:
timeframe:any - Params:
label(string="Timeframe"),order(int=0)
ui.readout — Readout
Displays a live numeric value in the strategy frontend. A non-finite input renders as a dash (—) instead of freezing on the last good value.
- In:
value:number* - Params:
label(string="Value"),format(select="number")— number, usd, pct —order(int=0)
ui.status — Status Badge
Displays a colored status badge from a value in the frontend.
- In:
value:any* - Params:
label(string="Status"),order(int=0)
ui.gauge — Gauge
Displays a value as a progress bar between min and max. A non-finite input renders as a dash (—).
- In:
value:number* - Params:
label(string="Gauge"),min(number=0),max(number=100),order(int=0)
Developer
Custom JS + helper markers.
dev.js — JavaScript
Custom JavaScript body with inputs a/b/c/d, persistent state, and ctx (candle/history/bbo/position/equity). Returns a number or { out, plot1, plot2, plot3 }. State commits only on bar close. Scripts are loop-budgeted at 1M loop iterations per tick — past the budget the script is aborted with a runtime error in the Console. Marketplace publish rejects graphs containing dev.js, and file imports containing it are blocked by the untrusted-graph guard (same policy for .borsa.json files as for marketplace forks).
- In:
a:number,b:number,c:number,d:number - Out:
out:number,plot1:number,plot2:number,plot3:number - Params:
coin(coin="$CURRENT_MARKET"),source(code=…)
helper.input — Helper Input
Exposes one input port of this graph (turns the graph into a helper). Connect downstream to consume the value from an invoker.
- Out:
out:any - Params:
portName(string="in"),portType(select="number")
helper.output — Helper Output
Exposes one output port of this graph (turns the graph into a helper). Connect upstream to assign the value visible to invokers.
- In:
in:any* - Params:
portName(string="out"),portType(select="number")