oakscriptjs 0.11.4 → 0.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/input.d.ts +19 -3
- package/dist/cjs/input.d.ts.map +1 -1
- package/dist/cjs/input.js +24 -1
- package/dist/cjs/input.js.map +2 -2
- package/dist/cjs/lib/zigzag/zigzag.d.ts +8 -3
- package/dist/cjs/lib/zigzag/zigzag.d.ts.map +1 -1
- package/dist/cjs/lib/zigzag/zigzag.js +16 -3
- package/dist/cjs/lib/zigzag/zigzag.js.map +2 -2
- package/dist/cjs/runtime/index.d.ts +1 -1
- package/dist/cjs/runtime/index.d.ts.map +1 -1
- package/dist/cjs/runtime/index.js +1 -0
- package/dist/cjs/runtime/index.js.map +2 -2
- package/dist/cjs/runtime/inputs.d.ts +9 -0
- package/dist/cjs/runtime/inputs.d.ts.map +1 -1
- package/dist/cjs/runtime/inputs.js +8 -0
- package/dist/cjs/runtime/inputs.js.map +2 -2
- package/dist/cjs/runtime/types.d.ts +4 -3
- package/dist/cjs/runtime/types.d.ts.map +1 -1
- package/dist/cjs/runtime/types.js.map +1 -1
- package/dist/cjs/script/index.d.ts +35 -3
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +40 -4
- package/dist/cjs/script/index.js.map +3 -3
- package/dist/cjs/security/other.d.ts +2 -1
- package/dist/cjs/security/other.d.ts.map +1 -1
- package/dist/cjs/security/other.js +1 -1
- package/dist/cjs/security/other.js.map +2 -2
- package/dist/cjs/ta/index.d.ts +1 -0
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +1 -1
- package/dist/cjs/ta/index.js.map +2 -2
- package/dist/cjs/time/index.d.ts +2 -0
- package/dist/cjs/time/index.d.ts.map +1 -1
- package/dist/cjs/time/index.js +1 -1
- package/dist/cjs/time/index.js.map +2 -2
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js.map +2 -2
- package/dist/cjs/utils/index.d.ts +5 -3
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +6 -0
- package/dist/cjs/utils/index.js.map +2 -2
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/input.d.ts +19 -3
- package/dist/esm/input.d.ts.map +1 -1
- package/dist/esm/input.js +24 -1
- package/dist/esm/input.js.map +1 -1
- package/dist/esm/lib/zigzag/zigzag.d.ts +8 -3
- package/dist/esm/lib/zigzag/zigzag.d.ts.map +1 -1
- package/dist/esm/lib/zigzag/zigzag.js +19 -4
- package/dist/esm/lib/zigzag/zigzag.js.map +1 -1
- package/dist/esm/runtime/index.d.ts +1 -1
- package/dist/esm/runtime/index.d.ts.map +1 -1
- package/dist/esm/runtime/index.js +1 -1
- package/dist/esm/runtime/index.js.map +1 -1
- package/dist/esm/runtime/inputs.d.ts +9 -0
- package/dist/esm/runtime/inputs.d.ts.map +1 -1
- package/dist/esm/runtime/inputs.js +15 -0
- package/dist/esm/runtime/inputs.js.map +1 -1
- package/dist/esm/runtime/types.d.ts +4 -3
- package/dist/esm/runtime/types.d.ts.map +1 -1
- package/dist/esm/script/index.d.ts +35 -3
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +49 -2
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/security/other.d.ts +2 -1
- package/dist/esm/security/other.d.ts.map +1 -1
- package/dist/esm/security/other.js +4 -2
- package/dist/esm/security/other.js.map +1 -1
- package/dist/esm/ta/index.d.ts +1 -0
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +3 -1
- package/dist/esm/ta/index.js.map +1 -1
- package/dist/esm/time/index.d.ts +2 -0
- package/dist/esm/time/index.d.ts.map +1 -1
- package/dist/esm/time/index.js +4 -1
- package/dist/esm/time/index.js.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/utils/index.d.ts +5 -3
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +5 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -1
- package/src/input.ts +28 -4
- package/src/lib/zigzag/zigzag.ts +20 -6
- package/src/runtime/index.ts +1 -0
- package/src/runtime/inputs.ts +16 -0
- package/src/runtime/types.ts +4 -3
- package/src/script/index.ts +71 -4
- package/src/security/other.ts +5 -2
- package/src/ta/index.ts +3 -1
- package/src/time/index.ts +4 -1
- package/src/types/index.ts +1 -0
- package/src/utils/index.ts +8 -3
package/dist/cjs/ta/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/ta/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Technical Analysis (ta) namespace\n * Mirrors PineScript's ta.* functions for technical analysis indicators and calculations.\n *\n * @remarks\n * All technical analysis functions in this namespace follow PineScript v6 API specifications.\n *\n * @version 6\n */\n\nimport type { series_float, series_bool, series_int, int, Source, simple_int, simple_float, simple_bool } from '../types/index.js';\nimport { eq, ge, gt, le, lt } from '../compare/index.js';\nimport { runningSum, runningSumSeries, runningVariance, runningVarianceSeries } from './running-sum.js';\nimport { checkPositiveLength, checkSumLength, checkWindowLength } from './limits.js';\n\n/**\n * Simple Moving Average - returns the moving average (sum of last y values divided by y).\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length), or one length per bar (a series length)\n * @returns Simple moving average of source for length bars back\n *\n * @remarks\n * - `na` values (also +/-Infinity) in the source series are ignored: the mean of the last `length` non-`na`\n * values, and a bar with an `na` source keeps the previous result (as in PineScript)\n * - Returns NaN until `length` non-`na` values are available\n * - The sum is a compensated running sum, as in PineScript, so the result can differ from the exact window mean in\n * the last bits (bit for bit with PineScript)\n * - With a series length, the running sum is moved to the new length when the length changes, as PineScript does\n * (see {@link math.sum}); a bar with an `na` source gives the mean of the last `length` earlier values\n *\n * @example\n * ```typescript\n * const closePrices = [10, 11, 12, 13, 14];\n * const sma5 = ta.sma(closePrices, 5); // Returns: [NaN, NaN, NaN, NaN, 12]\n * const smaVar = ta.sma(closePrices, [2, 2, 2, 3, 2]); // Returns: [NaN, 10.5, 11.5, 12, 13.5]\n * ```\n */\nexport function sma(source: Source, length: simple_int | ArrayLike<number>): series_float {\n if (typeof length !== 'number') {\n const sums = runningSumSeries(source, length, 'ta.sma');\n return sums.map((sum, i) => sum / Math.floor(length[i]!));\n }\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n checkSumLength('ta.sma', len, 0);\n return runningSum(source, len).map((sum) => sum / len);\n}\n\n/**\n * Exponential Moving Average - returns the exponentially weighted moving average.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Exponential moving average of source with alpha = 2 / (length + 1)\n *\n * @remarks\n * - In EMA, weighting factors decrease exponentially\n * - Formula: `EMA = alpha * source + (1 - alpha) * EMA[1]`, where `alpha = 2 / (length + 1)`\n * - `na` values (also +/-Infinity) in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n * - May cause indicator repainting\n *\n * @example\n * ```typescript\n * const closePrices = [10, 11, 12, 13, 14];\n * const ema5 = ta.ema(closePrices, 5);\n * ```\n */\nexport function ema(source: Source, length: simple_int): series_float {\n checkPositiveLength('ema', length, 0);\n const result: series_float = [];\n const len = Math.floor(length);\n const multiplier = 2 / (len + 1);\n\n // SMA seed on the bar of the `len`-th valid value. An infinite value is na, as in PineScript.\n let firstValidIndex = -1;\n let validCount = 0;\n\n for (let i = 0; i < source.length; i++) {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val) && ++validCount === len) {\n firstValidIndex = i;\n break;\n }\n }\n\n const emaInitialized = firstValidIndex >= 0;\n // The seed is ta.sma on that bar: the running sum of math.sum (PineScript bits), not a plain loop sum\n let emaValue = emaInitialized ? runningSum(source.slice(0, firstValidIndex + 1), len)[firstValidIndex]! / len : NaN;\n\n for (let i = 0; i < source.length; i++) {\n if (!emaInitialized || i < firstValidIndex) {\n result.push(NaN);\n } else if (i === firstValidIndex) {\n result.push(emaValue);\n } else {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val)) {\n emaValue = (val - emaValue) * multiplier + emaValue;\n result.push(emaValue);\n } else {\n // na source: na on this bar; the next bar continues from the last value (as in PineScript)\n result.push(NaN);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Relative Strength Index - momentum oscillator measuring speed and magnitude of price changes.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns RSI series (values range from 0 to 100)\n *\n * @remarks\n * - RSI values above 70 typically indicate overbought conditions\n * - RSI values below 30 typically indicate oversold conditions\n * - Uses `ta.rma()` (Relative Moving Average) for smoothing, matching PineScript v6\n * - Formula: RSI = 100 - (100 / (1 + RS)), where RS = Average Gain / Average Loss\n * - As in PineScript (`down == 0 ? 100 : up == 0 ? 0 : ...`): 100 when the average loss is 0, else 0 when the\n * average gain is 0, both with the 1e-10 tolerance of the comparison operators\n * - Average Gain and Average Loss are calculated using RMA (alpha = 1 / length)\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const rsi14 = ta.rsi(closePrices, 14);\n * // Identify overbought/oversold conditions\n * const overbought = rsi14.map(v => v > 70);\n * const oversold = rsi14.map(v => v < 30);\n * ```\n */\nexport function rsi(source: Source, length: simple_int): series_float;\n/**\n * PineScript v4 `rsi(x, y)` with two series (#180): `x` and `y` are the averages of the upward and downward changes,\n * already computed. As in PineScript: 100 when `y` is within 1e-10 of zero (also with an na `x`), else 0 when `x` is,\n * else `100 - 100 / (1 + x / y)`: -Infinity when `x == -y` (#182), which `na()` and `nz()` treat as na while comparisons\n * see it (`r < 30` is true). Versions 5 and 6 have the length form only.\n */\nexport function rsi(x: Source, y: Source): series_float;\nexport function rsi(source: Source, length: simple_int | Source): series_float {\n if (typeof length !== 'number') {\n return Array.from(source, (xv, i) => {\n const x = xv ?? NaN;\n const y = length[i] ?? NaN;\n if (eq(y, 0)) return 100;\n if (eq(x, 0)) return 0;\n return 100 - 100 / (1 + x / y);\n });\n }\n checkPositiveLength('rsi', length, 0, 'y');\n const result: series_float = [];\n\n // Calculate price changes\n const changes: number[] = [];\n for (let i = 1; i < source.length; i++) {\n changes.push(source[i]! - source[i - 1]!);\n }\n\n // Separate gains and losses; a change from or to na is na (skipped by rma), not a 0 gain / loss\n const gains: number[] = changes.map(c => (Number.isNaN(c) ? NaN : c > 0 ? c : 0));\n const losses: number[] = changes.map(c => (Number.isNaN(c) ? NaN : c < 0 ? -c : 0));\n\n // Calculate average gains and losses using RMA (not SMA)\n const avgGains = rma(gains, length);\n const avgLosses = rma(losses, length);\n\n result.push(NaN); // First value is NaN\n\n for (let i = 0; i < avgGains.length; i++) {\n if (eq(avgLosses[i]!, 0)) {\n result.push(100);\n } else if (eq(avgGains[i]!, 0)) {\n result.push(0);\n } else {\n const rs = avgGains[i]! / avgLosses[i]!;\n result.push(100 - (100 / (1 + rs)));\n }\n }\n\n return result;\n}\n\n/**\n * Moving Average Convergence Divergence - trend-following momentum indicator showing relationship\n * between two moving averages.\n *\n * @param source - Series of values to process\n * @param fastLength - Fast EMA length (typically 12)\n * @param slowLength - Slow EMA length (typically 26)\n * @param signalLength - Signal line EMA length (typically 9)\n * @returns Tuple of [macdLine, signalLine, histogram]\n *\n * @remarks\n * - MACD Line = Fast EMA - Slow EMA\n * - Signal Line = EMA of MACD Line\n * - Histogram = MACD Line - Signal Line\n * - Crossovers between MACD and signal line indicate potential buy/sell signals\n *\n * @example\n * ```typescript\n * const [macdLine, signal, histogram] = ta.macd(closePrices, 12, 26, 9);\n * ```\n */\nexport function macd(\n source: Source,\n fastLength: simple_int,\n slowLength: simple_int,\n signalLength: simple_int\n): [series_float, series_float, series_float] {\n const fastEma = ema(source, fastLength);\n const slowEma = ema(source, slowLength);\n\n const macdLine: series_float = [];\n for (let i = 0; i < source.length; i++) {\n macdLine.push(fastEma[i]! - slowEma[i]!);\n }\n\n const signalLine = ema(macdLine, signalLength);\n\n const histogram: series_float = [];\n for (let i = 0; i < source.length; i++) {\n histogram.push(macdLine[i]! - signalLine[i]!);\n }\n\n return [macdLine, signalLine, histogram];\n}\n\n/**\n * Bollinger Bands - a technical analysis tool defined by lines plotted two standard deviations\n * away from a simple moving average.\n *\n * @param series - Series of values to process\n * @param length - Number of bars (length)\n * @param mult - Standard deviation factor\n * @returns Tuple of [middle, upper, lower] bands\n *\n * @remarks\n * - Middle band is the SMA of the source\n * - Upper band = middle + (mult * standard deviation)\n * - Lower band = middle - (mult * standard deviation)\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const [middle, upper, lower] = ta.bb(closePrices, 20, 2);\n * ```\n */\nexport function bb(\n series: Source,\n length: simple_int,\n mult: simple_float\n): [series_float, series_float, series_float] {\n checkSumLength('ta.bb', length, 0);\n const basis = sma(series, length);\n const dev = stdev(series, length);\n\n const upper: series_float = [];\n const lower: series_float = [];\n\n for (let i = 0; i < series.length; i++) {\n upper.push(basis[i]! + mult * dev[i]!);\n lower.push(basis[i]! - mult * dev[i]!);\n }\n\n return [basis, upper, lower];\n}\n\n/**\n * Standard deviation over the last `length` non-na values.\n *\n * @param source - Series of values to process\n * @param length - Number of values, or one length per bar (a series length, see {@link sma})\n * @param biased - true (default): biased estimate (divides by `length`); false: unbiased (by `length - 1`)\n * @returns Standard deviation series (na until `length` non-na values exist)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the window holds the last\n * `length` non-na values, and a bar whose own value is `na` keeps the previous result.\n * The result is the square root of {@link variance} (0 when the variance is not positive), computed from\n * compensated running sums of the values and of their squares, bit for bit as PineScript.\n */\nexport function stdev(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: simple_bool = true\n): series_float {\n return varianceOf(source, length, biased, 'ta.stdev').map((v) => (Number.isNaN(v) ? NaN : v > 0 ? Math.sqrt(v) : 0));\n}\n\n/**\n * The last `length` non-na values up to bar `i` (the bar itself may be na), or null when fewer exist. +/-Infinity\n * counts as na (#183).\n */\nfunction lastValues(source: Source, i: number, length: number): number[] | null {\n const values: number[] = [];\n for (let j = i; j >= 0 && values.length < length; j--) {\n const x = source[j]!;\n if (Number.isFinite(x)) values.push(x);\n }\n return values.length === length ? values : null;\n}\n\n/**\n * The extreme of the window of `length` bars ending at each bar, in one pass (monotonic deque): the bar index of\n * the oldest highest (or lowest) value (the newest one with `newest`), or -1 when the window is empty. The window\n * stops at the first `na` value going back (the callers pass the non-na values only, see {@link keptValues}), and a\n * fractional length is truncated (7.5 is 7 bars), as PineScript does.\n * `zeros[i]` tells whether the window holds a +0 (highest) or a -0 (lowest), the zero that `Math.max` / `Math.min`\n * return when the extreme is 0 (not kept with `newest`).\n */\nfunction windowExtremes(\n source: Source,\n length: number,\n lowest: boolean,\n newest = false\n): { at: Int32Array; zeros: Uint8Array } {\n const n = source.length;\n const span = length > 0 ? Math.trunc(length) : 0; // PineScript casts the length to int\n const at = new Int32Array(n).fill(-1);\n const zeros = new Uint8Array(n);\n const queue = new Int32Array(n); // bar indices; values from best to worst, the oldest first among equal values\n const preferredZero = lowest ? -0 : 0;\n let head = 0;\n let tail = 0;\n let zeroCount = 0; // preferred zeros in the queue\n let lastNa = -1;\n const isPreferredZero = (k: number) => Object.is(source[k], preferredZero);\n for (let i = 0; i < n; i++) {\n const x = source[i]!;\n if (Number.isNaN(x)) {\n lastNa = i;\n head = tail = 0;\n zeroCount = 0;\n continue;\n }\n // drop the values that the new one beats; equal values stay (the oldest wins ties), or go with `newest`\n while (tail > head) {\n const last = source[queue[tail - 1]!]!;\n if (!(lowest ? last > x : last < x) && !(newest && last === x)) break;\n if (isPreferredZero(queue[--tail]!)) zeroCount--;\n }\n queue[tail++] = i;\n if (isPreferredZero(i)) zeroCount++;\n const start = Math.max(i - span + 1, lastNa + 1);\n while (head < tail && queue[head]! < start) {\n if (isPreferredZero(queue[head++]!)) zeroCount--;\n }\n if (head < tail) {\n at[i] = queue[head]!;\n zeros[i] = zeroCount > 0 ? 1 : 0;\n }\n }\n return { at, zeros };\n}\n\n/**\n * The non-na values of `source` with their bars, and for each bar the position of its last non-na value (-1 when\n * there is none yet). PineScript's ta.highest / ta.lowest / ta.highestbars / ta.lowestbars / ta.pivothigh /\n * ta.pivotlow keep the non-na values they receive and nothing else; +/-Infinity is skipped like na (#183).\n */\nfunction keptValues(source: Source): { values: number[]; bars: number[]; last: Int32Array } {\n const values: number[] = [];\n const bars: number[] = [];\n const last = new Int32Array(source.length);\n for (let i = 0; i < source.length; i++) {\n const x = source[i]!;\n if (Number.isFinite(x)) {\n values.push(x);\n bars.push(i);\n }\n last[i] = values.length - 1;\n }\n return { values, bars, last };\n}\n\n/**\n * ta.highest / ta.lowest / ta.highestbars / ta.lowestbars with a series length (a length per bar): on each bar the\n * best of the last `length[i]` non-na values (the newest one on ties), na before bar `length[i] - 1`, as PineScript\n * (measured with a length that changes on each bar, with and without na in the source).\n */\nfunction extremeSeriesLength(source: Source, lengths: ArrayLike<number>, lowest: boolean, offsets: boolean): number[] {\n const name = (lowest ? 'lowest' : 'highest') + (offsets ? 'bars' : '');\n const { values, bars, last } = keptValues(source);\n return Array.from(source, (_, i) => {\n const len = Math.trunc(lengths[i]!);\n checkWindowLength(name, len, i);\n const k = last[i]!;\n if (!(len >= 1) || i < len - 1 || k < 0) return NaN;\n let best = k;\n for (let j = k - 1; j >= 0 && j > k - len; j--) {\n if (lowest ? values[j]! < values[best]! : values[j]! > values[best]!) best = j;\n }\n return offsets ? -(i - bars[best]!) : values[best]!;\n });\n}\n\n/**\n * Offset to the best of the last `length` non-na values (the newest one on ties): the distance in bars, so below\n * `-(length - 1)` after an na value. na before bar `length - 1` and while there is no value.\n */\nfunction extremeOffset(source: Source, length: simple_int | ArrayLike<number>, lowest: boolean): series_int {\n if (typeof length !== 'number') return extremeSeriesLength(source, length, lowest, true);\n checkWindowLength(lowest ? 'lowestbars' : 'highestbars', length, 0);\n const { values, bars, last } = keptValues(source);\n const { at } = windowExtremes(values, length, lowest, true);\n const len = Math.trunc(length);\n // -(i - bar): -0 when the extreme is the current bar, as the offset -j of the window scan\n return source.map((_, i) => {\n const k = last[i]!;\n return i < len - 1 || k < 0 || at[k]! < 0 ? NaN : -(i - bars[at[k]!]!);\n });\n}\n\n/**\n * Best of the last `length` non-na values (of all of them when there are fewer), with the zero sign of `Math.max` /\n * `Math.min`. na before bar `length - 1` and while there is no value.\n */\nfunction extremeValue(source: Source, length: simple_int | ArrayLike<number>, lowest: boolean): series_float {\n if (typeof length !== 'number') return extremeSeriesLength(source, length, lowest, false);\n checkWindowLength(lowest ? 'lowest' : 'highest', length, 0);\n const { values, last } = keptValues(source);\n const { at, zeros } = windowExtremes(values, length, lowest);\n const len = Math.trunc(length);\n return source.map((_, i) => {\n const k = last[i]!;\n if (i < len - 1 || k < 0 || at[k]! < 0) return NaN;\n const v = values[at[k]!]!;\n return v === 0 && zeros[k] ? (lowest ? -0 : 0) : v;\n });\n}\n\n/**\n * Compares each bar with the last earlier bar where both values were not na (PineScript rule for ta.crossover,\n * ta.crossunder and ta.cross): false while there is no such bar, and false on a bar with an na value.\n *\n * @internal\n */\nfunction crossTest(\n series1: Source,\n series2: Source,\n test: (a: number, b: number, prevA: number, prevB: number) => boolean,\n): series_bool {\n const result: series_bool = [];\n let prevA = NaN;\n let prevB = NaN;\n for (let i = 0; i < series1.length; i++) {\n const a = series1[i]!;\n const b = series2[i]!;\n result.push(test(a, b, prevA, prevB));\n if (!Number.isNaN(a) && !Number.isNaN(b)) {\n prevA = a;\n prevB = b;\n }\n }\n return result;\n}\n\n/**\n * Crossover - returns true when series1 crosses over series2 (moves from below to above).\n *\n * @param series1 - First series\n * @param series2 - Second series\n * @returns Boolean series (true at crossover points)\n *\n * @remarks\n * - True when: series1[i] > series2[i] AND series1[j] <= series2[j], where j is the last bar before i where both\n * values were not na (PineScript rule: a crossing right after an na bar is not missed)\n * - First value is always false (no previous value to compare)\n * - Comparisons are exact (no tolerance)\n * - Useful for detecting bullish signals (e.g., fast MA crossing over slow MA)\n *\n * @example\n * ```typescript\n * const crossUp = ta.crossover(fastMA, slowMA);\n * ```\n */\nexport function crossover(series1: Source, series2: Source): series_bool {\n return crossTest(series1, series2, (a, b, pa, pb) => a > b && pa <= pb);\n}\n\n/**\n * Crossunder - returns true when series1 crosses under series2 (moves from above to below).\n *\n * @param series1 - First series\n * @param series2 - Second series\n * @returns Boolean series (true at crossunder points)\n *\n * @remarks\n * - True when: series1[i] < series2[i] AND series1[j] >= series2[j], where j is the last bar before i where both\n * values were not na\n * - First value is always false (no previous value to compare)\n * - Comparisons are exact (no tolerance)\n * - Useful for detecting bearish signals (e.g., fast MA crossing under slow MA)\n *\n * @example\n * ```typescript\n * const crossDown = ta.crossunder(fastMA, slowMA);\n * ```\n */\nexport function crossunder(series1: Source, series2: Source): series_bool {\n return crossTest(series1, series2, (a, b, pa, pb) => a < b && pa >= pb);\n}\n\n/**\n * Change - calculates the difference between the current value and its value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Number of bars back (default: 1)\n * @returns Change series (source[i]! - source[i - length])\n *\n * @remarks\n * - Returns NaN for the first `length` values\n * - Default length is 1 (difference from previous bar)\n * - Positive values indicate increase, negative values indicate decrease\n *\n * @example\n * ```typescript\n * const change1 = ta.change(closePrices); // Daily change\n * const change5 = ta.change(closePrices, 5); // 5-day change\n * ```\n */\nexport function change(source: Source, length: simple_int = 1): series_float {\n checkPositiveLength('change', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n result.push(source[i]! - source[i - length]!);\n }\n }\n\n return result;\n}\n\n/**\n * True Range - measures market volatility by calculating the greatest of three price ranges.\n *\n * @param handle_na - Defines how the function calculates when previous close is na (default: false)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns True range series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.tr(handle_na?)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - True Range = max(high - low, abs(high - close[1]), abs(low - close[1]))\n * - When `handle_na` is true: returns `high - low` if previous close is na\n * - When `handle_na` is false: returns na if previous close is na\n * - Used as a component in ATR calculations\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const trueRange = ta.tr(false, high, low, close);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const trueRange = ta.tr(); // Matches PineScript!\n * ```\n */\nexport function tr(\n handle_na: simple_bool = false,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.tr() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const result: series_float = [];\n\n for (let i = 0; i < high.length; i++) {\n if (i === 0) {\n // First bar: the previous close is na\n result.push(handle_na ? high[i]! - low[i]! : NaN);\n } else {\n const prevClose = close[i - 1]!;\n\n // Handle na previous close based on handle_na parameter\n if (isNaN(prevClose)) {\n if (handle_na) {\n result.push(high[i]! - low[i]!);\n } else {\n result.push(NaN);\n }\n } else {\n const tr = Math.max(\n high[i]! - low[i]!,\n Math.abs(high[i]! - prevClose),\n Math.abs(low[i]! - prevClose)\n );\n result.push(tr);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Average True Range - returns the RMA (Relative Moving Average) of true range.\n *\n * @param length - Number of bars (length)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns Average true range series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.atr(length)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - Uses `ta.rma()` (Relative Moving Average) for smoothing, matching PineScript v6\n * - True range is max(high - low, abs(high - close[1]), abs(low - close[1]))\n * - ATR is a measure of volatility, higher values indicate greater volatility\n * - `na` values in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const atr14 = ta.atr(14, high, low, close);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const atr14 = ta.atr(14); // Matches PineScript!\n * ```\n */\nexport function atr(length: simple_int, high?: Source, low?: Source, close?: Source): series_float {\n checkPositiveLength('atr->rma', length, 0);\n if (!high || !low || !close) {\n throw new Error(\n 'ta.atr() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n // PineScript: ta.atr uses ta.tr(true), so bar 0 is high - low\n const trueRange = tr(true, high, low, close);\n return rma(trueRange, length);\n}\n\n/**\n * SuperTrend Indicator - a trend-following indicator that helps identify trend direction.\n *\n * @param factor - The multiplier by which the ATR will get multiplied (series int/float)\n * @param atrPeriod - Length of ATR (simple int)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @param wicks - Whether to use wicks for trend reversal (NOT in PineScript v6 API, default: false)\n * @returns Tuple of [supertrend, direction] where direction is 1 (downtrend) or -1 (uptrend)\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.supertrend(factor, atrPeriod)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - The `wicks` parameter is NOT part of the official PineScript v6 API\n * - Direction: 1 = downtrend (red), -1 = uptrend (green)\n * - Uses hl2 (average of high and low) as the source\n * - SuperTrend helps identify the current market trend and potential reversal points\n * - As in PineScript (`nz` of the previous bands): 0 on bar 0, na on the next bars while the ATR is na\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const [supertrend, direction] = ta.supertrend(3, 10, high, low, close);\n * // Plot uptrend when direction < 0\n * // Plot downtrend when direction > 0\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const [supertrend, direction] = ta.supertrend(3, 10); // Matches PineScript!\n * ```\n */\nexport function supertrend(\n factor: simple_float,\n atrPeriod: simple_int,\n high?: Source,\n low?: Source,\n close?: Source,\n wicks: simple_bool = false\n): [series_float, series_int] {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.supertrend() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n const supertrendValues: series_float = [];\n const directions: series_int = [];\n\n // Calculate hl2 (average of high and low)\n const source: series_float = [];\n for (let i = 0; i < high.length; i++) {\n source.push((high[i]! + low[i]!) / 2);\n }\n\n // Calculate ATR\n const atrValues = atr(atrPeriod, high, low, close);\n\n // PineScript reference implementation (bar by bar):\n // prevLowerBand = nz(lowerBand[1]), prevUpperBand = nz(upperBand[1])\n // lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand\n // upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand\n // direction = na(atr[1]) ? 1 : prevSuperTrend == prevUpperBand ? (close > upperBand ? -1 : 1) : (close < lowerBand ? 1 : -1)\n // A comparison with na is false: on bar 0 (close[1] na) both bands take nz(na) = 0, so the supertrend is 0.\n const nz = (v: number) => (isNaN(v) ? 0 : v);\n let lastLowerBand = NaN;\n let lastUpperBand = NaN;\n let prevSuperTrend = NaN;\n\n for (let i = 0; i < source.length; i++) {\n const atrValue = atrValues[i]! * factor;\n let upperBand = source[i]! + atrValue;\n let lowerBand = source[i]! - atrValue;\n const prevLowerBand = nz(lastLowerBand);\n const prevUpperBand = nz(lastUpperBand);\n\n // Price compared with the bands: close, or low / high with wicks\n const highPrice = wicks ? high[i]! : close[i]!;\n const lowPrice = wicks ? low[i]! : close[i]!;\n const prevLowPrice = i > 0 ? (wicks ? low[i - 1]! : close[i - 1]!) : NaN;\n const prevHighPrice = i > 0 ? (wicks ? high[i - 1]! : close[i - 1]!) : NaN;\n\n lowerBand = lowerBand > prevLowerBand || prevLowPrice < prevLowerBand ? lowerBand : prevLowerBand;\n upperBand = upperBand < prevUpperBand || prevHighPrice > prevUpperBand ? upperBand : prevUpperBand;\n\n let currentDirection: int;\n if (i === 0 || isNaN(atrValues[i - 1]!)) {\n currentDirection = 1;\n } else if (prevSuperTrend === prevUpperBand) {\n // Was in downtrend (following upper band)\n currentDirection = highPrice > upperBand ? -1 : 1;\n } else {\n // Was in uptrend (following lower band)\n currentDirection = lowPrice < lowerBand ? 1 : -1;\n }\n\n const superTrendValue = currentDirection === -1 ? lowerBand : upperBand;\n supertrendValues.push(superTrendValue);\n directions.push(currentDirection);\n\n lastLowerBand = lowerBand;\n lastUpperBand = upperBand;\n prevSuperTrend = superTrendValue;\n }\n\n return [supertrendValues, directions];\n}\n/**\n * Relative Moving Average (RMA) - exponentially weighted moving average with alpha = 1 / length.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns RMA of source for length bars back\n *\n * @remarks\n * - Moving average used in RSI calculation\n * - Alpha = 1 / length (different from EMA which uses alpha = 2 / (length + 1))\n * - First value is initialized with SMA, then uses exponential smoothing. As in PineScript, the seed is the\n * `ta.sma` value (its compensated running sum), so it can differ from the exact mean in the last bits\n * - Formula: `RMA = (source + (length - 1) * RMA[1]) / length`, evaluated in this order as in PineScript\n * (equal to `alpha * source + (1 - alpha) * RMA[1]`, but bit for bit)\n * - `na` values (also +/-Infinity) in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n *\n * @example\n * ```typescript\n * const rma14 = ta.rma(closePrices, 14);\n * // Used internally by RSI:\n * // avgGain = ta.rma(gains, 14);\n * // avgLoss = ta.rma(losses, 14);\n * ```\n */\nexport function rma(source: Source, length: simple_int): series_float {\n checkPositiveLength('rma', length, 0);\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n\n // Find the first index where we have enough non-na values for SMA initialization.\n // An infinite value is na, as in PineScript.\n let firstValidIndex = -1;\n let validCount = 0;\n\n for (let i = 0; i < source.length; i++) {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val) && ++validCount === len) {\n firstValidIndex = i;\n break;\n }\n }\n\n const rmaInitialized = firstValidIndex >= 0;\n // The seed is ta.sma on that bar: the running sum of math.sum (PineScript bits), not a plain loop sum\n let rmaValue = rmaInitialized ? runningSum(source.slice(0, firstValidIndex + 1), len)[firstValidIndex]! / len : NaN;\n\n for (let i = 0; i < source.length; i++) {\n if (!rmaInitialized || i < firstValidIndex) {\n // Not enough data yet for RMA\n result.push(NaN);\n } else if (i === firstValidIndex) {\n // First valid RMA value\n result.push(rmaValue);\n } else {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val)) {\n // PineScript evaluates (source + (length - 1) * RMA[1]) / length; the form\n // alpha * source + (1 - alpha) * RMA[1] differs in the last bits\n rmaValue = (val + (len - 1) * rmaValue) / len;\n result.push(rmaValue);\n } else {\n // na source: na on this bar; the next bar continues from the last value (as in PineScript)\n result.push(NaN);\n }\n }\n }\n\n return result;\n}\n\n/**\n * One step of the PineScript ta.wma sum: `a + b`, or 0 when `|a + b| <= 1e-10 * max(1, |a| + |b|)`.\n * Measured bit for bit: a sum that cancels to a tiny residue (relative to the operands, or below 1e-10) is 0.\n */\nfunction wmaAdd(a: number, b: number): number {\n const sum = a + b;\n return Math.abs(sum) <= 1e-10 * Math.max(1, Math.abs(a) + Math.abs(b)) ? 0 : sum;\n}\n\n/**\n * Weighted Moving Average (WMA) - moving average with linearly decreasing weights.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns WMA of source for length bars back\n *\n * @remarks\n * - Weighting factors decrease in arithmetical progression\n * - Most recent value has weight `length`, previous has `length-1`, etc.\n * - Formula: `sum(source[i]! * (length - i)) / sum(length - i)` for i = 0 to length-1\n * - As in PineScript: na on a bar whose source is `na` (also +/-Infinity) and until `length` non-`na` values were\n * received; an `na` value inside the window is replaced by the previous non-`na` value\n * - Summed from the oldest value to the newest; as PineScript, a partial sum `s + t` with\n * `|s + t| <= 1e-10 * max(1, |s| + |t|)` is 0 (a cancellation residue, or values below 1e-10)\n * - More responsive to recent price changes than SMA\n * - `length` can be an array (a length per bar, PineScript series length): each bar gives the result of its own\n * length (`na` for a length below 1)\n *\n * @example\n * ```typescript\n * const wma20 = ta.wma(closePrices, 20);\n * // WMA gives more weight to recent prices\n * ```\n */\nexport function wma(source: Source, length: simple_int | ArrayLike<number>): series_float {\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const fixed = typeof length === 'number' ? Math.floor(length) : NaN;\n if (typeof length === 'number') checkPositiveLength('wma', fixed, 0);\n // PineScript: na on a bar with an na source (also +/-Infinity) and until `len` non-na values were received;\n // otherwise the last `len` bars, each na replaced by the previous non-na value\n const filled: number[] = [];\n let last = NaN;\n let count = 0;\n for (let i = 0; i < source.length; i++) {\n const v = source[i];\n const isNa = v === undefined || v === null || !Number.isFinite(v);\n if (!isNa) {\n last = v;\n count++;\n }\n filled.push(last);\n // a series length: the window of this bar's length (the result of ta.wma with that fixed length)\n const len = typeof length === 'number' ? fixed : Math.floor(length[i]!);\n if (typeof length !== 'number') checkPositiveLength('wma', len, i);\n if (isNa || !(len >= 1) || count < len) {\n result.push(NaN);\n continue;\n }\n // Summed from the oldest bar (weight 1) to the newest (weight len), as PineScript (bit for bit)\n let sum = 0;\n let weightSum = 0;\n for (let j = len - 1; j >= 0; j--) {\n const weight = len - j;\n sum = wmaAdd(sum, filled[i - j]! * weight);\n weightSum += weight;\n }\n result.push(sum / weightSum);\n }\n return result;\n}\n\n/**\n * Highest value over the last `length` bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns Highest value series (na on the first `length - 1` bars)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the highest of the last `length`\n * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar\n * `length - 1` and while no value was received. A fractional length is truncated (7.5 is 7 bars).\n * `length` can be an array (a length per bar, PineScript series length), also for `ta.lowest`, `ta.highestbars`\n * and `ta.lowestbars`: each bar uses its own length.\n * A length above 15,000 throws the PineScript runtime error (also `ta.lowest`, `ta.highestbars`, `ta.lowestbars`).\n * PineScript `ta.highest(length)` (source = high) is `ta.highest(length)` in the script API.\n */\nexport function highest(source: Source, length: simple_int | ArrayLike<number>): series_float {\n return extremeValue(source, length, false);\n}\n\n/**\n * Lowest value over the last `length` bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns Lowest value series (na on the first `length - 1` bars)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the lowest of the last `length`\n * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar\n * `length - 1` and while no value was received.\n */\nexport function lowest(source: Source, length: simple_int | ArrayLike<number>): series_float {\n return extremeValue(source, length, true);\n}\n\n/**\n * Cumulative Sum - returns the total sum of all elements from the beginning.\n *\n * @param source - Series of values to process\n * @returns Series containing the cumulative sum at each bar\n *\n * @remarks\n * - Returns the running total of all values from index 0 to current index\n * - As in PineScript: an `na` value adds nothing to the sum,\n * and the result is `na` on that bar only; the sum continues on the next bars\n * - Useful for calculating total volume, total trades, etc.\n *\n * @example\n * ```typescript\n * const cumulativeVolume = ta.cum(volume);\n * const totalGains = ta.cum(gains);\n * ```\n */\nexport function cum(source: Source): series_float {\n let sum = 0;\n return source.map((v) => {\n // PineScript: an na value (also +/-Infinity) gives na on its bar and is not added\n if (!Number.isFinite(v)) return NaN;\n sum += v;\n return sum;\n });\n}\n\n/**\n * Cross - returns true when two series cross each other (either direction).\n *\n * @param source1 - First series\n * @param source2 - Second series\n * @returns Boolean series (true at cross points)\n *\n * @remarks\n * PineScript rule (measured bit for bit; not `crossover or crossunder`):\n * - The call keeps the side of the last bar where `source1` was strictly above or strictly below `source2` (no\n * side before such a bar). Equal bars and bars with an `na` value do not change it.\n * - True when the values are strictly on the other side of the kept side: so a run of equal values is passed, and\n * a series that starts equal and then moves away is not a cross\n * - False on a bar with an `na` value\n * - Use `ta.crossover()` or `ta.crossunder()` for directional crosses\n *\n * @example\n * ```typescript\n * const crossed = ta.cross(fastMA, slowMA);\n * // Detect any MA crossover\n * ```\n */\nexport function cross(source1: Source, source2: Source): series_bool {\n const result: series_bool = [];\n let side = 0; // -1: last strictly below, 1: last strictly above, 0: none yet\n for (let i = 0; i < source1.length; i++) {\n const a = source1[i]!;\n const b = source2[i]!;\n if (Number.isNaN(a) || Number.isNaN(b)) {\n result.push(false);\n continue;\n }\n result.push((side < 0 && a > b) || (side > 0 && a < b));\n if (a < b) side = -1;\n else if (a > b) side = 1;\n }\n return result;\n}\n\n/**\n * ta.rising / ta.falling: a counter of the steps from one bar to the next that pass `step(newer, older)`, reset to 0\n * by a step that does not pass; a step with an na value (on either bar) leaves the counter unchanged. True when the\n * counter is at least `length`.\n *\n * @internal\n */\nfunction monotonic(source: Source, length: simple_int, step: (newer: number, older: number) => boolean): series_bool {\n const result: series_bool = [];\n let count = 0;\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n const prev = i > 0 ? source[i - 1]! : NaN;\n if (Number.isFinite(v) && Number.isFinite(prev)) count = step(v, prev) ? count + 1 : 0;\n result.push(count >= length);\n }\n return result;\n}\n\n/**\n * Rising - returns true if source is rising for length bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Boolean series (true when rising)\n *\n * @remarks\n * PineScript rules:\n * - a counter of rises from the previous bar (a rise is larger than the 1e-10 tolerance); a step that is not a rise\n * resets it to 0\n * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after\n * it, keep the result of the bar before the `na`)\n * - true when the counter is at least `length` (false at the start)\n *\n * @example\n * ```typescript\n * const isRising = ta.rising(close, 3);\n * // Detect upward momentum\n * ```\n */\nexport function rising(source: Source, length: simple_int): series_bool {\n checkPositiveLength('rising', length, 0);\n return monotonic(source, length, gt);\n}\n\n/**\n * Falling - returns true if source is falling for length bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Boolean series (true when falling)\n *\n * @remarks\n * PineScript rules:\n * - a counter of falls from the previous bar (a fall is larger than the 1e-10 tolerance); a step that is not a fall\n * resets it to 0\n * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after\n * it, keep the result of the bar before the `na`)\n * - true when the counter is at least `length` (false at the start)\n *\n * @example\n * ```typescript\n * const isFalling = ta.falling(close, 3);\n * // Detect downward momentum\n * ```\n */\nexport function falling(source: Source, length: simple_int): series_bool {\n checkPositiveLength('falling', length, 0);\n return monotonic(source, length, lt);\n}\n\n/**\n * Rate of Change (ROC) - percentage change between current value and value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns ROC series as percentage\n *\n * @remarks\n * - Formula: `100 * change(source, length) / source[length]`\n * - Equivalent to: `100 * (source - source[length]) / source[length]`\n * - Returns percentage change, e.g., 5.0 means 5% increase\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - Useful for momentum analysis and trend strength measurement\n *\n * @example\n * ```typescript\n * const roc10 = ta.roc(closePrices, 10);\n * // Positive ROC indicates upward momentum\n * // Negative ROC indicates downward momentum\n * ```\n */\nexport function roc(source: Source, length: simple_int): series_float {\n checkPositiveLength('roc', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n const oldValue = source[i - length]!;\n if (oldValue === 0 || isNaN(oldValue) || isNaN(source[i]!)) {\n result.push(NaN);\n } else {\n const changeValue = source[i]! - oldValue;\n result.push((100 * changeValue) / oldValue);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Momentum (MOM) - difference between current value and value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Offset from current bar to previous bar\n * @returns Momentum series\n *\n * @remarks\n * - Formula: `source - source[length]`\n * - Equivalent to `ta.change(source, length)`\n * - Positive momentum indicates upward movement\n * - Negative momentum indicates downward movement\n * - `na` values in the source series are included in calculations and will produce an `na` result\n *\n * @example\n * ```typescript\n * const mom10 = ta.mom(closePrices, 10);\n * // Measures raw price momentum over 10 bars\n * ```\n */\nexport function mom(source: Source, length: simple_int): series_float {\n checkPositiveLength('mom', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n if (isNaN(source[i]!) || isNaN(source[i - length]!)) {\n result.push(NaN);\n } else {\n result.push(source[i]! - source[i - length]!);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Mean Absolute Deviation - measure of difference between series and its SMA.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Mean absolute deviation series\n *\n * @remarks\n * - Measures average absolute distance from the mean\n * - Less sensitive to outliers than standard deviation\n * - PineScript rule (bit for bit): `sum(abs(source[i] - mean)) / length` for `i = 0 .. length - 1`, added newest\n * first, with `mean = ta.sma(source, length)` (its compensated running sum, so a flat window can give a tiny\n * non-zero deviation)\n * - The loop reads the last `length` bars: an `na` among them gives `na`\n *\n * @example\n * ```typescript\n * const dev10 = ta.dev(closePrices, 10);\n * // Measures volatility using mean absolute deviation\n * ```\n */\nexport function dev(source: Source, length: simple_int): series_float {\n checkPositiveLength('dev', length, 0);\n const len = Math.floor(length);\n return sma(source, len).map((mean, i) => {\n if (i < len - 1 || Number.isNaN(mean)) return NaN;\n let sum = 0;\n for (let k = 0; k < len; k++) sum += Math.abs(source[i - k]! - mean);\n return sum / len;\n });\n}\n\n/**\n * Variance - expectation of squared deviation from mean.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param biased - Use biased (true) or unbiased (false) estimate (default: true)\n * @returns Variance series\n *\n * @remarks\n * - Measures how far values are spread out from their mean\n * - If `biased` is true: divides by `length` (population variance)\n * - If `biased` is false: divides by `length - 1` (sample variance)\n * - Formula (biased): `sum((source[i]! - mean)^2) / length`\n * - Formula (unbiased): `sum((source[i]! - mean)^2) / (length - 1)`\n * - `na` values in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n * - Relationship: `stdev = sqrt(variance)`\n * - Computed as PineScript, bit for bit, from compensated running sums of the values and of their squares:\n * biased `sumSq / length - mean * mean`, unbiased `sumSq / (length - 1) - mean * sum / (length - 1)`\n *\n * @example\n * ```typescript\n * const variance20 = ta.variance(closePrices, 20);\n * const sampleVariance = ta.variance(closePrices, 20, false);\n * ```\n */\nexport function variance(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: simple_bool = true\n): series_float {\n return varianceOf(source, length, biased, 'ta.variance');\n}\n\n/** {@link variance} with a fixed or a series length; `name` is used in the error messages. */\nfunction varianceOf(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: boolean,\n name: string\n): series_float {\n if (typeof length !== 'number') {\n const result = runningVarianceSeries(source, length, biased, name);\n return biased ? result : result.map((v, i) => (Math.floor(length[i]!) > 1 ? v : NaN));\n }\n const len = Math.floor(length);\n checkSumLength(name, len, 0);\n // PineScript: the last `len` non-na values (also +/-Infinity skipped), as ta.sma\n if ((biased ? len : len - 1) <= 0) return source.map(() => NaN);\n return runningVariance(source, len, biased);\n}\n\n/**\n * Median - returns the median (middle value) of the series.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Median series\n *\n * @remarks\n * - Returns the middle value when values are sorted\n * - For an even length, returns the average of the two middle values\n * - As in PineScript: `na` values (also +/-Infinity) are skipped, the window holds the last `length` non-na values\n * (going back as many bars as needed), and a bar whose own value is `na` still gets a result\n * - Returns NaN until `length` non-na values exist\n * - More robust to outliers than mean (SMA)\n *\n * @example\n * ```typescript\n * const median20 = ta.median(closePrices, 20);\n * // Median is less affected by extreme values than SMA\n * ```\n */\nexport function median(source: Source, length: simple_int): series_float {\n checkPositiveLength('median', length, 0);\n const len = Math.floor(length);\n const n = source.length;\n const out: series_float = new Array<number>(n).fill(NaN);\n if (!(len >= 1)) return out;\n // The last `len` non-na values, sorted; equal values (also +0 / -0) from the newest to the oldest, which is the\n // order a stable sort of the window gives, so the middle values are the same numbers.\n const sorted: number[] = [];\n const kept = new Float64Array(n); // the non-na values in bar order\n let count = 0;\n /** First position whose value is >= v (`after`: > v). */\n const bound = (v: number, after: boolean): number => {\n let lo = 0;\n let hi = sorted.length;\n while (lo < hi) {\n const m = (lo + hi) >> 1;\n if (after ? sorted[m]! <= v : sorted[m]! < v) lo = m + 1;\n else hi = m;\n }\n return lo;\n };\n const mid = Math.floor(len / 2);\n for (let i = 0; i < n; i++) {\n const x = source[i]!;\n if (Number.isFinite(x)) {\n kept[count++] = x;\n sorted.splice(bound(x, false), 0, x); // before the equal values: the newest first\n // the value leaving the window is the oldest, so the last of its equal values\n if (count > len) sorted.splice(bound(kept[count - 1 - len]!, true) - 1, 1);\n }\n if (count >= len) out[i] = len % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n }\n return out;\n}\n\n/**\n * Symmetrically Weighted Moving Average (SWMA) - fixed length 4 with symmetric weights.\n *\n * @param source - Series of values to process\n * @returns SWMA series\n *\n * @remarks\n * - Fixed length of 4 bars\n * - Weights: [1/6, 2/6, 2/6, 1/6] (symmetric)\n * - Formula, in this order as in PineScript (bit for bit): `(source + 2 * source[1] + 2 * source[2] + source[3]) / 6`\n * - More weight given to middle values\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - Returns NaN for the first 3 bars\n *\n * @example\n * ```typescript\n * const swma = ta.swma(closePrices);\n * // Smoothed price with symmetric weighting\n * ```\n */\nexport function swma(source: Source): series_float {\n return Array.from({ length: source.length }, (_, i) =>\n i < 3 ? NaN : (source[i]! + 2 * source[i - 1]! + 2 * source[i - 2]! + source[i - 3]!) / 6\n );\n}\n\n/**\n * Volume Weighted Moving Average (VWMA) - moving average weighted by volume.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param volume - Volume series (required when not using context API)\n * @returns VWMA series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.vwma(source, length)` - uses implicit volume data\n * - **JavaScript signature**: Requires explicit `volume` OR use `createContext()`\n * - Formula: `sma(source * volume, length) / sma(volume, length)`\n * - Gives more weight to bars with higher volume\n * - `na` values in the source series are ignored\n * - Useful for price analysis considering volume significance\n *\n * @example\n * ```typescript\n * // Direct call with explicit volume\n * const vwma20 = ta.vwma(closePrices, 20, volumeData);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close, volume } });\n * const vwma20 = ta.vwma(close, 20); // Matches PineScript!\n * ```\n */\nexport function vwma(source: Source, length: simple_int, volume?: Source): series_float {\n checkPositiveLength('vwma->sma', length, 0);\n if (!volume) {\n throw new Error(\n 'ta.vwma() requires volume series. ' +\n 'Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data.'\n );\n }\n\n // Calculate source * volume\n const sourceTimesVolume: series_float = [];\n for (let i = 0; i < source.length; i++) {\n sourceTimesVolume.push(source[i]! * volume[i]!);\n }\n\n const numerator = sma(sourceTimesVolume, length);\n const denominator = sma(volume, length);\n\n const result: series_float = [];\n for (let i = 0; i < source.length; i++) {\n if (denominator[i]! === 0 || isNaN(denominator[i]!)) {\n result.push(NaN);\n } else {\n result.push(numerator[i]! / denominator[i]!);\n }\n }\n\n return result;\n}\n\n/**\n * Linear Regression - line that best fits prices using least squares method.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param offset - Offset (default: 0)\n * @returns Linear regression value\n *\n * @remarks\n * - Calculates line of best fit using least squares method\n * - Formula: `linreg = intercept + slope * (length - 1 - offset)`\n * - As PineScript (bit for bit): x = 1 (oldest) .. length (newest), sums from the oldest value,\n * `slope = (length * sumXY - sumX * sumY) / (length * sumX2 - sumX * sumX)`,\n * `intercept = sumY / length - slope * sumX / length + slope`\n * - offset=0 gives current fitted value, offset<0 gives future projection\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - Useful for trend detection and prediction\n *\n * @example\n * ```typescript\n * const linreg20 = ta.linreg(closePrices, 20, 0);\n * const linregFuture = ta.linreg(closePrices, 20, -5); // Project 5 bars ahead\n * ```\n */\nexport function linreg(source: Source, length: simple_int, offset: simple_int = 0): series_float {\n checkPositiveLength('linreg', length, 0);\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n\n for (let i = 0; i < source.length; i++) {\n if (i < len - 1) {\n result.push(NaN);\n } else {\n // Check for NaN values in window\n let hasNaN = false;\n for (let j = 0; j < len; j++) {\n if (isNaN(source[i - j]!)) {\n hasNaN = true;\n break;\n }\n }\n\n if (hasNaN) {\n result.push(NaN);\n } else {\n // Least squares as PineScript: x = 1 (oldest) .. len (newest), summed from the oldest value; the intercept\n // is the fitted value at x = 1\n let sumX = 0;\n let sumY = 0;\n let sumXY = 0;\n let sumX2 = 0;\n for (let j = 0; j < len; j++) {\n const x = j + 1;\n const y = source[i - (len - 1 - j)]!;\n sumX += x;\n sumY += y;\n sumXY += x * y;\n sumX2 += x * x;\n }\n const slope = (len * sumXY - sumX * sumY) / (len * sumX2 - sumX * sumX);\n const intercept = sumY / len - (slope * sumX) / len + slope;\n result.push(intercept + slope * (len - 1 - offset));\n }\n }\n }\n\n return result;\n}\n\n/**\n * Correlation Coefficient - measures degree to which two series deviate from their means together.\n *\n * @param source1 - First series\n * @param source2 - Second series \n * @param length - Number of bars (length)\n * @returns Correlation coefficient (-1 to +1)\n *\n * @remarks\n * - Returns value between -1 and +1\n * - +1 = perfect positive correlation\n * - -1 = perfect negative correlation\n * - 0 = no correlation\n * - Measures linear relationship between two series\n * - As PineScript: `cov = sma(x * y) - sma(x) * sma(y)`, `r = cov / sqrt(variance(x) * variance(y))` with the\n * compensated running sums of `ta.sma` / `ta.variance` (each skips its own `na` values); `|cov| <= 1e-10` gives 0, a\n * zero variance gives `na`\n *\n * @example\n * ```typescript\n * const corr = ta.correlation(series1, series2, 20);\n * // Values close to +1 or -1 indicate strong relationship\n * ```\n */\nexport function correlation(source1: Source, source2: Source, length: simple_int): series_float {\n checkPositiveLength('correlation', length, 0);\n // PineScript: from compensated running sums, cov = sma(x * y) - sma(x) * sma(y), r = cov / sqrt(var(x) * var(y))\n // (biased variances); each running sum skips its own na values\n const product = Array.from({ length: source1.length }, (_, i) => {\n const v1 = source1[i];\n const v2 = source2[i];\n return v1 === null || v1 === undefined || v2 === null || v2 === undefined ? NaN : v1 * v2;\n });\n const meanXY = sma(product, length);\n const meanX = sma(source1, length);\n const meanY = sma(source2, length);\n const varX = variance(source1, length);\n const varY = variance(source2, length);\n return meanXY.map((mxy, i) => {\n const cov = mxy - meanX[i]! * meanY[i]!;\n if (Number.isNaN(cov)) return NaN;\n // a covariance within 1e-10 of 0 gives 0; a zero denominator gives na (a division by zero)\n if (Math.abs(cov) <= 1e-10) return 0;\n const denominator = Math.sqrt(varX[i]! * varY[i]!);\n return denominator === 0 ? NaN : cov / denominator;\n });\n}\n\n/**\n * Percent Rank - percentage of how many previous values were less than or equal to current value.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Percent rank (0 to 100)\n *\n * @remarks\n * - Returns value between 0 and 100\n * - 0 = current value is lowest in the period\n * - 100 = current value is highest in the period\n * - 50 = current value is at median\n * - Useful for identifying relative strength within a period\n *\n * PineScript rules:\n * - percentrank = count(source[k] <= source, k = 1..length) * 100 / length (in this order: the PineScript bits)\n * - a value from bar `length` on; an `na` value in the window counts as not `<=` the current value, and an `na`\n * current value gives 0 (#177)\n * - the comparison uses the 1e-10 tolerance\n *\n * @example\n * ```typescript\n * const pctrank = ta.percentrank(closePrices, 100);\n * // Values near 100 indicate recent strength\n * // Values near 0 indicate recent weakness\n * ```\n */\nexport function percentrank(source: Source, length: simple_int): series_float {\n checkPositiveLength('percentrank', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n const currentValue = source[i]!;\n if (i < length) {\n result.push(NaN);\n continue;\n }\n // le() is false for an na value in the window, and for all of them when the current value is na (0)\n let countLessOrEqual = 0;\n for (let j = 1; j <= length; j++) {\n if (le(source[i - j]!, currentValue)) countLessOrEqual++;\n }\n result.push((countLessOrEqual * 100) / length);\n }\n\n return result;\n}\n\n/**\n * Commodity Channel Index (CCI) - measures deviation from average price.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns CCI series\n *\n * @remarks\n * - CCI = (Typical Price - SMA of TP) / (0.015 * Mean Deviation)\n * - Typical Price = (High + Low + Close) / 3\n * - Mean Deviation = Average of absolute differences from mean\n * - Scaled by 0.015 to provide more readable numbers\n * - Values above +100 indicate overbought conditions\n * - Values below -100 indicate oversold conditions\n *\n * PineScript rules (bit for bit):\n * - `(source - ta.sma(source, length)) / (0.015 * ta.dev(source, length))`\n * - when the mean deviation is 0 (1e-10 tolerance, a flat window), the last CCI value; 0 when there is none yet\n * (a flat first window)\n * - \\`na\\` when the mean or the deviation is \\`na\\` (an \\`na\\` in the last \\`length\\` bars)\n *\n * @example\n * \\`\\`\\`typescript\n * const cci20 = ta.cci(typicalPrice, 20);\n * // Overbought when cci > 100\n * // Oversold when cci < -100\n * \\`\\`\\`\n */\nexport function cci(source: Source, length: simple_int): series_float {\n checkPositiveLength('cci', length, 0);\n const smaValues = sma(source, length);\n const devValues = dev(source, length);\n let last = 0;\n return smaValues.map((mean, i) => {\n const d = devValues[i]!;\n if (Number.isNaN(mean) || Number.isNaN(d)) return NaN;\n if (!eq(d, 0)) last = (source[i]! - mean) / (0.015 * d);\n return last;\n });\n}\n\n/**\n * Stochastic Oscillator - momentum indicator comparing closing price to price range.\n *\n * @param source - Source series (typically close)\n * @param high - High price series\n * @param low - Low price series\n * @param length - Number of bars (length)\n * @returns Stochastic %K series (values range from 0 to 100)\n *\n * @remarks\n * - Formula: 100 * (close - lowest(low, length)) / (highest(high, length) - lowest(low, length))\n * - Measures where close is relative to the high-low range\n * - Values above 80 typically indicate overbought\n * - Values below 20 typically indicate oversold\n * - As PineScript: when the source, \\`highest(high, length)\\` or \\`lowest(low, length)\\` is \\`na\\`, or the range and\n * \\`source - lowest\\` are both 0, the result is the previous result of the call (\\`na\\` until a first value); a zero\n * range with another source value gives +/-Infinity (plotted as \\`na\\`)\n *\n * @example\n * \\`\\`\\`typescript\n * const stochK = ta.stoch(close, high, low, 14);\n * // Smooth with SMA for %D line:\n * const stochD = ta.sma(stochK, 3);\n * \\`\\`\\`\n */\nexport function stoch(source: Source, high: Source, low: Source, length: simple_int): series_float {\n checkPositiveLength('stoch->highest', length, 0);\n const result: series_float = [];\n const lowestValues = lowest(low, length);\n const highestValues = highest(high, length);\n\n // PineScript: an na (NaN) result keeps the previous one: an na input, or 0 / 0 on a zero range; a non-zero value\n // over a zero range gives +/-Infinity (#183)\n let previous = NaN;\n for (let i = 0; i < source.length; i++) {\n const lo = lowestValues[i]!;\n const k = (100 * (source[i]! - lo)) / (highestValues[i]! - lo);\n if (!Number.isNaN(k)) previous = k;\n result.push(previous);\n }\n\n return result;\n}\n\n\n/**\n * Money Flow Index (MFI) - volume-weighted RSI measuring buying and selling pressure.\n *\n * @param source - Source series (typically hlc3 or close)\n * @param length - Number of bars (length)\n * @param volume - Volume series (required when not using context API)\n * @returns MFI series (values range from 0 to 100)\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.mfi(source, length)` - uses implicit volume data\n * - **JavaScript signature**: Requires explicit `volume` OR use `createContext()`\n * - Combines price and volume to identify overbought/oversold conditions\n * - Formula: 100 - (100 / (1 + Positive Money Flow / Negative Money Flow))\n * - Values above 80 indicate overbought\n * - Values below 20 indicate oversold\n *\n * PineScript rules (bit for bit):\n * - the two flows are `math.sum` running sums; a sum within 1e-10 of 0 counts as 0 (the residue a running sum\n * keeps over a window of zeros)\n * - 100 when the negative flow is 0; `na` when `1 + positive / negative` is 0 (division by zero)\n * - a bar with an `na` source adds nothing to the sums and gives the previous result; the bar after it (an `na`\n * change) adds its money flow to both sums\n *\n * @example\n * ```typescript\n * // Direct call with explicit volume\n * const mfi14 = ta.mfi(hlc3, 14, volume);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close, volume } });\n * const mfi14 = ta.mfi(hlc3, 14); // Matches PineScript!\n * ```\n */\nexport function mfi(source: Source, length: simple_int, volume?: Source): series_float {\n checkPositiveLength('mfi', length, 0);\n if (!volume) {\n throw new Error(\n 'ta.mfi() requires volume series. ' +\n 'Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data.'\n );\n }\n\n // PineScript reference:\n // upper = math.sum(volume * (ta.change(src) <= 0 ? 0 : src), length)\n // lower = math.sum(volume * (ta.change(src) >= 0 ? 0 : src), length)\n // A comparison with na is false, so a bar with an na change (bar 0) adds its money flow to both sums.\n // The comparisons use the 1e-10 tolerance of Pine operators.\n const upperFlow: number[] = [];\n const lowerFlow: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const change = i === 0 ? NaN : source[i]! - source[i - 1]!;\n const flow = volume[i]! * source[i]!;\n upperFlow.push(le(change, 0) ? 0 : flow);\n lowerFlow.push(ge(change, 0) ? 0 : flow);\n }\n // math.sum: the compensated running sum of the last `length` non-na values (as PineScript, bit for bit)\n const upper = runningSum(upperFlow, length);\n const lower = runningSum(lowerFlow, length);\n\n // A sum within 1e-10 of 0 (the residue of a running sum over a window of zeros) is 0\n const zero = (x: number) => (Math.abs(x) <= 1e-10 ? 0 : x);\n return upper.map((sumUp, i) => {\n const u = zero(sumUp);\n const l = zero(lower[i]!);\n if (Number.isNaN(u) || Number.isNaN(l)) return NaN;\n if (l === 0) return 100;\n const ratio = 1 + u / l;\n // x / 0 is na in PineScript\n return ratio === 0 ? NaN : 100 - 100 / ratio;\n });\n}\n\n/**\n * Hull Moving Average (HMA) - improved moving average with reduced lag.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Hull moving average series\n *\n * @remarks\n * - Formula: WMA(2 * WMA(src, len/2) - WMA(src, len), sqrt(len))\n * - Significantly reduces lag compared to traditional moving averages\n * - Smoother than WMA while being more responsive\n * - Created by Alan Hull\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const hma20 = ta.hma(closePrices, 20);\n * // Faster response to price changes than SMA or EMA\n * ```\n */\nexport function hma(source: Source, length: simple_int): series_float {\n checkPositiveLength('hma', length, 0);\n const halfLength = Math.floor(length / 2);\n const sqrtLength = Math.floor(Math.sqrt(length));\n\n const wmaHalf = wma(source, halfLength);\n const wmaFull = wma(source, length);\n\n const diff: series_float = [];\n for (let i = 0; i < source.length; i++) {\n diff.push(2 * wmaHalf[i]! - wmaFull[i]!);\n }\n\n return wma(diff, sqrtLength);\n}\n\n/**\n * Parabolic SAR (Stop and Reverse) - trend-following indicator.\n *\n * @param start - Acceleration factor start value (typically 0.02)\n * @param inc - Acceleration factor increment (typically 0.02)\n * @param max - Maximum acceleration factor (typically 0.2)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns SAR series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.sar(start, inc, max)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - SAR below price indicates uptrend, above price indicates downtrend\n * - Created by J. Welles Wilder Jr.\n *\n * @example\n * ```typescript\n * const sar = ta.sar(0.02, 0.02, 0.2, high, low, close);\n * ```\n */\nexport function sar(\n start: simple_float,\n inc: simple_float,\n max: simple_float,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.sar() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const result: series_float = [];\n let sarValue = NaN;\n let extremePoint = NaN;\n let acceleration = start;\n let isUpTrend = false;\n let isFirstTrendBar = false;\n\n for (let i = 0; i < close.length; i++) {\n if (i === 0) {\n result.push(NaN);\n continue;\n }\n\n if (i === 1) {\n if (close[i]! > close[i - 1]!) {\n isUpTrend = true;\n extremePoint = high[i]!;\n sarValue = low[i - 1]!;\n } else {\n isUpTrend = false;\n extremePoint = low[i]!;\n sarValue = high[i - 1]!;\n }\n isFirstTrendBar = true;\n acceleration = start;\n }\n\n sarValue = sarValue + acceleration * (extremePoint - sarValue);\n\n if (isUpTrend) {\n if (sarValue > low[i]!) {\n isFirstTrendBar = true;\n isUpTrend = false;\n sarValue = Math.max(high[i]!, extremePoint);\n extremePoint = low[i]!;\n acceleration = start;\n }\n } else {\n if (sarValue < high[i]!) {\n isFirstTrendBar = true;\n isUpTrend = true;\n sarValue = Math.min(low[i]!, extremePoint);\n extremePoint = high[i]!;\n acceleration = start;\n }\n }\n\n if (!isFirstTrendBar) {\n if (isUpTrend) {\n if (high[i]! > extremePoint) {\n extremePoint = high[i]!;\n acceleration = Math.min(acceleration + inc, max);\n }\n } else {\n if (low[i]! < extremePoint) {\n extremePoint = low[i]!;\n acceleration = Math.min(acceleration + inc, max);\n }\n }\n }\n\n if (isUpTrend) {\n sarValue = Math.min(sarValue, low[i - 1]!);\n if (i > 1) {\n sarValue = Math.min(sarValue, low[i - 2]!);\n }\n } else {\n sarValue = Math.max(sarValue, high[i - 1]!);\n if (i > 1) {\n sarValue = Math.max(sarValue, high[i - 2]!);\n }\n }\n\n result.push(sarValue);\n isFirstTrendBar = false;\n }\n\n return result;\n}\n\n/** A pivot length: one value, or a value per bar (PineScript series length). */\ntype PivotLength = simple_int | ArrayLike<number>;\n\n/**\n * Pivot detection as PineScript computes it.\n *\n * The function keeps the non-na values it receives. On each bar it takes the last `leftbars + rightbars + 1` of them\n * (all of them when there are fewer) and finds the highest (the newest one on equal values; the lowest for a pivot\n * low): there is a pivot when that value is on the bar `rightbars` bars back, and its value is returned on this bar,\n * so no future bar is used. A pivot high may so equal values on its left but must be higher than every value on its\n * right. `na` before bar `leftbars + rightbars`.\n */\nfunction pivot(source: Source, leftbars: PivotLength, rightbars: PivotLength, isHigh: boolean): series_float {\n const { values, bars, last } = keptValues(source);\n return Array.from(source, (_, i) => {\n // a series length: the lengths of the current bar\n const left = Math.trunc(typeof leftbars === 'number' ? leftbars : leftbars[i]!);\n const right = Math.trunc(typeof rightbars === 'number' ? rightbars : rightbars[i]!);\n const k = last[i]!;\n if (!(i >= left + right) || k < 0) return NaN;\n let best = k;\n for (let j = k - 1; j >= 0 && j >= k - left - right; j--) {\n if (isHigh ? values[j]! > values[best]! : values[j]! < values[best]!) best = j;\n }\n return bars[best] === i - right ? values[best]! : NaN;\n });\n}\n\n/**\n * Pivot High - detects pivot high points in the price series.\n *\n * @param sourceOrLeftbars - Source series or leftbars (overloaded)\n * @param leftbarsOrRightbars - Leftbars or rightbars (overloaded)\n * @param rightbars - Number of bars to the right (optional)\n * @param high - High price series (used in 2-param version)\n * @returns Series with the pivot high value on the bar where the pivot is confirmed\n * (`rightbars` bars after the pivot bar), NaN elsewhere\n *\n * @remarks\n * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar\n * index is `i - rightbars`\n * - A pivot high may equal values on its left but must be higher than all values on its right\n * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,\n * and the highest of them must be on the bar `rightbars` bars back\n * - `leftbars` / `rightbars` can be arrays (a length per bar, PineScript series length), also for `ta.pivotlow`:\n * each bar uses its own lengths\n *\n * @example\n * ```typescript\n * const pivotHighs = ta.pivothigh(high, 2, 2);\n * // pivotHighs[i] is high[i - 2] when bar i - 2 is a pivot high\n * ```\n */\nexport function pivothigh(\n sourceOrLeftbars: Source | simple_int,\n leftbarsOrRightbars: PivotLength,\n rightbars?: PivotLength,\n high?: Source\n): series_float {\n if (rightbars === undefined) {\n if (!high) {\n throw new Error('ta.pivothigh() requires high series when using two-parameter version.');\n }\n return pivot(high, sourceOrLeftbars as simple_int, leftbarsOrRightbars, true);\n }\n return pivot(sourceOrLeftbars as Source, leftbarsOrRightbars, rightbars, true);\n}\n\n/**\n * Pivot Low - detects pivot low points in the price series.\n *\n * @param sourceOrLeftbars - Source series or leftbars (overloaded)\n * @param leftbarsOrRightbars - Leftbars or rightbars (overloaded)\n * @param rightbars - Number of bars to the right (optional)\n * @param low - Low price series (used in 2-param version)\n * @returns Series with the pivot low value on the bar where the pivot is confirmed\n * (`rightbars` bars after the pivot bar), NaN elsewhere\n *\n * @remarks\n * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar\n * index is `i - rightbars`\n * - A pivot low may equal values on its left but must be lower than all values on its right\n * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,\n * and the lowest of them must be on the bar `rightbars` bars back\n *\n * @example\n * ```typescript\n * const pivotLows = ta.pivotlow(low, 2, 2);\n * // pivotLows[i] is low[i - 2] when bar i - 2 is a pivot low\n * ```\n */\nexport function pivotlow(\n sourceOrLeftbars: Source | simple_int,\n leftbarsOrRightbars: PivotLength,\n rightbars?: PivotLength,\n low?: Source\n): series_float {\n if (rightbars === undefined) {\n if (!low) {\n throw new Error('ta.pivotlow() requires low series when using two-parameter version.');\n }\n return pivot(low, sourceOrLeftbars as simple_int, leftbarsOrRightbars, false);\n }\n return pivot(sourceOrLeftbars as Source, leftbarsOrRightbars, rightbars, false);\n}\n\n/**\n * Bars Since - returns number of bars since condition was true.\n *\n * @param condition - Boolean series condition\n * @returns Series with number of bars since condition was last true\n *\n * @remarks\n * - Returns 0 when condition is currently true\n * - Increments by 1 for each bar condition remains false\n * - Returns NaN if condition has never been true\n *\n * @example\n * ```typescript\n * const crossovers = ta.crossover(fastMA, slowMA);\n * const barsSinceCross = ta.barssince(crossovers);\n * ```\n */\nexport function barssince(condition: series_bool): series_float {\n const result: series_float = [];\n let barsSinceTrue = NaN;\n\n for (let i = 0; i < condition.length; i++) {\n if (condition[i]!) {\n barsSinceTrue = 0;\n } else if (!isNaN(barsSinceTrue)) {\n barsSinceTrue++;\n }\n result.push(barsSinceTrue);\n }\n\n return result;\n}\n\n/**\n * Value When - returns the value when condition was true.\n *\n * @param condition - Boolean series condition\n * @param source - Source series to get value from\n * @param occurrence - Which occurrence to get (0 = most recent)\n * @returns Series with values from when condition was true\n *\n * @remarks\n * - occurrence=0 returns value from most recent true condition\n * - occurrence=1 returns value from second most recent, etc.\n * - Returns NaN if condition hasn't been true occurrence+1 times yet\n *\n * @example\n * ```typescript\n * const crossovers = ta.crossover(fastMA, slowMA);\n * const lastCrossPrice = ta.valuewhen(crossovers, close, 0);\n * ```\n */\nexport function valuewhen(condition: series_bool, source: Source, occurrence: simple_int): series_float {\n const result: series_float = [];\n\n for (let i = 0; i < condition.length; i++) {\n let occurrenceCount = 0;\n let foundValue = NaN;\n\n for (let j = i; j >= 0; j--) {\n if (condition[j]) {\n if (occurrenceCount === occurrence) {\n foundValue = source[j]!;\n break;\n }\n occurrenceCount++;\n }\n }\n\n result.push(foundValue);\n }\n\n return result;\n}\n\n/**\n * Directional Movement Index - returns Directional Movement indicators.\n *\n * @param diLength - DI averaging length\n * @param adxSmoothing - ADX smoothing length\n * @returns Tuple of [plusDI, minusDI, ADX]\n *\n * @remarks\n * - +DI and -DI measure directional movement\n * - ADX measures trend strength (0-100)\n * - ADX above 25 typically indicates strong trend\n * - Requires high, low, and close data from context\n *\n * @example\n * ```typescript\n * const [plusDI, minusDI, adx] = ta.dmi(14, 14);\n * // When +DI > -DI and ADX > 25, strong uptrend\n * // When -DI > +DI and ADX > 25, strong downtrend\n * ```\n */\nexport function dmi(\n diLength: simple_int,\n adxSmoothing: simple_int,\n high: Source,\n low: Source,\n close: Source\n): [series_float, series_float, series_float] {\n // PineScript reference (built-in DMI):\n // up = ta.change(high), down = -ta.change(low)\n // plusDM = na(up) ? na : (up > down and up > 0 ? up : 0), minusDM likewise\n // trur = ta.rma(ta.tr, len)\n // plus = fixnan(100 * ta.rma(plusDM, len) / trur), minus likewise\n // adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), lensig)\n const len = Math.max(high.length, low.length, close.length);\n const plusDM: series_float = [];\n const minusDM: series_float = [];\n for (let i = 0; i < len; i++) {\n const up = i === 0 ? NaN : high[i]! - high[i - 1]!;\n const down = i === 0 ? NaN : low[i - 1]! - low[i]!;\n plusDM.push(Number.isNaN(up) ? NaN : gt(up, down) && gt(up, 0) ? up : 0);\n minusDM.push(Number.isNaN(down) ? NaN : gt(down, up) && gt(down, 0) ? down : 0);\n }\n\n const trur = rma(tr(false, high, low, close), diLength);\n const smoothedPlus = rma(plusDM, diLength);\n const smoothedMinus = rma(minusDM, diLength);\n // x / 0 is na; fixnan keeps the previous value\n const directional = (smoothed: series_float): series_float => {\n let last = NaN;\n return smoothed.map((v, i) => {\n const t = trur[i]!;\n const value = t === 0 ? NaN : (100 * v) / t;\n if (!Number.isNaN(value)) last = value;\n return last;\n });\n };\n const plusDI = directional(smoothedPlus);\n const minusDI = directional(smoothedMinus);\n\n const dx = plusDI.map((plus, i) => {\n const minus = minusDI[i]!;\n const sum = plus + minus;\n return Math.abs(plus - minus) / (eq(sum, 0) ? 1 : sum);\n });\n const adx = rma(dx, adxSmoothing).map((v) => 100 * v);\n\n return [plusDI, minusDI, adx];\n}\n\n/**\n * True Strength Index - momentum oscillator based on double smoothed momentum.\n *\n * @param source - Series of values to process\n * @param shortLength - Short smoothing length\n * @param longLength - Long smoothing length\n * @returns TSI series, a value in [-1, 1]\n *\n * @remarks\n * - As PineScript: `ta.ema(ta.ema(m, longLength), shortLength) / ta.ema(ta.ema(math.abs(m), longLength), shortLength)`\n * with `m = source - source[1]` (not scaled by 100)\n * - na when the denominator is 0 (a constant source), as a PineScript division by zero\n * - Positive values indicate bullish momentum\n * - Negative values indicate bearish momentum\n * - Crossovers of zero line can signal trend changes\n * - Less sensitive to short-term price fluctuations than RSI\n *\n * @example\n * ```typescript\n * const tsi = ta.tsi(close, 13, 25);\n * // TSI > 0: bullish momentum\n * // TSI < 0: bearish momentum\n * ```\n */\nexport function tsi(source: Source, shortLength: simple_int, longLength: simple_int): series_float {\n checkPositiveLength('tsi->ema', shortLength, 0);\n const momentum: series_float = [];\n\n // Calculate momentum (price change)\n for (let i = 0; i < source.length; i++) {\n if (i === 0) {\n momentum.push(NaN);\n } else {\n momentum.push(source[i]! - source[i - 1]!);\n }\n }\n\n // Double smooth momentum\n const smoothedMomentum = ema(ema(momentum, longLength), shortLength);\n\n // Double smooth absolute momentum\n const absMomentum = momentum.map(Math.abs);\n const smoothedAbsMomentum = ema(ema(absMomentum, longLength), shortLength);\n\n // PineScript: a value in [-1, 1]; a division by zero is na\n return smoothedMomentum.map((m, i) => {\n const d = smoothedAbsMomentum[i]!;\n return d === 0 ? NaN : m / d;\n });\n}\n\n/**\n * Chande Momentum Oscillator - momentum indicator similar to RSI.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns CMO series\n *\n * @remarks\n * - CMO oscillates between +100 and -100\n * - CMO > +50: overbought conditions\n * - CMO < -50: oversold conditions\n * - Unlike RSI, CMO uses sum of gains/losses instead of averages\n * - As in PineScript: the sums are the running sums of `math.sum` (bit for bit), and a flat window (every change 0)\n * is `0 / 0` = na\n * - More volatile than RSI\n *\n * @example\n * ```typescript\n * const cmo = ta.cmo(close, 14);\n * // CMO > 50: overbought\n * // CMO < -50: oversold\n * ```\n */\nexport function cmo(source: Source, length: simple_int): series_float {\n checkPositiveLength('cmo', length, 0);\n // PineScript definition: mom = ta.change(src), sm1 = math.sum(mom >= 0 ? mom : 0, length),\n // sm2 = math.sum(mom >= 0 ? 0 : -mom, length), cmo = 100 * (sm1 - sm2) / (sm1 + sm2), with the running sums of\n // math.sum (bit for bit). A comparison with na is false: an na change adds 0 to sm1 and na (skipped) to sm2.\n const up: number[] = [];\n const down: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const mom = i > 0 ? source[i]! - source[i - 1]! : NaN;\n up.push(mom >= 0 ? mom : 0);\n down.push(mom >= 0 ? 0 : -mom);\n }\n const sm1 = runningSum(up, length);\n const sm2 = runningSum(down, length);\n // a flat window is 0 / 0 = na\n return sm1.map((s1, i) => (100 * (s1 - sm2[i]!)) / (s1 + sm2[i]!));\n}\n\n/**\n * Keltner Channels - volatility-based envelope indicator.\n *\n * @param source - Series of values to process\n * @param length - Number of bars for EMA\n * @param mult - Multiplier for the range\n * @param useTrueRange - Use True Range (default: true) or high-low\n * @returns Tuple of [middle, upper, lower]\n *\n * @remarks\n * - Middle band is EMA of source\n * - Upper/lower bands are middle \u00B1 (range EMA \u00D7 multiplier)\n * - When useTrueRange=true, uses ATR for volatility\n * - When useTrueRange=false, uses high-low range\n * - Price breaking out of bands may signal trend continuation\n * - Requires high, low, close data from context when useTrueRange=true\n *\n * @example\n * ```typescript\n * const [middle, upper, lower] = ta.kc(close, 20, 2, true);\n * // Price above upper: potential uptrend\n * // Price below lower: potential downtrend\n * ```\n */\nexport function kc(\n source: Source,\n length: simple_int,\n mult: simple_float,\n useTrueRange: simple_bool = true,\n high?: Source,\n low?: Source,\n close?: Source\n): [series_float, series_float, series_float] {\n checkPositiveLength('kc', length, 0);\n // Calculate middle band (EMA of source)\n const middle = ema(source, length);\n\n // Calculate range\n let range: series_float;\n if (useTrueRange) {\n if (!high || !low || !close) {\n throw new Error('ta.kc() with useTrueRange=true requires high, low, and close data');\n }\n // PineScript reference: ta.tr, which is na on bar 0\n range = tr(false, high, low, close);\n } else {\n if (!high || !low) {\n throw new Error('ta.kc() requires high and low data');\n }\n range = [];\n for (let i = 0; i < high.length; i++) {\n range.push(high[i]! - low[i]!);\n }\n }\n\n // Smooth the range with EMA\n const rangeEma = ema(range, length);\n\n // Calculate upper and lower bands\n const upper: series_float = [];\n const lower: series_float = [];\n\n for (let i = 0; i < middle.length; i++) {\n upper.push(middle[i]! + rangeEma[i]! * mult);\n lower.push(middle[i]! - rangeEma[i]! * mult);\n }\n\n return [middle, upper, lower];\n}\n\n/**\n * Bollinger Bands Width - measures the width of Bollinger Bands.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @param mult - Standard deviation multiplier\n * @returns BBW series (percentage)\n *\n * @remarks\n * - BBW = ((upper band - lower band) / middle band) \u00D7 100\n * - Low BBW values indicate low volatility (potential breakout setup)\n * - High BBW values indicate high volatility\n * - BBW squeeze (narrowing bands) often precedes strong moves\n * - Works with existing bb() function\n *\n * @example\n * ```typescript\n * const bbw = ta.bbw(close, 20, 2);\n * // Low BBW: potential breakout coming\n * // High BBW: high volatility period\n * ```\n */\nexport function bbw(source: Source, length: simple_int, mult: simple_float): series_float {\n checkPositiveLength('bbw', length, 0);\n const [basis, upper, lower] = bb(source, length, mult);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (basis[i]! === 0) {\n result.push(NaN);\n } else {\n const width = ((upper[i]! - lower[i]!) / basis[i]!) * 100;\n result.push(width);\n }\n }\n\n return result;\n}\n\n/**\n * Williams %R (Williams Percent Range)\n *\n * Williams %R is a momentum indicator that measures overbought/oversold levels.\n * It compares the closing price to the high-low range over a specified period.\n *\n * Values range from -100 (oversold) to 0 (overbought):\n * - Above -20: Overbought\n * - Below -80: Oversold\n *\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @param length - Lookback period (default: 14)\n * @returns Williams %R series\n *\n * @remarks\n * PineScript rule (bit for bit): `100 * (close - max) / (max - min)` with `max = ta.highest(high, length)` and\n * `min = ta.lowest(low, length)` (their `na` rules); `na` when the range is 0.\n *\n * @example\n * ```typescript\n * const wpr = ta.wpr(high, low, close, 14);\n * // wpr < -80: oversold\n * // wpr > -20: overbought\n * ```\n */\nexport function wpr(high: Source, low: Source, close: Source, length: simple_int = 14): series_float {\n checkPositiveLength('wpr', length, 0);\n const highs = highest(high, length);\n const lows = lowest(low, length);\n return Array.from({ length: close.length }, (_, i) => {\n const hmax = highs[i]!;\n const range = hmax - lows[i]!;\n // PineScript, in this order (bit for bit): 100 * (close - max) / (max - min); x / 0 is na\n return range === 0 ? NaN : (100 * (close[i]! - hmax)) / range;\n });\n}\n\n/**\n * Volume Weighted Average Price, restarted on each bar where `anchor` is true.\n *\n * @param source - Source series (PineScript default `hlc3`)\n * @param volume - Volume series\n * @param anchor - Reset condition per bar (PineScript `anchor`). Without it the sums never restart;\n * PineScript's default anchor is a new day (`timeframe.change(\"1D\")`), which needs the exchange session\n * @param stdev_mult - When given, also returns the bands `vwap \u00B1 stdev_mult \u00D7 stdev`\n * @returns The VWAP series, or `[vwap, upper, lower]` when `stdev_mult` is given\n *\n * @remarks\n * As in PineScript: the sums restart on anchor bars; the standard deviation is\n * `sqrt(\u03A3(volume \u00D7 source\u00B2) / \u03A3volume \u2212 vwap\u00B2)`.\n * - With an anchor series: `na` before the first anchor bar\n * - A bar with an `na` source (or volume) makes the sums `na` until the next anchor bar (`na` values are not\n * skipped)\n */\nexport function vwap(source: Source, volume: Source, anchor?: ArrayLike<boolean | number>): series_float;\nexport function vwap(\n source: Source,\n volume: Source,\n anchor: ArrayLike<boolean | number> | undefined,\n stdev_mult: simple_float\n): [series_float, series_float, series_float];\nexport function vwap(\n source: Source,\n volume: Source,\n anchor?: ArrayLike<boolean | number>,\n stdev_mult?: simple_float\n): series_float | [series_float, series_float, series_float] {\n if (source.length !== volume.length) {\n throw new Error('ta.vwap: source and volume must have the same length');\n }\n const mid: series_float = [];\n const upper: series_float = [];\n const lower: series_float = [];\n // na until the first anchor (without an anchor series, bar 0 starts the sums)\n let sumPV = NaN;\n let sumV = NaN;\n let sumPPV = NaN;\n for (let i = 0; i < source.length; i++) {\n const s = source[i]!;\n const v = volume[i]!;\n if (anchor ? anchor[i] : i === 0) {\n sumPV = s * v;\n sumV = v;\n sumPPV = s * s * v;\n } else {\n // An na source or volume makes the sums na until the next anchor\n sumPV += s * v;\n sumV += v;\n sumPPV += s * s * v;\n }\n const m = sumV === 0 ? NaN : sumPV / sumV;\n mid.push(m);\n if (stdev_mult !== undefined) {\n const sd = Math.sqrt(Math.max(0, sumPPV / sumV - m * m));\n upper.push(m + stdev_mult * sd);\n lower.push(m - stdev_mult * sd);\n }\n }\n return stdev_mult === undefined ? mid : [mid, upper, lower];\n}\n\n/**\n * Arnaud Legoux Moving Average (ALMA)\n *\n * ALMA uses a Gaussian distribution for weighting, reducing lag while maintaining smoothness.\n * It's particularly good at tracking price action with minimal lag.\n *\n * @param source - Source series\n * @param length - Window size (default: 9)\n * @param offset - Controls the center of the Gaussian curve. 0.85 = focus on recent prices (default: 0.85)\n * @param sigma - Standard deviation of the Gaussian. Controls smoothness (default: 6)\n * @returns ALMA series\n *\n * @example\n * ```typescript\n * const alma = ta.alma(close, 9, 0.85, 6);\n * // offset closer to 1: more responsive\n * // offset closer to 0: smoother\n * ```\n */\nexport function alma(\n source: Source,\n length: simple_int = 9,\n offset: simple_float = 0.85,\n sigma: simple_float = 6,\n floor: boolean = false\n): series_float {\n checkPositiveLength('alma', length, 0);\n const result: series_float = [];\n const m = floor ? Math.floor(offset * (length - 1)) : offset * (length - 1);\n const s = length / sigma;\n\n // Pre-calculate weights\n const weights: number[] = [];\n let weightSum = 0;\n\n for (let i = 0; i < length; i++) {\n const weight = Math.exp(-1 * Math.pow(i - m, 2) / (2 * Math.pow(s, 2)));\n weights.push(weight);\n weightSum += weight;\n }\n\n // Normalize weights\n for (let i = 0; i < length; i++) {\n weights[i]! /= weightSum;\n }\n\n // Calculate ALMA\n for (let i = 0; i < source.length; i++) {\n if (i < length - 1) {\n result.push(NaN);\n continue;\n }\n\n let almaValue = 0;\n for (let j = 0; j < length; j++) {\n almaValue += source[i - length + 1 + j]! * weights[j]!;\n }\n\n result.push(almaValue);\n }\n\n return result;\n}\n\n/**\n * Keltner Channels Width (KCW)\n *\n * Measures the width of Keltner Channels relative to the middle line: `(upper - lower) / middle`, a ratio as in\n * PineScript (0.05 is a width of 5% of the middle line; not multiplied by 100).\n * Similar to BBW but uses ATR instead of standard deviation.\n *\n * Low KCW suggests consolidation/low volatility.\n * High KCW suggests expansion/high volatility.\n *\n * @param source - Source series\n * @param length - Number of bars for EMA and ATR (default: 20)\n * @param mult - ATR multiplier (default: 2)\n * @param useTrueRange - Use True Range instead of high-low (default: true)\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @returns KCW series\n *\n * @example\n * ```typescript\n * const kcw = ta.kcw(close, 20, 2, true, high, low, close);\n * // Low KCW: potential breakout coming\n * // High KCW: high volatility period\n * ```\n */\nexport function kcw(\n source: Source,\n length: simple_int = 20,\n mult: simple_float = 2,\n useTrueRange: simple_bool = true,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n const [basis, upper, lower] = kc(source, length, mult, useTrueRange, high, low, close);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (isNaN(basis[i]!) || basis[i]! === 0) {\n result.push(NaN);\n } else {\n // PineScript: (upper - lower) / basis, a ratio (not a percentage)\n result.push((upper[i]! - lower[i]!) / basis[i]!);\n }\n }\n\n return result;\n}\n\n/**\n * Difference between the highest and the lowest value over the last `length` non-na values\n * (PineScript `ta.range(source, length)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped (the window holds the last `length` non-na\n * values), and a bar whose own value is `na` still gets a result.\n */\nexport function range(source: Source, length: simple_int): series_float {\n checkPositiveLength('range', length, 0);\n return source.map((_, i) => {\n const values = lastValues(source, i, length);\n return values ? Math.max(...values) - Math.min(...values) : NaN;\n });\n}\n\n/**\n * Offset to the bar with the highest value over the last `length` bars: 0 for the current bar,\n * -1 for the previous bar, and so on (as in PineScript, the offset is negative).\n *\n * @remarks\n * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal\n * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were\n * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.\n */\nexport function highestbars(source: Source, length: simple_int | ArrayLike<number>): series_int {\n return extremeOffset(source, length, false);\n}\n\n/**\n * Offset to the bar with the lowest value over the last `length` bars: 0 for the current bar,\n * -1 for the previous bar, and so on (as in PineScript, the offset is negative).\n *\n * @remarks\n * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal\n * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were\n * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.\n */\nexport function lowestbars(source: Source, length: simple_int | ArrayLike<number>): series_int {\n return extremeOffset(source, length, true);\n}\n\n/**\n * All-time highest value of `source` up to each bar (PineScript `ta.max(source)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the\n * result is `na` until the first non-na value.\n */\nexport function max(source: Source): series_float {\n let best = NaN;\n return source.map((x) => {\n if (Number.isFinite(x) && !(x <= best)) best = x;\n return best;\n });\n}\n\n/**\n * All-time lowest value of `source` up to each bar (PineScript `ta.min(source)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the\n * result is `na` until the first non-na value.\n */\nexport function min(source: Source): series_float {\n let best = NaN;\n return source.map((x) => {\n if (Number.isFinite(x) && !(x >= best)) best = x;\n return best;\n });\n}\n\n/**\n * Center of Gravity (COG)\n *\n * The Center of Gravity indicator is an oscillator developed by John Ehlers.\n * It identifies turning points with minimal lag and provides clear signals.\n *\n * @param source - Source series (typically close)\n * @param length - Lookback period (default: 10)\n * @returns COG series\n *\n * @remarks\n * PineScript rule (bit for bit): `-num / math.sum(source, length)`, with `num` the sum of `source[i] * (i + 1)`\n * for `i = 0 .. length - 1`, added newest first.\n * - The denominator is the compensated running sum of `math.sum` (the last `length` non-`na` values)\n * - The numerator reads the last `length` bars, so an `na` among them gives `na`\n * - A zero denominator gives `na` (PineScript division by zero)\n *\n * @example\n * ```typescript\n * const cogValue = ta.cog(close, 10);\n * ```\n */\nexport function cog(source: Source, length: simple_int = 10): series_float {\n checkPositiveLength('cog', length, 0);\n const len = Math.floor(length);\n return runningSum(source, len).map((sum, i) => {\n if (i < len - 1 || Number.isNaN(sum) || sum === 0) return NaN;\n let num = 0;\n for (let k = 0; k < len; k++) num += source[i - k]! * (k + 1);\n return -num / sum;\n });\n}\n\n/**\n * Mode (Most Frequent Value)\n *\n * Returns the mode of the series - the most frequently occurring value.\n * If there are several values with the same frequency, it returns the smallest value.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @returns The most frequently occurring value\n *\n * @example\n * ```typescript\n * const values = [1, 2, 2, 3, 3, 3, 4, 4];\n * const modeValue = ta.mode(values, 8); // Returns 3 (most frequent)\n * ```\n *\n * @remarks\n * PineScript rules:\n * - the window is the last `length` non-`na` values (an `na` or +/-Infinity bar does not enter it, and gets the mode\n * of the window it keeps)\n * - NaN until `length` non-`na` values exist\n * - If no mode exists, returns the smallest value\n */\nexport function mode(source: Source, length: simple_int): series_float {\n checkPositiveLength('mode', length, 0);\n const result: series_float = [];\n const len = Math.floor(length);\n const seen: number[] = []; // non-na values so far\n\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n if (Number.isFinite(v)) seen.push(v);\n if (seen.length < len) {\n result.push(NaN);\n continue;\n }\n const values = seen.slice(seen.length - len);\n\n // Count frequency of each value\n const frequencyMap = new Map<number, number>();\n for (const value of values) {\n frequencyMap.set(value, (frequencyMap.get(value) || 0) + 1);\n }\n\n // Find the maximum frequency\n let maxFrequency = 0;\n frequencyMap.forEach((freq) => {\n if (freq > maxFrequency) {\n maxFrequency = freq;\n }\n });\n\n // Find all values with max frequency, then return the smallest\n const modesWithMaxFreq: number[] = [];\n frequencyMap.forEach((freq, value) => {\n if (freq === maxFrequency) {\n modesWithMaxFreq.push(value);\n }\n });\n\n result.push(Math.min(...modesWithMaxFreq));\n }\n\n return result;\n}\n\n/**\n * Percentile (Linear Interpolation Method)\n *\n * Calculates the percentile using the method of linear interpolation between\n * the two nearest ranks. This method may return values that are not members\n * of the input data set.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @param percentage - Percentile to calculate (0-100)\n * @returns The calculated percentile value\n *\n * @example\n * ```typescript\n * const p50 = ta.percentile_linear_interpolation(close, 20, 50); // Median\n * const p75 = ta.percentile_linear_interpolation(close, 20, 75); // 75th percentile\n * ```\n *\n * @remarks\n * - The result will NOT always be a member of the input data set\n * - Uses linear interpolation between adjacent values when needed\n * - Returns NaN for the first (length - 1) values where there's insufficient data\n *\n * PineScript rules:\n * - position in the sorted window: `percentage / 100 * length - 0.5`, clamped to the first / last value, linear\n * interpolation between the two neighbours (na when a neighbour is na, also at an exact position)\n * - `na` values stay in the window (window size = `length`). The window is kept sorted from bar to bar: the new\n * value is inserted before the first value `>=` it, passing the `na` values (an `na` goes last), then the value\n * leaving the window is removed. So the place of an `na` depends on the history: at the start of a series the\n * `na` values are before all numbers\n */\nexport function percentile_linear_interpolation(\n source: Source,\n length: simple_int,\n percentage: number\n): series_float {\n checkPositiveLength('percentile_linear_interpolation', length, 0);\n return sortedWindow(source, length, (s) => {\n const pos = (percentage / 100) * length - 0.5;\n if (pos <= 0) return s[0]!;\n if (pos >= length - 1) return s[length - 1]!;\n const lo = Math.floor(pos);\n return s[lo]! + (pos - lo) * (s[lo + 1]! - s[lo]!);\n });\n}\n\n/**\n * Sorted window of ta.percentile_*, as PineScript keeps it: each bar first inserts the new value before the first\n * value `>=` it (scanning from the start; an `na` is never `>=`, so a value passes the `na` values and an `na` goes\n * last), then removes the value of the bar leaving the window. `fn` reads the sorted window (`length` values).\n * na for the first `length - 1` bars.\n *\n * @internal\n */\nfunction sortedWindow(source: Source, length: simple_int, fn: (sorted: number[]) => number): series_float {\n const result: series_float = [];\n const values: number[] = []; // sorted window\n const bars: number[] = []; // bar index of each value\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n let k = 0;\n while (k < values.length && !(values[k]! >= v)) k++;\n values.splice(k, 0, v);\n bars.splice(k, 0, i);\n if (i >= length) {\n const old = bars.indexOf(i - length);\n values.splice(old, 1);\n bars.splice(old, 1);\n }\n result.push(i < length - 1 ? NaN : fn(values));\n }\n return result;\n}\n\n/**\n * Percentile (Nearest Rank Method)\n *\n * Calculates the percentile using the Nearest Rank method. This method\n * always returns a value that is a member of the input data set.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @param percentage - Percentile to calculate (0-100)\n * @returns The calculated percentile value\n *\n * @example\n * ```typescript\n * const p50 = ta.percentile_nearest_rank(close, 20, 50); // Median\n * const p90 = ta.percentile_nearest_rank(close, 20, 90); // 90th percentile\n * ```\n *\n * @remarks\n * - The result will ALWAYS be a member of the input data set\n * - The 100th percentile is defined as the largest value\n * - Using this method on lengths < 100 may result in the same value for multiple percentiles\n * - Returns NaN for the first (length - 1) values where there's insufficient data\n *\n * PineScript rules:\n * - the value at rank `ceil(percentage / 100 * length)` of the sorted window (na when that rank holds an `na`)\n * - `na` values stay in the window, sorted from bar to bar as in `ta.percentile_linear_interpolation`\n */\nexport function percentile_nearest_rank(\n source: Source,\n length: simple_int,\n percentage: number\n): series_float {\n checkPositiveLength('percentile_nearest_rank', length, 0);\n const rank = Math.min(length, Math.max(1, Math.ceil((percentage / 100) * length)));\n return sortedWindow(source, length, (s) => s[rank - 1]!);\n}\n\n/**\n * Rank Correlation Index (RCI)\n *\n * Calculates the Rank Correlation Index using Spearman's rank correlation coefficient.\n * RCI measures the directional consistency of price movements, indicating whether\n * the source consistently increased (positive values) or decreased (negative values).\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @returns RCI value scaled to range -100 to 100\n *\n * @example\n * ```typescript\n * const rci9 = ta.rci(close, 9);\n * // RCI near +100: strong upward consistency\n * // RCI near -100: strong downward consistency\n * // RCI near 0: no clear trend\n * ```\n *\n * @remarks\n * - Result is scaled to -100 to 100 range\n * - +100 indicates source consistently increased over the period\n * - -100 indicates source consistently decreased over the period\n * - 0 indicates no directional consistency\n * - As PineScript (bit for bit): the first value is on bar `length`; values less than 1e-10 above the smallest value\n * of a group (ascending sweep) are ties with their average rank; a window where all values are ties gives `na`;\n * moment-form variances of the bar positions and the ranks, `(100 * cov) / (sd_x * sd_y)`\n * - A bar with an `na` source keeps the previous result; the values are kept in a ring of `length + 1` slots by bar\n * index (0 at the start, not written on `na` bars), so a later window sees the value of `length + 1` bars earlier\n * where the `na` was\n */\nexport function rci(source: Source, length: simple_int): series_float {\n checkPositiveLength('rci', length, 0);\n const len = Math.floor(length);\n const result: series_float = [];\n // PineScript keeps the values in a ring of `length + 1` slots indexed by the bar index, filled with 0 at the start\n // and written only on bars with a value: a bar with an na source keeps the previous result, and later windows see\n // the value of `length + 1` bars earlier in that slot\n const ring = new Array<number>(len + 1).fill(0);\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n if (Number.isNaN(v)) {\n result.push(i > 0 ? result[i - 1]! : NaN);\n continue;\n }\n ring[i % (len + 1)] = v;\n // the first value is on bar `length` (one bar after the window is full)\n if (i < len) {\n result.push(NaN);\n continue;\n }\n // window newest first (position 0 = this bar)\n const values = Array.from({ length: len }, (_, j) => ring[(i - j) % (len + 1)]!);\n // Ranks: ascending sweep; a group collects the values less than 1e-10 above its smallest value; each group gets\n // its average 0-based rank counted from the largest value\n const order = values.map((_, j) => j).sort((a, b) => values[a]! - values[b]!);\n const ranks = new Array<number>(len);\n for (let g = 0; g < len; ) {\n const anchor = values[order[g]!]!;\n let end = g + 1;\n while (end < len && values[order[end]!]! - anchor < 1e-10) end++;\n const avgRank = len - 1 - (g + g + (end - g) - 1) / 2;\n for (let k = g; k < end; k++) ranks[order[k]!] = avgRank;\n g = end;\n }\n // moment-form variances, covariance from deviation products, (100 * cov) / (sd_x * sd_y): this operation order\n // gives PineScript's values bit for bit\n let sumX = 0;\n let sumY = 0;\n let sumX2 = 0;\n let sumY2 = 0;\n for (let k = 0; k < len; k++) {\n const y = ranks[k]!;\n sumX += k;\n sumY += y;\n sumX2 += k * k;\n sumY2 += y * y;\n }\n const meanX = sumX / len;\n const meanY = sumY / len;\n const varX = sumX2 / len - meanX * meanX;\n const varY = sumY2 / len - meanY * meanY;\n // a window where all values are ties has no correlation\n if (!(varX > 0) || !(varY > 0)) {\n result.push(NaN);\n continue;\n }\n let cov = 0;\n for (let k = 0; k < len; k++) cov += (k - meanX) * (ranks[k]! - meanY);\n cov /= len;\n result.push((100 * cov) / (Math.sqrt(varX) * Math.sqrt(varY)));\n }\n return result;\n}\n\n/**\n * Pivot Point Levels (PineScript `ta.pivot_point_levels`).\n *\n * Returns 11 series: [P, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5] (one value per bar in each).\n *\n * @param type - Calculation type: \"Traditional\", \"Fibonacci\", \"Woodie\", \"Classic\", \"DM\", \"Camarilla\"\n * @param anchor - Condition that starts a new period (`timeframe.change(\"W\")`...)\n * @param developing - false: the levels of the previous period, constant until the next anchor; true: the levels of\n * the current period so far, recalculated on each bar\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @param open - Open price series (Woodie and DM)\n * @returns 11 series of levels\n *\n * @example\n * ```typescript\n * const weekChange = [false, false, false, false, true, false, ...]; // Weekly anchor\n * const levels = ta.pivot_point_levels(\"Traditional\", weekChange, false, high, low, close, open);\n * // levels[0]![i] is P on bar i, levels[5]![i] is R3\n * ```\n *\n * @remarks\n * As in PineScript (#177):\n * - a period runs from an anchor bar to the bar before the next anchor; the bars before the first anchor are a\n * period too (from bar 0). The fixed levels use the high and low of the previous period and the close of the bar\n * before the anchor (na with an anchor on bar 0), and are na until the first anchor; the developing levels use\n * the current period's high and low and the bar's close, from bar 0\n * - Traditional: R3 = P * 2 + (H - 2 * L), S3 = P * 2 - (2 * H - L), R4 = P * 3 + (H - 3 * L), S4 = P * 3 - (3 * H - L),\n * R5 = P * 4 + (H - 4 * L), S5 = P * 4 - (4 * H - L)\n * - Fibonacci: P +- 0.382 / 0.618 / 1 * (H - L); R4 to S5 na\n * - Classic: R3 / S3 = P +- 2 * (H - L), R4 / S4 = P +- 3 * (H - L); R5 / S5 na\n * - Woodie: P = (H + L + 2 * open of the current period) / 4, R3 = H + 2 * (P - L), S3 = L - 2 * (H - P), R4 / S4 =\n * R3 + (H - L) / S3 - (H - L); R5 / S5 na. `developing` true throws (RE10128)\n * - DM: x = H + 2 * L + C (C < open of the period), 2 * H + L + C (C > O) or H + L + 2 * C; P = x / 4,\n * R1 = x / 2 - L, S1 = x / 2 - H; the other levels na\n * - Camarilla: C +- (H - L) * 1.1 / 12, / 6, / 4, / 2 for R1 to S4, R5 = (H / L) * C, S5 = 2 * C - R5\n */\nexport function pivot_point_levels(\n type: series_float | string,\n anchor: series_bool,\n developing: series_bool | boolean = false,\n high?: Source,\n low?: Source,\n close?: Source,\n open?: Source\n): series_float[] {\n const typeStr = typeof type === 'string' ? type : String(type[0]);\n const isDeveloping = typeof developing === 'boolean' ? developing : Boolean(developing[0]);\n if (typeStr === 'Woodie' && isDeveloping) {\n throw new Error(\n 'Error on bar 0: The `developing` parameter of the `ta.pivot_point_levels()` cannot be `true` when `type` is \"Woodie\".'\n );\n }\n const n = anchor.length;\n for (const [s, name] of [[high, 'High'], [low, 'Low'], [close, 'Close'], [open, 'Open']] as const) {\n if (s && s.length !== n) throw new Error(`${name} series length mismatch`);\n }\n const at = (s: Source | undefined, i: number): number => (s ? (s[i] ?? NaN) : NaN);\n const results: series_float[] = Array.from({ length: 11 }, () => new Array<number>(n));\n // the current period (from bar 0 until the first anchor) and the previous one\n let curH = NaN, curL = NaN, curO = NaN;\n let prevH = NaN, prevL = NaN, prevC = NaN, prevO = NaN;\n let anchored = false;\n for (let i = 0; i < n; i++) {\n const h = at(high, i), l = at(low, i);\n if (i === 0) {\n // the first period starts on bar 0: an anchor there makes bar 0 its own previous period\n curH = h;\n curL = l;\n curO = at(open, i);\n }\n if (anchor[i]) {\n prevH = curH;\n prevL = curL;\n prevC = i > 0 ? at(close, i - 1) : NaN;\n prevO = curO;\n curH = h;\n curL = l;\n curO = at(open, i);\n anchored = true;\n } else if (i > 0) {\n if (h > curH || Number.isNaN(curH)) curH = h;\n if (l < curL || Number.isNaN(curL)) curL = l;\n }\n const levels = isDeveloping\n ? pivotLevels(typeStr, curH, curL, at(close, i), curO, at(close, i))\n : anchored\n ? pivotLevels(typeStr, prevH, prevL, prevC, prevO, curO)\n : NA_LEVELS;\n for (let k = 0; k < 11; k++) results[k]![i] = levels[k]!;\n }\n return results;\n}\n\nconst NA_LEVELS: readonly number[] = new Array<number>(11).fill(NaN);\n\n/**\n * The 11 levels of one bar, in PineScript's operation order (bit for bit). `o` is the open of the period (DM),\n * `wo` the close term of Woodie (the open of the current period, or the bar's close while developing).\n */\nfunction pivotLevels(type: string, h: number, l: number, c: number, o: number, wo: number): readonly number[] {\n const N = NaN;\n const r = h - l;\n switch (type) {\n case 'Traditional': {\n const p = (h + l + c) / 3;\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, p * 2 + (h - 2 * l), p * 2 - (2 * h - l), p * 3 + (h - 3 * l),\n p * 3 - (3 * h - l), p * 4 + (h - 4 * l), p * 4 - (4 * h - l)];\n }\n case 'Fibonacci': {\n const p = (h + l + c) / 3;\n return [p, p + 0.382 * r, p - 0.382 * r, p + 0.618 * r, p - 0.618 * r, p + 1 * r, p - 1 * r, N, N, N, N];\n }\n case 'Classic': {\n const p = (h + l + c) / 3;\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, p + 2 * r, p - 2 * r, p + 3 * r, p - 3 * r, N, N];\n }\n case 'Woodie': {\n const p = (h + l + 2 * wo) / 4;\n const r3 = h + 2 * (p - l);\n const s3 = l - 2 * (h - p);\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, r3, s3, r3 + r, s3 - r, N, N];\n }\n case 'DM': {\n const x = c < o ? h + 2 * l + c : c > o ? 2 * h + l + c : h + l + 2 * c;\n return [x / 4, x / 2 - l, x / 2 - h, N, N, N, N, N, N, N, N];\n }\n case 'Camarilla': {\n const p = (h + l + c) / 3;\n const r5 = (h / l) * c;\n return [p, c + (r * 1.1) / 12, c - (r * 1.1) / 12, c + (r * 1.1) / 6, c - (r * 1.1) / 6, c + (r * 1.1) / 4,\n c - (r * 1.1) / 4, c + (r * 1.1) / 2, c - (r * 1.1) / 2, r5, 2 * c - r5];\n }\n default:\n return NA_LEVELS;\n }\n}\n\n/**\n * Ichimoku Kinko Hyo (Ichimoku Cloud) - Japanese charting technique for trend identification.\n *\n * @param conversionPeriods - Period for Tenkan-sen (Conversion Line), default: 9\n * @param basePeriods - Period for Kijun-sen (Base Line), default: 26\n * @param laggingSpan2Periods - Period for Senkou Span B (Leading Span B), default: 52\n * @param displacement - Displacement for Senkou Spans and Chikou Span, default: 26\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @returns Tuple of [tenkanSen, kijunSen, senkouSpanA, senkouSpanB, chikouSpan]\n *\n * @remarks\n * - **Tenkan-sen (Conversion Line)**: `(highest(high, conversionPeriods) + lowest(low, conversionPeriods)) / 2`\n * - **Kijun-sen (Base Line)**: `(highest(high, basePeriods) + lowest(low, basePeriods)) / 2`\n * - **Senkou Span A (Leading Span A)**: `(tenkan + kijun) / 2` offset forward by `displacement` periods\n * - **Senkou Span B (Leading Span B)**: `(highest(high, laggingSpan2Periods) + lowest(low, laggingSpan2Periods)) / 2` offset forward by `displacement` periods\n * - **Chikou Span (Lagging Span)**: `close` offset backward by `displacement` periods\n *\n * The forward offset for Senkou Spans means they are projected into the future (NaN values at the end).\n * The backward offset for Chikou Span means it shows past prices (NaN values at the beginning).\n *\n * @example\n * ```typescript\n * const [tenkan, kijun, senkouA, senkouB, chikou] = ta.ichimoku(9, 26, 52, 26, high, low, close);\n *\n * // Tenkan-sen crosses above Kijun-sen = bullish signal\n * const bullishSignal = ta.crossover(tenkan, kijun);\n *\n * // Price above cloud = bullish trend\n * // Cloud = area between senkouSpanA and senkouSpanB\n * ```\n */\nexport function ichimoku(\n conversionPeriods: simple_int,\n basePeriods: simple_int,\n laggingSpan2Periods: simple_int,\n displacement: simple_int,\n high: Source,\n low: Source,\n close: Source\n): [series_float, series_float, series_float, series_float, series_float] {\n const length = high.length;\n\n // Calculate Tenkan-sen (Conversion Line): (highest(high, 9) + lowest(low, 9)) / 2\n const highestConversion = highest(high, conversionPeriods);\n const lowestConversion = lowest(low, conversionPeriods);\n const tenkanSen: series_float = [];\n for (let i = 0; i < length; i++) {\n if (isNaN(highestConversion[i]!) || isNaN(lowestConversion[i]!)) {\n tenkanSen.push(NaN);\n } else {\n tenkanSen.push((highestConversion[i]! + lowestConversion[i]!) / 2);\n }\n }\n\n // Calculate Kijun-sen (Base Line): (highest(high, 26) + lowest(low, 26)) / 2\n const highestBase = highest(high, basePeriods);\n const lowestBase = lowest(low, basePeriods);\n const kijunSen: series_float = [];\n for (let i = 0; i < length; i++) {\n if (isNaN(highestBase[i]!) || isNaN(lowestBase[i]!)) {\n kijunSen.push(NaN);\n } else {\n kijunSen.push((highestBase[i]! + lowestBase[i]!) / 2);\n }\n }\n\n // Calculate Senkou Span A (Leading Span A): (tenkan + kijun) / 2, offset forward by displacement\n // This means at index i, we store the value that would normally be at index (i - displacement)\n // Result: first 'displacement' values are NaN, and last 'displacement' calculated values are lost\n const senkouSpanA: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i - displacement;\n if (sourceIndex < 0 || isNaN(tenkanSen[sourceIndex]!) || isNaN(kijunSen[sourceIndex]!)) {\n senkouSpanA.push(NaN);\n } else {\n senkouSpanA.push((tenkanSen[sourceIndex]! + kijunSen[sourceIndex]!) / 2);\n }\n }\n\n // Calculate Senkou Span B (Leading Span B): (highest(high, 52) + lowest(low, 52)) / 2, offset forward by displacement\n const highestLagging = highest(high, laggingSpan2Periods);\n const lowestLagging = lowest(low, laggingSpan2Periods);\n const senkouSpanB: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i - displacement;\n if (sourceIndex < 0 || isNaN(highestLagging[sourceIndex]!) || isNaN(lowestLagging[sourceIndex]!)) {\n senkouSpanB.push(NaN);\n } else {\n senkouSpanB.push((highestLagging[sourceIndex]! + lowestLagging[sourceIndex]!) / 2);\n }\n }\n\n // Calculate Chikou Span (Lagging Span): close, offset backward by displacement\n // This means at index i, we store the close value from index (i + displacement)\n // Result: last 'displacement' values are NaN\n const chikouSpan: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i + displacement;\n if (sourceIndex >= length || isNaN(close[sourceIndex]!)) {\n chikouSpan.push(NaN);\n } else {\n chikouSpan.push(close[sourceIndex]!);\n }\n }\n\n return [tenkanSen, kijunSen, senkouSpanA, senkouSpanB, chikouSpan];\n}\n\n/**\n * ZigZag indicator - identifies significant trend reversals by filtering out minor price movements.\n *\n * @param deviation - Minimum percentage price change to form a new pivot (default: 5.0)\n * @param depth - Minimum bars between pivots for pivot detection (default: 10)\n * @param backstep - Bars to look back for confirmation (default: 3)\n * @param source - Price source (optional, typically close)\n * @param high - High price series (optional, for high/low mode)\n * @param low - Low price series (optional, for high/low mode)\n * @returns Tuple of [zigzag values, direction, pivot flags (boolean)]\n *\n * @remarks\n * - **Parameter order differs from PineScript**: JavaScript signature puts deviation first,\n * while PineScript uses `ta.zigzag(source, deviation, depth, backstep)`. This allows\n * deviation to have a default value and makes the API more ergonomic for JS users.\n * - **JavaScript signature**: Requires explicit `source`, `high`, `low` OR use `createContext()`\n * - Returns the pivot price at pivot points, NaN for non-pivot bars\n * - Direction: 1 = uptrend (from low to high), -1 = downtrend (from high to low)\n * - The ZigZag indicator **repaints** by design - the last segment can change as new data arrives\n * - Supports two modes:\n * - Single source mode: uses same series for highs and lows\n * - High/Low mode: uses high for pivot highs, low for pivot lows\n *\n * @example\n * ```typescript\n * // Using high/low for more accurate pivots\n * const [zigzag, direction, isPivot] = ta.zigzag(5, 10, 3, undefined, high, low);\n *\n * // Find pivot prices\n * for (let i = 0; i < zigzag.length; i++) {\n * if (!isNaN(zigzag[i]!)) {\n * console.log(`Pivot at bar ${i}: ${zigzag[i]!}, direction: ${direction[i]! === 1 ? 'UP' : 'DOWN'}`);\n * }\n * }\n * ```\n */\nexport function zigzag(\n deviation: simple_float = 5.0,\n depth: simple_int = 10,\n backstep: simple_int = 3,\n source?: Source,\n high?: Source,\n low?: Source\n): [series_float, series_int, series_bool] {\n // Determine which mode we're in\n let highSource: Source;\n let lowSource: Source;\n \n if (high && low) {\n // High/Low mode\n highSource = high;\n lowSource = low;\n } else if (source) {\n // Single source mode\n highSource = source;\n lowSource = source;\n } else {\n throw new Error(\n 'ta.zigzag() requires either source series or high/low series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const length = highSource.length;\n if (lowSource.length !== length) {\n throw new Error('ta.zigzag: high and low must have the same length');\n }\n\n // Result arrays\n const zigzagValues: series_float = new Array(length).fill(NaN);\n const directions: series_int = new Array(length).fill(0);\n const isPivot: series_bool = new Array(length).fill(false);\n\n // Helper function to calculate percentage deviation\n const getDeviation = (price1: number, price2: number): number => {\n // Use epsilon threshold to avoid numerical instability with very small values\n if (Math.abs(price1) < 1e-10 || isNaN(price1) || isNaN(price2)) return 0;\n return Math.abs((price2 - price1) / price1) * 100;\n };\n\n // Track pivot state\n interface Pivot {\n index: number;\n price: number;\n type: 'high' | 'low';\n }\n\n let lastConfirmedPivot: Pivot | null = null;\n let potentialPivot: Pivot | null = null;\n let currentDirection = 0; // 0 = undefined, 1 = up, -1 = down\n\n // Store confirmed pivots for final zigzag construction\n const confirmedPivots: Pivot[] = [];\n\n // First pass: Find initial pivot to start\n let startIndex: number;\n let initialHighest = -Infinity;\n let initialLowest = Infinity;\n let initialHighIndex = -1;\n let initialLowIndex = -1;\n\n // Find the first significant pivot using depth bars\n for (let i = 0; i < Math.min(depth, length); i++) {\n if (!isNaN(highSource[i]!) && highSource[i]! > initialHighest) {\n initialHighest = highSource[i]!;\n initialHighIndex = i;\n }\n if (!isNaN(lowSource[i]!) && lowSource[i]! < initialLowest) {\n initialLowest = lowSource[i]!;\n initialLowIndex = i;\n }\n }\n\n // Determine starting direction based on which came first\n if (initialHighIndex >= 0 && initialLowIndex >= 0) {\n if (initialLowIndex <= initialHighIndex) {\n // Low came first or same - start with low, direction will be up\n lastConfirmedPivot = { index: initialLowIndex, price: initialLowest, type: 'low' };\n currentDirection = 1;\n } else {\n // High came first - start with high, direction will be down\n lastConfirmedPivot = { index: initialHighIndex, price: initialHighest, type: 'high' };\n currentDirection = -1;\n }\n confirmedPivots.push(lastConfirmedPivot);\n startIndex = lastConfirmedPivot.index + 1;\n } else {\n startIndex = depth;\n }\n\n // Main loop: process bars\n for (let i = Math.max(startIndex, depth); i < length; i++) {\n const currentHigh = highSource[i]!;\n const currentLow = lowSource[i]!;\n\n if (isNaN(currentHigh) || isNaN(currentLow)) {\n directions[i] = currentDirection;\n continue;\n }\n\n // Check for potential pivot high\n let isPotentialHigh = true;\n for (let j = 1; j <= backstep && i - j >= 0; j++) {\n if (!isNaN(highSource[i - j]!) && highSource[i - j]! >= currentHigh) {\n isPotentialHigh = false;\n break;\n }\n }\n\n // Check for potential pivot low\n let isPotentialLow = true;\n for (let j = 1; j <= backstep && i - j >= 0; j++) {\n if (!isNaN(lowSource[i - j]!) && lowSource[i - j]! <= currentLow) {\n isPotentialLow = false;\n break;\n }\n }\n\n if (currentDirection === 1) {\n // Looking for pivot high (uptrend ending)\n if (isPotentialHigh) {\n if (potentialPivot === null || potentialPivot.type !== 'high') {\n // New potential high\n if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {\n potentialPivot = { index: i, price: currentHigh, type: 'high' };\n }\n } else {\n // Already have a potential high - update if this is higher\n if (currentHigh > potentialPivot.price) {\n potentialPivot = { index: i, price: currentHigh, type: 'high' };\n }\n }\n }\n\n // Check if we should confirm the potential high and start looking for a low\n if (potentialPivot && potentialPivot.type === 'high') {\n const deviationFromPotential = getDeviation(potentialPivot.price, currentLow);\n if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {\n // Confirm the high pivot\n confirmedPivots.push(potentialPivot);\n lastConfirmedPivot = potentialPivot;\n currentDirection = -1;\n potentialPivot = null;\n }\n }\n } else if (currentDirection === -1) {\n // Looking for pivot low (downtrend ending)\n if (isPotentialLow) {\n if (potentialPivot === null || potentialPivot.type !== 'low') {\n // New potential low\n if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {\n potentialPivot = { index: i, price: currentLow, type: 'low' };\n }\n } else {\n // Already have a potential low - update if this is lower\n if (currentLow < potentialPivot.price) {\n potentialPivot = { index: i, price: currentLow, type: 'low' };\n }\n }\n }\n\n // Check if we should confirm the potential low and start looking for a high\n if (potentialPivot && potentialPivot.type === 'low') {\n const deviationFromPotential = getDeviation(potentialPivot.price, currentHigh);\n if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {\n // Confirm the low pivot\n confirmedPivots.push(potentialPivot);\n lastConfirmedPivot = potentialPivot;\n currentDirection = 1;\n potentialPivot = null;\n }\n }\n } else {\n // Initial state - determine direction based on first significant move\n if (lastConfirmedPivot) {\n if (lastConfirmedPivot.type === 'low' && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {\n currentDirection = 1;\n } else if (lastConfirmedPivot.type === 'high' && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {\n currentDirection = -1;\n }\n }\n }\n\n directions[i] = currentDirection;\n }\n\n // Include the last potential pivot if it exists (repaint behavior)\n // This shows where the zigzag line extends to, but doesn't change direction\n const lastPotentialWasAdded = potentialPivot !== null;\n if (potentialPivot) {\n confirmedPivots.push(potentialPivot);\n }\n\n // Build the final zigzag output\n for (const pivot of confirmedPivots) {\n zigzagValues[pivot.index] = pivot.price;\n isPivot[pivot.index] = true;\n }\n\n // Set directions for all bars based on confirmed pivots\n // Direction represents the current trend at each bar:\n // - After a LOW pivot, trend is UP (1) until the next HIGH\n // - After a HIGH pivot, trend is DOWN (-1) until the next LOW\n let currentDir = 0;\n let pivotIdx = 0;\n const numConfirmed = lastPotentialWasAdded ? confirmedPivots.length - 1 : confirmedPivots.length;\n \n for (let i = 0; i < length; i++) {\n // Move to next confirmed pivot if we passed the current one\n // Don't count the last potential pivot for direction changes\n while (pivotIdx < numConfirmed && confirmedPivots[pivotIdx]!.index <= i) {\n const pivot = confirmedPivots[pivotIdx]!;\n currentDir = pivot.type === 'low' ? 1 : -1;\n pivotIdx++;\n }\n directions[i] = currentDir;\n }\n\n return [zigzagValues, directions, isPivot];\n}\n\n// \u2500\u2500 Volume built-in variables (ta.obv, ta.pvt, ta.accdist, ta.nvi, ta.pvi, ta.iii, ta.wad, ta.wvad) \u2500\u2500\n//\n// In PineScript these are series variables computed from the chart bars. Here they take the\n// bar series explicitly.\n\n/**\n * On Balance Volume: `ta.cum(math.sign(ta.change(close)) * volume)`.\n *\n * @param close - Close price series\n * @param volume - Volume series\n * @returns OBV series (`na` on the first bar, and on bars without volume)\n */\nexport function obv(close: Source, volume: Source): series_float {\n return cum(close.map((c, i) => (i === 0 ? NaN : Math.sign(c - close[i - 1]!) * volume[i]!)));\n}\n\n/**\n * Price-Volume Trend: `ta.cum((ta.change(close) / close[1]) * volume)`.\n *\n * @param close - Close price series\n * @param volume - Volume series\n * @returns PVT series (`na` on the first bar, and on bars without volume)\n */\nexport function pvt(close: Source, volume: Source): series_float {\n return cum(\n close.map((c, i) => (i === 0 ? NaN : ((c - close[i - 1]!) / close[i - 1]!) * volume[i]!))\n );\n}\n\n/**\n * Accumulation/Distribution index: the running sum of\n * `((close - low) - (high - close)) / (high - low) * volume`, in this order as in PineScript (bit for bit).\n * A bar where this is `na` (`high == low`, an `na` volume) adds nothing and keeps the previous value.\n */\nexport function accdist(high: Source, low: Source, close: Source, volume: Source): series_float {\n let ad = 0;\n return close.map((c, i) => {\n const h = high[i]!;\n const l = low[i]!;\n const mfv = (((c - l) - (h - c)) / (h - l)) * volume[i]!;\n if (Number.isFinite(mfv)) ad += mfv;\n return ad;\n });\n}\n\n/**\n * Intraday Intensity Index: `(2 * close - high - low) / (high - low) * volume`.\n *\n * The PineScript built-in value is this formula. The formula shown in the PineScript reference,\n * `(2 * close - high - low) / ((high - low) * volume)`, gives other values.\n *\n * @returns III series (`na` where `high == low`)\n */\nexport function iii(high: Source, low: Source, close: Source, volume: Source): series_float {\n return close.map((c, i) => {\n const range = high[i]! - low[i]!;\n return range === 0 ? NaN : ((2 * c - high[i]! - low[i]!) / range) * volume[i]!;\n });\n}\n\n/**\n * Williams Variable Accumulation/Distribution: `(close - open) / (high - low) * volume`.\n *\n * @returns WVAD series (`na` where `high == low`)\n */\nexport function wvad(open: Source, high: Source, low: Source, close: Source, volume: Source): series_float {\n return close.map((c, i) => {\n const range = high[i]! - low[i]!;\n return range === 0 ? NaN : ((c - open[i]!) / range) * volume[i]!;\n });\n}\n\n/**\n * Williams Accumulation/Distribution: the running sum of `close - min(low, close[1])` on up\n * closes, `close - max(high, close[1])` on down closes, and 0 otherwise (first bar included).\n */\nexport function wad(high: Source, low: Source, close: Source): series_float {\n return cum(\n close.map((c, i) => {\n const prev = i === 0 ? NaN : close[i - 1]!;\n const mom = c - prev;\n if (mom > 0) return c - Math.min(low[i]!, prev);\n if (mom < 0) return c - Math.max(high[i]!, prev);\n return 0;\n })\n );\n}\n\n/** Volume index shared by NVI and PVI: moves with the close change on bars selected by `use`. */\nfunction volumeIndex(close: Source, volume: Source, use: (v: number, prevV: number) => boolean): series_float {\n const result: series_float = [];\n let prevIndex = NaN;\n for (let i = 0; i < close.length; i++) {\n const prev = !prevIndex ? 1 : prevIndex; // nz(index[1], 0) == 0 ? 1 : index[1]\n const c = close[i]!;\n const prevC = i === 0 ? NaN : close[i - 1]!;\n let value = prev;\n if (c && prevC) {\n const prevV = i === 0 || Number.isNaN(volume[i - 1]!) ? 0 : volume[i - 1]!;\n if (use(volume[i]!, prevV)) value = prev + ((c - prevC) / prevC) * prev;\n }\n result.push(value);\n prevIndex = value;\n }\n return result;\n}\n\n/**\n * Negative Volume Index: moves with the close change only on bars where volume falls.\n * Starts at 1.\n */\nexport function nvi(close: Source, volume: Source): series_float {\n return volumeIndex(close, volume, (v, prevV) => v < prevV);\n}\n\n/**\n * Positive Volume Index: moves with the close change only on bars where volume rises.\n * Starts at 1.\n */\nexport function pvi(close: Source, volume: Source): series_float {\n return volumeIndex(close, volume, (v, prevV) => v > prevV);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Technical Analysis (ta) namespace\n * Mirrors PineScript's ta.* functions for technical analysis indicators and calculations.\n *\n * @remarks\n * All technical analysis functions in this namespace follow PineScript v6 API specifications.\n *\n * @version 6\n */\n\nimport type { series_float, series_bool, series_int, int, Source, simple_int, simple_float, simple_bool } from '../types/index.js';\nimport { eq, ge, gt, le, lt } from '../compare/index.js';\nimport { runningSum, runningSumSeries, runningVariance, runningVarianceSeries } from './running-sum.js';\nimport { checkPositiveLength, checkSumLength, checkWindowLength } from './limits.js';\n\n/**\n * Simple Moving Average - returns the moving average (sum of last y values divided by y).\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length), or one length per bar (a series length)\n * @returns Simple moving average of source for length bars back\n *\n * @remarks\n * - `na` values (also +/-Infinity) in the source series are ignored: the mean of the last `length` non-`na`\n * values, and a bar with an `na` source keeps the previous result (as in PineScript)\n * - Returns NaN until `length` non-`na` values are available\n * - The sum is a compensated running sum, as in PineScript, so the result can differ from the exact window mean in\n * the last bits (bit for bit with PineScript)\n * - With a series length, the running sum is moved to the new length when the length changes, as PineScript does\n * (see {@link math.sum}); a bar with an `na` source gives the mean of the last `length` earlier values\n *\n * @example\n * ```typescript\n * const closePrices = [10, 11, 12, 13, 14];\n * const sma5 = ta.sma(closePrices, 5); // Returns: [NaN, NaN, NaN, NaN, 12]\n * const smaVar = ta.sma(closePrices, [2, 2, 2, 3, 2]); // Returns: [NaN, 10.5, 11.5, 12, 13.5]\n * ```\n */\nexport function sma(source: Source, length: simple_int | ArrayLike<number>): series_float {\n if (typeof length !== 'number') {\n const sums = runningSumSeries(source, length, 'ta.sma');\n return sums.map((sum, i) => sum / Math.floor(length[i]!));\n }\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n checkSumLength('ta.sma', len, 0);\n return runningSum(source, len).map((sum) => sum / len);\n}\n\n/**\n * Exponential Moving Average - returns the exponentially weighted moving average.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Exponential moving average of source with alpha = 2 / (length + 1)\n *\n * @remarks\n * - In EMA, weighting factors decrease exponentially\n * - Formula: `EMA = alpha * source + (1 - alpha) * EMA[1]`, where `alpha = 2 / (length + 1)`\n * - `na` values (also +/-Infinity) in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n * - May cause indicator repainting\n *\n * @example\n * ```typescript\n * const closePrices = [10, 11, 12, 13, 14];\n * const ema5 = ta.ema(closePrices, 5);\n * ```\n */\nexport function ema(source: Source, length: simple_int): series_float {\n checkPositiveLength('ema', length, 0);\n const result: series_float = [];\n const len = Math.floor(length);\n const multiplier = 2 / (len + 1);\n\n // SMA seed on the bar of the `len`-th valid value. An infinite value is na, as in PineScript.\n let firstValidIndex = -1;\n let validCount = 0;\n\n for (let i = 0; i < source.length; i++) {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val) && ++validCount === len) {\n firstValidIndex = i;\n break;\n }\n }\n\n const emaInitialized = firstValidIndex >= 0;\n // The seed is ta.sma on that bar: the running sum of math.sum (PineScript bits), not a plain loop sum\n let emaValue = emaInitialized ? runningSum(source.slice(0, firstValidIndex + 1), len)[firstValidIndex]! / len : NaN;\n\n for (let i = 0; i < source.length; i++) {\n if (!emaInitialized || i < firstValidIndex) {\n result.push(NaN);\n } else if (i === firstValidIndex) {\n result.push(emaValue);\n } else {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val)) {\n emaValue = (val - emaValue) * multiplier + emaValue;\n result.push(emaValue);\n } else {\n // na source: na on this bar; the next bar continues from the last value (as in PineScript)\n result.push(NaN);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Relative Strength Index - momentum oscillator measuring speed and magnitude of price changes.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns RSI series (values range from 0 to 100)\n *\n * @remarks\n * - RSI values above 70 typically indicate overbought conditions\n * - RSI values below 30 typically indicate oversold conditions\n * - Uses `ta.rma()` (Relative Moving Average) for smoothing, matching PineScript v6\n * - Formula: RSI = 100 - (100 / (1 + RS)), where RS = Average Gain / Average Loss\n * - As in PineScript (`down == 0 ? 100 : up == 0 ? 0 : ...`): 100 when the average loss is 0, else 0 when the\n * average gain is 0, both with the 1e-10 tolerance of the comparison operators\n * - Average Gain and Average Loss are calculated using RMA (alpha = 1 / length)\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const rsi14 = ta.rsi(closePrices, 14);\n * // Identify overbought/oversold conditions\n * const overbought = rsi14.map(v => v > 70);\n * const oversold = rsi14.map(v => v < 30);\n * ```\n */\nexport function rsi(source: Source, length: simple_int): series_float;\n/**\n * PineScript v4 `rsi(x, y)` with two series (#180): `x` and `y` are the averages of the upward and downward changes,\n * already computed. As in PineScript: 100 when `y` is within 1e-10 of zero (also with an na `x`), else 0 when `x` is,\n * else `100 - 100 / (1 + x / y)`: -Infinity when `x == -y` (#182), which `na()` and `nz()` treat as na while comparisons\n * see it (`r < 30` is true). Versions 5 and 6 have the length form only.\n */\nexport function rsi(x: Source, y: Source): series_float;\nexport function rsi(source: Source, length: simple_int | Source): series_float {\n if (typeof length !== 'number') {\n return Array.from(source, (xv, i) => {\n const x = xv ?? NaN;\n const y = length[i] ?? NaN;\n if (eq(y, 0)) return 100;\n if (eq(x, 0)) return 0;\n return 100 - 100 / (1 + x / y);\n });\n }\n checkPositiveLength('rsi', length, 0, 'y');\n const result: series_float = [];\n\n // Calculate price changes\n const changes: number[] = [];\n for (let i = 1; i < source.length; i++) {\n changes.push(source[i]! - source[i - 1]!);\n }\n\n // Separate gains and losses; a change from or to na is na (skipped by rma), not a 0 gain / loss\n const gains: number[] = changes.map(c => (Number.isNaN(c) ? NaN : c > 0 ? c : 0));\n const losses: number[] = changes.map(c => (Number.isNaN(c) ? NaN : c < 0 ? -c : 0));\n\n // Calculate average gains and losses using RMA (not SMA)\n const avgGains = rma(gains, length);\n const avgLosses = rma(losses, length);\n\n result.push(NaN); // First value is NaN\n\n for (let i = 0; i < avgGains.length; i++) {\n if (eq(avgLosses[i]!, 0)) {\n result.push(100);\n } else if (eq(avgGains[i]!, 0)) {\n result.push(0);\n } else {\n const rs = avgGains[i]! / avgLosses[i]!;\n result.push(100 - (100 / (1 + rs)));\n }\n }\n\n return result;\n}\n\n/**\n * Moving Average Convergence Divergence - trend-following momentum indicator showing relationship\n * between two moving averages.\n *\n * @param source - Series of values to process\n * @param fastLength - Fast EMA length (typically 12)\n * @param slowLength - Slow EMA length (typically 26)\n * @param signalLength - Signal line EMA length (typically 9)\n * @returns Tuple of [macdLine, signalLine, histogram]\n *\n * @remarks\n * - MACD Line = Fast EMA - Slow EMA\n * - Signal Line = EMA of MACD Line\n * - Histogram = MACD Line - Signal Line\n * - Crossovers between MACD and signal line indicate potential buy/sell signals\n *\n * @example\n * ```typescript\n * const [macdLine, signal, histogram] = ta.macd(closePrices, 12, 26, 9);\n * ```\n */\nexport function macd(\n source: Source,\n fastLength: simple_int,\n slowLength: simple_int,\n signalLength: simple_int\n): [series_float, series_float, series_float] {\n const fastEma = ema(source, fastLength);\n const slowEma = ema(source, slowLength);\n\n const macdLine: series_float = [];\n for (let i = 0; i < source.length; i++) {\n macdLine.push(fastEma[i]! - slowEma[i]!);\n }\n\n const signalLine = ema(macdLine, signalLength);\n\n const histogram: series_float = [];\n for (let i = 0; i < source.length; i++) {\n histogram.push(macdLine[i]! - signalLine[i]!);\n }\n\n return [macdLine, signalLine, histogram];\n}\n\n/**\n * Bollinger Bands - a technical analysis tool defined by lines plotted two standard deviations\n * away from a simple moving average.\n *\n * @param series - Series of values to process\n * @param length - Number of bars (length)\n * @param mult - Standard deviation factor\n * @returns Tuple of [middle, upper, lower] bands\n *\n * @remarks\n * - Middle band is the SMA of the source\n * - Upper band = middle + (mult * standard deviation)\n * - Lower band = middle - (mult * standard deviation)\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const [middle, upper, lower] = ta.bb(closePrices, 20, 2);\n * ```\n */\nexport function bb(\n series: Source,\n length: simple_int,\n mult: simple_float\n): [series_float, series_float, series_float] {\n checkSumLength('ta.bb', length, 0);\n const basis = sma(series, length);\n const dev = stdev(series, length);\n\n const upper: series_float = [];\n const lower: series_float = [];\n\n for (let i = 0; i < series.length; i++) {\n upper.push(basis[i]! + mult * dev[i]!);\n lower.push(basis[i]! - mult * dev[i]!);\n }\n\n return [basis, upper, lower];\n}\n\n/**\n * Standard deviation over the last `length` non-na values.\n *\n * @param source - Series of values to process\n * @param length - Number of values, or one length per bar (a series length, see {@link sma})\n * @param biased - true (default): biased estimate (divides by `length`); false: unbiased (by `length - 1`)\n * @returns Standard deviation series (na until `length` non-na values exist)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the window holds the last\n * `length` non-na values, and a bar whose own value is `na` keeps the previous result.\n * The result is the square root of {@link variance} (0 when the variance is not positive), computed from\n * compensated running sums of the values and of their squares, bit for bit as PineScript.\n */\nexport function stdev(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: simple_bool = true\n): series_float {\n return varianceOf(source, length, biased, 'ta.stdev').map((v) => (Number.isNaN(v) ? NaN : v > 0 ? Math.sqrt(v) : 0));\n}\n\n/**\n * The last `length` non-na values up to bar `i` (the bar itself may be na), or null when fewer exist. +/-Infinity\n * counts as na (#183).\n */\nfunction lastValues(source: Source, i: number, length: number): number[] | null {\n const values: number[] = [];\n for (let j = i; j >= 0 && values.length < length; j--) {\n const x = source[j]!;\n if (Number.isFinite(x)) values.push(x);\n }\n return values.length === length ? values : null;\n}\n\n/**\n * The extreme of the window of `length` bars ending at each bar, in one pass (monotonic deque): the bar index of\n * the oldest highest (or lowest) value (the newest one with `newest`), or -1 when the window is empty. The window\n * stops at the first `na` value going back (the callers pass the non-na values only, see {@link keptValues}), and a\n * fractional length is truncated (7.5 is 7 bars), as PineScript does.\n * `zeros[i]` tells whether the window holds a +0 (highest) or a -0 (lowest), the zero that `Math.max` / `Math.min`\n * return when the extreme is 0 (not kept with `newest`).\n */\nfunction windowExtremes(\n source: Source,\n length: number,\n lowest: boolean,\n newest = false\n): { at: Int32Array; zeros: Uint8Array } {\n const n = source.length;\n const span = length > 0 ? Math.trunc(length) : 0; // PineScript casts the length to int\n const at = new Int32Array(n).fill(-1);\n const zeros = new Uint8Array(n);\n const queue = new Int32Array(n); // bar indices; values from best to worst, the oldest first among equal values\n const preferredZero = lowest ? -0 : 0;\n let head = 0;\n let tail = 0;\n let zeroCount = 0; // preferred zeros in the queue\n let lastNa = -1;\n const isPreferredZero = (k: number) => Object.is(source[k], preferredZero);\n for (let i = 0; i < n; i++) {\n const x = source[i]!;\n if (Number.isNaN(x)) {\n lastNa = i;\n head = tail = 0;\n zeroCount = 0;\n continue;\n }\n // drop the values that the new one beats; equal values stay (the oldest wins ties), or go with `newest`\n while (tail > head) {\n const last = source[queue[tail - 1]!]!;\n if (!(lowest ? last > x : last < x) && !(newest && last === x)) break;\n if (isPreferredZero(queue[--tail]!)) zeroCount--;\n }\n queue[tail++] = i;\n if (isPreferredZero(i)) zeroCount++;\n const start = Math.max(i - span + 1, lastNa + 1);\n while (head < tail && queue[head]! < start) {\n if (isPreferredZero(queue[head++]!)) zeroCount--;\n }\n if (head < tail) {\n at[i] = queue[head]!;\n zeros[i] = zeroCount > 0 ? 1 : 0;\n }\n }\n return { at, zeros };\n}\n\n/**\n * The non-na values of `source` with their bars, and for each bar the position of its last non-na value (-1 when\n * there is none yet). PineScript's ta.highest / ta.lowest / ta.highestbars / ta.lowestbars / ta.pivothigh /\n * ta.pivotlow keep the non-na values they receive and nothing else; +/-Infinity is skipped like na (#183).\n */\nfunction keptValues(source: Source): { values: number[]; bars: number[]; last: Int32Array } {\n const values: number[] = [];\n const bars: number[] = [];\n const last = new Int32Array(source.length);\n for (let i = 0; i < source.length; i++) {\n const x = source[i]!;\n if (Number.isFinite(x)) {\n values.push(x);\n bars.push(i);\n }\n last[i] = values.length - 1;\n }\n return { values, bars, last };\n}\n\n/**\n * ta.highest / ta.lowest / ta.highestbars / ta.lowestbars with a series length (a length per bar): on each bar the\n * best of the last `length[i]` non-na values (the newest one on ties), na before bar `length[i] - 1`, as PineScript\n * (measured with a length that changes on each bar, with and without na in the source).\n */\nfunction extremeSeriesLength(source: Source, lengths: ArrayLike<number>, lowest: boolean, offsets: boolean): number[] {\n const name = (lowest ? 'lowest' : 'highest') + (offsets ? 'bars' : '');\n const { values, bars, last } = keptValues(source);\n return Array.from(source, (_, i) => {\n const len = Math.trunc(lengths[i]!);\n checkWindowLength(name, len, i);\n const k = last[i]!;\n if (!(len >= 1) || i < len - 1 || k < 0) return NaN;\n let best = k;\n for (let j = k - 1; j >= 0 && j > k - len; j--) {\n if (lowest ? values[j]! < values[best]! : values[j]! > values[best]!) best = j;\n }\n return offsets ? -(i - bars[best]!) : values[best]!;\n });\n}\n\n/**\n * Offset to the best of the last `length` non-na values (the newest one on ties): the distance in bars, so below\n * `-(length - 1)` after an na value. na before bar `length - 1` and while there is no value.\n */\nfunction extremeOffset(source: Source, length: simple_int | ArrayLike<number>, lowest: boolean): series_int {\n if (typeof length !== 'number') return extremeSeriesLength(source, length, lowest, true);\n checkWindowLength(lowest ? 'lowestbars' : 'highestbars', length, 0);\n const { values, bars, last } = keptValues(source);\n const { at } = windowExtremes(values, length, lowest, true);\n const len = Math.trunc(length);\n // -(i - bar): -0 when the extreme is the current bar, as the offset -j of the window scan\n return source.map((_, i) => {\n const k = last[i]!;\n return i < len - 1 || k < 0 || at[k]! < 0 ? NaN : -(i - bars[at[k]!]!);\n });\n}\n\n/**\n * Best of the last `length` non-na values (of all of them when there are fewer), with the zero sign of `Math.max` /\n * `Math.min`. na before bar `length - 1` and while there is no value.\n */\nfunction extremeValue(source: Source, length: simple_int | ArrayLike<number>, lowest: boolean): series_float {\n if (typeof length !== 'number') return extremeSeriesLength(source, length, lowest, false);\n checkWindowLength(lowest ? 'lowest' : 'highest', length, 0);\n const { values, last } = keptValues(source);\n const { at, zeros } = windowExtremes(values, length, lowest);\n const len = Math.trunc(length);\n return source.map((_, i) => {\n const k = last[i]!;\n if (i < len - 1 || k < 0 || at[k]! < 0) return NaN;\n const v = values[at[k]!]!;\n return v === 0 && zeros[k] ? (lowest ? -0 : 0) : v;\n });\n}\n\n/**\n * Compares each bar with the last earlier bar where both values were not na (PineScript rule for ta.crossover,\n * ta.crossunder and ta.cross): false while there is no such bar, and false on a bar with an na value.\n *\n * @internal\n */\nfunction crossTest(\n series1: Source,\n series2: Source,\n test: (a: number, b: number, prevA: number, prevB: number) => boolean,\n): series_bool {\n const result: series_bool = [];\n let prevA = NaN;\n let prevB = NaN;\n for (let i = 0; i < series1.length; i++) {\n const a = series1[i]!;\n const b = series2[i]!;\n result.push(test(a, b, prevA, prevB));\n if (!Number.isNaN(a) && !Number.isNaN(b)) {\n prevA = a;\n prevB = b;\n }\n }\n return result;\n}\n\n/**\n * Crossover - returns true when series1 crosses over series2 (moves from below to above).\n *\n * @param series1 - First series\n * @param series2 - Second series\n * @returns Boolean series (true at crossover points)\n *\n * @remarks\n * - True when: series1[i] > series2[i] AND series1[j] <= series2[j], where j is the last bar before i where both\n * values were not na (PineScript rule: a crossing right after an na bar is not missed)\n * - First value is always false (no previous value to compare)\n * - Comparisons are exact (no tolerance)\n * - Useful for detecting bullish signals (e.g., fast MA crossing over slow MA)\n *\n * @example\n * ```typescript\n * const crossUp = ta.crossover(fastMA, slowMA);\n * ```\n */\nexport function crossover(series1: Source, series2: Source): series_bool {\n return crossTest(series1, series2, (a, b, pa, pb) => a > b && pa <= pb);\n}\n\n/**\n * Crossunder - returns true when series1 crosses under series2 (moves from above to below).\n *\n * @param series1 - First series\n * @param series2 - Second series\n * @returns Boolean series (true at crossunder points)\n *\n * @remarks\n * - True when: series1[i] < series2[i] AND series1[j] >= series2[j], where j is the last bar before i where both\n * values were not na\n * - First value is always false (no previous value to compare)\n * - Comparisons are exact (no tolerance)\n * - Useful for detecting bearish signals (e.g., fast MA crossing under slow MA)\n *\n * @example\n * ```typescript\n * const crossDown = ta.crossunder(fastMA, slowMA);\n * ```\n */\nexport function crossunder(series1: Source, series2: Source): series_bool {\n return crossTest(series1, series2, (a, b, pa, pb) => a < b && pa >= pb);\n}\n\n/**\n * Change - calculates the difference between the current value and its value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Number of bars back (default: 1)\n * @returns Change series (source[i]! - source[i - length])\n *\n * @remarks\n * - Returns NaN for the first `length` values\n * - Default length is 1 (difference from previous bar)\n * - Positive values indicate increase, negative values indicate decrease\n *\n * @example\n * ```typescript\n * const change1 = ta.change(closePrices); // Daily change\n * const change5 = ta.change(closePrices, 5); // 5-day change\n * ```\n */\nexport function change(source: Source, length: simple_int = 1): series_float {\n checkPositiveLength('change', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n result.push(source[i]! - source[i - length]!);\n }\n }\n\n return result;\n}\n\n/**\n * True Range - measures market volatility by calculating the greatest of three price ranges.\n *\n * @param handle_na - Defines how the function calculates when previous close is na (default: false)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns True range series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.tr(handle_na?)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - True Range = max(high - low, abs(high - close[1]), abs(low - close[1]))\n * - When `handle_na` is true: returns `high - low` if previous close is na\n * - When `handle_na` is false: returns na if previous close is na\n * - Used as a component in ATR calculations\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const trueRange = ta.tr(false, high, low, close);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const trueRange = ta.tr(); // Matches PineScript!\n * ```\n */\nexport function tr(\n handle_na: simple_bool = false,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.tr() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const result: series_float = [];\n\n for (let i = 0; i < high.length; i++) {\n if (i === 0) {\n // First bar: the previous close is na\n result.push(handle_na ? high[i]! - low[i]! : NaN);\n } else {\n const prevClose = close[i - 1]!;\n\n // Handle na previous close based on handle_na parameter\n if (isNaN(prevClose)) {\n if (handle_na) {\n result.push(high[i]! - low[i]!);\n } else {\n result.push(NaN);\n }\n } else {\n const tr = Math.max(\n high[i]! - low[i]!,\n Math.abs(high[i]! - prevClose),\n Math.abs(low[i]! - prevClose)\n );\n result.push(tr);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Average True Range - returns the RMA (Relative Moving Average) of true range.\n *\n * @param length - Number of bars (length)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns Average true range series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.atr(length)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - Uses `ta.rma()` (Relative Moving Average) for smoothing, matching PineScript v6\n * - True range is max(high - low, abs(high - close[1]), abs(low - close[1]))\n * - ATR is a measure of volatility, higher values indicate greater volatility\n * - `na` values in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const atr14 = ta.atr(14, high, low, close);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const atr14 = ta.atr(14); // Matches PineScript!\n * ```\n */\nexport function atr(length: simple_int, high?: Source, low?: Source, close?: Source): series_float {\n checkPositiveLength('atr->rma', length, 0);\n if (!high || !low || !close) {\n throw new Error(\n 'ta.atr() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n // PineScript: ta.atr uses ta.tr(true), so bar 0 is high - low\n const trueRange = tr(true, high, low, close);\n return rma(trueRange, length);\n}\n\n/**\n * SuperTrend Indicator - a trend-following indicator that helps identify trend direction.\n *\n * @param factor - The multiplier by which the ATR will get multiplied (series int/float)\n * @param atrPeriod - Length of ATR (simple int)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @param wicks - Whether to use wicks for trend reversal (NOT in PineScript v6 API, default: false)\n * @returns Tuple of [supertrend, direction] where direction is 1 (downtrend) or -1 (uptrend)\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.supertrend(factor, atrPeriod)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - The `wicks` parameter is NOT part of the official PineScript v6 API\n * - Direction: 1 = downtrend (red), -1 = uptrend (green)\n * - Uses hl2 (average of high and low) as the source\n * - SuperTrend helps identify the current market trend and potential reversal points\n * - As in PineScript (`nz` of the previous bands): 0 on bar 0, na on the next bars while the ATR is na\n *\n * @example\n * ```typescript\n * // Direct call with explicit data\n * const [supertrend, direction] = ta.supertrend(3, 10, high, low, close);\n * // Plot uptrend when direction < 0\n * // Plot downtrend when direction > 0\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close } });\n * const [supertrend, direction] = ta.supertrend(3, 10); // Matches PineScript!\n * ```\n */\nexport function supertrend(\n factor: simple_float,\n atrPeriod: simple_int,\n high?: Source,\n low?: Source,\n close?: Source,\n wicks: simple_bool = false\n): [series_float, series_int] {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.supertrend() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n const supertrendValues: series_float = [];\n const directions: series_int = [];\n\n // Calculate hl2 (average of high and low)\n const source: series_float = [];\n for (let i = 0; i < high.length; i++) {\n source.push((high[i]! + low[i]!) / 2);\n }\n\n // Calculate ATR\n const atrValues = atr(atrPeriod, high, low, close);\n\n // PineScript reference implementation (bar by bar):\n // prevLowerBand = nz(lowerBand[1]), prevUpperBand = nz(upperBand[1])\n // lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand\n // upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand\n // direction = na(atr[1]) ? 1 : prevSuperTrend == prevUpperBand ? (close > upperBand ? -1 : 1) : (close < lowerBand ? 1 : -1)\n // A comparison with na is false: on bar 0 (close[1] na) both bands take nz(na) = 0, so the supertrend is 0.\n const nz = (v: number) => (isNaN(v) ? 0 : v);\n let lastLowerBand = NaN;\n let lastUpperBand = NaN;\n let prevSuperTrend = NaN;\n\n for (let i = 0; i < source.length; i++) {\n const atrValue = atrValues[i]! * factor;\n let upperBand = source[i]! + atrValue;\n let lowerBand = source[i]! - atrValue;\n const prevLowerBand = nz(lastLowerBand);\n const prevUpperBand = nz(lastUpperBand);\n\n // Price compared with the bands: close, or low / high with wicks\n const highPrice = wicks ? high[i]! : close[i]!;\n const lowPrice = wicks ? low[i]! : close[i]!;\n const prevLowPrice = i > 0 ? (wicks ? low[i - 1]! : close[i - 1]!) : NaN;\n const prevHighPrice = i > 0 ? (wicks ? high[i - 1]! : close[i - 1]!) : NaN;\n\n lowerBand = lowerBand > prevLowerBand || prevLowPrice < prevLowerBand ? lowerBand : prevLowerBand;\n upperBand = upperBand < prevUpperBand || prevHighPrice > prevUpperBand ? upperBand : prevUpperBand;\n\n let currentDirection: int;\n if (i === 0 || isNaN(atrValues[i - 1]!)) {\n currentDirection = 1;\n } else if (prevSuperTrend === prevUpperBand) {\n // Was in downtrend (following upper band)\n currentDirection = highPrice > upperBand ? -1 : 1;\n } else {\n // Was in uptrend (following lower band)\n currentDirection = lowPrice < lowerBand ? 1 : -1;\n }\n\n const superTrendValue = currentDirection === -1 ? lowerBand : upperBand;\n supertrendValues.push(superTrendValue);\n directions.push(currentDirection);\n\n lastLowerBand = lowerBand;\n lastUpperBand = upperBand;\n prevSuperTrend = superTrendValue;\n }\n\n return [supertrendValues, directions];\n}\n/**\n * Relative Moving Average (RMA) - exponentially weighted moving average with alpha = 1 / length.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns RMA of source for length bars back\n *\n * @remarks\n * - Moving average used in RSI calculation\n * - Alpha = 1 / length (different from EMA which uses alpha = 2 / (length + 1))\n * - First value is initialized with SMA, then uses exponential smoothing. As in PineScript, the seed is the\n * `ta.sma` value (its compensated running sum), so it can differ from the exact mean in the last bits\n * - Formula: `RMA = (source + (length - 1) * RMA[1]) / length`, evaluated in this order as in PineScript\n * (equal to `alpha * source + (1 - alpha) * RMA[1]`, but bit for bit)\n * - `na` values (also +/-Infinity) in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n *\n * @example\n * ```typescript\n * const rma14 = ta.rma(closePrices, 14);\n * // Used internally by RSI:\n * // avgGain = ta.rma(gains, 14);\n * // avgLoss = ta.rma(losses, 14);\n * ```\n */\nexport function rma(source: Source, length: simple_int): series_float {\n checkPositiveLength('rma', length, 0);\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n\n // Find the first index where we have enough non-na values for SMA initialization.\n // An infinite value is na, as in PineScript.\n let firstValidIndex = -1;\n let validCount = 0;\n\n for (let i = 0; i < source.length; i++) {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val) && ++validCount === len) {\n firstValidIndex = i;\n break;\n }\n }\n\n const rmaInitialized = firstValidIndex >= 0;\n // The seed is ta.sma on that bar: the running sum of math.sum (PineScript bits), not a plain loop sum\n let rmaValue = rmaInitialized ? runningSum(source.slice(0, firstValidIndex + 1), len)[firstValidIndex]! / len : NaN;\n\n for (let i = 0; i < source.length; i++) {\n if (!rmaInitialized || i < firstValidIndex) {\n // Not enough data yet for RMA\n result.push(NaN);\n } else if (i === firstValidIndex) {\n // First valid RMA value\n result.push(rmaValue);\n } else {\n const val = source[i];\n if (val !== undefined && Number.isFinite(val)) {\n // PineScript evaluates (source + (length - 1) * RMA[1]) / length; the form\n // alpha * source + (1 - alpha) * RMA[1] differs in the last bits\n rmaValue = (val + (len - 1) * rmaValue) / len;\n result.push(rmaValue);\n } else {\n // na source: na on this bar; the next bar continues from the last value (as in PineScript)\n result.push(NaN);\n }\n }\n }\n\n return result;\n}\n\n/**\n * One step of the PineScript ta.wma sum: `a + b`, or 0 when `|a + b| <= 1e-10 * max(1, |a| + |b|)`.\n * Measured bit for bit: a sum that cancels to a tiny residue (relative to the operands, or below 1e-10) is 0.\n */\nfunction wmaAdd(a: number, b: number): number {\n const sum = a + b;\n return Math.abs(sum) <= 1e-10 * Math.max(1, Math.abs(a) + Math.abs(b)) ? 0 : sum;\n}\n\n/**\n * Weighted Moving Average (WMA) - moving average with linearly decreasing weights.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns WMA of source for length bars back\n *\n * @remarks\n * - Weighting factors decrease in arithmetical progression\n * - Most recent value has weight `length`, previous has `length-1`, etc.\n * - Formula: `sum(source[i]! * (length - i)) / sum(length - i)` for i = 0 to length-1\n * - As in PineScript: na on a bar whose source is `na` (also +/-Infinity) and until `length` non-`na` values were\n * received; an `na` value inside the window is replaced by the previous non-`na` value\n * - Summed from the oldest value to the newest; as PineScript, a partial sum `s + t` with\n * `|s + t| <= 1e-10 * max(1, |s| + |t|)` is 0 (a cancellation residue, or values below 1e-10)\n * - More responsive to recent price changes than SMA\n * - `length` can be an array (a length per bar, PineScript series length): each bar gives the result of its own\n * length (`na` for a length below 1)\n *\n * @example\n * ```typescript\n * const wma20 = ta.wma(closePrices, 20);\n * // WMA gives more weight to recent prices\n * ```\n */\nexport function wma(source: Source, length: simple_int | ArrayLike<number>): series_float {\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const fixed = typeof length === 'number' ? Math.floor(length) : NaN;\n if (typeof length === 'number') checkPositiveLength('wma', fixed, 0);\n // PineScript: na on a bar with an na source (also +/-Infinity) and until `len` non-na values were received;\n // otherwise the last `len` bars, each na replaced by the previous non-na value\n const filled: number[] = [];\n let last = NaN;\n let count = 0;\n for (let i = 0; i < source.length; i++) {\n const v = source[i];\n const isNa = v === undefined || v === null || !Number.isFinite(v);\n if (!isNa) {\n last = v;\n count++;\n }\n filled.push(last);\n // a series length: the window of this bar's length (the result of ta.wma with that fixed length)\n const len = typeof length === 'number' ? fixed : Math.floor(length[i]!);\n if (typeof length !== 'number') checkPositiveLength('wma', len, i);\n if (isNa || !(len >= 1) || count < len) {\n result.push(NaN);\n continue;\n }\n // Summed from the oldest bar (weight 1) to the newest (weight len), as PineScript (bit for bit)\n let sum = 0;\n let weightSum = 0;\n for (let j = len - 1; j >= 0; j--) {\n const weight = len - j;\n sum = wmaAdd(sum, filled[i - j]! * weight);\n weightSum += weight;\n }\n result.push(sum / weightSum);\n }\n return result;\n}\n\n/**\n * Highest value over the last `length` bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns Highest value series (na on the first `length - 1` bars)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the highest of the last `length`\n * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar\n * `length - 1` and while no value was received. A fractional length is truncated (7.5 is 7 bars).\n * `length` can be an array (a length per bar, PineScript series length), also for `ta.lowest`, `ta.highestbars`\n * and `ta.lowestbars`: each bar uses its own length.\n * A length above 15,000 throws the PineScript runtime error (also `ta.lowest`, `ta.highestbars`, `ta.lowestbars`).\n * PineScript `ta.highest(length)` (source = high) is `ta.highest(length)` in the script API.\n */\nexport function highest(source: Source, length: simple_int | ArrayLike<number>): series_float {\n return extremeValue(source, length, false);\n}\n\n/**\n * Lowest value over the last `length` bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns Lowest value series (na on the first `length - 1` bars)\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the lowest of the last `length`\n * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar\n * `length - 1` and while no value was received.\n */\nexport function lowest(source: Source, length: simple_int | ArrayLike<number>): series_float {\n return extremeValue(source, length, true);\n}\n\n/**\n * Cumulative Sum - returns the total sum of all elements from the beginning.\n *\n * @param source - Series of values to process\n * @returns Series containing the cumulative sum at each bar\n *\n * @remarks\n * - Returns the running total of all values from index 0 to current index\n * - As in PineScript: an `na` value adds nothing to the sum,\n * and the result is `na` on that bar only; the sum continues on the next bars\n * - Useful for calculating total volume, total trades, etc.\n *\n * @example\n * ```typescript\n * const cumulativeVolume = ta.cum(volume);\n * const totalGains = ta.cum(gains);\n * ```\n */\nexport function cum(source: Source): series_float {\n let sum = 0;\n return source.map((v) => {\n // PineScript: an na value (also +/-Infinity) gives na on its bar and is not added\n if (!Number.isFinite(v)) return NaN;\n sum += v;\n return sum;\n });\n}\n\n/**\n * Cross - returns true when two series cross each other (either direction).\n *\n * @param source1 - First series\n * @param source2 - Second series\n * @returns Boolean series (true at cross points)\n *\n * @remarks\n * PineScript rule (measured bit for bit; not `crossover or crossunder`):\n * - The call keeps the side of the last bar where `source1` was strictly above or strictly below `source2` (no\n * side before such a bar). Equal bars and bars with an `na` value do not change it.\n * - True when the values are strictly on the other side of the kept side: so a run of equal values is passed, and\n * a series that starts equal and then moves away is not a cross\n * - False on a bar with an `na` value\n * - Use `ta.crossover()` or `ta.crossunder()` for directional crosses\n *\n * @example\n * ```typescript\n * const crossed = ta.cross(fastMA, slowMA);\n * // Detect any MA crossover\n * ```\n */\nexport function cross(source1: Source, source2: Source): series_bool {\n const result: series_bool = [];\n let side = 0; // -1: last strictly below, 1: last strictly above, 0: none yet\n for (let i = 0; i < source1.length; i++) {\n const a = source1[i]!;\n const b = source2[i]!;\n if (Number.isNaN(a) || Number.isNaN(b)) {\n result.push(false);\n continue;\n }\n result.push((side < 0 && a > b) || (side > 0 && a < b));\n if (a < b) side = -1;\n else if (a > b) side = 1;\n }\n return result;\n}\n\n/**\n * ta.rising / ta.falling: a counter of the steps from one bar to the next that pass `step(newer, older)`, reset to 0\n * by a step that does not pass; a step with an na value (on either bar) leaves the counter unchanged. True when the\n * counter is at least `length`.\n *\n * @internal\n */\nfunction monotonic(source: Source, length: simple_int, step: (newer: number, older: number) => boolean): series_bool {\n const result: series_bool = [];\n let count = 0;\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n const prev = i > 0 ? source[i - 1]! : NaN;\n if (Number.isFinite(v) && Number.isFinite(prev)) count = step(v, prev) ? count + 1 : 0;\n result.push(count >= length);\n }\n return result;\n}\n\n/**\n * Rising - returns true if source is rising for length bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Boolean series (true when rising)\n *\n * @remarks\n * PineScript rules:\n * - a counter of rises from the previous bar (a rise is larger than the 1e-10 tolerance); a step that is not a rise\n * resets it to 0\n * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after\n * it, keep the result of the bar before the `na`)\n * - true when the counter is at least `length` (false at the start)\n *\n * @example\n * ```typescript\n * const isRising = ta.rising(close, 3);\n * // Detect upward momentum\n * ```\n */\nexport function rising(source: Source, length: simple_int): series_bool {\n checkPositiveLength('rising', length, 0);\n return monotonic(source, length, gt);\n}\n\n/**\n * Falling - returns true if source is falling for length bars.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Boolean series (true when falling)\n *\n * @remarks\n * PineScript rules:\n * - a counter of falls from the previous bar (a fall is larger than the 1e-10 tolerance); a step that is not a fall\n * resets it to 0\n * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after\n * it, keep the result of the bar before the `na`)\n * - true when the counter is at least `length` (false at the start)\n *\n * @example\n * ```typescript\n * const isFalling = ta.falling(close, 3);\n * // Detect downward momentum\n * ```\n */\nexport function falling(source: Source, length: simple_int): series_bool {\n checkPositiveLength('falling', length, 0);\n return monotonic(source, length, lt);\n}\n\n/**\n * Rate of Change (ROC) - percentage change between current value and value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns ROC series as percentage\n *\n * @remarks\n * - Formula: `100 * change(source, length) / source[length]`\n * - Equivalent to: `100 * (source - source[length]) / source[length]`\n * - Returns percentage change, e.g., 5.0 means 5% increase\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - A zero `source[length]` gives +/-Infinity (NaN when `source` is 0 too), as in PineScript\n * - Useful for momentum analysis and trend strength measurement\n *\n * @example\n * ```typescript\n * const roc10 = ta.roc(closePrices, 10);\n * // Positive ROC indicates upward momentum\n * // Negative ROC indicates downward momentum\n * ```\n */\nexport function roc(source: Source, length: simple_int): series_float {\n checkPositiveLength('roc', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n const oldValue = source[i - length]!;\n if (isNaN(oldValue) || isNaN(source[i]!)) {\n result.push(NaN);\n } else {\n // a zero base divides by zero as in PineScript: +/-Infinity, NaN for 0 / 0 (#184)\n const changeValue = source[i]! - oldValue;\n result.push((100 * changeValue) / oldValue);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Momentum (MOM) - difference between current value and value length bars ago.\n *\n * @param source - Series of values to process\n * @param length - Offset from current bar to previous bar\n * @returns Momentum series\n *\n * @remarks\n * - Formula: `source - source[length]`\n * - Equivalent to `ta.change(source, length)`\n * - Positive momentum indicates upward movement\n * - Negative momentum indicates downward movement\n * - `na` values in the source series are included in calculations and will produce an `na` result\n *\n * @example\n * ```typescript\n * const mom10 = ta.mom(closePrices, 10);\n * // Measures raw price momentum over 10 bars\n * ```\n */\nexport function mom(source: Source, length: simple_int): series_float {\n checkPositiveLength('mom', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (i < length) {\n result.push(NaN);\n } else {\n if (isNaN(source[i]!) || isNaN(source[i - length]!)) {\n result.push(NaN);\n } else {\n result.push(source[i]! - source[i - length]!);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Mean Absolute Deviation - measure of difference between series and its SMA.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Mean absolute deviation series\n *\n * @remarks\n * - Measures average absolute distance from the mean\n * - Less sensitive to outliers than standard deviation\n * - PineScript rule (bit for bit): `sum(abs(source[i] - mean)) / length` for `i = 0 .. length - 1`, added newest\n * first, with `mean = ta.sma(source, length)` (its compensated running sum, so a flat window can give a tiny\n * non-zero deviation)\n * - The loop reads the last `length` bars: an `na` among them gives `na`\n *\n * @example\n * ```typescript\n * const dev10 = ta.dev(closePrices, 10);\n * // Measures volatility using mean absolute deviation\n * ```\n */\nexport function dev(source: Source, length: simple_int): series_float {\n checkPositiveLength('dev', length, 0);\n const len = Math.floor(length);\n return sma(source, len).map((mean, i) => {\n if (i < len - 1 || Number.isNaN(mean)) return NaN;\n let sum = 0;\n for (let k = 0; k < len; k++) sum += Math.abs(source[i - k]! - mean);\n return sum / len;\n });\n}\n\n/**\n * Variance - expectation of squared deviation from mean.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param biased - Use biased (true) or unbiased (false) estimate (default: true)\n * @returns Variance series\n *\n * @remarks\n * - Measures how far values are spread out from their mean\n * - If `biased` is true: divides by `length` (population variance)\n * - If `biased` is false: divides by `length - 1` (sample variance)\n * - Formula (biased): `sum((source[i]! - mean)^2) / length`\n * - Formula (unbiased): `sum((source[i]! - mean)^2) / (length - 1)`\n * - `na` values in the source series are ignored\n * - The function calculates on the `length` quantity of non-`na` values\n * - Relationship: `stdev = sqrt(variance)`\n * - Computed as PineScript, bit for bit, from compensated running sums of the values and of their squares:\n * biased `sumSq / length - mean * mean`, unbiased `sumSq / (length - 1) - mean * sum / (length - 1)`\n *\n * @example\n * ```typescript\n * const variance20 = ta.variance(closePrices, 20);\n * const sampleVariance = ta.variance(closePrices, 20, false);\n * ```\n */\nexport function variance(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: simple_bool = true\n): series_float {\n return varianceOf(source, length, biased, 'ta.variance');\n}\n\n/** {@link variance} with a fixed or a series length; `name` is used in the error messages. */\nfunction varianceOf(\n source: Source,\n length: simple_int | ArrayLike<number>,\n biased: boolean,\n name: string\n): series_float {\n if (typeof length !== 'number') {\n const result = runningVarianceSeries(source, length, biased, name);\n return biased ? result : result.map((v, i) => (Math.floor(length[i]!) > 1 ? v : NaN));\n }\n const len = Math.floor(length);\n checkSumLength(name, len, 0);\n // PineScript: the last `len` non-na values (also +/-Infinity skipped), as ta.sma\n if ((biased ? len : len - 1) <= 0) return source.map(() => NaN);\n return runningVariance(source, len, biased);\n}\n\n/**\n * Median - returns the median (middle value) of the series.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Median series\n *\n * @remarks\n * - Returns the middle value when values are sorted\n * - For an even length, returns the average of the two middle values\n * - As in PineScript: `na` values (also +/-Infinity) are skipped, the window holds the last `length` non-na values\n * (going back as many bars as needed), and a bar whose own value is `na` still gets a result\n * - Returns NaN until `length` non-na values exist\n * - More robust to outliers than mean (SMA)\n *\n * @example\n * ```typescript\n * const median20 = ta.median(closePrices, 20);\n * // Median is less affected by extreme values than SMA\n * ```\n */\nexport function median(source: Source, length: simple_int): series_float {\n checkPositiveLength('median', length, 0);\n const len = Math.floor(length);\n const n = source.length;\n const out: series_float = new Array<number>(n).fill(NaN);\n if (!(len >= 1)) return out;\n // The last `len` non-na values, sorted; equal values (also +0 / -0) from the newest to the oldest, which is the\n // order a stable sort of the window gives, so the middle values are the same numbers.\n const sorted: number[] = [];\n const kept = new Float64Array(n); // the non-na values in bar order\n let count = 0;\n /** First position whose value is >= v (`after`: > v). */\n const bound = (v: number, after: boolean): number => {\n let lo = 0;\n let hi = sorted.length;\n while (lo < hi) {\n const m = (lo + hi) >> 1;\n if (after ? sorted[m]! <= v : sorted[m]! < v) lo = m + 1;\n else hi = m;\n }\n return lo;\n };\n const mid = Math.floor(len / 2);\n for (let i = 0; i < n; i++) {\n const x = source[i]!;\n if (Number.isFinite(x)) {\n kept[count++] = x;\n sorted.splice(bound(x, false), 0, x); // before the equal values: the newest first\n // the value leaving the window is the oldest, so the last of its equal values\n if (count > len) sorted.splice(bound(kept[count - 1 - len]!, true) - 1, 1);\n }\n if (count >= len) out[i] = len % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n }\n return out;\n}\n\n/**\n * Symmetrically Weighted Moving Average (SWMA) - fixed length 4 with symmetric weights.\n *\n * @param source - Series of values to process\n * @returns SWMA series\n *\n * @remarks\n * - Fixed length of 4 bars\n * - Weights: [1/6, 2/6, 2/6, 1/6] (symmetric)\n * - Formula, in this order as in PineScript (bit for bit): `(source + 2 * source[1] + 2 * source[2] + source[3]) / 6`\n * - More weight given to middle values\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - Returns NaN for the first 3 bars\n *\n * @example\n * ```typescript\n * const swma = ta.swma(closePrices);\n * // Smoothed price with symmetric weighting\n * ```\n */\nexport function swma(source: Source): series_float {\n return Array.from({ length: source.length }, (_, i) =>\n i < 3 ? NaN : (source[i]! + 2 * source[i - 1]! + 2 * source[i - 2]! + source[i - 3]!) / 6\n );\n}\n\n/**\n * Volume Weighted Moving Average (VWMA) - moving average weighted by volume.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param volume - Volume series (required when not using context API)\n * @returns VWMA series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.vwma(source, length)` - uses implicit volume data\n * - **JavaScript signature**: Requires explicit `volume` OR use `createContext()`\n * - Formula: `sma(source * volume, length) / sma(volume, length)`\n * - Gives more weight to bars with higher volume\n * - `na` values in the source series are ignored\n * - Useful for price analysis considering volume significance\n *\n * @example\n * ```typescript\n * // Direct call with explicit volume\n * const vwma20 = ta.vwma(closePrices, 20, volumeData);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close, volume } });\n * const vwma20 = ta.vwma(close, 20); // Matches PineScript!\n * ```\n */\nexport function vwma(source: Source, length: simple_int, volume?: Source): series_float {\n checkPositiveLength('vwma->sma', length, 0);\n if (!volume) {\n throw new Error(\n 'ta.vwma() requires volume series. ' +\n 'Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data.'\n );\n }\n\n // Calculate source * volume\n const sourceTimesVolume: series_float = [];\n for (let i = 0; i < source.length; i++) {\n sourceTimesVolume.push(source[i]! * volume[i]!);\n }\n\n const numerator = sma(sourceTimesVolume, length);\n const denominator = sma(volume, length);\n\n const result: series_float = [];\n for (let i = 0; i < source.length; i++) {\n if (denominator[i]! === 0 || isNaN(denominator[i]!)) {\n result.push(NaN);\n } else {\n result.push(numerator[i]! / denominator[i]!);\n }\n }\n\n return result;\n}\n\n/**\n * Linear Regression - line that best fits prices using least squares method.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @param offset - Offset (default: 0)\n * @returns Linear regression value\n *\n * @remarks\n * - Calculates line of best fit using least squares method\n * - Formula: `linreg = intercept + slope * (length - 1 - offset)`\n * - As PineScript (bit for bit): x = 1 (oldest) .. length (newest), sums from the oldest value,\n * `slope = (length * sumXY - sumX * sumY) / (length * sumX2 - sumX * sumX)`,\n * `intercept = sumY / length - slope * sumX / length + slope`\n * - offset=0 gives current fitted value, offset<0 gives future projection\n * - `na` values in the source series are included in calculations and will produce an `na` result\n * - Useful for trend detection and prediction\n *\n * @example\n * ```typescript\n * const linreg20 = ta.linreg(closePrices, 20, 0);\n * const linregFuture = ta.linreg(closePrices, 20, -5); // Project 5 bars ahead\n * ```\n */\nexport function linreg(source: Source, length: simple_int, offset: simple_int = 0): series_float {\n checkPositiveLength('linreg', length, 0);\n const result: series_float = [];\n // Floor the length to match PineScript's auto-truncation of float to int\n const len = Math.floor(length);\n\n for (let i = 0; i < source.length; i++) {\n if (i < len - 1) {\n result.push(NaN);\n } else {\n // Check for NaN values in window\n let hasNaN = false;\n for (let j = 0; j < len; j++) {\n if (isNaN(source[i - j]!)) {\n hasNaN = true;\n break;\n }\n }\n\n if (hasNaN) {\n result.push(NaN);\n } else {\n // Least squares as PineScript: x = 1 (oldest) .. len (newest), summed from the oldest value; the intercept\n // is the fitted value at x = 1\n let sumX = 0;\n let sumY = 0;\n let sumXY = 0;\n let sumX2 = 0;\n for (let j = 0; j < len; j++) {\n const x = j + 1;\n const y = source[i - (len - 1 - j)]!;\n sumX += x;\n sumY += y;\n sumXY += x * y;\n sumX2 += x * x;\n }\n const slope = (len * sumXY - sumX * sumY) / (len * sumX2 - sumX * sumX);\n const intercept = sumY / len - (slope * sumX) / len + slope;\n result.push(intercept + slope * (len - 1 - offset));\n }\n }\n }\n\n return result;\n}\n\n/**\n * Correlation Coefficient - measures degree to which two series deviate from their means together.\n *\n * @param source1 - First series\n * @param source2 - Second series \n * @param length - Number of bars (length)\n * @returns Correlation coefficient (-1 to +1)\n *\n * @remarks\n * - Returns value between -1 and +1\n * - +1 = perfect positive correlation\n * - -1 = perfect negative correlation\n * - 0 = no correlation\n * - Measures linear relationship between two series\n * - As PineScript: `cov = sma(x * y) - sma(x) * sma(y)`, `r = cov / sqrt(variance(x) * variance(y))` with the\n * compensated running sums of `ta.sma` / `ta.variance` (each skips its own `na` values); `|cov| <= 1e-10` gives 0, a\n * zero variance gives `na`\n *\n * @example\n * ```typescript\n * const corr = ta.correlation(series1, series2, 20);\n * // Values close to +1 or -1 indicate strong relationship\n * ```\n */\nexport function correlation(source1: Source, source2: Source, length: simple_int): series_float {\n checkPositiveLength('correlation', length, 0);\n // PineScript: from compensated running sums, cov = sma(x * y) - sma(x) * sma(y), r = cov / sqrt(var(x) * var(y))\n // (biased variances); each running sum skips its own na values\n const product = Array.from({ length: source1.length }, (_, i) => {\n const v1 = source1[i];\n const v2 = source2[i];\n return v1 === null || v1 === undefined || v2 === null || v2 === undefined ? NaN : v1 * v2;\n });\n const meanXY = sma(product, length);\n const meanX = sma(source1, length);\n const meanY = sma(source2, length);\n const varX = variance(source1, length);\n const varY = variance(source2, length);\n return meanXY.map((mxy, i) => {\n const cov = mxy - meanX[i]! * meanY[i]!;\n if (Number.isNaN(cov)) return NaN;\n // a covariance within 1e-10 of 0 gives 0; a zero denominator gives na (a division by zero)\n if (Math.abs(cov) <= 1e-10) return 0;\n const denominator = Math.sqrt(varX[i]! * varY[i]!);\n return denominator === 0 ? NaN : cov / denominator;\n });\n}\n\n/**\n * Percent Rank - percentage of how many previous values were less than or equal to current value.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Percent rank (0 to 100)\n *\n * @remarks\n * - Returns value between 0 and 100\n * - 0 = current value is lowest in the period\n * - 100 = current value is highest in the period\n * - 50 = current value is at median\n * - Useful for identifying relative strength within a period\n *\n * PineScript rules:\n * - percentrank = count(source[k] <= source, k = 1..length) * 100 / length (in this order: the PineScript bits)\n * - a value from bar `length` on; an `na` value in the window counts as not `<=` the current value, and an `na`\n * current value gives 0 (#177)\n * - the comparison uses the 1e-10 tolerance\n *\n * @example\n * ```typescript\n * const pctrank = ta.percentrank(closePrices, 100);\n * // Values near 100 indicate recent strength\n * // Values near 0 indicate recent weakness\n * ```\n */\nexport function percentrank(source: Source, length: simple_int): series_float {\n checkPositiveLength('percentrank', length, 0);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n const currentValue = source[i]!;\n if (i < length) {\n result.push(NaN);\n continue;\n }\n // le() is false for an na value in the window, and for all of them when the current value is na (0)\n let countLessOrEqual = 0;\n for (let j = 1; j <= length; j++) {\n if (le(source[i - j]!, currentValue)) countLessOrEqual++;\n }\n result.push((countLessOrEqual * 100) / length);\n }\n\n return result;\n}\n\n/**\n * Commodity Channel Index (CCI) - measures deviation from average price.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns CCI series\n *\n * @remarks\n * - CCI = (Typical Price - SMA of TP) / (0.015 * Mean Deviation)\n * - Typical Price = (High + Low + Close) / 3\n * - Mean Deviation = Average of absolute differences from mean\n * - Scaled by 0.015 to provide more readable numbers\n * - Values above +100 indicate overbought conditions\n * - Values below -100 indicate oversold conditions\n *\n * PineScript rules (bit for bit):\n * - `(source - ta.sma(source, length)) / (0.015 * ta.dev(source, length))`\n * - when the mean deviation is 0 (1e-10 tolerance, a flat window), the last CCI value; 0 when there is none yet\n * (a flat first window)\n * - \\`na\\` when the mean or the deviation is \\`na\\` (an \\`na\\` in the last \\`length\\` bars)\n *\n * @example\n * \\`\\`\\`typescript\n * const cci20 = ta.cci(typicalPrice, 20);\n * // Overbought when cci > 100\n * // Oversold when cci < -100\n * \\`\\`\\`\n */\nexport function cci(source: Source, length: simple_int): series_float {\n checkPositiveLength('cci', length, 0);\n const smaValues = sma(source, length);\n const devValues = dev(source, length);\n let last = 0;\n return smaValues.map((mean, i) => {\n const d = devValues[i]!;\n if (Number.isNaN(mean) || Number.isNaN(d)) return NaN;\n if (!eq(d, 0)) last = (source[i]! - mean) / (0.015 * d);\n return last;\n });\n}\n\n/**\n * Stochastic Oscillator - momentum indicator comparing closing price to price range.\n *\n * @param source - Source series (typically close)\n * @param high - High price series\n * @param low - Low price series\n * @param length - Number of bars (length)\n * @returns Stochastic %K series (values range from 0 to 100)\n *\n * @remarks\n * - Formula: 100 * (close - lowest(low, length)) / (highest(high, length) - lowest(low, length))\n * - Measures where close is relative to the high-low range\n * - Values above 80 typically indicate overbought\n * - Values below 20 typically indicate oversold\n * - As PineScript: when the source, \\`highest(high, length)\\` or \\`lowest(low, length)\\` is \\`na\\`, or the range and\n * \\`source - lowest\\` are both 0, the result is the previous result of the call (\\`na\\` until a first value); a zero\n * range with another source value gives +/-Infinity (plotted as \\`na\\`)\n *\n * @example\n * \\`\\`\\`typescript\n * const stochK = ta.stoch(close, high, low, 14);\n * // Smooth with SMA for %D line:\n * const stochD = ta.sma(stochK, 3);\n * \\`\\`\\`\n */\nexport function stoch(source: Source, high: Source, low: Source, length: simple_int): series_float {\n checkPositiveLength('stoch->highest', length, 0);\n const result: series_float = [];\n const lowestValues = lowest(low, length);\n const highestValues = highest(high, length);\n\n // PineScript: an na (NaN) result keeps the previous one: an na input, or 0 / 0 on a zero range; a non-zero value\n // over a zero range gives +/-Infinity (#183)\n let previous = NaN;\n for (let i = 0; i < source.length; i++) {\n const lo = lowestValues[i]!;\n const k = (100 * (source[i]! - lo)) / (highestValues[i]! - lo);\n if (!Number.isNaN(k)) previous = k;\n result.push(previous);\n }\n\n return result;\n}\n\n\n/**\n * Money Flow Index (MFI) - volume-weighted RSI measuring buying and selling pressure.\n *\n * @param source - Source series (typically hlc3 or close)\n * @param length - Number of bars (length)\n * @param volume - Volume series (required when not using context API)\n * @returns MFI series (values range from 0 to 100)\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.mfi(source, length)` - uses implicit volume data\n * - **JavaScript signature**: Requires explicit `volume` OR use `createContext()`\n * - Combines price and volume to identify overbought/oversold conditions\n * - Formula: 100 - (100 / (1 + Positive Money Flow / Negative Money Flow))\n * - Values above 80 indicate overbought\n * - Values below 20 indicate oversold\n *\n * PineScript rules (bit for bit):\n * - the two flows are `math.sum` running sums; a sum within 1e-10 of 0 counts as 0 (the residue a running sum\n * keeps over a window of zeros)\n * - 100 when the negative flow is 0; `na` when `1 + positive / negative` is 0 (division by zero)\n * - a bar with an `na` source adds nothing to the sums and gives the previous result; the bar after it (an `na`\n * change) adds its money flow to both sums\n *\n * @example\n * ```typescript\n * // Direct call with explicit volume\n * const mfi14 = ta.mfi(hlc3, 14, volume);\n *\n * // Or use context API for cleaner syntax\n * const { ta } = createContext({ chart: { high, low, close, volume } });\n * const mfi14 = ta.mfi(hlc3, 14); // Matches PineScript!\n * ```\n */\nexport function mfi(source: Source, length: simple_int, volume?: Source): series_float {\n checkPositiveLength('mfi', length, 0);\n if (!volume) {\n throw new Error(\n 'ta.mfi() requires volume series. ' +\n 'Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data.'\n );\n }\n\n // PineScript reference:\n // upper = math.sum(volume * (ta.change(src) <= 0 ? 0 : src), length)\n // lower = math.sum(volume * (ta.change(src) >= 0 ? 0 : src), length)\n // A comparison with na is false, so a bar with an na change (bar 0) adds its money flow to both sums.\n // The comparisons use the 1e-10 tolerance of Pine operators.\n const upperFlow: number[] = [];\n const lowerFlow: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const change = i === 0 ? NaN : source[i]! - source[i - 1]!;\n const flow = volume[i]! * source[i]!;\n upperFlow.push(le(change, 0) ? 0 : flow);\n lowerFlow.push(ge(change, 0) ? 0 : flow);\n }\n // math.sum: the compensated running sum of the last `length` non-na values (as PineScript, bit for bit)\n const upper = runningSum(upperFlow, length);\n const lower = runningSum(lowerFlow, length);\n\n // A sum within 1e-10 of 0 (the residue of a running sum over a window of zeros) is 0\n const zero = (x: number) => (Math.abs(x) <= 1e-10 ? 0 : x);\n return upper.map((sumUp, i) => {\n const u = zero(sumUp);\n const l = zero(lower[i]!);\n if (Number.isNaN(u) || Number.isNaN(l)) return NaN;\n if (l === 0) return 100;\n const ratio = 1 + u / l;\n // x / 0 is na in PineScript\n return ratio === 0 ? NaN : 100 - 100 / ratio;\n });\n}\n\n/**\n * Hull Moving Average (HMA) - improved moving average with reduced lag.\n *\n * @param source - Series of values to process\n * @param length - Number of bars (length)\n * @returns Hull moving average series\n *\n * @remarks\n * - Formula: WMA(2 * WMA(src, len/2) - WMA(src, len), sqrt(len))\n * - Significantly reduces lag compared to traditional moving averages\n * - Smoother than WMA while being more responsive\n * - Created by Alan Hull\n * - `na` values in the source series are ignored\n *\n * @example\n * ```typescript\n * const hma20 = ta.hma(closePrices, 20);\n * // Faster response to price changes than SMA or EMA\n * ```\n */\nexport function hma(source: Source, length: simple_int): series_float {\n checkPositiveLength('hma', length, 0);\n const halfLength = Math.floor(length / 2);\n const sqrtLength = Math.floor(Math.sqrt(length));\n\n const wmaHalf = wma(source, halfLength);\n const wmaFull = wma(source, length);\n\n const diff: series_float = [];\n for (let i = 0; i < source.length; i++) {\n diff.push(2 * wmaHalf[i]! - wmaFull[i]!);\n }\n\n return wma(diff, sqrtLength);\n}\n\n/**\n * Parabolic SAR (Stop and Reverse) - trend-following indicator.\n *\n * @param start - Acceleration factor start value (typically 0.02)\n * @param inc - Acceleration factor increment (typically 0.02)\n * @param max - Maximum acceleration factor (typically 0.2)\n * @param high - High price series (required when not using context API)\n * @param low - Low price series (required when not using context API)\n * @param close - Close price series (required when not using context API)\n * @returns SAR series\n *\n * @remarks\n * - **PineScript v6 signature**: `ta.sar(start, inc, max)` - uses implicit chart data\n * - **JavaScript signature**: Requires explicit `high`, `low`, `close` OR use `createContext()`\n * - SAR below price indicates uptrend, above price indicates downtrend\n * - Created by J. Welles Wilder Jr.\n *\n * @example\n * ```typescript\n * const sar = ta.sar(0.02, 0.02, 0.2, high, low, close);\n * ```\n */\nexport function sar(\n start: simple_float,\n inc: simple_float,\n max: simple_float,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n if (!high || !low || !close) {\n throw new Error(\n 'ta.sar() requires high, low, and close series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const result: series_float = [];\n let sarValue = NaN;\n let extremePoint = NaN;\n let acceleration = start;\n let isUpTrend = false;\n let isFirstTrendBar = false;\n\n for (let i = 0; i < close.length; i++) {\n if (i === 0) {\n result.push(NaN);\n continue;\n }\n\n if (i === 1) {\n if (close[i]! > close[i - 1]!) {\n isUpTrend = true;\n extremePoint = high[i]!;\n sarValue = low[i - 1]!;\n } else {\n isUpTrend = false;\n extremePoint = low[i]!;\n sarValue = high[i - 1]!;\n }\n isFirstTrendBar = true;\n acceleration = start;\n }\n\n sarValue = sarValue + acceleration * (extremePoint - sarValue);\n\n if (isUpTrend) {\n if (sarValue > low[i]!) {\n isFirstTrendBar = true;\n isUpTrend = false;\n sarValue = Math.max(high[i]!, extremePoint);\n extremePoint = low[i]!;\n acceleration = start;\n }\n } else {\n if (sarValue < high[i]!) {\n isFirstTrendBar = true;\n isUpTrend = true;\n sarValue = Math.min(low[i]!, extremePoint);\n extremePoint = high[i]!;\n acceleration = start;\n }\n }\n\n if (!isFirstTrendBar) {\n if (isUpTrend) {\n if (high[i]! > extremePoint) {\n extremePoint = high[i]!;\n acceleration = Math.min(acceleration + inc, max);\n }\n } else {\n if (low[i]! < extremePoint) {\n extremePoint = low[i]!;\n acceleration = Math.min(acceleration + inc, max);\n }\n }\n }\n\n if (isUpTrend) {\n sarValue = Math.min(sarValue, low[i - 1]!);\n if (i > 1) {\n sarValue = Math.min(sarValue, low[i - 2]!);\n }\n } else {\n sarValue = Math.max(sarValue, high[i - 1]!);\n if (i > 1) {\n sarValue = Math.max(sarValue, high[i - 2]!);\n }\n }\n\n result.push(sarValue);\n isFirstTrendBar = false;\n }\n\n return result;\n}\n\n/** A pivot length: one value, or a value per bar (PineScript series length). */\ntype PivotLength = simple_int | ArrayLike<number>;\n\n/**\n * Pivot detection as PineScript computes it.\n *\n * The function keeps the non-na values it receives. On each bar it takes the last `leftbars + rightbars + 1` of them\n * (all of them when there are fewer) and finds the highest (the newest one on equal values; the lowest for a pivot\n * low): there is a pivot when that value is on the bar `rightbars` bars back, and its value is returned on this bar,\n * so no future bar is used. A pivot high may so equal values on its left but must be higher than every value on its\n * right. `na` before bar `leftbars + rightbars`.\n */\nfunction pivot(source: Source, leftbars: PivotLength, rightbars: PivotLength, isHigh: boolean): series_float {\n const { values, bars, last } = keptValues(source);\n return Array.from(source, (_, i) => {\n // a series length: the lengths of the current bar\n const left = Math.trunc(typeof leftbars === 'number' ? leftbars : leftbars[i]!);\n const right = Math.trunc(typeof rightbars === 'number' ? rightbars : rightbars[i]!);\n const k = last[i]!;\n if (!(i >= left + right) || k < 0) return NaN;\n let best = k;\n for (let j = k - 1; j >= 0 && j >= k - left - right; j--) {\n if (isHigh ? values[j]! > values[best]! : values[j]! < values[best]!) best = j;\n }\n return bars[best] === i - right ? values[best]! : NaN;\n });\n}\n\n/**\n * Pivot High - detects pivot high points in the price series.\n *\n * @param sourceOrLeftbars - Source series or leftbars (overloaded)\n * @param leftbarsOrRightbars - Leftbars or rightbars (overloaded)\n * @param rightbars - Number of bars to the right (optional)\n * @param high - High price series (used in 2-param version)\n * @returns Series with the pivot high value on the bar where the pivot is confirmed\n * (`rightbars` bars after the pivot bar), NaN elsewhere\n *\n * @remarks\n * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar\n * index is `i - rightbars`\n * - A pivot high may equal values on its left but must be higher than all values on its right\n * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,\n * and the highest of them must be on the bar `rightbars` bars back\n * - `leftbars` / `rightbars` can be arrays (a length per bar, PineScript series length), also for `ta.pivotlow`:\n * each bar uses its own lengths\n *\n * @example\n * ```typescript\n * const pivotHighs = ta.pivothigh(high, 2, 2);\n * // pivotHighs[i] is high[i - 2] when bar i - 2 is a pivot high\n * ```\n */\nexport function pivothigh(\n sourceOrLeftbars: Source | simple_int,\n leftbarsOrRightbars: PivotLength,\n rightbars?: PivotLength,\n high?: Source\n): series_float {\n if (rightbars === undefined) {\n if (!high) {\n throw new Error('ta.pivothigh() requires high series when using two-parameter version.');\n }\n return pivot(high, sourceOrLeftbars as simple_int, leftbarsOrRightbars, true);\n }\n return pivot(sourceOrLeftbars as Source, leftbarsOrRightbars, rightbars, true);\n}\n\n/**\n * Pivot Low - detects pivot low points in the price series.\n *\n * @param sourceOrLeftbars - Source series or leftbars (overloaded)\n * @param leftbarsOrRightbars - Leftbars or rightbars (overloaded)\n * @param rightbars - Number of bars to the right (optional)\n * @param low - Low price series (used in 2-param version)\n * @returns Series with the pivot low value on the bar where the pivot is confirmed\n * (`rightbars` bars after the pivot bar), NaN elsewhere\n *\n * @remarks\n * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar\n * index is `i - rightbars`\n * - A pivot low may equal values on its left but must be lower than all values on its right\n * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,\n * and the lowest of them must be on the bar `rightbars` bars back\n *\n * @example\n * ```typescript\n * const pivotLows = ta.pivotlow(low, 2, 2);\n * // pivotLows[i] is low[i - 2] when bar i - 2 is a pivot low\n * ```\n */\nexport function pivotlow(\n sourceOrLeftbars: Source | simple_int,\n leftbarsOrRightbars: PivotLength,\n rightbars?: PivotLength,\n low?: Source\n): series_float {\n if (rightbars === undefined) {\n if (!low) {\n throw new Error('ta.pivotlow() requires low series when using two-parameter version.');\n }\n return pivot(low, sourceOrLeftbars as simple_int, leftbarsOrRightbars, false);\n }\n return pivot(sourceOrLeftbars as Source, leftbarsOrRightbars, rightbars, false);\n}\n\n/**\n * Bars Since - returns number of bars since condition was true.\n *\n * @param condition - Boolean series condition\n * @returns Series with number of bars since condition was last true\n *\n * @remarks\n * - Returns 0 when condition is currently true\n * - Increments by 1 for each bar condition remains false\n * - Returns NaN if condition has never been true\n *\n * @example\n * ```typescript\n * const crossovers = ta.crossover(fastMA, slowMA);\n * const barsSinceCross = ta.barssince(crossovers);\n * ```\n */\nexport function barssince(condition: series_bool): series_float {\n const result: series_float = [];\n let barsSinceTrue = NaN;\n\n for (let i = 0; i < condition.length; i++) {\n if (condition[i]!) {\n barsSinceTrue = 0;\n } else if (!isNaN(barsSinceTrue)) {\n barsSinceTrue++;\n }\n result.push(barsSinceTrue);\n }\n\n return result;\n}\n\n/**\n * Value When - returns the value when condition was true.\n *\n * @param condition - Boolean series condition\n * @param source - Source series to get value from\n * @param occurrence - Which occurrence to get (0 = most recent)\n * @returns Series with values from when condition was true\n *\n * @remarks\n * - occurrence=0 returns value from most recent true condition\n * - occurrence=1 returns value from second most recent, etc.\n * - Returns NaN if condition hasn't been true occurrence+1 times yet\n *\n * @example\n * ```typescript\n * const crossovers = ta.crossover(fastMA, slowMA);\n * const lastCrossPrice = ta.valuewhen(crossovers, close, 0);\n * ```\n */\nexport function valuewhen(condition: series_bool, source: Source, occurrence: simple_int): series_float {\n const result: series_float = [];\n\n for (let i = 0; i < condition.length; i++) {\n let occurrenceCount = 0;\n let foundValue = NaN;\n\n for (let j = i; j >= 0; j--) {\n if (condition[j]) {\n if (occurrenceCount === occurrence) {\n foundValue = source[j]!;\n break;\n }\n occurrenceCount++;\n }\n }\n\n result.push(foundValue);\n }\n\n return result;\n}\n\n/**\n * Directional Movement Index - returns Directional Movement indicators.\n *\n * @param diLength - DI averaging length\n * @param adxSmoothing - ADX smoothing length\n * @returns Tuple of [plusDI, minusDI, ADX]\n *\n * @remarks\n * - +DI and -DI measure directional movement\n * - ADX measures trend strength (0-100)\n * - ADX above 25 typically indicates strong trend\n * - Requires high, low, and close data from context\n *\n * @example\n * ```typescript\n * const [plusDI, minusDI, adx] = ta.dmi(14, 14);\n * // When +DI > -DI and ADX > 25, strong uptrend\n * // When -DI > +DI and ADX > 25, strong downtrend\n * ```\n */\nexport function dmi(\n diLength: simple_int,\n adxSmoothing: simple_int,\n high: Source,\n low: Source,\n close: Source\n): [series_float, series_float, series_float] {\n // PineScript reference (built-in DMI):\n // up = ta.change(high), down = -ta.change(low)\n // plusDM = na(up) ? na : (up > down and up > 0 ? up : 0), minusDM likewise\n // trur = ta.rma(ta.tr, len)\n // plus = fixnan(100 * ta.rma(plusDM, len) / trur), minus likewise\n // adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), lensig)\n const len = Math.max(high.length, low.length, close.length);\n const plusDM: series_float = [];\n const minusDM: series_float = [];\n for (let i = 0; i < len; i++) {\n const up = i === 0 ? NaN : high[i]! - high[i - 1]!;\n const down = i === 0 ? NaN : low[i - 1]! - low[i]!;\n plusDM.push(Number.isNaN(up) ? NaN : gt(up, down) && gt(up, 0) ? up : 0);\n minusDM.push(Number.isNaN(down) ? NaN : gt(down, up) && gt(down, 0) ? down : 0);\n }\n\n const trur = rma(tr(false, high, low, close), diLength);\n const smoothedPlus = rma(plusDM, diLength);\n const smoothedMinus = rma(minusDM, diLength);\n // x / 0 is na; fixnan keeps the previous value\n const directional = (smoothed: series_float): series_float => {\n let last = NaN;\n return smoothed.map((v, i) => {\n const t = trur[i]!;\n const value = t === 0 ? NaN : (100 * v) / t;\n if (!Number.isNaN(value)) last = value;\n return last;\n });\n };\n const plusDI = directional(smoothedPlus);\n const minusDI = directional(smoothedMinus);\n\n const dx = plusDI.map((plus, i) => {\n const minus = minusDI[i]!;\n const sum = plus + minus;\n return Math.abs(plus - minus) / (eq(sum, 0) ? 1 : sum);\n });\n const adx = rma(dx, adxSmoothing).map((v) => 100 * v);\n\n return [plusDI, minusDI, adx];\n}\n\n/**\n * True Strength Index - momentum oscillator based on double smoothed momentum.\n *\n * @param source - Series of values to process\n * @param shortLength - Short smoothing length\n * @param longLength - Long smoothing length\n * @returns TSI series, a value in [-1, 1]\n *\n * @remarks\n * - As PineScript: `ta.ema(ta.ema(m, longLength), shortLength) / ta.ema(ta.ema(math.abs(m), longLength), shortLength)`\n * with `m = source - source[1]` (not scaled by 100)\n * - na when the denominator is 0 (a constant source), as a PineScript division by zero\n * - Positive values indicate bullish momentum\n * - Negative values indicate bearish momentum\n * - Crossovers of zero line can signal trend changes\n * - Less sensitive to short-term price fluctuations than RSI\n *\n * @example\n * ```typescript\n * const tsi = ta.tsi(close, 13, 25);\n * // TSI > 0: bullish momentum\n * // TSI < 0: bearish momentum\n * ```\n */\nexport function tsi(source: Source, shortLength: simple_int, longLength: simple_int): series_float {\n checkPositiveLength('tsi->ema', shortLength, 0);\n const momentum: series_float = [];\n\n // Calculate momentum (price change)\n for (let i = 0; i < source.length; i++) {\n if (i === 0) {\n momentum.push(NaN);\n } else {\n momentum.push(source[i]! - source[i - 1]!);\n }\n }\n\n // Double smooth momentum\n const smoothedMomentum = ema(ema(momentum, longLength), shortLength);\n\n // Double smooth absolute momentum\n const absMomentum = momentum.map(Math.abs);\n const smoothedAbsMomentum = ema(ema(absMomentum, longLength), shortLength);\n\n // PineScript: a value in [-1, 1]; a division by zero is na\n return smoothedMomentum.map((m, i) => {\n const d = smoothedAbsMomentum[i]!;\n return d === 0 ? NaN : m / d;\n });\n}\n\n/**\n * Chande Momentum Oscillator - momentum indicator similar to RSI.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @returns CMO series\n *\n * @remarks\n * - CMO oscillates between +100 and -100\n * - CMO > +50: overbought conditions\n * - CMO < -50: oversold conditions\n * - Unlike RSI, CMO uses sum of gains/losses instead of averages\n * - As in PineScript: the sums are the running sums of `math.sum` (bit for bit), and a flat window (every change 0)\n * is `0 / 0` = na\n * - More volatile than RSI\n *\n * @example\n * ```typescript\n * const cmo = ta.cmo(close, 14);\n * // CMO > 50: overbought\n * // CMO < -50: oversold\n * ```\n */\nexport function cmo(source: Source, length: simple_int): series_float {\n checkPositiveLength('cmo', length, 0);\n // PineScript definition: mom = ta.change(src), sm1 = math.sum(mom >= 0 ? mom : 0, length),\n // sm2 = math.sum(mom >= 0 ? 0 : -mom, length), cmo = 100 * (sm1 - sm2) / (sm1 + sm2), with the running sums of\n // math.sum (bit for bit). A comparison with na is false: an na change adds 0 to sm1 and na (skipped) to sm2.\n const up: number[] = [];\n const down: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const mom = i > 0 ? source[i]! - source[i - 1]! : NaN;\n up.push(mom >= 0 ? mom : 0);\n down.push(mom >= 0 ? 0 : -mom);\n }\n const sm1 = runningSum(up, length);\n const sm2 = runningSum(down, length);\n // a flat window is 0 / 0 = na\n return sm1.map((s1, i) => (100 * (s1 - sm2[i]!)) / (s1 + sm2[i]!));\n}\n\n/**\n * Keltner Channels - volatility-based envelope indicator.\n *\n * @param source - Series of values to process\n * @param length - Number of bars for EMA\n * @param mult - Multiplier for the range\n * @param useTrueRange - Use True Range (default: true) or high-low\n * @returns Tuple of [middle, upper, lower]\n *\n * @remarks\n * - Middle band is EMA of source\n * - Upper/lower bands are middle \u00B1 (range EMA \u00D7 multiplier)\n * - When useTrueRange=true, uses ATR for volatility\n * - When useTrueRange=false, uses high-low range\n * - Price breaking out of bands may signal trend continuation\n * - Requires high, low, close data from context when useTrueRange=true\n *\n * @example\n * ```typescript\n * const [middle, upper, lower] = ta.kc(close, 20, 2, true);\n * // Price above upper: potential uptrend\n * // Price below lower: potential downtrend\n * ```\n */\nexport function kc(\n source: Source,\n length: simple_int,\n mult: simple_float,\n useTrueRange: simple_bool = true,\n high?: Source,\n low?: Source,\n close?: Source\n): [series_float, series_float, series_float] {\n checkPositiveLength('kc', length, 0);\n // Calculate middle band (EMA of source)\n const middle = ema(source, length);\n\n // Calculate range\n let range: series_float;\n if (useTrueRange) {\n if (!high || !low || !close) {\n throw new Error('ta.kc() with useTrueRange=true requires high, low, and close data');\n }\n // PineScript reference: ta.tr, which is na on bar 0\n range = tr(false, high, low, close);\n } else {\n if (!high || !low) {\n throw new Error('ta.kc() requires high and low data');\n }\n range = [];\n for (let i = 0; i < high.length; i++) {\n range.push(high[i]! - low[i]!);\n }\n }\n\n // Smooth the range with EMA\n const rangeEma = ema(range, length);\n\n // Calculate upper and lower bands\n const upper: series_float = [];\n const lower: series_float = [];\n\n for (let i = 0; i < middle.length; i++) {\n upper.push(middle[i]! + rangeEma[i]! * mult);\n lower.push(middle[i]! - rangeEma[i]! * mult);\n }\n\n return [middle, upper, lower];\n}\n\n/**\n * Bollinger Bands Width - measures the width of Bollinger Bands.\n *\n * @param source - Series of values to process\n * @param length - Number of bars\n * @param mult - Standard deviation multiplier\n * @returns BBW series (percentage)\n *\n * @remarks\n * - BBW = ((upper band - lower band) / middle band) \u00D7 100\n * - Low BBW values indicate low volatility (potential breakout setup)\n * - High BBW values indicate high volatility\n * - BBW squeeze (narrowing bands) often precedes strong moves\n * - Works with existing bb() function\n *\n * @example\n * ```typescript\n * const bbw = ta.bbw(close, 20, 2);\n * // Low BBW: potential breakout coming\n * // High BBW: high volatility period\n * ```\n */\nexport function bbw(source: Source, length: simple_int, mult: simple_float): series_float {\n checkPositiveLength('bbw', length, 0);\n const [basis, upper, lower] = bb(source, length, mult);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (basis[i]! === 0) {\n result.push(NaN);\n } else {\n const width = ((upper[i]! - lower[i]!) / basis[i]!) * 100;\n result.push(width);\n }\n }\n\n return result;\n}\n\n/**\n * Williams %R (Williams Percent Range)\n *\n * Williams %R is a momentum indicator that measures overbought/oversold levels.\n * It compares the closing price to the high-low range over a specified period.\n *\n * Values range from -100 (oversold) to 0 (overbought):\n * - Above -20: Overbought\n * - Below -80: Oversold\n *\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @param length - Lookback period (default: 14)\n * @returns Williams %R series\n *\n * @remarks\n * PineScript rule (bit for bit): `100 * (close - max) / (max - min)` with `max = ta.highest(high, length)` and\n * `min = ta.lowest(low, length)` (their `na` rules); `na` when the range is 0.\n *\n * @example\n * ```typescript\n * const wpr = ta.wpr(high, low, close, 14);\n * // wpr < -80: oversold\n * // wpr > -20: overbought\n * ```\n */\nexport function wpr(high: Source, low: Source, close: Source, length: simple_int = 14): series_float {\n checkPositiveLength('wpr', length, 0);\n const highs = highest(high, length);\n const lows = lowest(low, length);\n return Array.from({ length: close.length }, (_, i) => {\n const hmax = highs[i]!;\n const range = hmax - lows[i]!;\n // PineScript, in this order (bit for bit): 100 * (close - max) / (max - min); x / 0 is na\n return range === 0 ? NaN : (100 * (close[i]! - hmax)) / range;\n });\n}\n\n/**\n * Volume Weighted Average Price, restarted on each bar where `anchor` is true.\n *\n * @param source - Source series (PineScript default `hlc3`)\n * @param volume - Volume series\n * @param anchor - Reset condition per bar (PineScript `anchor`). Without it the sums never restart;\n * PineScript's default anchor is a new day (`timeframe.change(\"1D\")`), which needs the exchange session\n * @param stdev_mult - When given, also returns the bands `vwap \u00B1 stdev_mult \u00D7 stdev`\n * @returns The VWAP series, or `[vwap, upper, lower]` when `stdev_mult` is given\n *\n * @remarks\n * As in PineScript: the sums restart on anchor bars; the standard deviation is\n * `sqrt(\u03A3(volume \u00D7 source\u00B2) / \u03A3volume \u2212 vwap\u00B2)`.\n * - With an anchor series: `na` before the first anchor bar\n * - A bar with an `na` source (or volume) makes the sums `na` until the next anchor bar (`na` values are not\n * skipped)\n */\nexport function vwap(source: Source, volume: Source, anchor?: ArrayLike<boolean | number>): series_float;\nexport function vwap(\n source: Source,\n volume: Source,\n anchor: ArrayLike<boolean | number> | undefined,\n stdev_mult: simple_float\n): [series_float, series_float, series_float];\nexport function vwap(\n source: Source,\n volume: Source,\n anchor?: ArrayLike<boolean | number>,\n stdev_mult?: simple_float\n): series_float | [series_float, series_float, series_float] {\n if (source.length !== volume.length) {\n throw new Error('ta.vwap: source and volume must have the same length');\n }\n const mid: series_float = [];\n const upper: series_float = [];\n const lower: series_float = [];\n // na until the first anchor (without an anchor series, bar 0 starts the sums)\n let sumPV = NaN;\n let sumV = NaN;\n let sumPPV = NaN;\n for (let i = 0; i < source.length; i++) {\n const s = source[i]!;\n const v = volume[i]!;\n if (anchor ? anchor[i] : i === 0) {\n sumPV = s * v;\n sumV = v;\n sumPPV = s * s * v;\n } else {\n // An na source or volume makes the sums na until the next anchor\n sumPV += s * v;\n sumV += v;\n sumPPV += s * s * v;\n }\n const m = sumV === 0 ? NaN : sumPV / sumV;\n mid.push(m);\n if (stdev_mult !== undefined) {\n const sd = Math.sqrt(Math.max(0, sumPPV / sumV - m * m));\n upper.push(m + stdev_mult * sd);\n lower.push(m - stdev_mult * sd);\n }\n }\n return stdev_mult === undefined ? mid : [mid, upper, lower];\n}\n\n/**\n * Arnaud Legoux Moving Average (ALMA)\n *\n * ALMA uses a Gaussian distribution for weighting, reducing lag while maintaining smoothness.\n * It's particularly good at tracking price action with minimal lag.\n *\n * @param source - Source series\n * @param length - Window size (default: 9)\n * @param offset - Controls the center of the Gaussian curve. 0.85 = focus on recent prices (default: 0.85)\n * @param sigma - Standard deviation of the Gaussian. Controls smoothness (default: 6)\n * @returns ALMA series\n *\n * @example\n * ```typescript\n * const alma = ta.alma(close, 9, 0.85, 6);\n * // offset closer to 1: more responsive\n * // offset closer to 0: smoother\n * ```\n */\nexport function alma(\n source: Source,\n length: simple_int = 9,\n offset: simple_float = 0.85,\n sigma: simple_float = 6,\n floor: boolean = false\n): series_float {\n checkPositiveLength('alma', length, 0);\n const result: series_float = [];\n const m = floor ? Math.floor(offset * (length - 1)) : offset * (length - 1);\n const s = length / sigma;\n\n // Pre-calculate weights\n const weights: number[] = [];\n let weightSum = 0;\n\n for (let i = 0; i < length; i++) {\n const weight = Math.exp(-1 * Math.pow(i - m, 2) / (2 * Math.pow(s, 2)));\n weights.push(weight);\n weightSum += weight;\n }\n\n // Normalize weights\n for (let i = 0; i < length; i++) {\n weights[i]! /= weightSum;\n }\n\n // Calculate ALMA\n for (let i = 0; i < source.length; i++) {\n if (i < length - 1) {\n result.push(NaN);\n continue;\n }\n\n let almaValue = 0;\n for (let j = 0; j < length; j++) {\n almaValue += source[i - length + 1 + j]! * weights[j]!;\n }\n\n result.push(almaValue);\n }\n\n return result;\n}\n\n/**\n * Keltner Channels Width (KCW)\n *\n * Measures the width of Keltner Channels relative to the middle line: `(upper - lower) / middle`, a ratio as in\n * PineScript (0.05 is a width of 5% of the middle line; not multiplied by 100).\n * Similar to BBW but uses ATR instead of standard deviation.\n *\n * Low KCW suggests consolidation/low volatility.\n * High KCW suggests expansion/high volatility.\n *\n * @param source - Source series\n * @param length - Number of bars for EMA and ATR (default: 20)\n * @param mult - ATR multiplier (default: 2)\n * @param useTrueRange - Use True Range instead of high-low (default: true)\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @returns KCW series\n *\n * @example\n * ```typescript\n * const kcw = ta.kcw(close, 20, 2, true, high, low, close);\n * // Low KCW: potential breakout coming\n * // High KCW: high volatility period\n * ```\n */\nexport function kcw(\n source: Source,\n length: simple_int = 20,\n mult: simple_float = 2,\n useTrueRange: simple_bool = true,\n high?: Source,\n low?: Source,\n close?: Source\n): series_float {\n const [basis, upper, lower] = kc(source, length, mult, useTrueRange, high, low, close);\n const result: series_float = [];\n\n for (let i = 0; i < source.length; i++) {\n if (isNaN(basis[i]!) || basis[i]! === 0) {\n result.push(NaN);\n } else {\n // PineScript: (upper - lower) / basis, a ratio (not a percentage)\n result.push((upper[i]! - lower[i]!) / basis[i]!);\n }\n }\n\n return result;\n}\n\n/**\n * Difference between the highest and the lowest value over the last `length` non-na values\n * (PineScript `ta.range(source, length)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped (the window holds the last `length` non-na\n * values), and a bar whose own value is `na` still gets a result.\n */\nexport function range(source: Source, length: simple_int): series_float {\n checkPositiveLength('range', length, 0);\n return source.map((_, i) => {\n const values = lastValues(source, i, length);\n return values ? Math.max(...values) - Math.min(...values) : NaN;\n });\n}\n\n/**\n * Offset to the bar with the highest value over the last `length` bars: 0 for the current bar,\n * -1 for the previous bar, and so on (as in PineScript, the offset is negative).\n *\n * @remarks\n * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal\n * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were\n * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.\n */\nexport function highestbars(source: Source, length: simple_int | ArrayLike<number>): series_int {\n return extremeOffset(source, length, false);\n}\n\n/**\n * Offset to the bar with the lowest value over the last `length` bars: 0 for the current bar,\n * -1 for the previous bar, and so on (as in PineScript, the offset is negative).\n *\n * @remarks\n * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal\n * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were\n * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.\n */\nexport function lowestbars(source: Source, length: simple_int | ArrayLike<number>): series_int {\n return extremeOffset(source, length, true);\n}\n\n/**\n * All-time highest value of `source` up to each bar (PineScript `ta.max(source)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the\n * result is `na` until the first non-na value.\n */\nexport function max(source: Source): series_float {\n let best = NaN;\n return source.map((x) => {\n if (Number.isFinite(x) && !(x <= best)) best = x;\n return best;\n });\n}\n\n/**\n * All-time lowest value of `source` up to each bar (PineScript `ta.min(source)`).\n *\n * @remarks\n * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the\n * result is `na` until the first non-na value.\n */\nexport function min(source: Source): series_float {\n let best = NaN;\n return source.map((x) => {\n if (Number.isFinite(x) && !(x >= best)) best = x;\n return best;\n });\n}\n\n/**\n * Center of Gravity (COG)\n *\n * The Center of Gravity indicator is an oscillator developed by John Ehlers.\n * It identifies turning points with minimal lag and provides clear signals.\n *\n * @param source - Source series (typically close)\n * @param length - Lookback period (default: 10)\n * @returns COG series\n *\n * @remarks\n * PineScript rule (bit for bit): `-num / math.sum(source, length)`, with `num` the sum of `source[i] * (i + 1)`\n * for `i = 0 .. length - 1`, added newest first.\n * - The denominator is the compensated running sum of `math.sum` (the last `length` non-`na` values)\n * - The numerator reads the last `length` bars, so an `na` among them gives `na`\n * - A zero denominator gives `na` (PineScript division by zero)\n *\n * @example\n * ```typescript\n * const cogValue = ta.cog(close, 10);\n * ```\n */\nexport function cog(source: Source, length: simple_int = 10): series_float {\n checkPositiveLength('cog', length, 0);\n const len = Math.floor(length);\n return runningSum(source, len).map((sum, i) => {\n if (i < len - 1 || Number.isNaN(sum) || sum === 0) return NaN;\n let num = 0;\n for (let k = 0; k < len; k++) num += source[i - k]! * (k + 1);\n return -num / sum;\n });\n}\n\n/**\n * Mode (Most Frequent Value)\n *\n * Returns the mode of the series - the most frequently occurring value.\n * If there are several values with the same frequency, it returns the smallest value.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @returns The most frequently occurring value\n *\n * @example\n * ```typescript\n * const values = [1, 2, 2, 3, 3, 3, 4, 4];\n * const modeValue = ta.mode(values, 8); // Returns 3 (most frequent)\n * ```\n *\n * @remarks\n * PineScript rules:\n * - the window is the last `length` non-`na` values (an `na` or +/-Infinity bar does not enter it, and gets the mode\n * of the window it keeps)\n * - NaN until `length` non-`na` values exist\n * - If no mode exists, returns the smallest value\n */\nexport function mode(source: Source, length: simple_int): series_float {\n checkPositiveLength('mode', length, 0);\n const result: series_float = [];\n const len = Math.floor(length);\n const seen: number[] = []; // non-na values so far\n\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n if (Number.isFinite(v)) seen.push(v);\n if (seen.length < len) {\n result.push(NaN);\n continue;\n }\n const values = seen.slice(seen.length - len);\n\n // Count frequency of each value\n const frequencyMap = new Map<number, number>();\n for (const value of values) {\n frequencyMap.set(value, (frequencyMap.get(value) || 0) + 1);\n }\n\n // Find the maximum frequency\n let maxFrequency = 0;\n frequencyMap.forEach((freq) => {\n if (freq > maxFrequency) {\n maxFrequency = freq;\n }\n });\n\n // Find all values with max frequency, then return the smallest\n const modesWithMaxFreq: number[] = [];\n frequencyMap.forEach((freq, value) => {\n if (freq === maxFrequency) {\n modesWithMaxFreq.push(value);\n }\n });\n\n result.push(Math.min(...modesWithMaxFreq));\n }\n\n return result;\n}\n\n/**\n * Percentile (Linear Interpolation Method)\n *\n * Calculates the percentile using the method of linear interpolation between\n * the two nearest ranks. This method may return values that are not members\n * of the input data set.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @param percentage - Percentile to calculate (0-100)\n * @returns The calculated percentile value\n *\n * @example\n * ```typescript\n * const p50 = ta.percentile_linear_interpolation(close, 20, 50); // Median\n * const p75 = ta.percentile_linear_interpolation(close, 20, 75); // 75th percentile\n * ```\n *\n * @remarks\n * - The result will NOT always be a member of the input data set\n * - Uses linear interpolation between adjacent values when needed\n * - Returns NaN for the first (length - 1) values where there's insufficient data\n *\n * PineScript rules:\n * - position in the sorted window: `percentage / 100 * length - 0.5`, clamped to the first / last value, linear\n * interpolation between the two neighbours (na when a neighbour is na, also at an exact position)\n * - `na` values stay in the window (window size = `length`). The window is kept sorted from bar to bar: the new\n * value is inserted before the first value `>=` it, passing the `na` values (an `na` goes last), then the value\n * leaving the window is removed. So the place of an `na` depends on the history: at the start of a series the\n * `na` values are before all numbers\n */\nexport function percentile_linear_interpolation(\n source: Source,\n length: simple_int,\n percentage: number\n): series_float {\n checkPositiveLength('percentile_linear_interpolation', length, 0);\n return sortedWindow(source, length, (s) => {\n const pos = (percentage / 100) * length - 0.5;\n if (pos <= 0) return s[0]!;\n if (pos >= length - 1) return s[length - 1]!;\n const lo = Math.floor(pos);\n return s[lo]! + (pos - lo) * (s[lo + 1]! - s[lo]!);\n });\n}\n\n/**\n * Sorted window of ta.percentile_*, as PineScript keeps it: each bar first inserts the new value before the first\n * value `>=` it (scanning from the start; an `na` is never `>=`, so a value passes the `na` values and an `na` goes\n * last), then removes the value of the bar leaving the window. `fn` reads the sorted window (`length` values).\n * na for the first `length - 1` bars.\n *\n * @internal\n */\nfunction sortedWindow(source: Source, length: simple_int, fn: (sorted: number[]) => number): series_float {\n const result: series_float = [];\n const values: number[] = []; // sorted window\n const bars: number[] = []; // bar index of each value\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n let k = 0;\n while (k < values.length && !(values[k]! >= v)) k++;\n values.splice(k, 0, v);\n bars.splice(k, 0, i);\n if (i >= length) {\n const old = bars.indexOf(i - length);\n values.splice(old, 1);\n bars.splice(old, 1);\n }\n result.push(i < length - 1 ? NaN : fn(values));\n }\n return result;\n}\n\n/**\n * Percentile (Nearest Rank Method)\n *\n * Calculates the percentile using the Nearest Rank method. This method\n * always returns a value that is a member of the input data set.\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @param percentage - Percentile to calculate (0-100)\n * @returns The calculated percentile value\n *\n * @example\n * ```typescript\n * const p50 = ta.percentile_nearest_rank(close, 20, 50); // Median\n * const p90 = ta.percentile_nearest_rank(close, 20, 90); // 90th percentile\n * ```\n *\n * @remarks\n * - The result will ALWAYS be a member of the input data set\n * - The 100th percentile is defined as the largest value\n * - Using this method on lengths < 100 may result in the same value for multiple percentiles\n * - Returns NaN for the first (length - 1) values where there's insufficient data\n *\n * PineScript rules:\n * - the value at rank `ceil(percentage / 100 * length)` of the sorted window (na when that rank holds an `na`)\n * - `na` values stay in the window, sorted from bar to bar as in `ta.percentile_linear_interpolation`\n */\nexport function percentile_nearest_rank(\n source: Source,\n length: simple_int,\n percentage: number\n): series_float {\n checkPositiveLength('percentile_nearest_rank', length, 0);\n const rank = Math.min(length, Math.max(1, Math.ceil((percentage / 100) * length)));\n return sortedWindow(source, length, (s) => s[rank - 1]!);\n}\n\n/**\n * Rank Correlation Index (RCI)\n *\n * Calculates the Rank Correlation Index using Spearman's rank correlation coefficient.\n * RCI measures the directional consistency of price movements, indicating whether\n * the source consistently increased (positive values) or decreased (negative values).\n *\n * @param source - Series of values to process\n * @param length - Number of bars to look back\n * @returns RCI value scaled to range -100 to 100\n *\n * @example\n * ```typescript\n * const rci9 = ta.rci(close, 9);\n * // RCI near +100: strong upward consistency\n * // RCI near -100: strong downward consistency\n * // RCI near 0: no clear trend\n * ```\n *\n * @remarks\n * - Result is scaled to -100 to 100 range\n * - +100 indicates source consistently increased over the period\n * - -100 indicates source consistently decreased over the period\n * - 0 indicates no directional consistency\n * - As PineScript (bit for bit): the first value is on bar `length`; values less than 1e-10 above the smallest value\n * of a group (ascending sweep) are ties with their average rank; a window where all values are ties gives `na`;\n * moment-form variances of the bar positions and the ranks, `(100 * cov) / (sd_x * sd_y)`\n * - A bar with an `na` source keeps the previous result; the values are kept in a ring of `length + 1` slots by bar\n * index (0 at the start, not written on `na` bars), so a later window sees the value of `length + 1` bars earlier\n * where the `na` was\n */\nexport function rci(source: Source, length: simple_int): series_float {\n checkPositiveLength('rci', length, 0);\n const len = Math.floor(length);\n const result: series_float = [];\n // PineScript keeps the values in a ring of `length + 1` slots indexed by the bar index, filled with 0 at the start\n // and written only on bars with a value: a bar with an na source keeps the previous result, and later windows see\n // the value of `length + 1` bars earlier in that slot\n const ring = new Array<number>(len + 1).fill(0);\n for (let i = 0; i < source.length; i++) {\n const v = source[i]!;\n if (Number.isNaN(v)) {\n result.push(i > 0 ? result[i - 1]! : NaN);\n continue;\n }\n ring[i % (len + 1)] = v;\n // the first value is on bar `length` (one bar after the window is full)\n if (i < len) {\n result.push(NaN);\n continue;\n }\n // window newest first (position 0 = this bar)\n const values = Array.from({ length: len }, (_, j) => ring[(i - j) % (len + 1)]!);\n // Ranks: ascending sweep; a group collects the values less than 1e-10 above its smallest value; each group gets\n // its average 0-based rank counted from the largest value\n const order = values.map((_, j) => j).sort((a, b) => values[a]! - values[b]!);\n const ranks = new Array<number>(len);\n for (let g = 0; g < len; ) {\n const anchor = values[order[g]!]!;\n let end = g + 1;\n while (end < len && values[order[end]!]! - anchor < 1e-10) end++;\n const avgRank = len - 1 - (g + g + (end - g) - 1) / 2;\n for (let k = g; k < end; k++) ranks[order[k]!] = avgRank;\n g = end;\n }\n // moment-form variances, covariance from deviation products, (100 * cov) / (sd_x * sd_y): this operation order\n // gives PineScript's values bit for bit\n let sumX = 0;\n let sumY = 0;\n let sumX2 = 0;\n let sumY2 = 0;\n for (let k = 0; k < len; k++) {\n const y = ranks[k]!;\n sumX += k;\n sumY += y;\n sumX2 += k * k;\n sumY2 += y * y;\n }\n const meanX = sumX / len;\n const meanY = sumY / len;\n const varX = sumX2 / len - meanX * meanX;\n const varY = sumY2 / len - meanY * meanY;\n // a window where all values are ties has no correlation\n if (!(varX > 0) || !(varY > 0)) {\n result.push(NaN);\n continue;\n }\n let cov = 0;\n for (let k = 0; k < len; k++) cov += (k - meanX) * (ranks[k]! - meanY);\n cov /= len;\n result.push((100 * cov) / (Math.sqrt(varX) * Math.sqrt(varY)));\n }\n return result;\n}\n\n/**\n * Pivot Point Levels (PineScript `ta.pivot_point_levels`).\n *\n * Returns 11 series: [P, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5] (one value per bar in each).\n *\n * @param type - Calculation type: \"Traditional\", \"Fibonacci\", \"Woodie\", \"Classic\", \"DM\", \"Camarilla\"\n * @param anchor - Condition that starts a new period (`timeframe.change(\"W\")`...)\n * @param developing - false: the levels of the previous period, constant until the next anchor; true: the levels of\n * the current period so far, recalculated on each bar\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @param open - Open price series (Woodie and DM)\n * @returns 11 series of levels\n *\n * @example\n * ```typescript\n * const weekChange = [false, false, false, false, true, false, ...]; // Weekly anchor\n * const levels = ta.pivot_point_levels(\"Traditional\", weekChange, false, high, low, close, open);\n * // levels[0]![i] is P on bar i, levels[5]![i] is R3\n * ```\n *\n * @remarks\n * As in PineScript (#177):\n * - a period runs from an anchor bar to the bar before the next anchor; the bars before the first anchor are a\n * period too (from bar 0). The fixed levels use the high and low of the previous period and the close of the bar\n * before the anchor (na with an anchor on bar 0), and are na until the first anchor; the developing levels use\n * the current period's high and low and the bar's close, from bar 0\n * - Traditional: R3 = P * 2 + (H - 2 * L), S3 = P * 2 - (2 * H - L), R4 = P * 3 + (H - 3 * L), S4 = P * 3 - (3 * H - L),\n * R5 = P * 4 + (H - 4 * L), S5 = P * 4 - (4 * H - L)\n * - Fibonacci: P +- 0.382 / 0.618 / 1 * (H - L); R4 to S5 na\n * - Classic: R3 / S3 = P +- 2 * (H - L), R4 / S4 = P +- 3 * (H - L); R5 / S5 na\n * - Woodie: P = (H + L + 2 * open of the current period) / 4, R3 = H + 2 * (P - L), S3 = L - 2 * (H - P), R4 / S4 =\n * R3 + (H - L) / S3 - (H - L); R5 / S5 na. `developing` true throws (RE10128)\n * - DM: x = H + 2 * L + C (C < open of the period), 2 * H + L + C (C > O) or H + L + 2 * C; P = x / 4,\n * R1 = x / 2 - L, S1 = x / 2 - H; the other levels na\n * - Camarilla: C +- (H - L) * 1.1 / 12, / 6, / 4, / 2 for R1 to S4, R5 = (H / L) * C, S5 = 2 * C - R5\n */\nexport function pivot_point_levels(\n type: series_float | string,\n anchor: series_bool,\n developing: series_bool | boolean = false,\n high?: Source,\n low?: Source,\n close?: Source,\n open?: Source\n): series_float[] {\n const typeStr = typeof type === 'string' ? type : String(type[0]);\n const isDeveloping = typeof developing === 'boolean' ? developing : Boolean(developing[0]);\n if (typeStr === 'Woodie' && isDeveloping) {\n throw new Error(\n 'Error on bar 0: The `developing` parameter of the `ta.pivot_point_levels()` cannot be `true` when `type` is \"Woodie\".'\n );\n }\n const n = anchor.length;\n for (const [s, name] of [[high, 'High'], [low, 'Low'], [close, 'Close'], [open, 'Open']] as const) {\n if (s && s.length !== n) throw new Error(`${name} series length mismatch`);\n }\n const at = (s: Source | undefined, i: number): number => (s ? (s[i] ?? NaN) : NaN);\n const results: series_float[] = Array.from({ length: 11 }, () => new Array<number>(n));\n // the current period (from bar 0 until the first anchor) and the previous one\n let curH = NaN, curL = NaN, curO = NaN;\n let prevH = NaN, prevL = NaN, prevC = NaN, prevO = NaN;\n let anchored = false;\n for (let i = 0; i < n; i++) {\n const h = at(high, i), l = at(low, i);\n if (i === 0) {\n // the first period starts on bar 0: an anchor there makes bar 0 its own previous period\n curH = h;\n curL = l;\n curO = at(open, i);\n }\n if (anchor[i]) {\n prevH = curH;\n prevL = curL;\n prevC = i > 0 ? at(close, i - 1) : NaN;\n prevO = curO;\n curH = h;\n curL = l;\n curO = at(open, i);\n anchored = true;\n } else if (i > 0) {\n if (h > curH || Number.isNaN(curH)) curH = h;\n if (l < curL || Number.isNaN(curL)) curL = l;\n }\n const levels = isDeveloping\n ? pivotLevels(typeStr, curH, curL, at(close, i), curO, at(close, i))\n : anchored\n ? pivotLevels(typeStr, prevH, prevL, prevC, prevO, curO)\n : NA_LEVELS;\n for (let k = 0; k < 11; k++) results[k]![i] = levels[k]!;\n }\n return results;\n}\n\nconst NA_LEVELS: readonly number[] = new Array<number>(11).fill(NaN);\n\n/**\n * The 11 levels of one bar, in PineScript's operation order (bit for bit). `o` is the open of the period (DM),\n * `wo` the close term of Woodie (the open of the current period, or the bar's close while developing).\n */\nfunction pivotLevels(type: string, h: number, l: number, c: number, o: number, wo: number): readonly number[] {\n const N = NaN;\n const r = h - l;\n switch (type) {\n case 'Traditional': {\n const p = (h + l + c) / 3;\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, p * 2 + (h - 2 * l), p * 2 - (2 * h - l), p * 3 + (h - 3 * l),\n p * 3 - (3 * h - l), p * 4 + (h - 4 * l), p * 4 - (4 * h - l)];\n }\n case 'Fibonacci': {\n const p = (h + l + c) / 3;\n return [p, p + 0.382 * r, p - 0.382 * r, p + 0.618 * r, p - 0.618 * r, p + 1 * r, p - 1 * r, N, N, N, N];\n }\n case 'Classic': {\n const p = (h + l + c) / 3;\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, p + 2 * r, p - 2 * r, p + 3 * r, p - 3 * r, N, N];\n }\n case 'Woodie': {\n const p = (h + l + 2 * wo) / 4;\n const r3 = h + 2 * (p - l);\n const s3 = l - 2 * (h - p);\n return [p, 2 * p - l, 2 * p - h, p + r, p - r, r3, s3, r3 + r, s3 - r, N, N];\n }\n case 'DM': {\n const x = c < o ? h + 2 * l + c : c > o ? 2 * h + l + c : h + l + 2 * c;\n return [x / 4, x / 2 - l, x / 2 - h, N, N, N, N, N, N, N, N];\n }\n case 'Camarilla': {\n const p = (h + l + c) / 3;\n const r5 = (h / l) * c;\n return [p, c + (r * 1.1) / 12, c - (r * 1.1) / 12, c + (r * 1.1) / 6, c - (r * 1.1) / 6, c + (r * 1.1) / 4,\n c - (r * 1.1) / 4, c + (r * 1.1) / 2, c - (r * 1.1) / 2, r5, 2 * c - r5];\n }\n default:\n return NA_LEVELS;\n }\n}\n\n/**\n * Ichimoku Kinko Hyo (Ichimoku Cloud) - Japanese charting technique for trend identification.\n *\n * @param conversionPeriods - Period for Tenkan-sen (Conversion Line), default: 9\n * @param basePeriods - Period for Kijun-sen (Base Line), default: 26\n * @param laggingSpan2Periods - Period for Senkou Span B (Leading Span B), default: 52\n * @param displacement - Displacement for Senkou Spans and Chikou Span, default: 26\n * @param high - High price series\n * @param low - Low price series\n * @param close - Close price series\n * @returns Tuple of [tenkanSen, kijunSen, senkouSpanA, senkouSpanB, chikouSpan]\n *\n * @remarks\n * - **Tenkan-sen (Conversion Line)**: `(highest(high, conversionPeriods) + lowest(low, conversionPeriods)) / 2`\n * - **Kijun-sen (Base Line)**: `(highest(high, basePeriods) + lowest(low, basePeriods)) / 2`\n * - **Senkou Span A (Leading Span A)**: `(tenkan + kijun) / 2` offset forward by `displacement` periods\n * - **Senkou Span B (Leading Span B)**: `(highest(high, laggingSpan2Periods) + lowest(low, laggingSpan2Periods)) / 2` offset forward by `displacement` periods\n * - **Chikou Span (Lagging Span)**: `close` offset backward by `displacement` periods\n *\n * The forward offset for Senkou Spans means they are projected into the future (NaN values at the end).\n * The backward offset for Chikou Span means it shows past prices (NaN values at the beginning).\n *\n * @example\n * ```typescript\n * const [tenkan, kijun, senkouA, senkouB, chikou] = ta.ichimoku(9, 26, 52, 26, high, low, close);\n *\n * // Tenkan-sen crosses above Kijun-sen = bullish signal\n * const bullishSignal = ta.crossover(tenkan, kijun);\n *\n * // Price above cloud = bullish trend\n * // Cloud = area between senkouSpanA and senkouSpanB\n * ```\n */\nexport function ichimoku(\n conversionPeriods: simple_int,\n basePeriods: simple_int,\n laggingSpan2Periods: simple_int,\n displacement: simple_int,\n high: Source,\n low: Source,\n close: Source\n): [series_float, series_float, series_float, series_float, series_float] {\n const length = high.length;\n\n // Calculate Tenkan-sen (Conversion Line): (highest(high, 9) + lowest(low, 9)) / 2\n const highestConversion = highest(high, conversionPeriods);\n const lowestConversion = lowest(low, conversionPeriods);\n const tenkanSen: series_float = [];\n for (let i = 0; i < length; i++) {\n if (isNaN(highestConversion[i]!) || isNaN(lowestConversion[i]!)) {\n tenkanSen.push(NaN);\n } else {\n tenkanSen.push((highestConversion[i]! + lowestConversion[i]!) / 2);\n }\n }\n\n // Calculate Kijun-sen (Base Line): (highest(high, 26) + lowest(low, 26)) / 2\n const highestBase = highest(high, basePeriods);\n const lowestBase = lowest(low, basePeriods);\n const kijunSen: series_float = [];\n for (let i = 0; i < length; i++) {\n if (isNaN(highestBase[i]!) || isNaN(lowestBase[i]!)) {\n kijunSen.push(NaN);\n } else {\n kijunSen.push((highestBase[i]! + lowestBase[i]!) / 2);\n }\n }\n\n // Calculate Senkou Span A (Leading Span A): (tenkan + kijun) / 2, offset forward by displacement\n // This means at index i, we store the value that would normally be at index (i - displacement)\n // Result: first 'displacement' values are NaN, and last 'displacement' calculated values are lost\n const senkouSpanA: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i - displacement;\n if (sourceIndex < 0 || isNaN(tenkanSen[sourceIndex]!) || isNaN(kijunSen[sourceIndex]!)) {\n senkouSpanA.push(NaN);\n } else {\n senkouSpanA.push((tenkanSen[sourceIndex]! + kijunSen[sourceIndex]!) / 2);\n }\n }\n\n // Calculate Senkou Span B (Leading Span B): (highest(high, 52) + lowest(low, 52)) / 2, offset forward by displacement\n const highestLagging = highest(high, laggingSpan2Periods);\n const lowestLagging = lowest(low, laggingSpan2Periods);\n const senkouSpanB: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i - displacement;\n if (sourceIndex < 0 || isNaN(highestLagging[sourceIndex]!) || isNaN(lowestLagging[sourceIndex]!)) {\n senkouSpanB.push(NaN);\n } else {\n senkouSpanB.push((highestLagging[sourceIndex]! + lowestLagging[sourceIndex]!) / 2);\n }\n }\n\n // Calculate Chikou Span (Lagging Span): close, offset backward by displacement\n // This means at index i, we store the close value from index (i + displacement)\n // Result: last 'displacement' values are NaN\n const chikouSpan: series_float = [];\n for (let i = 0; i < length; i++) {\n const sourceIndex = i + displacement;\n if (sourceIndex >= length || isNaN(close[sourceIndex]!)) {\n chikouSpan.push(NaN);\n } else {\n chikouSpan.push(close[sourceIndex]!);\n }\n }\n\n return [tenkanSen, kijunSen, senkouSpanA, senkouSpanB, chikouSpan];\n}\n\n/**\n * ZigZag indicator - identifies significant trend reversals by filtering out minor price movements.\n *\n * @param deviation - Minimum percentage price change to form a new pivot (default: 5.0)\n * @param depth - Minimum bars between pivots for pivot detection (default: 10)\n * @param backstep - Bars to look back for confirmation (default: 3)\n * @param source - Price source (optional, typically close)\n * @param high - High price series (optional, for high/low mode)\n * @param low - Low price series (optional, for high/low mode)\n * @returns Tuple of [zigzag values, direction, pivot flags (boolean)]\n *\n * @remarks\n * - **Parameter order differs from PineScript**: JavaScript signature puts deviation first,\n * while PineScript uses `ta.zigzag(source, deviation, depth, backstep)`. This allows\n * deviation to have a default value and makes the API more ergonomic for JS users.\n * - **JavaScript signature**: Requires explicit `source`, `high`, `low` OR use `createContext()`\n * - Returns the pivot price at pivot points, NaN for non-pivot bars\n * - Direction: 1 = uptrend (from low to high), -1 = downtrend (from high to low)\n * - The ZigZag indicator **repaints** by design - the last segment can change as new data arrives\n * - Supports two modes:\n * - Single source mode: uses same series for highs and lows\n * - High/Low mode: uses high for pivot highs, low for pivot lows\n *\n * @example\n * ```typescript\n * // Using high/low for more accurate pivots\n * const [zigzag, direction, isPivot] = ta.zigzag(5, 10, 3, undefined, high, low);\n *\n * // Find pivot prices\n * for (let i = 0; i < zigzag.length; i++) {\n * if (!isNaN(zigzag[i]!)) {\n * console.log(`Pivot at bar ${i}: ${zigzag[i]!}, direction: ${direction[i]! === 1 ? 'UP' : 'DOWN'}`);\n * }\n * }\n * ```\n */\nexport function zigzag(\n deviation: simple_float = 5.0,\n depth: simple_int = 10,\n backstep: simple_int = 3,\n source?: Source,\n high?: Source,\n low?: Source\n): [series_float, series_int, series_bool] {\n // Determine which mode we're in\n let highSource: Source;\n let lowSource: Source;\n \n if (high && low) {\n // High/Low mode\n highSource = high;\n lowSource = low;\n } else if (source) {\n // Single source mode\n highSource = source;\n lowSource = source;\n } else {\n throw new Error(\n 'ta.zigzag() requires either source series or high/low series. ' +\n 'Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data.'\n );\n }\n\n const length = highSource.length;\n if (lowSource.length !== length) {\n throw new Error('ta.zigzag: high and low must have the same length');\n }\n\n // Result arrays\n const zigzagValues: series_float = new Array(length).fill(NaN);\n const directions: series_int = new Array(length).fill(0);\n const isPivot: series_bool = new Array(length).fill(false);\n\n // Helper function to calculate percentage deviation\n const getDeviation = (price1: number, price2: number): number => {\n // Use epsilon threshold to avoid numerical instability with very small values\n if (Math.abs(price1) < 1e-10 || isNaN(price1) || isNaN(price2)) return 0;\n return Math.abs((price2 - price1) / price1) * 100;\n };\n\n // Track pivot state\n interface Pivot {\n index: number;\n price: number;\n type: 'high' | 'low';\n }\n\n let lastConfirmedPivot: Pivot | null = null;\n let potentialPivot: Pivot | null = null;\n let currentDirection = 0; // 0 = undefined, 1 = up, -1 = down\n\n // Store confirmed pivots for final zigzag construction\n const confirmedPivots: Pivot[] = [];\n\n // First pass: Find initial pivot to start\n let startIndex: number;\n let initialHighest = -Infinity;\n let initialLowest = Infinity;\n let initialHighIndex = -1;\n let initialLowIndex = -1;\n\n // Find the first significant pivot using depth bars\n for (let i = 0; i < Math.min(depth, length); i++) {\n if (!isNaN(highSource[i]!) && highSource[i]! > initialHighest) {\n initialHighest = highSource[i]!;\n initialHighIndex = i;\n }\n if (!isNaN(lowSource[i]!) && lowSource[i]! < initialLowest) {\n initialLowest = lowSource[i]!;\n initialLowIndex = i;\n }\n }\n\n // Determine starting direction based on which came first\n if (initialHighIndex >= 0 && initialLowIndex >= 0) {\n if (initialLowIndex <= initialHighIndex) {\n // Low came first or same - start with low, direction will be up\n lastConfirmedPivot = { index: initialLowIndex, price: initialLowest, type: 'low' };\n currentDirection = 1;\n } else {\n // High came first - start with high, direction will be down\n lastConfirmedPivot = { index: initialHighIndex, price: initialHighest, type: 'high' };\n currentDirection = -1;\n }\n confirmedPivots.push(lastConfirmedPivot);\n startIndex = lastConfirmedPivot.index + 1;\n } else {\n startIndex = depth;\n }\n\n // Main loop: process bars\n for (let i = Math.max(startIndex, depth); i < length; i++) {\n const currentHigh = highSource[i]!;\n const currentLow = lowSource[i]!;\n\n if (isNaN(currentHigh) || isNaN(currentLow)) {\n directions[i] = currentDirection;\n continue;\n }\n\n // Check for potential pivot high\n let isPotentialHigh = true;\n for (let j = 1; j <= backstep && i - j >= 0; j++) {\n if (!isNaN(highSource[i - j]!) && highSource[i - j]! >= currentHigh) {\n isPotentialHigh = false;\n break;\n }\n }\n\n // Check for potential pivot low\n let isPotentialLow = true;\n for (let j = 1; j <= backstep && i - j >= 0; j++) {\n if (!isNaN(lowSource[i - j]!) && lowSource[i - j]! <= currentLow) {\n isPotentialLow = false;\n break;\n }\n }\n\n if (currentDirection === 1) {\n // Looking for pivot high (uptrend ending)\n if (isPotentialHigh) {\n if (potentialPivot === null || potentialPivot.type !== 'high') {\n // New potential high\n if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {\n potentialPivot = { index: i, price: currentHigh, type: 'high' };\n }\n } else {\n // Already have a potential high - update if this is higher\n if (currentHigh > potentialPivot.price) {\n potentialPivot = { index: i, price: currentHigh, type: 'high' };\n }\n }\n }\n\n // Check if we should confirm the potential high and start looking for a low\n if (potentialPivot && potentialPivot.type === 'high') {\n const deviationFromPotential = getDeviation(potentialPivot.price, currentLow);\n if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {\n // Confirm the high pivot\n confirmedPivots.push(potentialPivot);\n lastConfirmedPivot = potentialPivot;\n currentDirection = -1;\n potentialPivot = null;\n }\n }\n } else if (currentDirection === -1) {\n // Looking for pivot low (downtrend ending)\n if (isPotentialLow) {\n if (potentialPivot === null || potentialPivot.type !== 'low') {\n // New potential low\n if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {\n potentialPivot = { index: i, price: currentLow, type: 'low' };\n }\n } else {\n // Already have a potential low - update if this is lower\n if (currentLow < potentialPivot.price) {\n potentialPivot = { index: i, price: currentLow, type: 'low' };\n }\n }\n }\n\n // Check if we should confirm the potential low and start looking for a high\n if (potentialPivot && potentialPivot.type === 'low') {\n const deviationFromPotential = getDeviation(potentialPivot.price, currentHigh);\n if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {\n // Confirm the low pivot\n confirmedPivots.push(potentialPivot);\n lastConfirmedPivot = potentialPivot;\n currentDirection = 1;\n potentialPivot = null;\n }\n }\n } else {\n // Initial state - determine direction based on first significant move\n if (lastConfirmedPivot) {\n if (lastConfirmedPivot.type === 'low' && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {\n currentDirection = 1;\n } else if (lastConfirmedPivot.type === 'high' && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {\n currentDirection = -1;\n }\n }\n }\n\n directions[i] = currentDirection;\n }\n\n // Include the last potential pivot if it exists (repaint behavior)\n // This shows where the zigzag line extends to, but doesn't change direction\n const lastPotentialWasAdded = potentialPivot !== null;\n if (potentialPivot) {\n confirmedPivots.push(potentialPivot);\n }\n\n // Build the final zigzag output\n for (const pivot of confirmedPivots) {\n zigzagValues[pivot.index] = pivot.price;\n isPivot[pivot.index] = true;\n }\n\n // Set directions for all bars based on confirmed pivots\n // Direction represents the current trend at each bar:\n // - After a LOW pivot, trend is UP (1) until the next HIGH\n // - After a HIGH pivot, trend is DOWN (-1) until the next LOW\n let currentDir = 0;\n let pivotIdx = 0;\n const numConfirmed = lastPotentialWasAdded ? confirmedPivots.length - 1 : confirmedPivots.length;\n \n for (let i = 0; i < length; i++) {\n // Move to next confirmed pivot if we passed the current one\n // Don't count the last potential pivot for direction changes\n while (pivotIdx < numConfirmed && confirmedPivots[pivotIdx]!.index <= i) {\n const pivot = confirmedPivots[pivotIdx]!;\n currentDir = pivot.type === 'low' ? 1 : -1;\n pivotIdx++;\n }\n directions[i] = currentDir;\n }\n\n return [zigzagValues, directions, isPivot];\n}\n\n// \u2500\u2500 Volume built-in variables (ta.obv, ta.pvt, ta.accdist, ta.nvi, ta.pvi, ta.iii, ta.wad, ta.wvad) \u2500\u2500\n//\n// In PineScript these are series variables computed from the chart bars. Here they take the\n// bar series explicitly.\n\n/**\n * On Balance Volume: `ta.cum(math.sign(ta.change(close)) * volume)`.\n *\n * @param close - Close price series\n * @param volume - Volume series\n * @returns OBV series (`na` on the first bar, and on bars without volume)\n */\nexport function obv(close: Source, volume: Source): series_float {\n return cum(close.map((c, i) => (i === 0 ? NaN : Math.sign(c - close[i - 1]!) * volume[i]!)));\n}\n\n/**\n * Price-Volume Trend: `ta.cum((ta.change(close) / close[1]) * volume)`.\n *\n * @param close - Close price series\n * @param volume - Volume series\n * @returns PVT series (`na` on the first bar, and on bars without volume)\n */\nexport function pvt(close: Source, volume: Source): series_float {\n return cum(\n close.map((c, i) => (i === 0 ? NaN : ((c - close[i - 1]!) / close[i - 1]!) * volume[i]!))\n );\n}\n\n/**\n * Accumulation/Distribution index: the running sum of\n * `((close - low) - (high - close)) / (high - low) * volume`, in this order as in PineScript (bit for bit).\n * A bar where this is `na` (`high == low`, an `na` volume) adds nothing and keeps the previous value.\n */\nexport function accdist(high: Source, low: Source, close: Source, volume: Source): series_float {\n let ad = 0;\n return close.map((c, i) => {\n const h = high[i]!;\n const l = low[i]!;\n const mfv = (((c - l) - (h - c)) / (h - l)) * volume[i]!;\n if (Number.isFinite(mfv)) ad += mfv;\n return ad;\n });\n}\n\n/**\n * Intraday Intensity Index: `(2 * close - high - low) / (high - low) * volume`.\n *\n * The PineScript built-in value is this formula. The formula shown in the PineScript reference,\n * `(2 * close - high - low) / ((high - low) * volume)`, gives other values.\n *\n * @returns III series (`na` where `high == low`)\n */\nexport function iii(high: Source, low: Source, close: Source, volume: Source): series_float {\n return close.map((c, i) => {\n const range = high[i]! - low[i]!;\n return range === 0 ? NaN : ((2 * c - high[i]! - low[i]!) / range) * volume[i]!;\n });\n}\n\n/**\n * Williams Variable Accumulation/Distribution: `(close - open) / (high - low) * volume`.\n *\n * @returns WVAD series (`na` where `high == low`)\n */\nexport function wvad(open: Source, high: Source, low: Source, close: Source, volume: Source): series_float {\n return close.map((c, i) => {\n const range = high[i]! - low[i]!;\n return range === 0 ? NaN : ((c - open[i]!) / range) * volume[i]!;\n });\n}\n\n/**\n * Williams Accumulation/Distribution: the running sum of `close - min(low, close[1])` on up\n * closes, `close - max(high, close[1])` on down closes, and 0 otherwise (first bar included).\n */\nexport function wad(high: Source, low: Source, close: Source): series_float {\n return cum(\n close.map((c, i) => {\n const prev = i === 0 ? NaN : close[i - 1]!;\n const mom = c - prev;\n if (mom > 0) return c - Math.min(low[i]!, prev);\n if (mom < 0) return c - Math.max(high[i]!, prev);\n return 0;\n })\n );\n}\n\n/** Volume index shared by NVI and PVI: moves with the close change on bars selected by `use`. */\nfunction volumeIndex(close: Source, volume: Source, use: (v: number, prevV: number) => boolean): series_float {\n const result: series_float = [];\n let prevIndex = NaN;\n for (let i = 0; i < close.length; i++) {\n const prev = !prevIndex ? 1 : prevIndex; // nz(index[1], 0) == 0 ? 1 : index[1]\n const c = close[i]!;\n const prevC = i === 0 ? NaN : close[i - 1]!;\n let value = prev;\n if (c && prevC) {\n const prevV = i === 0 || Number.isNaN(volume[i - 1]!) ? 0 : volume[i - 1]!;\n if (use(volume[i]!, prevV)) value = prev + ((c - prevC) / prevC) * prev;\n }\n result.push(value);\n prevIndex = value;\n }\n return result;\n}\n\n/**\n * Negative Volume Index: moves with the close change only on bars where volume falls.\n * Starts at 1.\n */\nexport function nvi(close: Source, volume: Source): series_float {\n return volumeIndex(close, volume, (v, prevV) => v < prevV);\n}\n\n/**\n * Positive Volume Index: moves with the close change only on bars where volume rises.\n * Starts at 1.\n */\nexport function pvi(close: Source, volume: Source): series_float {\n return volumeIndex(close, volume, (v, prevV) => v > prevV);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["dev", "lowest", "tr", "change", "max", "mom", "range", "pivot"]
|
|
7
7
|
}
|