Indicators
Every ta.* function returns a Series, so results can be indexed ([0],
[1]), plotted, and passed into other indicators. The math is shared with the
Coinray charts and scanner, so values match what you see elsewhere in the app.
| Group | Functions |
|---|---|
| Moving averages | ta.sma ema rma wma hma alma vwma vwap linreg swma cum |
| Oscillators | ta.rsi macd cci wpr mfi cmo cog mom roc change stochK stoch stochRsi tsi |
| Volatility | ta.tr atr stdev variance dev range bb bbw kc kcw |
| Trend | ta.dmi supertrend sar |
| Volume | ta.obv accdist pvt iii wvad |
| Extremes and statistics | ta.highest lowest highestbars lowestbars pivothigh pivotlow median percentrank percentileNearestRank percentileLinearInterpolation |
| Two series | ta.correlation(a, b, length) |
| Anchored | ta.vwapBands(source, Anchor.Day | Anchor.Week, mult) |
See the API Reference for every signature.
Multi-output indicators
Some indicators return an object of series:
const bb = ta.bb(src.close, 20, 2.0); // bb.lower, bb.middle, bb.upper
const m = ta.macd(src.close, 12, 26, 9); // m.macd, m.signal, m.histogram
const d = ta.dmi(14, 14); // d.plus, d.minus, d.adx
const st = ta.supertrend(10, 3.0); // st.value, st.direction
const vb = ta.vwapBands(src.hlc3, Anchor.Week, 2.0); // vb.vwap, vb.upper, vb.lower
Indicators over your own formulas
Put any formula into a series and it becomes an indicator input:
const range = series();
export function onBar(): void {
range[0] = src.high[0] - src.low[0];
const avgRange = ta.sma(range, 20);
plotPane("range", avgRange, "range");
}
Crosses, rising, bars since
Stateful helpers are created at top level and updated every bar:
const cross = new Cross();
const since = new BarsSince();
export function onBar(): void {
const fast = ta.ema(src.close, 9)[0];
const slow = ta.ema(src.close, 21)[0];
const dir = cross.update(fast, slow); // 1 = crossed above, -1 = crossed below, 0 = none
const barsAgo = since.update(dir > 0); // bars since the last cross above, -1 if never
}
Rising and Falling report whether a value moved one way on each of the last
length bars, and ValueWhen returns a value from the bar a condition last
fired.
Math and helpers
math.* mirrors Pine's math namespace: abs sign floor ceil round sqrt pow exp log log10 sin cos tan asin acos atan todegrees toradians max min avg sum roundToMintick, plus the constants math.pi e phi rphi. Every function takes a
number or a series (read at the current bar).
na(x) tests for a missing value, nz(x, replacement) replaces it, and
round(x, decimals) / toFixed(x, decimals) format numbers.
Shading between two levels
fillLevels fills the band between two hlines — an RSI 30–70 zone, or the
overbought and oversold backgrounds of Bollinger %b:
import { color, fillLevels, hline, plotPane } from "@coinray/strategy"
hline(70, color.withTransp(color.red, 50), Stroke.Dashed, "RSI")
hline(30, color.withTransp(color.green, 50), Stroke.Dashed, "RSI")
fillLevels(70, 30, color.withTransp(color.blue, 90), "RSI")
Declare it at module top level beside the levels it refers to, naming their
prices rather than the lines; order does not matter. The band spans the pane's
width, so the levels need not be visible — Pine's habit of anchoring a fill to
an off-scale hline(100, display = display.none) becomes naming that price.
Shading a bar's background
bgcolor fills the whole height of the pane behind one bar, which is how
session windows, regimes and "this bar matters" states are usually drawn:
import { bgcolor, color, hour, plot, src } from "@coinray/strategy"
export function onBar(): void {
const h = hour() // UTC, like every time helper
if (h >= 12 && h < 14) bgcolor(color.withTransp(color.red, 90))
plot("close", src.close[0])
}
Call it only on the bars it applies to — a bar you skip keeps the chart's own
background, which is Pine's na. The colour carries its own alpha, so Pine's
transp = argument is color.withTransp(c, transp). Two calls on one bar do
not composite: the last one wins, so a script layering several zones should
pick the colour itself and call once. A second argument names a sub-pane to
shade, exactly as in plotPane.
Colouring candles
barcolor recolours the candle itself (Pine barcolor). Like bgcolor, call
it on the bars it applies to; a bar you skip keeps the chart's candle colour,
and the last call on a bar wins:
import { barcolor, color, param, src } from "@coinray/strategy"
const up = param.color("Up colour", color.green)
const down = param.color("Down colour", color.red)
export function onBar(): void {
if (src.volume[0] > src.volume[1] * 2) barcolor(src.close[0] >= src.open[0] ? up : down)
}
Notes
ta.cumsums from the first loaded bar (the start of the warmup window), not from the first bar ever traded.ta.vwapresets at 00:00 UTC.ta.vwapBandscan anchor on the day, the week (Monday 00:00 UTC), or any number of seconds. There is no monthly anchor.ta.correlationneeds both series on the same timeframe.