---
title: TA Library
description: >-
  The v3 technical-analysis library: the full indicator catalog, multi-output
  indicators, warmup and forward-fill conventions, and reference-validated
  accuracy.
---

<div class="flex gap-3 mb-6">
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-green-50 text-green-600 text-sm font-medium">
    Essential
  </span>
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-gray-100 text-gray-600 text-sm font-medium">
    12 min read
  </span>
</div>

## Introduction

kScript v3 ships a complete, **reference-validated** technical-analysis library. Every indicator below is tested bar-for-bar against an independent textbook implementation (relative error at most 1e-6 across the validation corpus, with exact `na` warmup positions), in both of the engine's execution paths. When kScript says RSI, it computes Wilder's RSI to the decimal.

## The catalog

**Moving averages & smoothing**
`sma`, `ema`, `alma`, `swma`, `wma`, `vwma`, `hma`, `rma` (legacy recurrence; see notes)

**Oscillators & momentum**
`rsi`, `wpr`, `cmo`, `tsi`, `macd` (line/signal/histogram), `stoch` (%K/%D), `cci`, `mfi`, `change`, `roc`, `mom`

**Trend & volatility**
`adx`, `psar`, `supertrend` (line/direction), `tr`, `atr`, `hl2`, `hlc3`, `ohlc4`, `hlcc4`, `bb` (basis/upper/lower), `keltner` (basis/upper/lower), `stdev`, `variance`

**Volume**
`obv`, `vwap` (cumulative, or calendar-anchored via `vwap(anchor="day"|"week"|"month")`), `cum`

**Statistics**
`correlation` (Pearson), `median`, `percentile` (nearest-rank, 0..100), `linreg` (least-squares endpoint)

**Bars & events**
`highest`, `lowest`, `highestbars`, `lowestbars`, `pivothigh`, `pivotlow`, `valuewhen`, `barssince`, `rising`, `falling`, `crossover`, `crossunder`, `fixnan`, `isna`, `nz`

```javascript
timeseries basis = sma(source=trade_data, period=20)
var bands = bb(source=trade_data, period=20, mult=2)     // multi-output
timeseries st = supertrend(factor=3, atrPeriod=10)
```
## Conventions (read this once)

These rules are uniform across the library; knowing them explains nearly every edge case:

**Warmup is `na`.** An indicator with a `p`-bar window emits `na` until it has a full window of finite values. No fabricated early values. Compose with `isna`/`nz` as needed.

**Indicators compose.** Any indicator accepts any series as `source`, including other indicators (`rsi(source=sma(...))`) and microstructure-derived series. Warmup propagates correctly through the composition.

**Values forward-fill; events do not.** Reading a value series past a gap or a shorter timeline forward-fills the last value (so math keeps working). Event conditions (`valuewhen`, `barssince`, the crosses) are stricter: a missing condition is **false**, never a carried-over `true`, so stale data cannot fabricate signals.

**`stdev` vs `stddev`.** `stdev` is the textbook one: strict full finite window, population divisor; any missing sample in the window yields `na`. `stddev` is the legacy lenient variant (skips non-finite samples, divides by the finite count), preserved unchanged for old scripts. New code should use `stdev`. The same strict-window rule covers `bb`, `variance`, `correlation`, `median`, `percentile`, `linreg`.

**Gaps in stateful indicators are honest.** `supertrend` emits `na` on a bar whose inputs are not finite (and re-converges after), rather than carrying a stale flip.

**`rma` note.** The legacy `rma` builtin uses a recurrence based on the previous source value rather than the previous RMA, so it is *not* Wilder smoothing. `rsi`, `atr`, and `adx` implement true Wilder smoothing internally; for textbook smoothing of an arbitrary series, build on `ema`/`sma`.

## Multi-output indicators

`macd`, `bb`, `keltner`, `supertrend`, and `stoch` return multiple streams; plot family functions accept them directly and each stream is addressable by name:

| Indicator | Streams |
| --- | --- |
| `bb`, `keltner` | `.basis`, `.upper`, `.lower` |
| `macd` | `.macd`, `.signal`, `.histogram` (alias `.hist`) |
| `stoch` | `.k`, `.d` |
| `supertrend` | `.line`, `.direction` |

Named streams support history indexing (`macd.signal[1]`) and feed `fillBetween` directly:

```javascript
var bands = bb(source=trade_data, period=20, mult=2)
fillBetween(bands.upper, bands.lower, "#0ea5e9", 0.12)
plotLine(bands.basis, color="#64748b")
```
## Over microstructure

Every windowed function in the library also runs over order-flow-derived series, which is where the library stops being a Pine clone:

```javascript
timeseries delta = fp.cells.map((c) => c[2] - c[3]).reduce((s, x) => s + x, 0)

timeseries deltaRsi = rsi(source=delta, period=14)      // delta-RSI
timeseries cvd = cum(delta)                              // cumulative volume delta
timeseries imbalanceMa = ema(source=bookImbalance, period=21)
```



The validation suite covers these compositions explicitly (27 windowed functions over a footprint-derived series, plus end-to-end microstructure-only indicators: CVD, delta-RSI, largest-bucket drift, book-imbalance EMA, POC migration speed).
## Accuracy as a contract

The reference suite (independent plain implementations, never the engine itself) is part of the build: a change that drifts any indicator from its textbook formula fails CI. v3 in fact *corrected* eight long-standing indicators to their textbook forms; if you maintain very old scripts, see the [migration notes](../migrations/v2-vs-v3.md) for the early-bar value changes that correction implies.
