DocsType Reference

Helper Functions (q)

The q namespace provides 12 utility functions available globally in onBar(). These are pure functions — they do not modify state.

Reference

FunctionSignatureDescription
q.crossOver(a: number[], b: number[]|number, i: number) => booleana crosses above b at bar i
q.crossUnder(a: number[], b: number[]|number, i: number) => booleana crosses below b at bar i
q.highest(series: number[], period: number, i: number) => numberHighest value in lookback
q.lowest(series: number[], period: number, i: number) => numberLowest value in lookback
q.sma(series: number[], period: number, i: number) => numberSimple moving average over lookback
q.isNaN(value: number) => booleanCheck if indicator is not yet computed
q.clamp(value: number, min: number, max: number) => numberConstrain value within range
q.between(value: number, min: number, max: number) => booleanCheck if value is within range
q.pctChange(a: number, b: number) => numberPercentage change from b to a
q.sign(value: number) => -1 | 0 | 1Sign of a number
q.abs(value: number) => numberAbsolute value
q.round(value: number, decimals: number) => numberRound to N decimal places

Examples

function onBar(ctx, i) { const close = ctx.series.close; const ema = ctx.ind.ema; // Skip bars where indicator isn't ready if (q.isNaN(ema[i])) return; // Detect crossover if (q.crossOver(close, ema, i)) { ctx.order.market('ASSET', 1, { signal: 'buy' }); } // Use a constant threshold if (q.crossUnder(ctx.ind.rsi, 30, i)) { ctx.order.market('ASSET', 1, { signal: 'rsi_oversold' }); } // Donchian-style breakout using helpers const highest20 = q.highest(ctx.series.high, 20, i); if (close[i] > highest20) { ctx.order.market('ASSET', 1, { signal: 'breakout' }); } // Inline SMA for volume filter const avgVol = q.sma(ctx.series.volume, 20, i); if (ctx.series.volume[i] < avgVol * 0.5) return; // Low volume, skip // Position sizing with clamp const rawSize = q.round(10000 / close[i], 4); const size = q.clamp(rawSize, 0.01, 5); // RSI neutral zone check if (q.between(ctx.ind.rsi[i], 40, 60)) { // Neutral — no strong signal } }

Notes

  • q.crossOver and q.crossUnder accept either an array or a constant as the second argument
  • All lookback functions (highest, lowest, sma) return NaN if the lookback window extends before bar 0
  • q.pctChange(a, b) returns (a - b) / b as a decimal (0.05 = 5%)
helpersqcrossOvercrossUnderisNaNhighestlowestsmaclampbetweenpctChangesignabsround