@lacspace/indicators 1.0.3 → 1.1.0
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/README.md +18 -0
- package/dist/index.cjs +82 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +81 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,6 +103,24 @@ Batch equivalents: `sma` `ema` `wma` `rsi` `macd` `bollinger` `atr` `supertrend`
|
|
|
103
103
|
| [`@lacspace/market-clock`](https://www.npmjs.com/package/@lacspace/market-clock) | Is the market open? holidays |
|
|
104
104
|
| [`@lacspace/paper-trade`](https://www.npmjs.com/package/@lacspace/paper-trade) | Headless paper-trading engine |
|
|
105
105
|
|
|
106
|
+
## New in 1.1 — candle aggregation & pattern detection
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { CandleAggregator, detectPatterns } from "@lacspace/indicators";
|
|
110
|
+
|
|
111
|
+
// Turn a live LTP/tick feed into fixed-interval OHLC candles
|
|
112
|
+
const agg = new CandleAggregator(60_000); // 1-minute
|
|
113
|
+
onTick(({ time, price, volume }) => {
|
|
114
|
+
const candle = agg.add({ time, price, volume });
|
|
115
|
+
if (candle) store.push(candle); // completed candle on each rollover
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Spot candlestick patterns across a series
|
|
119
|
+
detectPatterns(candles);
|
|
120
|
+
// → [{ index: 42, pattern: "bullishEngulfing", bullish: true }, …]
|
|
121
|
+
// doji · hammer · shootingStar · marubozu · bullish/bearish engulfing · harami
|
|
122
|
+
```
|
|
123
|
+
|
|
106
124
|
## Licensing
|
|
107
125
|
|
|
108
126
|
This package is **free** under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** — MIT-equivalent freedoms. Use it in personal and commercial projects at no cost; just keep the notice.
|
package/dist/index.cjs
CHANGED
|
@@ -362,10 +362,91 @@ function crossedAbove(prev, curr) {
|
|
|
362
362
|
function crossedBelow(prev, curr) {
|
|
363
363
|
return prev.a >= prev.b && curr.a < curr.b;
|
|
364
364
|
}
|
|
365
|
+
var CandleAggregator = class {
|
|
366
|
+
constructor(intervalMs) {
|
|
367
|
+
this.intervalMs = intervalMs;
|
|
368
|
+
this.current = null;
|
|
369
|
+
this.bucketStart = 0;
|
|
370
|
+
if (!(intervalMs > 0)) throw new RangeError(`intervalMs must be > 0, got ${intervalMs}`);
|
|
371
|
+
}
|
|
372
|
+
openCandle(tick, bucket) {
|
|
373
|
+
return { time: bucket, open: tick.price, high: tick.price, low: tick.price, close: tick.price, volume: tick.volume ?? 0 };
|
|
374
|
+
}
|
|
375
|
+
/** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */
|
|
376
|
+
add(tick) {
|
|
377
|
+
const bucket = Math.floor(tick.time / this.intervalMs) * this.intervalMs;
|
|
378
|
+
if (this.current === null) {
|
|
379
|
+
this.bucketStart = bucket;
|
|
380
|
+
this.current = this.openCandle(tick, bucket);
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
if (bucket > this.bucketStart) {
|
|
384
|
+
const completed = this.current;
|
|
385
|
+
this.bucketStart = bucket;
|
|
386
|
+
this.current = this.openCandle(tick, bucket);
|
|
387
|
+
return completed;
|
|
388
|
+
}
|
|
389
|
+
this.current.high = Math.max(this.current.high, tick.price);
|
|
390
|
+
this.current.low = Math.min(this.current.low, tick.price);
|
|
391
|
+
this.current.close = tick.price;
|
|
392
|
+
if (tick.volume) this.current.volume = (this.current.volume ?? 0) + tick.volume;
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
/** The in-progress (not yet closed) candle, if any. */
|
|
396
|
+
get pending() {
|
|
397
|
+
return this.current ? { ...this.current } : null;
|
|
398
|
+
}
|
|
399
|
+
/** Close and return the current candle (e.g. at session end). */
|
|
400
|
+
flush() {
|
|
401
|
+
const c = this.current;
|
|
402
|
+
this.current = null;
|
|
403
|
+
return c;
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
function body(c) {
|
|
407
|
+
return Math.abs(c.close - c.open);
|
|
408
|
+
}
|
|
409
|
+
function upperWick(c) {
|
|
410
|
+
return c.high - Math.max(c.open, c.close);
|
|
411
|
+
}
|
|
412
|
+
function lowerWick(c) {
|
|
413
|
+
return Math.min(c.open, c.close) - c.low;
|
|
414
|
+
}
|
|
415
|
+
function detectPatterns(candles) {
|
|
416
|
+
const hits = [];
|
|
417
|
+
for (let i = 0; i < candles.length; i++) {
|
|
418
|
+
const c = candles[i];
|
|
419
|
+
const range = c.high - c.low;
|
|
420
|
+
if (range <= 0) continue;
|
|
421
|
+
const b = body(c);
|
|
422
|
+
const up = upperWick(c);
|
|
423
|
+
const lo = lowerWick(c);
|
|
424
|
+
const bullish = c.close > c.open;
|
|
425
|
+
if (b <= range * 0.1) hits.push({ index: i, pattern: "doji", bullish });
|
|
426
|
+
else if (up <= range * 0.05 && lo <= range * 0.05) hits.push({ index: i, pattern: "marubozu", bullish });
|
|
427
|
+
else if (lo >= b * 2 && up <= b * 0.6) hits.push({ index: i, pattern: "hammer", bullish: true });
|
|
428
|
+
else if (up >= b * 2 && lo <= b * 0.6) hits.push({ index: i, pattern: "shootingStar", bullish: false });
|
|
429
|
+
if (i > 0) {
|
|
430
|
+
const p = candles[i - 1];
|
|
431
|
+
const pBull = p.close > p.open;
|
|
432
|
+
const pBody = body(p);
|
|
433
|
+
if (!pBull && bullish && c.close >= p.open && c.open <= p.close && b > pBody)
|
|
434
|
+
hits.push({ index: i, pattern: "bullishEngulfing", bullish: true });
|
|
435
|
+
else if (pBull && !bullish && c.open >= p.close && c.close <= p.open && b > pBody)
|
|
436
|
+
hits.push({ index: i, pattern: "bearishEngulfing", bullish: false });
|
|
437
|
+
else if (!pBull && bullish && c.open >= p.close && c.close <= p.open && b < pBody)
|
|
438
|
+
hits.push({ index: i, pattern: "bullishHarami", bullish: true });
|
|
439
|
+
else if (pBull && !bullish && c.close >= p.open && c.open <= p.close && b < pBody)
|
|
440
|
+
hits.push({ index: i, pattern: "bearishHarami", bullish: false });
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return hits;
|
|
444
|
+
}
|
|
365
445
|
|
|
366
446
|
exports.ADX = ADX;
|
|
367
447
|
exports.ATR = ATR;
|
|
368
448
|
exports.BollingerBands = BollingerBands;
|
|
449
|
+
exports.CandleAggregator = CandleAggregator;
|
|
369
450
|
exports.EMA = EMA;
|
|
370
451
|
exports.MACD = MACD;
|
|
371
452
|
exports.RSI = RSI;
|
|
@@ -379,6 +460,7 @@ exports.atr = atr;
|
|
|
379
460
|
exports.bollinger = bollinger;
|
|
380
461
|
exports.crossedAbove = crossedAbove;
|
|
381
462
|
exports.crossedBelow = crossedBelow;
|
|
463
|
+
exports.detectPatterns = detectPatterns;
|
|
382
464
|
exports.ema = ema;
|
|
383
465
|
exports.macd = macd;
|
|
384
466
|
exports.rsi = rsi;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["macd","atr"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lacspace/indicators\n * Streaming technical indicators for stock-market apps.\n *\n * Every indicator is a small class with an incremental `next()` that updates in\n * O(1) (or O(period) for window-based ones) — push one live tick, get the new\n * value, without recomputing the whole series. Perfect for live LTP feeds.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\nexport interface Candle {\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n time?: number;\n}\n\n/** A high/low/close bar — the minimum most range-based indicators need. */\nexport interface HLC {\n high: number;\n low: number;\n close: number;\n}\n\nfunction assertPeriod(period: number): void {\n if (!Number.isInteger(period) || period < 1) {\n throw new RangeError(`period must be a positive integer, got ${period}`);\n }\n}\n\n/** Simple Moving Average. Incremental O(1) using a running window sum. */\nexport class SMA {\n private buf: number[] = [];\n private sum = 0;\n /** Latest value, or `null` until `period` samples have been seen. */\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n this.value = this.buf.length === this.period ? this.sum / this.period : null;\n return this.value;\n }\n}\n\n/** Exponential Moving Average. Seeded with an SMA of the first `period` values. */\nexport class EMA {\n private readonly k: number;\n private seed: number[] = [];\n private ema: number | null = null;\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n this.k = 2 / (period + 1);\n }\n\n next(price: number): number | null {\n if (this.ema === null) {\n this.seed.push(price);\n if (this.seed.length < this.period) return (this.value = null);\n this.ema = this.seed.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.ema = price * this.k + this.ema * (1 - this.k);\n }\n return (this.value = this.ema);\n }\n}\n\n/** Weighted Moving Average — recent samples weighted linearly higher. */\nexport class WMA {\n private buf: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n if (this.buf.length > this.period) this.buf.shift();\n if (this.buf.length < this.period) return (this.value = null);\n let num = 0;\n let den = 0;\n for (let i = 0; i < this.period; i++) {\n const w = i + 1;\n num += this.buf[i]! * w;\n den += w;\n }\n return (this.value = num / den);\n }\n}\n\n/** Relative Strength Index (Wilder's smoothing). O(1) per tick. */\nexport class RSI {\n private prev: number | null = null;\n private avgGain = 0;\n private avgLoss = 0;\n private count = 0;\n value: number | null = null;\n\n constructor(public readonly period: number = 14) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n if (this.prev === null) {\n this.prev = price;\n return (this.value = null);\n }\n const change = price - this.prev;\n this.prev = price;\n const gain = change > 0 ? change : 0;\n const loss = change < 0 ? -change : 0;\n this.count++;\n\n if (this.count <= this.period) {\n this.avgGain += gain;\n this.avgLoss += loss;\n if (this.count < this.period) return (this.value = null);\n this.avgGain /= this.period;\n this.avgLoss /= this.period;\n } else {\n this.avgGain = (this.avgGain * (this.period - 1) + gain) / this.period;\n this.avgLoss = (this.avgLoss * (this.period - 1) + loss) / this.period;\n }\n return (this.value = this.compute());\n }\n\n private compute(): number {\n if (this.avgLoss === 0) return 100;\n const rs = this.avgGain / this.avgLoss;\n return 100 - 100 / (1 + rs);\n }\n}\n\nexport interface MACDValue {\n macd: number;\n signal: number;\n histogram: number;\n}\n\n/** Moving Average Convergence Divergence. Defaults 12 / 26 / 9. */\nexport class MACD {\n private readonly fastEma: EMA;\n private readonly slowEma: EMA;\n private readonly signalEma: EMA;\n value: MACDValue | null = null;\n\n constructor(fast = 12, slow = 26, signal = 9) {\n this.fastEma = new EMA(fast);\n this.slowEma = new EMA(slow);\n this.signalEma = new EMA(signal);\n }\n\n next(price: number): MACDValue | null {\n const f = this.fastEma.next(price);\n const s = this.slowEma.next(price);\n if (f === null || s === null) return (this.value = null);\n const macd = f - s;\n const signal = this.signalEma.next(macd);\n if (signal === null) return (this.value = null);\n return (this.value = { macd, signal, histogram: macd - signal });\n }\n}\n\nexport interface BollingerValue {\n middle: number;\n upper: number;\n lower: number;\n /** (upper - lower) / middle — normalised band width. */\n bandwidth: number;\n}\n\n/** Bollinger Bands — SMA middle band ± `mult` standard deviations. */\nexport class BollingerBands {\n private buf: number[] = [];\n private sum = 0;\n value: BollingerValue | null = null;\n\n constructor(\n public readonly period = 20,\n public readonly mult = 2,\n ) {\n assertPeriod(period);\n }\n\n next(price: number): BollingerValue | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n if (this.buf.length < this.period) return (this.value = null);\n const mean = this.sum / this.period;\n let variance = 0;\n for (const v of this.buf) variance += (v - mean) ** 2;\n const sd = Math.sqrt(variance / this.period);\n const upper = mean + this.mult * sd;\n const lower = mean - this.mult * sd;\n return (this.value = {\n middle: mean,\n upper,\n lower,\n bandwidth: mean === 0 ? 0 : (upper - lower) / mean,\n });\n }\n}\n\n/** Average True Range (Wilder). Feed it high/low/close bars. */\nexport class ATR {\n private prevClose: number | null = null;\n private atr: number | null = null;\n private seed: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): number | null {\n const tr =\n this.prevClose === null\n ? bar.high - bar.low\n : Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevClose = bar.close;\n\n if (this.atr === null) {\n this.seed.push(tr);\n if (this.seed.length < this.period) return (this.value = null);\n this.atr = this.seed.reduce((a, b) => a + b, 0) / this.period;\n return (this.value = this.atr);\n }\n this.atr = (this.atr * (this.period - 1) + tr) / this.period;\n return (this.value = this.atr);\n }\n}\n\n/** Volume-Weighted Average Price. Cumulative — call `reset()` per session. */\nexport class VWAP {\n private pv = 0;\n private vol = 0;\n value: number | null = null;\n\n next(bar: Required<Pick<Candle, \"high\" | \"low\" | \"close\" | \"volume\">>): number | null {\n const typical = (bar.high + bar.low + bar.close) / 3;\n this.pv += typical * bar.volume;\n this.vol += bar.volume;\n return (this.value = this.vol === 0 ? null : this.pv / this.vol);\n }\n\n reset(): void {\n this.pv = 0;\n this.vol = 0;\n this.value = null;\n }\n}\n\nexport interface StochasticValue {\n /** %K — position of close within the recent high/low range (0–100). */\n k: number;\n /** %D — SMA of %K. */\n d: number;\n}\n\n/** Stochastic Oscillator (%K / %D). */\nexport class Stochastic {\n private highs: number[] = [];\n private lows: number[] = [];\n private readonly dSma: SMA;\n value: StochasticValue | null = null;\n\n constructor(\n public readonly period = 14,\n public readonly signal = 3,\n ) {\n assertPeriod(period);\n this.dSma = new SMA(signal);\n }\n\n next(bar: HLC): StochasticValue | null {\n this.highs.push(bar.high);\n this.lows.push(bar.low);\n if (this.highs.length > this.period) {\n this.highs.shift();\n this.lows.shift();\n }\n if (this.highs.length < this.period) return (this.value = null);\n const hh = Math.max(...this.highs);\n const ll = Math.min(...this.lows);\n const k = hh === ll ? 100 : ((bar.close - ll) / (hh - ll)) * 100;\n const d = this.dSma.next(k);\n if (d === null) return (this.value = null);\n return (this.value = { k, d });\n }\n}\n\nexport interface SupertrendValue {\n value: number;\n /** 1 = uptrend (price above band), -1 = downtrend. */\n direction: 1 | -1;\n}\n\n/** Supertrend — ATR-based trend follower. Defaults period 10, multiplier 3. */\nexport class Supertrend {\n private readonly atr: ATR;\n private prevClose: number | null = null;\n private prevFinalUpper = 0;\n private prevFinalLower = 0;\n private prevSupertrend: number | null = null;\n value: SupertrendValue | null = null;\n\n constructor(\n public readonly period = 10,\n public readonly mult = 3,\n ) {\n this.atr = new ATR(period);\n }\n\n next(bar: HLC): SupertrendValue | null {\n const atr = this.atr.next(bar);\n if (atr === null) {\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const hl2 = (bar.high + bar.low) / 2;\n const basicUpper = hl2 + this.mult * atr;\n const basicLower = hl2 - this.mult * atr;\n const pc = this.prevClose ?? bar.close;\n\n const first = this.prevSupertrend === null;\n const finalUpper =\n first || basicUpper < this.prevFinalUpper || pc > this.prevFinalUpper\n ? basicUpper\n : this.prevFinalUpper;\n const finalLower =\n first || basicLower > this.prevFinalLower || pc < this.prevFinalLower\n ? basicLower\n : this.prevFinalLower;\n\n let st: number;\n let direction: 1 | -1;\n if (first) {\n direction = bar.close <= finalUpper ? -1 : 1;\n st = direction === -1 ? finalUpper : finalLower;\n } else if (this.prevSupertrend === this.prevFinalUpper) {\n if (bar.close <= finalUpper) {\n st = finalUpper;\n direction = -1;\n } else {\n st = finalLower;\n direction = 1;\n }\n } else {\n if (bar.close >= finalLower) {\n st = finalLower;\n direction = 1;\n } else {\n st = finalUpper;\n direction = -1;\n }\n }\n\n this.prevFinalUpper = finalUpper;\n this.prevFinalLower = finalLower;\n this.prevSupertrend = st;\n this.prevClose = bar.close;\n return (this.value = { value: st, direction });\n }\n}\n\nexport interface ADXValue {\n adx: number;\n plusDI: number;\n minusDI: number;\n}\n\n/** Average Directional Index with +DI / -DI (Wilder). */\nexport class ADX {\n private prevHigh: number | null = null;\n private prevLow = 0;\n private prevClose = 0;\n private smTR = 0;\n private smPDM = 0;\n private smMDM = 0;\n private dxs: number[] = [];\n private adx: number | null = null;\n private count = 0;\n value: ADXValue | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): ADXValue | null {\n if (this.prevHigh === null) {\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const upMove = bar.high - this.prevHigh;\n const downMove = this.prevLow - bar.low;\n const pdm = upMove > downMove && upMove > 0 ? upMove : 0;\n const mdm = downMove > upMove && downMove > 0 ? downMove : 0;\n const tr = Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n this.count++;\n\n if (this.count <= this.period) {\n this.smTR += tr;\n this.smPDM += pdm;\n this.smMDM += mdm;\n if (this.count < this.period) return (this.value = null);\n } else {\n this.smTR = this.smTR - this.smTR / this.period + tr;\n this.smPDM = this.smPDM - this.smPDM / this.period + pdm;\n this.smMDM = this.smMDM - this.smMDM / this.period + mdm;\n }\n\n const plusDI = this.smTR === 0 ? 0 : (100 * this.smPDM) / this.smTR;\n const minusDI = this.smTR === 0 ? 0 : (100 * this.smMDM) / this.smTR;\n const diSum = plusDI + minusDI;\n const dx = diSum === 0 ? 0 : (100 * Math.abs(plusDI - minusDI)) / diSum;\n\n if (this.adx === null) {\n this.dxs.push(dx);\n if (this.dxs.length < this.period) return (this.value = null);\n this.adx = this.dxs.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.adx = (this.adx * (this.period - 1) + dx) / this.period;\n }\n return (this.value = { adx: this.adx, plusDI, minusDI });\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Batch helpers — run an indicator over an existing array in one call.\n * Each returns an array aligned to the input (nulls during warm-up).\n * ------------------------------------------------------------------ */\n\nfunction runNumber<T extends { next(v: number): number | null }>(\n ind: T,\n values: number[],\n): (number | null)[] {\n return values.map((v) => ind.next(v));\n}\n\nexport const sma = (values: number[], period: number) => runNumber(new SMA(period), values);\nexport const ema = (values: number[], period: number) => runNumber(new EMA(period), values);\nexport const wma = (values: number[], period: number) => runNumber(new WMA(period), values);\nexport const rsi = (values: number[], period = 14) => runNumber(new RSI(period), values);\n\nexport function macd(values: number[], fast = 12, slow = 26, signal = 9): (MACDValue | null)[] {\n const ind = new MACD(fast, slow, signal);\n return values.map((v) => ind.next(v));\n}\n\nexport function bollinger(values: number[], period = 20, mult = 2): (BollingerValue | null)[] {\n const ind = new BollingerBands(period, mult);\n return values.map((v) => ind.next(v));\n}\n\nexport function atr(bars: HLC[], period = 14): (number | null)[] {\n const ind = new ATR(period);\n return bars.map((b) => ind.next(b));\n}\n\nexport function supertrend(bars: HLC[], period = 10, mult = 3): (SupertrendValue | null)[] {\n const ind = new Supertrend(period, mult);\n return bars.map((b) => ind.next(b));\n}\n\nexport function adx(bars: HLC[], period = 14): (ADXValue | null)[] {\n const ind = new ADX(period);\n return bars.map((b) => ind.next(b));\n}\n\n/* ------------------------------------------------------------------ *\n * Crossover helpers — the backbone of most signal logic.\n * ------------------------------------------------------------------ */\n\n/** True when series A crossed from at-or-below B to strictly above B. */\nexport function crossedAbove(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a <= prev.b && curr.a > curr.b;\n}\n\n/** True when series A crossed from at-or-above B to strictly below B. */\nexport function crossedBelow(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a >= prev.b && curr.a < curr.b;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["macd","atr"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lacspace/indicators\n * Streaming technical indicators for stock-market apps.\n *\n * Every indicator is a small class with an incremental `next()` that updates in\n * O(1) (or O(period) for window-based ones) — push one live tick, get the new\n * value, without recomputing the whole series. Perfect for live LTP feeds.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\nexport interface Candle {\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n time?: number;\n}\n\n/** A high/low/close bar — the minimum most range-based indicators need. */\nexport interface HLC {\n high: number;\n low: number;\n close: number;\n}\n\nfunction assertPeriod(period: number): void {\n if (!Number.isInteger(period) || period < 1) {\n throw new RangeError(`period must be a positive integer, got ${period}`);\n }\n}\n\n/** Simple Moving Average. Incremental O(1) using a running window sum. */\nexport class SMA {\n private buf: number[] = [];\n private sum = 0;\n /** Latest value, or `null` until `period` samples have been seen. */\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n this.value = this.buf.length === this.period ? this.sum / this.period : null;\n return this.value;\n }\n}\n\n/** Exponential Moving Average. Seeded with an SMA of the first `period` values. */\nexport class EMA {\n private readonly k: number;\n private seed: number[] = [];\n private ema: number | null = null;\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n this.k = 2 / (period + 1);\n }\n\n next(price: number): number | null {\n if (this.ema === null) {\n this.seed.push(price);\n if (this.seed.length < this.period) return (this.value = null);\n this.ema = this.seed.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.ema = price * this.k + this.ema * (1 - this.k);\n }\n return (this.value = this.ema);\n }\n}\n\n/** Weighted Moving Average — recent samples weighted linearly higher. */\nexport class WMA {\n private buf: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n if (this.buf.length > this.period) this.buf.shift();\n if (this.buf.length < this.period) return (this.value = null);\n let num = 0;\n let den = 0;\n for (let i = 0; i < this.period; i++) {\n const w = i + 1;\n num += this.buf[i]! * w;\n den += w;\n }\n return (this.value = num / den);\n }\n}\n\n/** Relative Strength Index (Wilder's smoothing). O(1) per tick. */\nexport class RSI {\n private prev: number | null = null;\n private avgGain = 0;\n private avgLoss = 0;\n private count = 0;\n value: number | null = null;\n\n constructor(public readonly period: number = 14) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n if (this.prev === null) {\n this.prev = price;\n return (this.value = null);\n }\n const change = price - this.prev;\n this.prev = price;\n const gain = change > 0 ? change : 0;\n const loss = change < 0 ? -change : 0;\n this.count++;\n\n if (this.count <= this.period) {\n this.avgGain += gain;\n this.avgLoss += loss;\n if (this.count < this.period) return (this.value = null);\n this.avgGain /= this.period;\n this.avgLoss /= this.period;\n } else {\n this.avgGain = (this.avgGain * (this.period - 1) + gain) / this.period;\n this.avgLoss = (this.avgLoss * (this.period - 1) + loss) / this.period;\n }\n return (this.value = this.compute());\n }\n\n private compute(): number {\n if (this.avgLoss === 0) return 100;\n const rs = this.avgGain / this.avgLoss;\n return 100 - 100 / (1 + rs);\n }\n}\n\nexport interface MACDValue {\n macd: number;\n signal: number;\n histogram: number;\n}\n\n/** Moving Average Convergence Divergence. Defaults 12 / 26 / 9. */\nexport class MACD {\n private readonly fastEma: EMA;\n private readonly slowEma: EMA;\n private readonly signalEma: EMA;\n value: MACDValue | null = null;\n\n constructor(fast = 12, slow = 26, signal = 9) {\n this.fastEma = new EMA(fast);\n this.slowEma = new EMA(slow);\n this.signalEma = new EMA(signal);\n }\n\n next(price: number): MACDValue | null {\n const f = this.fastEma.next(price);\n const s = this.slowEma.next(price);\n if (f === null || s === null) return (this.value = null);\n const macd = f - s;\n const signal = this.signalEma.next(macd);\n if (signal === null) return (this.value = null);\n return (this.value = { macd, signal, histogram: macd - signal });\n }\n}\n\nexport interface BollingerValue {\n middle: number;\n upper: number;\n lower: number;\n /** (upper - lower) / middle — normalised band width. */\n bandwidth: number;\n}\n\n/** Bollinger Bands — SMA middle band ± `mult` standard deviations. */\nexport class BollingerBands {\n private buf: number[] = [];\n private sum = 0;\n value: BollingerValue | null = null;\n\n constructor(\n public readonly period = 20,\n public readonly mult = 2,\n ) {\n assertPeriod(period);\n }\n\n next(price: number): BollingerValue | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n if (this.buf.length < this.period) return (this.value = null);\n const mean = this.sum / this.period;\n let variance = 0;\n for (const v of this.buf) variance += (v - mean) ** 2;\n const sd = Math.sqrt(variance / this.period);\n const upper = mean + this.mult * sd;\n const lower = mean - this.mult * sd;\n return (this.value = {\n middle: mean,\n upper,\n lower,\n bandwidth: mean === 0 ? 0 : (upper - lower) / mean,\n });\n }\n}\n\n/** Average True Range (Wilder). Feed it high/low/close bars. */\nexport class ATR {\n private prevClose: number | null = null;\n private atr: number | null = null;\n private seed: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): number | null {\n const tr =\n this.prevClose === null\n ? bar.high - bar.low\n : Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevClose = bar.close;\n\n if (this.atr === null) {\n this.seed.push(tr);\n if (this.seed.length < this.period) return (this.value = null);\n this.atr = this.seed.reduce((a, b) => a + b, 0) / this.period;\n return (this.value = this.atr);\n }\n this.atr = (this.atr * (this.period - 1) + tr) / this.period;\n return (this.value = this.atr);\n }\n}\n\n/** Volume-Weighted Average Price. Cumulative — call `reset()` per session. */\nexport class VWAP {\n private pv = 0;\n private vol = 0;\n value: number | null = null;\n\n next(bar: Required<Pick<Candle, \"high\" | \"low\" | \"close\" | \"volume\">>): number | null {\n const typical = (bar.high + bar.low + bar.close) / 3;\n this.pv += typical * bar.volume;\n this.vol += bar.volume;\n return (this.value = this.vol === 0 ? null : this.pv / this.vol);\n }\n\n reset(): void {\n this.pv = 0;\n this.vol = 0;\n this.value = null;\n }\n}\n\nexport interface StochasticValue {\n /** %K — position of close within the recent high/low range (0–100). */\n k: number;\n /** %D — SMA of %K. */\n d: number;\n}\n\n/** Stochastic Oscillator (%K / %D). */\nexport class Stochastic {\n private highs: number[] = [];\n private lows: number[] = [];\n private readonly dSma: SMA;\n value: StochasticValue | null = null;\n\n constructor(\n public readonly period = 14,\n public readonly signal = 3,\n ) {\n assertPeriod(period);\n this.dSma = new SMA(signal);\n }\n\n next(bar: HLC): StochasticValue | null {\n this.highs.push(bar.high);\n this.lows.push(bar.low);\n if (this.highs.length > this.period) {\n this.highs.shift();\n this.lows.shift();\n }\n if (this.highs.length < this.period) return (this.value = null);\n const hh = Math.max(...this.highs);\n const ll = Math.min(...this.lows);\n const k = hh === ll ? 100 : ((bar.close - ll) / (hh - ll)) * 100;\n const d = this.dSma.next(k);\n if (d === null) return (this.value = null);\n return (this.value = { k, d });\n }\n}\n\nexport interface SupertrendValue {\n value: number;\n /** 1 = uptrend (price above band), -1 = downtrend. */\n direction: 1 | -1;\n}\n\n/** Supertrend — ATR-based trend follower. Defaults period 10, multiplier 3. */\nexport class Supertrend {\n private readonly atr: ATR;\n private prevClose: number | null = null;\n private prevFinalUpper = 0;\n private prevFinalLower = 0;\n private prevSupertrend: number | null = null;\n value: SupertrendValue | null = null;\n\n constructor(\n public readonly period = 10,\n public readonly mult = 3,\n ) {\n this.atr = new ATR(period);\n }\n\n next(bar: HLC): SupertrendValue | null {\n const atr = this.atr.next(bar);\n if (atr === null) {\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const hl2 = (bar.high + bar.low) / 2;\n const basicUpper = hl2 + this.mult * atr;\n const basicLower = hl2 - this.mult * atr;\n const pc = this.prevClose ?? bar.close;\n\n const first = this.prevSupertrend === null;\n const finalUpper =\n first || basicUpper < this.prevFinalUpper || pc > this.prevFinalUpper\n ? basicUpper\n : this.prevFinalUpper;\n const finalLower =\n first || basicLower > this.prevFinalLower || pc < this.prevFinalLower\n ? basicLower\n : this.prevFinalLower;\n\n let st: number;\n let direction: 1 | -1;\n if (first) {\n direction = bar.close <= finalUpper ? -1 : 1;\n st = direction === -1 ? finalUpper : finalLower;\n } else if (this.prevSupertrend === this.prevFinalUpper) {\n if (bar.close <= finalUpper) {\n st = finalUpper;\n direction = -1;\n } else {\n st = finalLower;\n direction = 1;\n }\n } else {\n if (bar.close >= finalLower) {\n st = finalLower;\n direction = 1;\n } else {\n st = finalUpper;\n direction = -1;\n }\n }\n\n this.prevFinalUpper = finalUpper;\n this.prevFinalLower = finalLower;\n this.prevSupertrend = st;\n this.prevClose = bar.close;\n return (this.value = { value: st, direction });\n }\n}\n\nexport interface ADXValue {\n adx: number;\n plusDI: number;\n minusDI: number;\n}\n\n/** Average Directional Index with +DI / -DI (Wilder). */\nexport class ADX {\n private prevHigh: number | null = null;\n private prevLow = 0;\n private prevClose = 0;\n private smTR = 0;\n private smPDM = 0;\n private smMDM = 0;\n private dxs: number[] = [];\n private adx: number | null = null;\n private count = 0;\n value: ADXValue | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): ADXValue | null {\n if (this.prevHigh === null) {\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const upMove = bar.high - this.prevHigh;\n const downMove = this.prevLow - bar.low;\n const pdm = upMove > downMove && upMove > 0 ? upMove : 0;\n const mdm = downMove > upMove && downMove > 0 ? downMove : 0;\n const tr = Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n this.count++;\n\n if (this.count <= this.period) {\n this.smTR += tr;\n this.smPDM += pdm;\n this.smMDM += mdm;\n if (this.count < this.period) return (this.value = null);\n } else {\n this.smTR = this.smTR - this.smTR / this.period + tr;\n this.smPDM = this.smPDM - this.smPDM / this.period + pdm;\n this.smMDM = this.smMDM - this.smMDM / this.period + mdm;\n }\n\n const plusDI = this.smTR === 0 ? 0 : (100 * this.smPDM) / this.smTR;\n const minusDI = this.smTR === 0 ? 0 : (100 * this.smMDM) / this.smTR;\n const diSum = plusDI + minusDI;\n const dx = diSum === 0 ? 0 : (100 * Math.abs(plusDI - minusDI)) / diSum;\n\n if (this.adx === null) {\n this.dxs.push(dx);\n if (this.dxs.length < this.period) return (this.value = null);\n this.adx = this.dxs.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.adx = (this.adx * (this.period - 1) + dx) / this.period;\n }\n return (this.value = { adx: this.adx, plusDI, minusDI });\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Batch helpers — run an indicator over an existing array in one call.\n * Each returns an array aligned to the input (nulls during warm-up).\n * ------------------------------------------------------------------ */\n\nfunction runNumber<T extends { next(v: number): number | null }>(\n ind: T,\n values: number[],\n): (number | null)[] {\n return values.map((v) => ind.next(v));\n}\n\nexport const sma = (values: number[], period: number) => runNumber(new SMA(period), values);\nexport const ema = (values: number[], period: number) => runNumber(new EMA(period), values);\nexport const wma = (values: number[], period: number) => runNumber(new WMA(period), values);\nexport const rsi = (values: number[], period = 14) => runNumber(new RSI(period), values);\n\nexport function macd(values: number[], fast = 12, slow = 26, signal = 9): (MACDValue | null)[] {\n const ind = new MACD(fast, slow, signal);\n return values.map((v) => ind.next(v));\n}\n\nexport function bollinger(values: number[], period = 20, mult = 2): (BollingerValue | null)[] {\n const ind = new BollingerBands(period, mult);\n return values.map((v) => ind.next(v));\n}\n\nexport function atr(bars: HLC[], period = 14): (number | null)[] {\n const ind = new ATR(period);\n return bars.map((b) => ind.next(b));\n}\n\nexport function supertrend(bars: HLC[], period = 10, mult = 3): (SupertrendValue | null)[] {\n const ind = new Supertrend(period, mult);\n return bars.map((b) => ind.next(b));\n}\n\nexport function adx(bars: HLC[], period = 14): (ADXValue | null)[] {\n const ind = new ADX(period);\n return bars.map((b) => ind.next(b));\n}\n\n/* ------------------------------------------------------------------ *\n * Crossover helpers — the backbone of most signal logic.\n * ------------------------------------------------------------------ */\n\n/** True when series A crossed from at-or-below B to strictly above B. */\nexport function crossedAbove(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a <= prev.b && curr.a > curr.b;\n}\n\n/** True when series A crossed from at-or-above B to strictly below B. */\nexport function crossedBelow(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a >= prev.b && curr.a < curr.b;\n}\n\n/* ------------------------------ tick → candle aggregation ------------------------------ */\n\nexport interface Tick {\n /** Epoch ms of the tick. */\n time: number;\n price: number;\n volume?: number;\n}\n\n/**\n * Aggregate a live tick/LTP stream into fixed-interval OHLC candles.\n * `add()` returns a COMPLETED candle when the interval rolls over, else null.\n * @example const agg = new CandleAggregator(60_000); // 1-minute candles\n */\nexport class CandleAggregator {\n private current: Candle | null = null;\n private bucketStart = 0;\n\n constructor(public readonly intervalMs: number) {\n if (!(intervalMs > 0)) throw new RangeError(`intervalMs must be > 0, got ${intervalMs}`);\n }\n\n private openCandle(tick: Tick, bucket: number): Candle {\n return { time: bucket, open: tick.price, high: tick.price, low: tick.price, close: tick.price, volume: tick.volume ?? 0 };\n }\n\n /** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */\n add(tick: Tick): Candle | null {\n const bucket = Math.floor(tick.time / this.intervalMs) * this.intervalMs;\n if (this.current === null) {\n this.bucketStart = bucket;\n this.current = this.openCandle(tick, bucket);\n return null;\n }\n if (bucket > this.bucketStart) {\n const completed = this.current;\n this.bucketStart = bucket;\n this.current = this.openCandle(tick, bucket);\n return completed;\n }\n this.current.high = Math.max(this.current.high, tick.price);\n this.current.low = Math.min(this.current.low, tick.price);\n this.current.close = tick.price;\n if (tick.volume) this.current.volume = (this.current.volume ?? 0) + tick.volume;\n return null;\n }\n\n /** The in-progress (not yet closed) candle, if any. */\n get pending(): Candle | null {\n return this.current ? { ...this.current } : null;\n }\n\n /** Close and return the current candle (e.g. at session end). */\n flush(): Candle | null {\n const c = this.current;\n this.current = null;\n return c;\n }\n}\n\n/* ------------------------------ candlestick patterns ------------------------------ */\n\nexport type CandlePattern =\n | \"doji\"\n | \"hammer\"\n | \"shootingStar\"\n | \"marubozu\"\n | \"bullishEngulfing\"\n | \"bearishEngulfing\"\n | \"bullishHarami\"\n | \"bearishHarami\";\n\nexport interface PatternHit {\n /** Index in the input array where the pattern completes. */\n index: number;\n pattern: CandlePattern;\n bullish: boolean;\n}\n\nfunction body(c: Candle): number {\n return Math.abs(c.close - c.open);\n}\nfunction upperWick(c: Candle): number {\n return c.high - Math.max(c.open, c.close);\n}\nfunction lowerWick(c: Candle): number {\n return Math.min(c.open, c.close) - c.low;\n}\n\n/** Detect common single- and two-candle patterns across a series. */\nexport function detectPatterns(candles: Candle[]): PatternHit[] {\n const hits: PatternHit[] = [];\n for (let i = 0; i < candles.length; i++) {\n const c = candles[i]!;\n const range = c.high - c.low;\n if (range <= 0) continue;\n const b = body(c);\n const up = upperWick(c);\n const lo = lowerWick(c);\n const bullish = c.close > c.open;\n\n if (b <= range * 0.1) hits.push({ index: i, pattern: \"doji\", bullish });\n else if (up <= range * 0.05 && lo <= range * 0.05) hits.push({ index: i, pattern: \"marubozu\", bullish });\n else if (lo >= b * 2 && up <= b * 0.6) hits.push({ index: i, pattern: \"hammer\", bullish: true });\n else if (up >= b * 2 && lo <= b * 0.6) hits.push({ index: i, pattern: \"shootingStar\", bullish: false });\n\n if (i > 0) {\n const p = candles[i - 1]!;\n const pBull = p.close > p.open;\n const pBody = body(p);\n // engulfing: current real body fully engulfs the previous real body\n if (!pBull && bullish && c.close >= p.open && c.open <= p.close && b > pBody)\n hits.push({ index: i, pattern: \"bullishEngulfing\", bullish: true });\n else if (pBull && !bullish && c.open >= p.close && c.close <= p.open && b > pBody)\n hits.push({ index: i, pattern: \"bearishEngulfing\", bullish: false });\n // harami: current small real body sits inside the previous real body\n else if (!pBull && bullish && c.open >= p.close && c.close <= p.open && b < pBody)\n hits.push({ index: i, pattern: \"bullishHarami\", bullish: true });\n else if (pBull && !bullish && c.close >= p.open && c.open <= p.close && b < pBody)\n hits.push({ index: i, pattern: \"bearishHarami\", bullish: false });\n }\n }\n return hits;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -192,5 +192,38 @@ declare function crossedBelow(prev: {
|
|
|
192
192
|
a: number;
|
|
193
193
|
b: number;
|
|
194
194
|
}): boolean;
|
|
195
|
+
interface Tick {
|
|
196
|
+
/** Epoch ms of the tick. */
|
|
197
|
+
time: number;
|
|
198
|
+
price: number;
|
|
199
|
+
volume?: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Aggregate a live tick/LTP stream into fixed-interval OHLC candles.
|
|
203
|
+
* `add()` returns a COMPLETED candle when the interval rolls over, else null.
|
|
204
|
+
* @example const agg = new CandleAggregator(60_000); // 1-minute candles
|
|
205
|
+
*/
|
|
206
|
+
declare class CandleAggregator {
|
|
207
|
+
readonly intervalMs: number;
|
|
208
|
+
private current;
|
|
209
|
+
private bucketStart;
|
|
210
|
+
constructor(intervalMs: number);
|
|
211
|
+
private openCandle;
|
|
212
|
+
/** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */
|
|
213
|
+
add(tick: Tick): Candle | null;
|
|
214
|
+
/** The in-progress (not yet closed) candle, if any. */
|
|
215
|
+
get pending(): Candle | null;
|
|
216
|
+
/** Close and return the current candle (e.g. at session end). */
|
|
217
|
+
flush(): Candle | null;
|
|
218
|
+
}
|
|
219
|
+
type CandlePattern = "doji" | "hammer" | "shootingStar" | "marubozu" | "bullishEngulfing" | "bearishEngulfing" | "bullishHarami" | "bearishHarami";
|
|
220
|
+
interface PatternHit {
|
|
221
|
+
/** Index in the input array where the pattern completes. */
|
|
222
|
+
index: number;
|
|
223
|
+
pattern: CandlePattern;
|
|
224
|
+
bullish: boolean;
|
|
225
|
+
}
|
|
226
|
+
/** Detect common single- and two-candle patterns across a series. */
|
|
227
|
+
declare function detectPatterns(candles: Candle[]): PatternHit[];
|
|
195
228
|
|
|
196
|
-
export { ADX, type ADXValue, ATR, BollingerBands, type BollingerValue, type Candle, EMA, type HLC, MACD, type MACDValue, RSI, SMA, Stochastic, type StochasticValue, Supertrend, type SupertrendValue, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, ema, macd, rsi, sma, supertrend, wma };
|
|
229
|
+
export { ADX, type ADXValue, ATR, BollingerBands, type BollingerValue, type Candle, CandleAggregator, type CandlePattern, EMA, type HLC, MACD, type MACDValue, type PatternHit, RSI, SMA, Stochastic, type StochasticValue, Supertrend, type SupertrendValue, type Tick, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, detectPatterns, ema, macd, rsi, sma, supertrend, wma };
|
package/dist/index.d.ts
CHANGED
|
@@ -192,5 +192,38 @@ declare function crossedBelow(prev: {
|
|
|
192
192
|
a: number;
|
|
193
193
|
b: number;
|
|
194
194
|
}): boolean;
|
|
195
|
+
interface Tick {
|
|
196
|
+
/** Epoch ms of the tick. */
|
|
197
|
+
time: number;
|
|
198
|
+
price: number;
|
|
199
|
+
volume?: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Aggregate a live tick/LTP stream into fixed-interval OHLC candles.
|
|
203
|
+
* `add()` returns a COMPLETED candle when the interval rolls over, else null.
|
|
204
|
+
* @example const agg = new CandleAggregator(60_000); // 1-minute candles
|
|
205
|
+
*/
|
|
206
|
+
declare class CandleAggregator {
|
|
207
|
+
readonly intervalMs: number;
|
|
208
|
+
private current;
|
|
209
|
+
private bucketStart;
|
|
210
|
+
constructor(intervalMs: number);
|
|
211
|
+
private openCandle;
|
|
212
|
+
/** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */
|
|
213
|
+
add(tick: Tick): Candle | null;
|
|
214
|
+
/** The in-progress (not yet closed) candle, if any. */
|
|
215
|
+
get pending(): Candle | null;
|
|
216
|
+
/** Close and return the current candle (e.g. at session end). */
|
|
217
|
+
flush(): Candle | null;
|
|
218
|
+
}
|
|
219
|
+
type CandlePattern = "doji" | "hammer" | "shootingStar" | "marubozu" | "bullishEngulfing" | "bearishEngulfing" | "bullishHarami" | "bearishHarami";
|
|
220
|
+
interface PatternHit {
|
|
221
|
+
/** Index in the input array where the pattern completes. */
|
|
222
|
+
index: number;
|
|
223
|
+
pattern: CandlePattern;
|
|
224
|
+
bullish: boolean;
|
|
225
|
+
}
|
|
226
|
+
/** Detect common single- and two-candle patterns across a series. */
|
|
227
|
+
declare function detectPatterns(candles: Candle[]): PatternHit[];
|
|
195
228
|
|
|
196
|
-
export { ADX, type ADXValue, ATR, BollingerBands, type BollingerValue, type Candle, EMA, type HLC, MACD, type MACDValue, RSI, SMA, Stochastic, type StochasticValue, Supertrend, type SupertrendValue, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, ema, macd, rsi, sma, supertrend, wma };
|
|
229
|
+
export { ADX, type ADXValue, ATR, BollingerBands, type BollingerValue, type Candle, CandleAggregator, type CandlePattern, EMA, type HLC, MACD, type MACDValue, type PatternHit, RSI, SMA, Stochastic, type StochasticValue, Supertrend, type SupertrendValue, type Tick, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, detectPatterns, ema, macd, rsi, sma, supertrend, wma };
|
package/dist/index.js
CHANGED
|
@@ -360,7 +360,87 @@ function crossedAbove(prev, curr) {
|
|
|
360
360
|
function crossedBelow(prev, curr) {
|
|
361
361
|
return prev.a >= prev.b && curr.a < curr.b;
|
|
362
362
|
}
|
|
363
|
+
var CandleAggregator = class {
|
|
364
|
+
constructor(intervalMs) {
|
|
365
|
+
this.intervalMs = intervalMs;
|
|
366
|
+
this.current = null;
|
|
367
|
+
this.bucketStart = 0;
|
|
368
|
+
if (!(intervalMs > 0)) throw new RangeError(`intervalMs must be > 0, got ${intervalMs}`);
|
|
369
|
+
}
|
|
370
|
+
openCandle(tick, bucket) {
|
|
371
|
+
return { time: bucket, open: tick.price, high: tick.price, low: tick.price, close: tick.price, volume: tick.volume ?? 0 };
|
|
372
|
+
}
|
|
373
|
+
/** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */
|
|
374
|
+
add(tick) {
|
|
375
|
+
const bucket = Math.floor(tick.time / this.intervalMs) * this.intervalMs;
|
|
376
|
+
if (this.current === null) {
|
|
377
|
+
this.bucketStart = bucket;
|
|
378
|
+
this.current = this.openCandle(tick, bucket);
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
if (bucket > this.bucketStart) {
|
|
382
|
+
const completed = this.current;
|
|
383
|
+
this.bucketStart = bucket;
|
|
384
|
+
this.current = this.openCandle(tick, bucket);
|
|
385
|
+
return completed;
|
|
386
|
+
}
|
|
387
|
+
this.current.high = Math.max(this.current.high, tick.price);
|
|
388
|
+
this.current.low = Math.min(this.current.low, tick.price);
|
|
389
|
+
this.current.close = tick.price;
|
|
390
|
+
if (tick.volume) this.current.volume = (this.current.volume ?? 0) + tick.volume;
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
/** The in-progress (not yet closed) candle, if any. */
|
|
394
|
+
get pending() {
|
|
395
|
+
return this.current ? { ...this.current } : null;
|
|
396
|
+
}
|
|
397
|
+
/** Close and return the current candle (e.g. at session end). */
|
|
398
|
+
flush() {
|
|
399
|
+
const c = this.current;
|
|
400
|
+
this.current = null;
|
|
401
|
+
return c;
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
function body(c) {
|
|
405
|
+
return Math.abs(c.close - c.open);
|
|
406
|
+
}
|
|
407
|
+
function upperWick(c) {
|
|
408
|
+
return c.high - Math.max(c.open, c.close);
|
|
409
|
+
}
|
|
410
|
+
function lowerWick(c) {
|
|
411
|
+
return Math.min(c.open, c.close) - c.low;
|
|
412
|
+
}
|
|
413
|
+
function detectPatterns(candles) {
|
|
414
|
+
const hits = [];
|
|
415
|
+
for (let i = 0; i < candles.length; i++) {
|
|
416
|
+
const c = candles[i];
|
|
417
|
+
const range = c.high - c.low;
|
|
418
|
+
if (range <= 0) continue;
|
|
419
|
+
const b = body(c);
|
|
420
|
+
const up = upperWick(c);
|
|
421
|
+
const lo = lowerWick(c);
|
|
422
|
+
const bullish = c.close > c.open;
|
|
423
|
+
if (b <= range * 0.1) hits.push({ index: i, pattern: "doji", bullish });
|
|
424
|
+
else if (up <= range * 0.05 && lo <= range * 0.05) hits.push({ index: i, pattern: "marubozu", bullish });
|
|
425
|
+
else if (lo >= b * 2 && up <= b * 0.6) hits.push({ index: i, pattern: "hammer", bullish: true });
|
|
426
|
+
else if (up >= b * 2 && lo <= b * 0.6) hits.push({ index: i, pattern: "shootingStar", bullish: false });
|
|
427
|
+
if (i > 0) {
|
|
428
|
+
const p = candles[i - 1];
|
|
429
|
+
const pBull = p.close > p.open;
|
|
430
|
+
const pBody = body(p);
|
|
431
|
+
if (!pBull && bullish && c.close >= p.open && c.open <= p.close && b > pBody)
|
|
432
|
+
hits.push({ index: i, pattern: "bullishEngulfing", bullish: true });
|
|
433
|
+
else if (pBull && !bullish && c.open >= p.close && c.close <= p.open && b > pBody)
|
|
434
|
+
hits.push({ index: i, pattern: "bearishEngulfing", bullish: false });
|
|
435
|
+
else if (!pBull && bullish && c.open >= p.close && c.close <= p.open && b < pBody)
|
|
436
|
+
hits.push({ index: i, pattern: "bullishHarami", bullish: true });
|
|
437
|
+
else if (pBull && !bullish && c.close >= p.open && c.open <= p.close && b < pBody)
|
|
438
|
+
hits.push({ index: i, pattern: "bearishHarami", bullish: false });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return hits;
|
|
442
|
+
}
|
|
363
443
|
|
|
364
|
-
export { ADX, ATR, BollingerBands, EMA, MACD, RSI, SMA, Stochastic, Supertrend, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, ema, macd, rsi, sma, supertrend, wma };
|
|
444
|
+
export { ADX, ATR, BollingerBands, CandleAggregator, EMA, MACD, RSI, SMA, Stochastic, Supertrend, VWAP, WMA, adx, atr, bollinger, crossedAbove, crossedBelow, detectPatterns, ema, macd, rsi, sma, supertrend, wma };
|
|
365
445
|
//# sourceMappingURL=index.js.map
|
|
366
446
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["macd","atr"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @lacspace/indicators\n * Streaming technical indicators for stock-market apps.\n *\n * Every indicator is a small class with an incremental `next()` that updates in\n * O(1) (or O(period) for window-based ones) — push one live tick, get the new\n * value, without recomputing the whole series. Perfect for live LTP feeds.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\nexport interface Candle {\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n time?: number;\n}\n\n/** A high/low/close bar — the minimum most range-based indicators need. */\nexport interface HLC {\n high: number;\n low: number;\n close: number;\n}\n\nfunction assertPeriod(period: number): void {\n if (!Number.isInteger(period) || period < 1) {\n throw new RangeError(`period must be a positive integer, got ${period}`);\n }\n}\n\n/** Simple Moving Average. Incremental O(1) using a running window sum. */\nexport class SMA {\n private buf: number[] = [];\n private sum = 0;\n /** Latest value, or `null` until `period` samples have been seen. */\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n this.value = this.buf.length === this.period ? this.sum / this.period : null;\n return this.value;\n }\n}\n\n/** Exponential Moving Average. Seeded with an SMA of the first `period` values. */\nexport class EMA {\n private readonly k: number;\n private seed: number[] = [];\n private ema: number | null = null;\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n this.k = 2 / (period + 1);\n }\n\n next(price: number): number | null {\n if (this.ema === null) {\n this.seed.push(price);\n if (this.seed.length < this.period) return (this.value = null);\n this.ema = this.seed.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.ema = price * this.k + this.ema * (1 - this.k);\n }\n return (this.value = this.ema);\n }\n}\n\n/** Weighted Moving Average — recent samples weighted linearly higher. */\nexport class WMA {\n private buf: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n if (this.buf.length > this.period) this.buf.shift();\n if (this.buf.length < this.period) return (this.value = null);\n let num = 0;\n let den = 0;\n for (let i = 0; i < this.period; i++) {\n const w = i + 1;\n num += this.buf[i]! * w;\n den += w;\n }\n return (this.value = num / den);\n }\n}\n\n/** Relative Strength Index (Wilder's smoothing). O(1) per tick. */\nexport class RSI {\n private prev: number | null = null;\n private avgGain = 0;\n private avgLoss = 0;\n private count = 0;\n value: number | null = null;\n\n constructor(public readonly period: number = 14) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n if (this.prev === null) {\n this.prev = price;\n return (this.value = null);\n }\n const change = price - this.prev;\n this.prev = price;\n const gain = change > 0 ? change : 0;\n const loss = change < 0 ? -change : 0;\n this.count++;\n\n if (this.count <= this.period) {\n this.avgGain += gain;\n this.avgLoss += loss;\n if (this.count < this.period) return (this.value = null);\n this.avgGain /= this.period;\n this.avgLoss /= this.period;\n } else {\n this.avgGain = (this.avgGain * (this.period - 1) + gain) / this.period;\n this.avgLoss = (this.avgLoss * (this.period - 1) + loss) / this.period;\n }\n return (this.value = this.compute());\n }\n\n private compute(): number {\n if (this.avgLoss === 0) return 100;\n const rs = this.avgGain / this.avgLoss;\n return 100 - 100 / (1 + rs);\n }\n}\n\nexport interface MACDValue {\n macd: number;\n signal: number;\n histogram: number;\n}\n\n/** Moving Average Convergence Divergence. Defaults 12 / 26 / 9. */\nexport class MACD {\n private readonly fastEma: EMA;\n private readonly slowEma: EMA;\n private readonly signalEma: EMA;\n value: MACDValue | null = null;\n\n constructor(fast = 12, slow = 26, signal = 9) {\n this.fastEma = new EMA(fast);\n this.slowEma = new EMA(slow);\n this.signalEma = new EMA(signal);\n }\n\n next(price: number): MACDValue | null {\n const f = this.fastEma.next(price);\n const s = this.slowEma.next(price);\n if (f === null || s === null) return (this.value = null);\n const macd = f - s;\n const signal = this.signalEma.next(macd);\n if (signal === null) return (this.value = null);\n return (this.value = { macd, signal, histogram: macd - signal });\n }\n}\n\nexport interface BollingerValue {\n middle: number;\n upper: number;\n lower: number;\n /** (upper - lower) / middle — normalised band width. */\n bandwidth: number;\n}\n\n/** Bollinger Bands — SMA middle band ± `mult` standard deviations. */\nexport class BollingerBands {\n private buf: number[] = [];\n private sum = 0;\n value: BollingerValue | null = null;\n\n constructor(\n public readonly period = 20,\n public readonly mult = 2,\n ) {\n assertPeriod(period);\n }\n\n next(price: number): BollingerValue | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n if (this.buf.length < this.period) return (this.value = null);\n const mean = this.sum / this.period;\n let variance = 0;\n for (const v of this.buf) variance += (v - mean) ** 2;\n const sd = Math.sqrt(variance / this.period);\n const upper = mean + this.mult * sd;\n const lower = mean - this.mult * sd;\n return (this.value = {\n middle: mean,\n upper,\n lower,\n bandwidth: mean === 0 ? 0 : (upper - lower) / mean,\n });\n }\n}\n\n/** Average True Range (Wilder). Feed it high/low/close bars. */\nexport class ATR {\n private prevClose: number | null = null;\n private atr: number | null = null;\n private seed: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): number | null {\n const tr =\n this.prevClose === null\n ? bar.high - bar.low\n : Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevClose = bar.close;\n\n if (this.atr === null) {\n this.seed.push(tr);\n if (this.seed.length < this.period) return (this.value = null);\n this.atr = this.seed.reduce((a, b) => a + b, 0) / this.period;\n return (this.value = this.atr);\n }\n this.atr = (this.atr * (this.period - 1) + tr) / this.period;\n return (this.value = this.atr);\n }\n}\n\n/** Volume-Weighted Average Price. Cumulative — call `reset()` per session. */\nexport class VWAP {\n private pv = 0;\n private vol = 0;\n value: number | null = null;\n\n next(bar: Required<Pick<Candle, \"high\" | \"low\" | \"close\" | \"volume\">>): number | null {\n const typical = (bar.high + bar.low + bar.close) / 3;\n this.pv += typical * bar.volume;\n this.vol += bar.volume;\n return (this.value = this.vol === 0 ? null : this.pv / this.vol);\n }\n\n reset(): void {\n this.pv = 0;\n this.vol = 0;\n this.value = null;\n }\n}\n\nexport interface StochasticValue {\n /** %K — position of close within the recent high/low range (0–100). */\n k: number;\n /** %D — SMA of %K. */\n d: number;\n}\n\n/** Stochastic Oscillator (%K / %D). */\nexport class Stochastic {\n private highs: number[] = [];\n private lows: number[] = [];\n private readonly dSma: SMA;\n value: StochasticValue | null = null;\n\n constructor(\n public readonly period = 14,\n public readonly signal = 3,\n ) {\n assertPeriod(period);\n this.dSma = new SMA(signal);\n }\n\n next(bar: HLC): StochasticValue | null {\n this.highs.push(bar.high);\n this.lows.push(bar.low);\n if (this.highs.length > this.period) {\n this.highs.shift();\n this.lows.shift();\n }\n if (this.highs.length < this.period) return (this.value = null);\n const hh = Math.max(...this.highs);\n const ll = Math.min(...this.lows);\n const k = hh === ll ? 100 : ((bar.close - ll) / (hh - ll)) * 100;\n const d = this.dSma.next(k);\n if (d === null) return (this.value = null);\n return (this.value = { k, d });\n }\n}\n\nexport interface SupertrendValue {\n value: number;\n /** 1 = uptrend (price above band), -1 = downtrend. */\n direction: 1 | -1;\n}\n\n/** Supertrend — ATR-based trend follower. Defaults period 10, multiplier 3. */\nexport class Supertrend {\n private readonly atr: ATR;\n private prevClose: number | null = null;\n private prevFinalUpper = 0;\n private prevFinalLower = 0;\n private prevSupertrend: number | null = null;\n value: SupertrendValue | null = null;\n\n constructor(\n public readonly period = 10,\n public readonly mult = 3,\n ) {\n this.atr = new ATR(period);\n }\n\n next(bar: HLC): SupertrendValue | null {\n const atr = this.atr.next(bar);\n if (atr === null) {\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const hl2 = (bar.high + bar.low) / 2;\n const basicUpper = hl2 + this.mult * atr;\n const basicLower = hl2 - this.mult * atr;\n const pc = this.prevClose ?? bar.close;\n\n const first = this.prevSupertrend === null;\n const finalUpper =\n first || basicUpper < this.prevFinalUpper || pc > this.prevFinalUpper\n ? basicUpper\n : this.prevFinalUpper;\n const finalLower =\n first || basicLower > this.prevFinalLower || pc < this.prevFinalLower\n ? basicLower\n : this.prevFinalLower;\n\n let st: number;\n let direction: 1 | -1;\n if (first) {\n direction = bar.close <= finalUpper ? -1 : 1;\n st = direction === -1 ? finalUpper : finalLower;\n } else if (this.prevSupertrend === this.prevFinalUpper) {\n if (bar.close <= finalUpper) {\n st = finalUpper;\n direction = -1;\n } else {\n st = finalLower;\n direction = 1;\n }\n } else {\n if (bar.close >= finalLower) {\n st = finalLower;\n direction = 1;\n } else {\n st = finalUpper;\n direction = -1;\n }\n }\n\n this.prevFinalUpper = finalUpper;\n this.prevFinalLower = finalLower;\n this.prevSupertrend = st;\n this.prevClose = bar.close;\n return (this.value = { value: st, direction });\n }\n}\n\nexport interface ADXValue {\n adx: number;\n plusDI: number;\n minusDI: number;\n}\n\n/** Average Directional Index with +DI / -DI (Wilder). */\nexport class ADX {\n private prevHigh: number | null = null;\n private prevLow = 0;\n private prevClose = 0;\n private smTR = 0;\n private smPDM = 0;\n private smMDM = 0;\n private dxs: number[] = [];\n private adx: number | null = null;\n private count = 0;\n value: ADXValue | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): ADXValue | null {\n if (this.prevHigh === null) {\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const upMove = bar.high - this.prevHigh;\n const downMove = this.prevLow - bar.low;\n const pdm = upMove > downMove && upMove > 0 ? upMove : 0;\n const mdm = downMove > upMove && downMove > 0 ? downMove : 0;\n const tr = Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n this.count++;\n\n if (this.count <= this.period) {\n this.smTR += tr;\n this.smPDM += pdm;\n this.smMDM += mdm;\n if (this.count < this.period) return (this.value = null);\n } else {\n this.smTR = this.smTR - this.smTR / this.period + tr;\n this.smPDM = this.smPDM - this.smPDM / this.period + pdm;\n this.smMDM = this.smMDM - this.smMDM / this.period + mdm;\n }\n\n const plusDI = this.smTR === 0 ? 0 : (100 * this.smPDM) / this.smTR;\n const minusDI = this.smTR === 0 ? 0 : (100 * this.smMDM) / this.smTR;\n const diSum = plusDI + minusDI;\n const dx = diSum === 0 ? 0 : (100 * Math.abs(plusDI - minusDI)) / diSum;\n\n if (this.adx === null) {\n this.dxs.push(dx);\n if (this.dxs.length < this.period) return (this.value = null);\n this.adx = this.dxs.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.adx = (this.adx * (this.period - 1) + dx) / this.period;\n }\n return (this.value = { adx: this.adx, plusDI, minusDI });\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Batch helpers — run an indicator over an existing array in one call.\n * Each returns an array aligned to the input (nulls during warm-up).\n * ------------------------------------------------------------------ */\n\nfunction runNumber<T extends { next(v: number): number | null }>(\n ind: T,\n values: number[],\n): (number | null)[] {\n return values.map((v) => ind.next(v));\n}\n\nexport const sma = (values: number[], period: number) => runNumber(new SMA(period), values);\nexport const ema = (values: number[], period: number) => runNumber(new EMA(period), values);\nexport const wma = (values: number[], period: number) => runNumber(new WMA(period), values);\nexport const rsi = (values: number[], period = 14) => runNumber(new RSI(period), values);\n\nexport function macd(values: number[], fast = 12, slow = 26, signal = 9): (MACDValue | null)[] {\n const ind = new MACD(fast, slow, signal);\n return values.map((v) => ind.next(v));\n}\n\nexport function bollinger(values: number[], period = 20, mult = 2): (BollingerValue | null)[] {\n const ind = new BollingerBands(period, mult);\n return values.map((v) => ind.next(v));\n}\n\nexport function atr(bars: HLC[], period = 14): (number | null)[] {\n const ind = new ATR(period);\n return bars.map((b) => ind.next(b));\n}\n\nexport function supertrend(bars: HLC[], period = 10, mult = 3): (SupertrendValue | null)[] {\n const ind = new Supertrend(period, mult);\n return bars.map((b) => ind.next(b));\n}\n\nexport function adx(bars: HLC[], period = 14): (ADXValue | null)[] {\n const ind = new ADX(period);\n return bars.map((b) => ind.next(b));\n}\n\n/* ------------------------------------------------------------------ *\n * Crossover helpers — the backbone of most signal logic.\n * ------------------------------------------------------------------ */\n\n/** True when series A crossed from at-or-below B to strictly above B. */\nexport function crossedAbove(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a <= prev.b && curr.a > curr.b;\n}\n\n/** True when series A crossed from at-or-above B to strictly below B. */\nexport function crossedBelow(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a >= prev.b && curr.a < curr.b;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["macd","atr"],"mappings":";AA2BA,SAAS,aAAa,MAAA,EAAsB;AAC1C,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,IAAK,SAAS,CAAA,EAAG;AAC3C,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,uCAAA,EAA0C,MAAM,CAAA,CAAE,CAAA;AAAA,EACzE;AACF;AAGO,IAAM,MAAN,MAAU;AAAA,EAMf,YAA4B,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAL5B,IAAA,IAAA,CAAQ,MAAgB,EAAC;AACzB,IAAA,IAAA,CAAQ,GAAA,GAAM,CAAA;AAEd;AAAA,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAGrB,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,KAAK,CAAA;AACnB,IAAA,IAAA,CAAK,GAAA,IAAO,KAAA;AACZ,IAAA,IAAI,IAAA,CAAK,IAAI,MAAA,GAAS,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,GAAA,CAAI,KAAA,EAAM;AAC9D,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAK,GAAA,CAAI,MAAA,KAAW,KAAK,MAAA,GAAS,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,MAAA,GAAS,IAAA;AACxE,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF;AAGO,IAAM,MAAN,MAAU;AAAA,EAMf,YAA4B,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAJ5B,IAAA,IAAA,CAAQ,OAAiB,EAAC;AAC1B,IAAA,IAAA,CAAQ,GAAA,GAAqB,IAAA;AAC7B,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAGrB,IAAA,YAAA,CAAa,MAAM,CAAA;AACnB,IAAA,IAAA,CAAK,CAAA,GAAI,KAAK,MAAA,GAAS,CAAA,CAAA;AAAA,EACzB;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,IAAA,CAAK,IAAA,CAAK,KAAK,KAAK,CAAA;AACpB,MAAA,IAAI,KAAK,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACzD,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,MAAA;AAAA,IACzD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAI,IAAA,CAAK,GAAA,IAAO,IAAI,IAAA,CAAK,CAAA,CAAA;AAAA,IACnD;AACA,IAAA,OAAQ,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA;AAAA,EAC5B;AACF;AAGO,IAAM,MAAN,MAAU;AAAA,EAIf,YAA4B,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAH5B,IAAA,IAAA,CAAQ,MAAgB,EAAC;AACzB,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAGrB,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,KAAK,CAAA;AACnB,IAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAK,MAAA,EAAQ,IAAA,CAAK,IAAI,KAAA,EAAM;AAClD,IAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACxD,IAAA,IAAI,GAAA,GAAM,CAAA;AACV,IAAA,IAAI,GAAA,GAAM,CAAA;AACV,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,MAAA,MAAM,IAAI,CAAA,GAAI,CAAA;AACd,MAAA,GAAA,IAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAK,CAAA;AACtB,MAAA,GAAA,IAAO,CAAA;AAAA,IACT;AACA,IAAA,OAAQ,IAAA,CAAK,QAAQ,GAAA,GAAM,GAAA;AAAA,EAC7B;AACF;AAGO,IAAM,MAAN,MAAU;AAAA,EAOf,WAAA,CAA4B,SAAiB,EAAA,EAAI;AAArB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAN5B,IAAA,IAAA,CAAQ,IAAA,GAAsB,IAAA;AAC9B,IAAA,IAAA,CAAQ,OAAA,GAAU,CAAA;AAClB,IAAA,IAAA,CAAQ,OAAA,GAAU,CAAA;AAClB,IAAA,IAAA,CAAQ,KAAA,GAAQ,CAAA;AAChB,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAGrB,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,IAAI,IAAA,CAAK,SAAS,IAAA,EAAM;AACtB,MAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,MAAA,OAAQ,KAAK,KAAA,GAAQ,IAAA;AAAA,IACvB;AACA,IAAA,MAAM,MAAA,GAAS,QAAQ,IAAA,CAAK,IAAA;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,IAAA,MAAM,IAAA,GAAO,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS,CAAA;AACnC,IAAA,MAAM,IAAA,GAAO,MAAA,GAAS,CAAA,GAAI,CAAC,MAAA,GAAS,CAAA;AACpC,IAAA,IAAA,CAAK,KAAA,EAAA;AAEL,IAAA,IAAI,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,MAAA,EAAQ;AAC7B,MAAA,IAAA,CAAK,OAAA,IAAW,IAAA;AAChB,MAAA,IAAA,CAAK,OAAA,IAAW,IAAA;AAChB,MAAA,IAAI,KAAK,KAAA,GAAQ,IAAA,CAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACnD,MAAA,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA;AACrB,MAAA,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA;AAAA,IACvB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,WAAW,IAAA,CAAK,OAAA,IAAW,KAAK,MAAA,GAAS,CAAA,CAAA,GAAK,QAAQ,IAAA,CAAK,MAAA;AAChE,MAAA,IAAA,CAAK,WAAW,IAAA,CAAK,OAAA,IAAW,KAAK,MAAA,GAAS,CAAA,CAAA,GAAK,QAAQ,IAAA,CAAK,MAAA;AAAA,IAClE;AACA,IAAA,OAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,OAAA,EAAQ;AAAA,EACpC;AAAA,EAEQ,OAAA,GAAkB;AACxB,IAAA,IAAI,IAAA,CAAK,OAAA,KAAY,CAAA,EAAG,OAAO,GAAA;AAC/B,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,OAAA;AAC/B,IAAA,OAAO,GAAA,GAAM,OAAO,CAAA,GAAI,EAAA,CAAA;AAAA,EAC1B;AACF;AASO,IAAM,OAAN,MAAW;AAAA,EAMhB,YAAY,IAAA,GAAO,EAAA,EAAI,IAAA,GAAO,EAAA,EAAI,SAAS,CAAA,EAAG;AAF9C,IAAA,IAAA,CAAA,KAAA,GAA0B,IAAA;AAGxB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,GAAA,CAAI,IAAI,CAAA;AAC3B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,GAAA,CAAI,IAAI,CAAA;AAC3B,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,GAAA,CAAI,MAAM,CAAA;AAAA,EACjC;AAAA,EAEA,KAAK,KAAA,EAAiC;AACpC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AACjC,IAAA,IAAI,MAAM,IAAA,IAAQ,CAAA,KAAM,IAAA,EAAM,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACnD,IAAA,MAAMA,QAAO,CAAA,GAAI,CAAA;AACjB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,IAAA,CAAKA,KAAI,CAAA;AACvC,IAAA,IAAI,MAAA,KAAW,IAAA,EAAM,OAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA;AAC1C,IAAA,OAAQ,IAAA,CAAK,QAAQ,EAAE,IAAA,EAAAA,OAAM,MAAA,EAAQ,SAAA,EAAWA,QAAO,MAAA,EAAO;AAAA,EAChE;AACF;AAWO,IAAM,iBAAN,MAAqB;AAAA,EAK1B,WAAA,CACkB,MAAA,GAAS,EAAA,EACT,IAAA,GAAO,CAAA,EACvB;AAFgB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AANlB,IAAA,IAAA,CAAQ,MAAgB,EAAC;AACzB,IAAA,IAAA,CAAQ,GAAA,GAAM,CAAA;AACd,IAAA,IAAA,CAAA,KAAA,GAA+B,IAAA;AAM7B,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,KAAA,EAAsC;AACzC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,KAAK,CAAA;AACnB,IAAA,IAAA,CAAK,GAAA,IAAO,KAAA;AACZ,IAAA,IAAI,IAAA,CAAK,IAAI,MAAA,GAAS,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,GAAA,CAAI,KAAA,EAAM;AAC9D,IAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACxD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,MAAA;AAC7B,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,GAAA,EAAK,QAAA,IAAA,CAAa,IAAI,IAAA,KAAS,CAAA;AACpD,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,QAAA,GAAW,KAAK,MAAM,CAAA;AAC3C,IAAA,MAAM,KAAA,GAAQ,IAAA,GAAO,IAAA,CAAK,IAAA,GAAO,EAAA;AACjC,IAAA,MAAM,KAAA,GAAQ,IAAA,GAAO,IAAA,CAAK,IAAA,GAAO,EAAA;AACjC,IAAA,OAAQ,KAAK,KAAA,GAAQ;AAAA,MACnB,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA,EAAW,IAAA,KAAS,CAAA,GAAI,CAAA,GAAA,CAAK,QAAQ,KAAA,IAAS;AAAA,KAChD;AAAA,EACF;AACF;AAGO,IAAM,MAAN,MAAU;AAAA,EAMf,WAAA,CAA4B,SAAS,EAAA,EAAI;AAAb,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAL5B,IAAA,IAAA,CAAQ,SAAA,GAA2B,IAAA;AACnC,IAAA,IAAA,CAAQ,GAAA,GAAqB,IAAA;AAC7B,IAAA,IAAA,CAAQ,OAAiB,EAAC;AAC1B,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAGrB,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,GAAA,EAAyB;AAC5B,IAAA,MAAM,EAAA,GACJ,KAAK,SAAA,KAAc,IAAA,GACf,IAAI,IAAA,GAAO,GAAA,CAAI,MACf,IAAA,CAAK,GAAA;AAAA,MACH,GAAA,CAAI,OAAO,GAAA,CAAI,GAAA;AAAA,MACf,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,IAAA,GAAO,KAAK,SAAS,CAAA;AAAA,MAClC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,GAAM,KAAK,SAAS;AAAA,KACnC;AACN,IAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAA;AAErB,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,IAAA,CAAK,IAAA,CAAK,KAAK,EAAE,CAAA;AACjB,MAAA,IAAI,KAAK,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACzD,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,MAAA;AACvD,MAAA,OAAQ,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA;AAAA,IAC5B;AACA,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,GAAA,IAAO,KAAK,MAAA,GAAS,CAAA,CAAA,GAAK,MAAM,IAAA,CAAK,MAAA;AACtD,IAAA,OAAQ,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA;AAAA,EAC5B;AACF;AAGO,IAAM,OAAN,MAAW;AAAA,EAAX,WAAA,GAAA;AACL,IAAA,IAAA,CAAQ,EAAA,GAAK,CAAA;AACb,IAAA,IAAA,CAAQ,GAAA,GAAM,CAAA;AACd,IAAA,IAAA,CAAA,KAAA,GAAuB,IAAA;AAAA,EAAA;AAAA,EAEvB,KAAK,GAAA,EAAiF;AACpF,IAAA,MAAM,WAAW,GAAA,CAAI,IAAA,GAAO,GAAA,CAAI,GAAA,GAAM,IAAI,KAAA,IAAS,CAAA;AACnD,IAAA,IAAA,CAAK,EAAA,IAAM,UAAU,GAAA,CAAI,MAAA;AACzB,IAAA,IAAA,CAAK,OAAO,GAAA,CAAI,MAAA;AAChB,IAAA,OAAQ,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA,KAAQ,IAAI,IAAA,GAAO,IAAA,CAAK,KAAK,IAAA,CAAK,GAAA;AAAA,EAC9D;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,EAAA,GAAK,CAAA;AACV,IAAA,IAAA,CAAK,GAAA,GAAM,CAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACf;AACF;AAUO,IAAM,aAAN,MAAiB;AAAA,EAMtB,WAAA,CACkB,MAAA,GAAS,EAAA,EACT,MAAA,GAAS,CAAA,EACzB;AAFgB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAPlB,IAAA,IAAA,CAAQ,QAAkB,EAAC;AAC3B,IAAA,IAAA,CAAQ,OAAiB,EAAC;AAE1B,IAAA,IAAA,CAAA,KAAA,GAAgC,IAAA;AAM9B,IAAA,YAAA,CAAa,MAAM,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,GAAA,CAAI,MAAM,CAAA;AAAA,EAC5B;AAAA,EAEA,KAAK,GAAA,EAAkC;AACrC,IAAA,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AACtB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,IAAA,CAAK,MAAA,EAAQ;AACnC,MAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,MAAA,IAAA,CAAK,KAAK,KAAA,EAAM;AAAA,IAClB;AACA,IAAA,IAAI,KAAK,KAAA,CAAM,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AAC1D,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,KAAK,CAAA;AACjC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,IAAI,CAAA;AAChC,IAAA,MAAM,CAAA,GAAI,OAAO,EAAA,GAAK,GAAA,GAAA,CAAQ,IAAI,KAAA,GAAQ,EAAA,KAAO,KAAK,EAAA,CAAA,GAAO,GAAA;AAC7D,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAC1B,IAAA,IAAI,CAAA,KAAM,IAAA,EAAM,OAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA;AACrC,IAAA,OAAQ,IAAA,CAAK,KAAA,GAAQ,EAAE,CAAA,EAAG,CAAA,EAAE;AAAA,EAC9B;AACF;AASO,IAAM,aAAN,MAAiB;AAAA,EAQtB,WAAA,CACkB,MAAA,GAAS,EAAA,EACT,IAAA,GAAO,CAAA,EACvB;AAFgB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AARlB,IAAA,IAAA,CAAQ,SAAA,GAA2B,IAAA;AACnC,IAAA,IAAA,CAAQ,cAAA,GAAiB,CAAA;AACzB,IAAA,IAAA,CAAQ,cAAA,GAAiB,CAAA;AACzB,IAAA,IAAA,CAAQ,cAAA,GAAgC,IAAA;AACxC,IAAA,IAAA,CAAA,KAAA,GAAgC,IAAA;AAM9B,IAAA,IAAA,CAAK,GAAA,GAAM,IAAI,GAAA,CAAI,MAAM,CAAA;AAAA,EAC3B;AAAA,EAEA,KAAK,GAAA,EAAkC;AACrC,IAAA,MAAMC,IAAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA;AAC7B,IAAA,IAAIA,SAAQ,IAAA,EAAM;AAChB,MAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAA;AACrB,MAAA,OAAQ,KAAK,KAAA,GAAQ,IAAA;AAAA,IACvB;AACA,IAAA,MAAM,GAAA,GAAA,CAAO,GAAA,CAAI,IAAA,GAAO,GAAA,CAAI,GAAA,IAAO,CAAA;AACnC,IAAA,MAAM,UAAA,GAAa,GAAA,GAAM,IAAA,CAAK,IAAA,GAAOA,IAAAA;AACrC,IAAA,MAAM,UAAA,GAAa,GAAA,GAAM,IAAA,CAAK,IAAA,GAAOA,IAAAA;AACrC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,SAAA,IAAa,GAAA,CAAI,KAAA;AAEjC,IAAA,MAAM,KAAA,GAAQ,KAAK,cAAA,KAAmB,IAAA;AACtC,IAAA,MAAM,UAAA,GACJ,SAAS,UAAA,GAAa,IAAA,CAAK,kBAAkB,EAAA,GAAK,IAAA,CAAK,cAAA,GACnD,UAAA,GACA,IAAA,CAAK,cAAA;AACX,IAAA,MAAM,UAAA,GACJ,SAAS,UAAA,GAAa,IAAA,CAAK,kBAAkB,EAAA,GAAK,IAAA,CAAK,cAAA,GACnD,UAAA,GACA,IAAA,CAAK,cAAA;AAEX,IAAA,IAAI,EAAA;AACJ,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,SAAA,GAAY,GAAA,CAAI,KAAA,IAAS,UAAA,GAAa,EAAA,GAAK,CAAA;AAC3C,MAAA,EAAA,GAAK,SAAA,KAAc,KAAK,UAAA,GAAa,UAAA;AAAA,IACvC,CAAA,MAAA,IAAW,IAAA,CAAK,cAAA,KAAmB,IAAA,CAAK,cAAA,EAAgB;AACtD,MAAA,IAAI,GAAA,CAAI,SAAS,UAAA,EAAY;AAC3B,QAAA,EAAA,GAAK,UAAA;AACL,QAAA,SAAA,GAAY,EAAA;AAAA,MACd,CAAA,MAAO;AACL,QAAA,EAAA,GAAK,UAAA;AACL,QAAA,SAAA,GAAY,CAAA;AAAA,MACd;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAI,GAAA,CAAI,SAAS,UAAA,EAAY;AAC3B,QAAA,EAAA,GAAK,UAAA;AACL,QAAA,SAAA,GAAY,CAAA;AAAA,MACd,CAAA,MAAO;AACL,QAAA,EAAA,GAAK,UAAA;AACL,QAAA,SAAA,GAAY,EAAA;AAAA,MACd;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,cAAA,GAAiB,UAAA;AACtB,IAAA,IAAA,CAAK,cAAA,GAAiB,UAAA;AACtB,IAAA,IAAA,CAAK,cAAA,GAAiB,EAAA;AACtB,IAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAA;AACrB,IAAA,OAAQ,IAAA,CAAK,KAAA,GAAQ,EAAE,KAAA,EAAO,IAAI,SAAA,EAAU;AAAA,EAC9C;AACF;AASO,IAAM,MAAN,MAAU;AAAA,EAYf,WAAA,CAA4B,SAAS,EAAA,EAAI;AAAb,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAX5B,IAAA,IAAA,CAAQ,QAAA,GAA0B,IAAA;AAClC,IAAA,IAAA,CAAQ,OAAA,GAAU,CAAA;AAClB,IAAA,IAAA,CAAQ,SAAA,GAAY,CAAA;AACpB,IAAA,IAAA,CAAQ,IAAA,GAAO,CAAA;AACf,IAAA,IAAA,CAAQ,KAAA,GAAQ,CAAA;AAChB,IAAA,IAAA,CAAQ,KAAA,GAAQ,CAAA;AAChB,IAAA,IAAA,CAAQ,MAAgB,EAAC;AACzB,IAAA,IAAA,CAAQ,GAAA,GAAqB,IAAA;AAC7B,IAAA,IAAA,CAAQ,KAAA,GAAQ,CAAA;AAChB,IAAA,IAAA,CAAA,KAAA,GAAyB,IAAA;AAGvB,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,GAAA,EAA2B;AAC9B,IAAA,IAAI,IAAA,CAAK,aAAa,IAAA,EAAM;AAC1B,MAAA,IAAA,CAAK,WAAW,GAAA,CAAI,IAAA;AACpB,MAAA,IAAA,CAAK,UAAU,GAAA,CAAI,GAAA;AACnB,MAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAA;AACrB,MAAA,OAAQ,KAAK,KAAA,GAAQ,IAAA;AAAA,IACvB;AACA,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,IAAA,GAAO,IAAA,CAAK,QAAA;AAC/B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,GAAU,GAAA,CAAI,GAAA;AACpC,IAAA,MAAM,GAAA,GAAM,MAAA,GAAS,QAAA,IAAY,MAAA,GAAS,IAAI,MAAA,GAAS,CAAA;AACvD,IAAA,MAAM,GAAA,GAAM,QAAA,GAAW,MAAA,IAAU,QAAA,GAAW,IAAI,QAAA,GAAW,CAAA;AAC3D,IAAA,MAAM,KAAK,IAAA,CAAK,GAAA;AAAA,MACd,GAAA,CAAI,OAAO,GAAA,CAAI,GAAA;AAAA,MACf,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,IAAA,GAAO,KAAK,SAAS,CAAA;AAAA,MAClC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,GAAM,KAAK,SAAS;AAAA,KACnC;AACA,IAAA,IAAA,CAAK,WAAW,GAAA,CAAI,IAAA;AACpB,IAAA,IAAA,CAAK,UAAU,GAAA,CAAI,GAAA;AACnB,IAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAA;AACrB,IAAA,IAAA,CAAK,KAAA,EAAA;AAEL,IAAA,IAAI,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,MAAA,EAAQ;AAC7B,MAAA,IAAA,CAAK,IAAA,IAAQ,EAAA;AACb,MAAA,IAAA,CAAK,KAAA,IAAS,GAAA;AACd,MAAA,IAAA,CAAK,KAAA,IAAS,GAAA;AACd,MAAA,IAAI,KAAK,KAAA,GAAQ,IAAA,CAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AAAA,IACrD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,GAAO,KAAK,MAAA,GAAS,EAAA;AAClD,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,GAAQ,KAAK,MAAA,GAAS,GAAA;AACrD,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,GAAQ,KAAK,MAAA,GAAS,GAAA;AAAA,IACvD;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,IAAA,KAAS,CAAA,GAAI,IAAK,GAAA,GAAM,IAAA,CAAK,QAAS,IAAA,CAAK,IAAA;AAC/D,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,KAAS,CAAA,GAAI,IAAK,GAAA,GAAM,IAAA,CAAK,QAAS,IAAA,CAAK,IAAA;AAChE,IAAA,MAAM,QAAQ,MAAA,GAAS,OAAA;AACvB,IAAA,MAAM,EAAA,GAAK,UAAU,CAAA,GAAI,CAAA,GAAK,MAAM,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,OAAO,CAAA,GAAK,KAAA;AAElE,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,IAAA,CAAK,GAAA,CAAI,KAAK,EAAE,CAAA;AAChB,MAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAK,MAAA,EAAQ,OAAQ,KAAK,KAAA,GAAQ,IAAA;AACxD,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,MAAA;AAAA,IACxD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK,GAAA,IAAO,KAAK,MAAA,GAAS,CAAA,CAAA,GAAK,MAAM,IAAA,CAAK,MAAA;AAAA,IACxD;AACA,IAAA,OAAQ,KAAK,KAAA,GAAQ,EAAE,KAAK,IAAA,CAAK,GAAA,EAAK,QAAQ,OAAA,EAAQ;AAAA,EACxD;AACF;AAOA,SAAS,SAAA,CACP,KACA,MAAA,EACmB;AACnB,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACtC;AAEO,IAAM,GAAA,GAAM,CAAC,MAAA,EAAkB,MAAA,KAAmB,UAAU,IAAI,GAAA,CAAI,MAAM,CAAA,EAAG,MAAM;AACnF,IAAM,GAAA,GAAM,CAAC,MAAA,EAAkB,MAAA,KAAmB,UAAU,IAAI,GAAA,CAAI,MAAM,CAAA,EAAG,MAAM;AACnF,IAAM,GAAA,GAAM,CAAC,MAAA,EAAkB,MAAA,KAAmB,UAAU,IAAI,GAAA,CAAI,MAAM,CAAA,EAAG,MAAM;AACnF,IAAM,GAAA,GAAM,CAAC,MAAA,EAAkB,MAAA,GAAS,EAAA,KAAO,UAAU,IAAI,GAAA,CAAI,MAAM,CAAA,EAAG,MAAM;AAEhF,SAAS,KAAK,MAAA,EAAkB,IAAA,GAAO,IAAI,IAAA,GAAO,EAAA,EAAI,SAAS,CAAA,EAAyB;AAC7F,EAAA,MAAM,GAAA,GAAM,IAAI,IAAA,CAAK,IAAA,EAAM,MAAM,MAAM,CAAA;AACvC,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACtC;AAEO,SAAS,SAAA,CAAU,MAAA,EAAkB,MAAA,GAAS,EAAA,EAAI,OAAO,CAAA,EAA8B;AAC5F,EAAA,MAAM,GAAA,GAAM,IAAI,cAAA,CAAe,MAAA,EAAQ,IAAI,CAAA;AAC3C,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACtC;AAEO,SAAS,GAAA,CAAI,IAAA,EAAa,MAAA,GAAS,EAAA,EAAuB;AAC/D,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,MAAM,CAAA;AAC1B,EAAA,OAAO,KAAK,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACpC;AAEO,SAAS,UAAA,CAAW,IAAA,EAAa,MAAA,GAAS,EAAA,EAAI,OAAO,CAAA,EAA+B;AACzF,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,MAAA,EAAQ,IAAI,CAAA;AACvC,EAAA,OAAO,KAAK,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACpC;AAEO,SAAS,GAAA,CAAI,IAAA,EAAa,MAAA,GAAS,EAAA,EAAyB;AACjE,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,MAAM,CAAA;AAC1B,EAAA,OAAO,KAAK,GAAA,CAAI,CAAC,MAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACpC;AAOO,SAAS,YAAA,CACd,MACA,IAAA,EACS;AACT,EAAA,OAAO,KAAK,CAAA,IAAK,IAAA,CAAK,CAAA,IAAK,IAAA,CAAK,IAAI,IAAA,CAAK,CAAA;AAC3C;AAGO,SAAS,YAAA,CACd,MACA,IAAA,EACS;AACT,EAAA,OAAO,KAAK,CAAA,IAAK,IAAA,CAAK,CAAA,IAAK,IAAA,CAAK,IAAI,IAAA,CAAK,CAAA;AAC3C;AAgBO,IAAM,mBAAN,MAAuB;AAAA,EAI5B,YAA4B,UAAA,EAAoB;AAApB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAH5B,IAAA,IAAA,CAAQ,OAAA,GAAyB,IAAA;AACjC,IAAA,IAAA,CAAQ,WAAA,GAAc,CAAA;AAGpB,IAAA,IAAI,EAAE,aAAa,CAAA,CAAA,EAAI,MAAM,IAAI,UAAA,CAAW,CAAA,4BAAA,EAA+B,UAAU,CAAA,CAAE,CAAA;AAAA,EACzF;AAAA,EAEQ,UAAA,CAAW,MAAY,MAAA,EAAwB;AACrD,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,IAAA,CAAK,KAAA,EAAO,MAAM,IAAA,CAAK,KAAA,EAAO,GAAA,EAAK,IAAA,CAAK,OAAO,KAAA,EAAO,IAAA,CAAK,OAAO,MAAA,EAAQ,IAAA,CAAK,UAAU,CAAA,EAAE;AAAA,EAC1H;AAAA;AAAA,EAGA,IAAI,IAAA,EAA2B;AAC7B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAM,IAAA,CAAK,OAAO,IAAA,CAAK,UAAU,IAAI,IAAA,CAAK,UAAA;AAC9D,IAAA,IAAI,IAAA,CAAK,YAAY,IAAA,EAAM;AACzB,MAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AACnB,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AAC3C,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,MAAA,GAAS,KAAK,WAAA,EAAa;AAC7B,MAAA,MAAM,YAAY,IAAA,CAAK,OAAA;AACvB,MAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AACnB,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AAC3C,MAAA,OAAO,SAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,IAAA,CAAK,GAAA,CAAI,KAAK,OAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC1D,IAAA,IAAA,CAAK,OAAA,CAAQ,MAAM,IAAA,CAAK,GAAA,CAAI,KAAK,OAAA,CAAQ,GAAA,EAAK,KAAK,KAAK,CAAA;AACxD,IAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,IAAA,CAAK,KAAA;AAC1B,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,CAAK,OAAA,CAAQ,UAAU,IAAA,CAAK,OAAA,CAAQ,MAAA,IAAU,CAAA,IAAK,IAAA,CAAK,MAAA;AACzE,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,OAAA,GAAyB;AAC3B,IAAA,OAAO,KAAK,OAAA,GAAU,EAAE,GAAG,IAAA,CAAK,SAAQ,GAAI,IAAA;AAAA,EAC9C;AAAA;AAAA,EAGA,KAAA,GAAuB;AACrB,IAAA,MAAM,IAAI,IAAA,CAAK,OAAA;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,OAAO,CAAA;AAAA,EACT;AACF;AAqBA,SAAS,KAAK,CAAA,EAAmB;AAC/B,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,KAAA,GAAQ,EAAE,IAAI,CAAA;AAClC;AACA,SAAS,UAAU,CAAA,EAAmB;AACpC,EAAA,OAAO,EAAE,IAAA,GAAO,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA,EAAM,EAAE,KAAK,CAAA;AAC1C;AACA,SAAS,UAAU,CAAA,EAAmB;AACpC,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,CAAE,MAAM,CAAA,CAAE,KAAK,IAAI,CAAA,CAAE,GAAA;AACvC;AAGO,SAAS,eAAe,OAAA,EAAiC;AAC9D,EAAA,MAAM,OAAqB,EAAC;AAC5B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,MAAM,CAAA,GAAI,QAAQ,CAAC,CAAA;AACnB,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,GAAA;AACzB,IAAA,IAAI,SAAS,CAAA,EAAG;AAChB,IAAA,MAAM,CAAA,GAAI,KAAK,CAAC,CAAA;AAChB,IAAA,MAAM,EAAA,GAAK,UAAU,CAAC,CAAA;AACtB,IAAA,MAAM,EAAA,GAAK,UAAU,CAAC,CAAA;AACtB,IAAA,MAAM,OAAA,GAAU,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,IAAA;AAE5B,IAAA,IAAI,CAAA,IAAK,KAAA,GAAQ,GAAA,EAAK,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,SAAA,IAC7D,EAAA,IAAM,KAAA,GAAQ,IAAA,IAAQ,EAAA,IAAM,QAAQ,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,UAAA,EAAY,SAAS,CAAA;AAAA,SAAA,IAC9F,EAAA,IAAM,CAAA,GAAI,CAAA,IAAK,EAAA,IAAM,IAAI,GAAA,EAAK,IAAA,CAAK,IAAA,CAAK,EAAE,OAAO,CAAA,EAAG,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,MAAM,CAAA;AAAA,SAAA,IACtF,EAAA,IAAM,CAAA,GAAI,CAAA,IAAK,EAAA,IAAM,IAAI,GAAA,EAAK,IAAA,CAAK,IAAA,CAAK,EAAE,OAAO,CAAA,EAAG,OAAA,EAAS,cAAA,EAAgB,OAAA,EAAS,OAAO,CAAA;AAEtG,IAAA,IAAI,IAAI,CAAA,EAAG;AACT,MAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,CAAA,GAAI,CAAC,CAAA;AACvB,MAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,IAAA;AAC1B,MAAA,MAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AAEpB,MAAA,IAAI,CAAC,KAAA,IAAS,OAAA,IAAW,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,KAAA,IAAS,CAAA,GAAI,KAAA;AACrE,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,kBAAA,EAAoB,OAAA,EAAS,MAAM,CAAA;AAAA,WAAA,IAC3D,KAAA,IAAS,CAAC,OAAA,IAAW,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,IAAA,IAAQ,CAAA,GAAI,KAAA;AAC1E,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,kBAAA,EAAoB,OAAA,EAAS,OAAO,CAAA;AAAA,WAAA,IAE5D,CAAC,KAAA,IAAS,OAAA,IAAW,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,IAAA,IAAQ,CAAA,GAAI,KAAA;AAC1E,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,eAAA,EAAiB,OAAA,EAAS,MAAM,CAAA;AAAA,WAAA,IACxD,KAAA,IAAS,CAAC,OAAA,IAAW,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,KAAA,IAAS,CAAA,GAAI,KAAA;AAC1E,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,eAAA,EAAiB,OAAA,EAAS,OAAO,CAAA;AAAA,IACpE;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT","file":"index.js","sourcesContent":["/**\n * @lacspace/indicators\n * Streaming technical indicators for stock-market apps.\n *\n * Every indicator is a small class with an incremental `next()` that updates in\n * O(1) (or O(period) for window-based ones) — push one live tick, get the new\n * value, without recomputing the whole series. Perfect for live LTP feeds.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\nexport interface Candle {\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n time?: number;\n}\n\n/** A high/low/close bar — the minimum most range-based indicators need. */\nexport interface HLC {\n high: number;\n low: number;\n close: number;\n}\n\nfunction assertPeriod(period: number): void {\n if (!Number.isInteger(period) || period < 1) {\n throw new RangeError(`period must be a positive integer, got ${period}`);\n }\n}\n\n/** Simple Moving Average. Incremental O(1) using a running window sum. */\nexport class SMA {\n private buf: number[] = [];\n private sum = 0;\n /** Latest value, or `null` until `period` samples have been seen. */\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n this.value = this.buf.length === this.period ? this.sum / this.period : null;\n return this.value;\n }\n}\n\n/** Exponential Moving Average. Seeded with an SMA of the first `period` values. */\nexport class EMA {\n private readonly k: number;\n private seed: number[] = [];\n private ema: number | null = null;\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n this.k = 2 / (period + 1);\n }\n\n next(price: number): number | null {\n if (this.ema === null) {\n this.seed.push(price);\n if (this.seed.length < this.period) return (this.value = null);\n this.ema = this.seed.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.ema = price * this.k + this.ema * (1 - this.k);\n }\n return (this.value = this.ema);\n }\n}\n\n/** Weighted Moving Average — recent samples weighted linearly higher. */\nexport class WMA {\n private buf: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period: number) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n this.buf.push(price);\n if (this.buf.length > this.period) this.buf.shift();\n if (this.buf.length < this.period) return (this.value = null);\n let num = 0;\n let den = 0;\n for (let i = 0; i < this.period; i++) {\n const w = i + 1;\n num += this.buf[i]! * w;\n den += w;\n }\n return (this.value = num / den);\n }\n}\n\n/** Relative Strength Index (Wilder's smoothing). O(1) per tick. */\nexport class RSI {\n private prev: number | null = null;\n private avgGain = 0;\n private avgLoss = 0;\n private count = 0;\n value: number | null = null;\n\n constructor(public readonly period: number = 14) {\n assertPeriod(period);\n }\n\n next(price: number): number | null {\n if (this.prev === null) {\n this.prev = price;\n return (this.value = null);\n }\n const change = price - this.prev;\n this.prev = price;\n const gain = change > 0 ? change : 0;\n const loss = change < 0 ? -change : 0;\n this.count++;\n\n if (this.count <= this.period) {\n this.avgGain += gain;\n this.avgLoss += loss;\n if (this.count < this.period) return (this.value = null);\n this.avgGain /= this.period;\n this.avgLoss /= this.period;\n } else {\n this.avgGain = (this.avgGain * (this.period - 1) + gain) / this.period;\n this.avgLoss = (this.avgLoss * (this.period - 1) + loss) / this.period;\n }\n return (this.value = this.compute());\n }\n\n private compute(): number {\n if (this.avgLoss === 0) return 100;\n const rs = this.avgGain / this.avgLoss;\n return 100 - 100 / (1 + rs);\n }\n}\n\nexport interface MACDValue {\n macd: number;\n signal: number;\n histogram: number;\n}\n\n/** Moving Average Convergence Divergence. Defaults 12 / 26 / 9. */\nexport class MACD {\n private readonly fastEma: EMA;\n private readonly slowEma: EMA;\n private readonly signalEma: EMA;\n value: MACDValue | null = null;\n\n constructor(fast = 12, slow = 26, signal = 9) {\n this.fastEma = new EMA(fast);\n this.slowEma = new EMA(slow);\n this.signalEma = new EMA(signal);\n }\n\n next(price: number): MACDValue | null {\n const f = this.fastEma.next(price);\n const s = this.slowEma.next(price);\n if (f === null || s === null) return (this.value = null);\n const macd = f - s;\n const signal = this.signalEma.next(macd);\n if (signal === null) return (this.value = null);\n return (this.value = { macd, signal, histogram: macd - signal });\n }\n}\n\nexport interface BollingerValue {\n middle: number;\n upper: number;\n lower: number;\n /** (upper - lower) / middle — normalised band width. */\n bandwidth: number;\n}\n\n/** Bollinger Bands — SMA middle band ± `mult` standard deviations. */\nexport class BollingerBands {\n private buf: number[] = [];\n private sum = 0;\n value: BollingerValue | null = null;\n\n constructor(\n public readonly period = 20,\n public readonly mult = 2,\n ) {\n assertPeriod(period);\n }\n\n next(price: number): BollingerValue | null {\n this.buf.push(price);\n this.sum += price;\n if (this.buf.length > this.period) this.sum -= this.buf.shift()!;\n if (this.buf.length < this.period) return (this.value = null);\n const mean = this.sum / this.period;\n let variance = 0;\n for (const v of this.buf) variance += (v - mean) ** 2;\n const sd = Math.sqrt(variance / this.period);\n const upper = mean + this.mult * sd;\n const lower = mean - this.mult * sd;\n return (this.value = {\n middle: mean,\n upper,\n lower,\n bandwidth: mean === 0 ? 0 : (upper - lower) / mean,\n });\n }\n}\n\n/** Average True Range (Wilder). Feed it high/low/close bars. */\nexport class ATR {\n private prevClose: number | null = null;\n private atr: number | null = null;\n private seed: number[] = [];\n value: number | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): number | null {\n const tr =\n this.prevClose === null\n ? bar.high - bar.low\n : Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevClose = bar.close;\n\n if (this.atr === null) {\n this.seed.push(tr);\n if (this.seed.length < this.period) return (this.value = null);\n this.atr = this.seed.reduce((a, b) => a + b, 0) / this.period;\n return (this.value = this.atr);\n }\n this.atr = (this.atr * (this.period - 1) + tr) / this.period;\n return (this.value = this.atr);\n }\n}\n\n/** Volume-Weighted Average Price. Cumulative — call `reset()` per session. */\nexport class VWAP {\n private pv = 0;\n private vol = 0;\n value: number | null = null;\n\n next(bar: Required<Pick<Candle, \"high\" | \"low\" | \"close\" | \"volume\">>): number | null {\n const typical = (bar.high + bar.low + bar.close) / 3;\n this.pv += typical * bar.volume;\n this.vol += bar.volume;\n return (this.value = this.vol === 0 ? null : this.pv / this.vol);\n }\n\n reset(): void {\n this.pv = 0;\n this.vol = 0;\n this.value = null;\n }\n}\n\nexport interface StochasticValue {\n /** %K — position of close within the recent high/low range (0–100). */\n k: number;\n /** %D — SMA of %K. */\n d: number;\n}\n\n/** Stochastic Oscillator (%K / %D). */\nexport class Stochastic {\n private highs: number[] = [];\n private lows: number[] = [];\n private readonly dSma: SMA;\n value: StochasticValue | null = null;\n\n constructor(\n public readonly period = 14,\n public readonly signal = 3,\n ) {\n assertPeriod(period);\n this.dSma = new SMA(signal);\n }\n\n next(bar: HLC): StochasticValue | null {\n this.highs.push(bar.high);\n this.lows.push(bar.low);\n if (this.highs.length > this.period) {\n this.highs.shift();\n this.lows.shift();\n }\n if (this.highs.length < this.period) return (this.value = null);\n const hh = Math.max(...this.highs);\n const ll = Math.min(...this.lows);\n const k = hh === ll ? 100 : ((bar.close - ll) / (hh - ll)) * 100;\n const d = this.dSma.next(k);\n if (d === null) return (this.value = null);\n return (this.value = { k, d });\n }\n}\n\nexport interface SupertrendValue {\n value: number;\n /** 1 = uptrend (price above band), -1 = downtrend. */\n direction: 1 | -1;\n}\n\n/** Supertrend — ATR-based trend follower. Defaults period 10, multiplier 3. */\nexport class Supertrend {\n private readonly atr: ATR;\n private prevClose: number | null = null;\n private prevFinalUpper = 0;\n private prevFinalLower = 0;\n private prevSupertrend: number | null = null;\n value: SupertrendValue | null = null;\n\n constructor(\n public readonly period = 10,\n public readonly mult = 3,\n ) {\n this.atr = new ATR(period);\n }\n\n next(bar: HLC): SupertrendValue | null {\n const atr = this.atr.next(bar);\n if (atr === null) {\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const hl2 = (bar.high + bar.low) / 2;\n const basicUpper = hl2 + this.mult * atr;\n const basicLower = hl2 - this.mult * atr;\n const pc = this.prevClose ?? bar.close;\n\n const first = this.prevSupertrend === null;\n const finalUpper =\n first || basicUpper < this.prevFinalUpper || pc > this.prevFinalUpper\n ? basicUpper\n : this.prevFinalUpper;\n const finalLower =\n first || basicLower > this.prevFinalLower || pc < this.prevFinalLower\n ? basicLower\n : this.prevFinalLower;\n\n let st: number;\n let direction: 1 | -1;\n if (first) {\n direction = bar.close <= finalUpper ? -1 : 1;\n st = direction === -1 ? finalUpper : finalLower;\n } else if (this.prevSupertrend === this.prevFinalUpper) {\n if (bar.close <= finalUpper) {\n st = finalUpper;\n direction = -1;\n } else {\n st = finalLower;\n direction = 1;\n }\n } else {\n if (bar.close >= finalLower) {\n st = finalLower;\n direction = 1;\n } else {\n st = finalUpper;\n direction = -1;\n }\n }\n\n this.prevFinalUpper = finalUpper;\n this.prevFinalLower = finalLower;\n this.prevSupertrend = st;\n this.prevClose = bar.close;\n return (this.value = { value: st, direction });\n }\n}\n\nexport interface ADXValue {\n adx: number;\n plusDI: number;\n minusDI: number;\n}\n\n/** Average Directional Index with +DI / -DI (Wilder). */\nexport class ADX {\n private prevHigh: number | null = null;\n private prevLow = 0;\n private prevClose = 0;\n private smTR = 0;\n private smPDM = 0;\n private smMDM = 0;\n private dxs: number[] = [];\n private adx: number | null = null;\n private count = 0;\n value: ADXValue | null = null;\n\n constructor(public readonly period = 14) {\n assertPeriod(period);\n }\n\n next(bar: HLC): ADXValue | null {\n if (this.prevHigh === null) {\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n return (this.value = null);\n }\n const upMove = bar.high - this.prevHigh;\n const downMove = this.prevLow - bar.low;\n const pdm = upMove > downMove && upMove > 0 ? upMove : 0;\n const mdm = downMove > upMove && downMove > 0 ? downMove : 0;\n const tr = Math.max(\n bar.high - bar.low,\n Math.abs(bar.high - this.prevClose),\n Math.abs(bar.low - this.prevClose),\n );\n this.prevHigh = bar.high;\n this.prevLow = bar.low;\n this.prevClose = bar.close;\n this.count++;\n\n if (this.count <= this.period) {\n this.smTR += tr;\n this.smPDM += pdm;\n this.smMDM += mdm;\n if (this.count < this.period) return (this.value = null);\n } else {\n this.smTR = this.smTR - this.smTR / this.period + tr;\n this.smPDM = this.smPDM - this.smPDM / this.period + pdm;\n this.smMDM = this.smMDM - this.smMDM / this.period + mdm;\n }\n\n const plusDI = this.smTR === 0 ? 0 : (100 * this.smPDM) / this.smTR;\n const minusDI = this.smTR === 0 ? 0 : (100 * this.smMDM) / this.smTR;\n const diSum = plusDI + minusDI;\n const dx = diSum === 0 ? 0 : (100 * Math.abs(plusDI - minusDI)) / diSum;\n\n if (this.adx === null) {\n this.dxs.push(dx);\n if (this.dxs.length < this.period) return (this.value = null);\n this.adx = this.dxs.reduce((a, b) => a + b, 0) / this.period;\n } else {\n this.adx = (this.adx * (this.period - 1) + dx) / this.period;\n }\n return (this.value = { adx: this.adx, plusDI, minusDI });\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Batch helpers — run an indicator over an existing array in one call.\n * Each returns an array aligned to the input (nulls during warm-up).\n * ------------------------------------------------------------------ */\n\nfunction runNumber<T extends { next(v: number): number | null }>(\n ind: T,\n values: number[],\n): (number | null)[] {\n return values.map((v) => ind.next(v));\n}\n\nexport const sma = (values: number[], period: number) => runNumber(new SMA(period), values);\nexport const ema = (values: number[], period: number) => runNumber(new EMA(period), values);\nexport const wma = (values: number[], period: number) => runNumber(new WMA(period), values);\nexport const rsi = (values: number[], period = 14) => runNumber(new RSI(period), values);\n\nexport function macd(values: number[], fast = 12, slow = 26, signal = 9): (MACDValue | null)[] {\n const ind = new MACD(fast, slow, signal);\n return values.map((v) => ind.next(v));\n}\n\nexport function bollinger(values: number[], period = 20, mult = 2): (BollingerValue | null)[] {\n const ind = new BollingerBands(period, mult);\n return values.map((v) => ind.next(v));\n}\n\nexport function atr(bars: HLC[], period = 14): (number | null)[] {\n const ind = new ATR(period);\n return bars.map((b) => ind.next(b));\n}\n\nexport function supertrend(bars: HLC[], period = 10, mult = 3): (SupertrendValue | null)[] {\n const ind = new Supertrend(period, mult);\n return bars.map((b) => ind.next(b));\n}\n\nexport function adx(bars: HLC[], period = 14): (ADXValue | null)[] {\n const ind = new ADX(period);\n return bars.map((b) => ind.next(b));\n}\n\n/* ------------------------------------------------------------------ *\n * Crossover helpers — the backbone of most signal logic.\n * ------------------------------------------------------------------ */\n\n/** True when series A crossed from at-or-below B to strictly above B. */\nexport function crossedAbove(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a <= prev.b && curr.a > curr.b;\n}\n\n/** True when series A crossed from at-or-above B to strictly below B. */\nexport function crossedBelow(\n prev: { a: number; b: number },\n curr: { a: number; b: number },\n): boolean {\n return prev.a >= prev.b && curr.a < curr.b;\n}\n\n/* ------------------------------ tick → candle aggregation ------------------------------ */\n\nexport interface Tick {\n /** Epoch ms of the tick. */\n time: number;\n price: number;\n volume?: number;\n}\n\n/**\n * Aggregate a live tick/LTP stream into fixed-interval OHLC candles.\n * `add()` returns a COMPLETED candle when the interval rolls over, else null.\n * @example const agg = new CandleAggregator(60_000); // 1-minute candles\n */\nexport class CandleAggregator {\n private current: Candle | null = null;\n private bucketStart = 0;\n\n constructor(public readonly intervalMs: number) {\n if (!(intervalMs > 0)) throw new RangeError(`intervalMs must be > 0, got ${intervalMs}`);\n }\n\n private openCandle(tick: Tick, bucket: number): Candle {\n return { time: bucket, open: tick.price, high: tick.price, low: tick.price, close: tick.price, volume: tick.volume ?? 0 };\n }\n\n /** Feed a tick. Returns the just-completed candle when the bucket advances, else null. */\n add(tick: Tick): Candle | null {\n const bucket = Math.floor(tick.time / this.intervalMs) * this.intervalMs;\n if (this.current === null) {\n this.bucketStart = bucket;\n this.current = this.openCandle(tick, bucket);\n return null;\n }\n if (bucket > this.bucketStart) {\n const completed = this.current;\n this.bucketStart = bucket;\n this.current = this.openCandle(tick, bucket);\n return completed;\n }\n this.current.high = Math.max(this.current.high, tick.price);\n this.current.low = Math.min(this.current.low, tick.price);\n this.current.close = tick.price;\n if (tick.volume) this.current.volume = (this.current.volume ?? 0) + tick.volume;\n return null;\n }\n\n /** The in-progress (not yet closed) candle, if any. */\n get pending(): Candle | null {\n return this.current ? { ...this.current } : null;\n }\n\n /** Close and return the current candle (e.g. at session end). */\n flush(): Candle | null {\n const c = this.current;\n this.current = null;\n return c;\n }\n}\n\n/* ------------------------------ candlestick patterns ------------------------------ */\n\nexport type CandlePattern =\n | \"doji\"\n | \"hammer\"\n | \"shootingStar\"\n | \"marubozu\"\n | \"bullishEngulfing\"\n | \"bearishEngulfing\"\n | \"bullishHarami\"\n | \"bearishHarami\";\n\nexport interface PatternHit {\n /** Index in the input array where the pattern completes. */\n index: number;\n pattern: CandlePattern;\n bullish: boolean;\n}\n\nfunction body(c: Candle): number {\n return Math.abs(c.close - c.open);\n}\nfunction upperWick(c: Candle): number {\n return c.high - Math.max(c.open, c.close);\n}\nfunction lowerWick(c: Candle): number {\n return Math.min(c.open, c.close) - c.low;\n}\n\n/** Detect common single- and two-candle patterns across a series. */\nexport function detectPatterns(candles: Candle[]): PatternHit[] {\n const hits: PatternHit[] = [];\n for (let i = 0; i < candles.length; i++) {\n const c = candles[i]!;\n const range = c.high - c.low;\n if (range <= 0) continue;\n const b = body(c);\n const up = upperWick(c);\n const lo = lowerWick(c);\n const bullish = c.close > c.open;\n\n if (b <= range * 0.1) hits.push({ index: i, pattern: \"doji\", bullish });\n else if (up <= range * 0.05 && lo <= range * 0.05) hits.push({ index: i, pattern: \"marubozu\", bullish });\n else if (lo >= b * 2 && up <= b * 0.6) hits.push({ index: i, pattern: \"hammer\", bullish: true });\n else if (up >= b * 2 && lo <= b * 0.6) hits.push({ index: i, pattern: \"shootingStar\", bullish: false });\n\n if (i > 0) {\n const p = candles[i - 1]!;\n const pBull = p.close > p.open;\n const pBody = body(p);\n // engulfing: current real body fully engulfs the previous real body\n if (!pBull && bullish && c.close >= p.open && c.open <= p.close && b > pBody)\n hits.push({ index: i, pattern: \"bullishEngulfing\", bullish: true });\n else if (pBull && !bullish && c.open >= p.close && c.close <= p.open && b > pBody)\n hits.push({ index: i, pattern: \"bearishEngulfing\", bullish: false });\n // harami: current small real body sits inside the previous real body\n else if (!pBull && bullish && c.open >= p.close && c.close <= p.open && b < pBody)\n hits.push({ index: i, pattern: \"bullishHarami\", bullish: true });\n else if (pBull && !bullish && c.close >= p.open && c.open <= p.close && b < pBody)\n hits.push({ index: i, pattern: \"bearishHarami\", bullish: false });\n }\n }\n return hits;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lacspace/indicators",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Streaming technical indicators (RSI, MACD, EMA, Bollinger, ATR, Supertrend, ADX, VWAP) with O(1) incremental updates for live price feeds. Zero-dependency.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|