Built-In Functions
Market Lab helper functions exposed to JavaScript scripts.
Built-In Functions
Scripts can call helper functions through ctx.study inside onData(ctx, input).
These helpers execute the same Rust functions used by Market Lab's built-in study commands. JavaScript only passes inputs and receives the serialized result; it does not maintain a separate calculation implementation.
Candle Functions
Candle helpers use an array from input.candles.candles.
Available helpers:
ctx.study.sma(candles, { field, window })ctx.study.ema(candles, { field, window })
Example:
export function onData(ctx, input) {
const candles = input.candles.candles
const sma20 = ctx.study.sma(candles, { field: "c", window: 20 })
return {
metrics: {
sma20: sma20.latest
}
}
}ctx.study.sma
Calculates a simple moving average.
const result = ctx.study.sma(candles, {
field: "c",
window: 20
})Returns:
{
latest: number | null;
previous: number | null;
points: Array<number | null>;
}ctx.study.ema
Calculates an exponential moving average.
const result = ctx.study.ema(candles, {
field: "c",
window: 20
})EMA is seeded with the SMA of the first full window.
ctx.study.cvd
Calculates cumulative volume delta from MMT VD candles only.
Do not pass normal OHLCVT candles into this helper. CVD in Market Lab is tied to the vd source because MMT already buckets the underlying trades by notional size.
const result = ctx.study.cvd(input.vd.candles, {
bucket: input.vd.bucket
})You can also pass a single live record:
const result = ctx.study.cvd(input.vd.candle, {
bucket: input.vd.bucket
})Returns:
{
latest: number | null;
previous: number | null;
delta: number;
bucket: number;
points: Array<{
t: number | null;
delta: number;
cumulative: number;
}>;
}Window VD example:
export function onData(ctx, input) {
const cvd = ctx.study.cvd(input.vd.candles, {
bucket: input.vd.bucket
})
return {
metrics: {
cvd_delta: cvd.delta,
latest_cvd: cvd.latest,
points: cvd.points.length
}
}
}Live VD example:
export function onData(ctx, input) {
if (input.source !== "vd") return { metrics: { skipped: true } }
const cvd = ctx.study.cvd(input.vd.candle, {
bucket: input.vd.bucket
})
return {
metrics: {
vd_delta: cvd.delta,
latest_cvd: cvd.latest
}
}
}Orderbook Functions
Orderbook helpers use a book from input.orderbook.books.
Available helpers:
ctx.study.spread(book)ctx.study.depth(book, { levels })ctx.study.imbalance(book, { depth })ctx.study.slippage(book, { side, notional })ctx.study.vamp(book, { dollar_depth })
Example:
export function onData(ctx, input) {
const book = input.orderbook.books.at(-1)
const spread = ctx.study.spread(book)
const slippage = ctx.study.slippage(book, {
side: "buy",
notional: 100000
})
return {
metrics: {
spread_bps: spread.spread_bps,
slippage_bps: slippage.slippage_bps
}
}
}ctx.study.spread
Calculates best bid, best ask, absolute spread, spread in basis points, and mid price.
const result = ctx.study.spread(book)Returns:
{
best_bid: number;
best_ask: number;
spread_abs: number;
spread_bps: number;
mid: number;
}ctx.study.depth
Sums base and quote depth across a fixed number of levels.
const result = ctx.study.depth(book, {
levels: 20
})Returns:
{
bid_base: number;
ask_base: number;
bid_quote: number;
ask_quote: number;
total_quote: number;
}ctx.study.imbalance
Calculates book imbalance across a fixed depth.
const result = ctx.study.imbalance(book, {
depth: 20
})Returns:
{
bid_volume: number;
ask_volume: number;
imbalance: number;
}ctx.study.slippage
Estimates market-order slippage against available book levels.
const result = ctx.study.slippage(book, {
side: "buy",
notional: 100000
})Returns:
{
avg_fill_price: number;
best_price: number;
slippage_abs: number;
slippage_bps: number;
levels_consumed: number;
}ctx.study.vamp
Calculates VAMP from bid and ask VWAP at a target quote depth.
const result = ctx.study.vamp(book, {
dollar_depth: 250000
})Returns:
{
ask_vwap: number;
bid_vwap: number;
vamp: number;
ask_levels_consumed: number;
bid_levels_consumed: number;
max_reachable_quote_ask: number;
max_reachable_quote_bid: number;
complete: boolean;
}