diff --git a/.gitignore b/.gitignore index 736d056a..a12d3792 100644 --- a/.gitignore +++ b/.gitignore @@ -44,8 +44,10 @@ tarpaulin-report.html # Node binding artifacts **/node_modules/ bindings/node/*.node -bindings/node/index.d.ts bindings/node/npm-debug.log* +# index.js + index.d.ts are generated by `napi build` but committed (a matched +# pair) so consumers and the repo get TypeScript types; CONTRIBUTING requires +# regenerating both when a binding's public API changes. # package-lock.json is committed for the tracked Node packages — bindings/node/ # and examples/node/ — so contributors get reproducible npm installs. There is # no top-level npm package, and the ghost-ignored site/ keeps its lockfile local. diff --git a/CHANGELOG.md b/CHANGELOG.md index 43c491e2..c31e70e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- **Node binding: invalid indicator periods now throw instead of being silently + clamped.** The scalar-indicator constructors previously clamped `period = 0` + to `1`; every Node constructor now propagates the core's validation error + (e.g. `period must be greater than zero`), matching the Python and WASM + bindings and the Rust core. Constructing with a valid period is unaffected. + ## [0.3.1] - 2026-05-30 ### Fixed diff --git a/bindings/node/__tests__/smoke.test.js b/bindings/node/__tests__/smoke.test.js index 377fe978..dde1a647 100644 --- a/bindings/node/__tests__/smoke.test.js +++ b/bindings/node/__tests__/smoke.test.js @@ -73,10 +73,10 @@ test('ATR batch shape', () => { } }); -test('zero period is clamped to a valid window', () => { - // Constructors cannot throw from JS (napi-rs 2.16 limitation), so they - // clamp pathological values like period=0 to the smallest valid window. - const sma = new wickra.SMA(0); - assert.equal(sma.warmupPeriod(), 1); - assert.equal(sma.update(42), 42); +test('zero period is rejected at construction', () => { + // The core rejects period 0 (Error::PeriodZero); the Node binding propagates + // it as a thrown JS error, consistent with the Python and WASM bindings. + assert.throws(() => new wickra.SMA(0), /period must be greater than zero/); + // A valid period still constructs and runs. + assert.equal(new wickra.SMA(1).update(42), 42); }); diff --git a/bindings/node/index.d.ts b/bindings/node/index.d.ts new file mode 100644 index 00000000..31639ac8 --- /dev/null +++ b/bindings/node/index.d.ts @@ -0,0 +1,2243 @@ +/* tslint:disable */ +/* eslint-disable */ + +/* auto-generated by NAPI-RS */ + +/** Library version (matches the Rust crate version). */ +export declare function version(): string +/** MACD triple: macd line, signal line, histogram. */ +export interface MacdValue { + macd: number + signal: number + histogram: number +} +export interface BollingerValue { + upper: number + middle: number + lower: number + stddev: number +} +export interface StochValue { + k: number + d: number +} +export interface AdxValue { + plusDi: number + minusDi: number + adx: number +} +export interface KeltnerValue { + upper: number + middle: number + lower: number +} +export interface DonchianValue { + upper: number + middle: number + lower: number +} +export interface AroonValue { + up: number + down: number +} +export interface KstValue { + kst: number + signal: number +} +export interface ZeroLagMacdValue { + macd: number + signal: number + histogram: number +} +export interface AlligatorValue { + jaw: number + teeth: number + lips: number +} +export interface SuperTrendValue { + value: number + direction: number +} +export interface ChandelierExitValue { + longStop: number + shortStop: number +} +export interface ChandeKrollStopValue { + stopLong: number + stopShort: number +} +export interface DonchianStopValue { + stopLong: number + stopShort: number +} +/** Vortex Indicator pair: `VI+` and `VI-`. */ +export interface VortexValue { + plus: number + minus: number +} +/** Random Walk Index pair: `RWI_High` and `RWI_Low`. */ +export interface RwiValue { + high: number + low: number +} +/** Wave Trend Oscillator pair: `wt1` (channel index) and `wt2` (signal SMA). */ +export interface WaveTrendValue { + wt1: number + wt2: number +} +export interface MaEnvelopeValue { + upper: number + middle: number + lower: number +} +export interface AccelerationBandsValue { + upper: number + middle: number + lower: number +} +export interface StarcBandsValue { + upper: number + middle: number + lower: number +} +export interface AtrBandsValue { + upper: number + middle: number + lower: number +} +export interface HurstChannelValue { + upper: number + middle: number + lower: number +} +export interface LinRegChannelValue { + upper: number + middle: number + lower: number +} +export interface StandardErrorBandsValue { + upper: number + middle: number + lower: number +} +export interface DoubleBollingerValue { + upperOuter: number + upperInner: number + middle: number + lowerInner: number + lowerOuter: number +} +export interface TtmSqueezeValue { + squeeze: number + momentum: number +} +export interface FractalChaosBandsValue { + upper: number + lower: number +} +export interface VwapStdDevBandsValue { + upper: number + middle: number + lower: number + stddev: number +} +export interface ClassicPivotsValue { + pp: number + r1: number + r2: number + r3: number + s1: number + s2: number + s3: number +} +export interface FibonacciPivotsValue { + pp: number + r1: number + r2: number + r3: number + s1: number + s2: number + s3: number +} +export interface CamarillaValue { + pp: number + r1: number + r2: number + r3: number + r4: number + s1: number + s2: number + s3: number + s4: number +} +export interface WoodiePivotsValue { + pp: number + r1: number + r2: number + s1: number + s2: number +} +export interface DemarkPivotsValue { + pp: number + r1: number + s1: number +} +export interface WilliamsFractalsValue { + /** Up fractal price; NaN when no up fractal was confirmed on this bar. */ + up: number + /** Down fractal price; NaN when no down fractal was confirmed on this bar. */ + down: number +} +export interface ZigZagValue { + swing: number + direction: number +} +/** TD Sequential output triple: setup count, countdown count, direction. */ +export interface TdSequentialValue { + setup: number + countdown: number + direction: number +} +/** TD Lines output pair: latest TDST resistance / support (NaN if unset). */ +export interface TdLinesValue { + resistance: number + support: number +} +/** TD Range Projection output pair: projected next-bar high / low. */ +export interface TdRangeProjectionValue { + high: number + low: number +} +/** + * TD Risk Level output pair: buy-side / sell-side protective stop levels + * (NaN if unset). + */ +export interface TdRiskLevelValue { + buyRisk: number + sellRisk: number +} +export interface MamaValue { + mama: number + fama: number +} +/** + * Ichimoku output: five lines, any of which may be `NaN` while the indicator + * is still warming up. + */ +export interface IchimokuValue { + tenkan: number + kijun: number + senkouA: number + senkouB: number + chikou: number +} +export interface HeikinAshiValue { + open: number + high: number + low: number + close: number +} +export interface ValueAreaValue { + poc: number + vah: number + val: number +} +export interface InitialBalanceValue { + high: number + low: number +} +export interface OpeningRangeValue { + high: number + low: number + breakoutDistance: number +} +export type SmaNode = SMA +export declare class SMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type EmaNode = EMA +export declare class EMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type WmaNode = WMA +export declare class WMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RsiNode = RSI +export declare class RSI { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DemaNode = DEMA +export declare class DEMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TemaNode = TEMA +export declare class TEMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HmaNode = HMA +export declare class HMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RocNode = ROC +export declare class ROC { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TrixNode = TRIX +export declare class TRIX { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SmmaNode = SMMA +export declare class SMMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TrimaNode = TRIMA +export declare class TRIMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ZlemaNode = ZLEMA +export declare class ZLEMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MomNode = MOM +export declare class MOM { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CmoNode = CMO +export declare class CMO { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DpoNode = DPO +export declare class DPO { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StdDevNode = StdDev +export declare class StdDev { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type UlcerIndexNode = UlcerIndex +export declare class UlcerIndex { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VerticalHorizontalFilterNode = VerticalHorizontalFilter +export declare class VerticalHorizontalFilter { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ZScoreNode = ZScore +export declare class ZScore { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type McGinleyDynamicNode = McGinleyDynamic +export declare class McGinleyDynamic { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type FramaNode = FRAMA +export declare class FRAMA { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SuperSmootherNode = SuperSmoother +export declare class SuperSmoother { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type FisherTransformNode = FisherTransform +export declare class FisherTransform { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DecyclerNode = Decycler +export declare class Decycler { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CenterOfGravityNode = CenterOfGravity +export declare class CenterOfGravity { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CyberneticCycleNode = CyberneticCycle +export declare class CyberneticCycle { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type InstantaneousTrendlineNode = InstantaneousTrendline +export declare class InstantaneousTrendline { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type EhlersStochasticNode = EhlersStochastic +export declare class EhlersStochastic { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RviVolatilityNode = RVIVolatility +export declare class RVIVolatility { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VarianceNode = Variance +export declare class Variance { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CoefficientOfVariationNode = CoefficientOfVariation +export declare class CoefficientOfVariation { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SkewnessNode = Skewness +export declare class Skewness { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type KurtosisNode = Kurtosis +export declare class Kurtosis { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StandardErrorNode = StandardError +export declare class StandardError { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DetrendedStdDevNode = DetrendedStdDev +export declare class DetrendedStdDev { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RSquaredNode = RSquared +export declare class RSquared { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MedianAbsoluteDeviationNode = MedianAbsoluteDeviation +export declare class MedianAbsoluteDeviation { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AutocorrelationNode = Autocorrelation +export declare class Autocorrelation { + constructor(period: number, lag: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HurstExponentNode = HurstExponent +export declare class HurstExponent { + constructor(period: number, chunks: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PearsonCorrelationNode = PearsonCorrelation +export declare class PearsonCorrelation { + constructor(period: number) + update(x: number, y: number): number | null + /** + * Batch over two equally-sized arrays. Returns a length-`n` array + * with `NaN` for warmup positions. + */ + batch(x: Array, y: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type BetaNode = Beta +export declare class Beta { + constructor(period: number) + update(x: number, y: number): number | null + /** + * Batch over two equally-sized arrays. Returns a length-`n` array + * with `NaN` for warmup positions. + */ + batch(x: Array, y: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SpearmanCorrelationNode = SpearmanCorrelation +export declare class SpearmanCorrelation { + constructor(period: number) + update(x: number, y: number): number | null + /** + * Batch over two equally-sized arrays. Returns a length-`n` array + * with `NaN` for warmup positions. + */ + batch(x: Array, y: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MacdNode = MACD +export declare class MACD { + constructor(fast: number, slow: number, signal: number) + update(value: number): MacdValue | null + /** + * Batch over a price array. Returns a flat array of length `3 * n`, + * interleaved per row as `[macd0, signal0, histogram0, macd1, ...]`. + * Read column `j` of row `i` as `result[i * 3 + j]`. Warmup rows are `NaN`. + */ + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type BollingerNode = BollingerBands +export declare class BollingerBands { + constructor(period: number, multiplier: number) + update(value: number): BollingerValue | null + /** + * Batch over a price array. Returns a flat array of length `4 * n`, + * interleaved per row as `[upper0, middle0, lower0, stddev0, upper1, ...]`. + * Read column `j` of row `i` as `result[i * 4 + j]`. Warmup rows are `NaN`. + */ + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AtrNode = ATR +export declare class ATR { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StochNode = Stochastic +export declare class Stochastic { + constructor(kPeriod: number, dPeriod: number) + update(high: number, low: number, close: number): StochValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ObvNode = OBV +export declare class OBV { + constructor() + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AdxNode = ADX +export declare class ADX { + constructor(period: number) + update(high: number, low: number, close: number): AdxValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AdxrNode = ADXR +export declare class ADXR { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CciNode = CCI +export declare class CCI { + constructor(period: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array +} +export type WilliamsRNode = WilliamsR +export declare class WilliamsR { + constructor(period: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array +} +export type MfiNode = MFI +export declare class MFI { + constructor(period: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array +} +export type PsarNode = PSAR +export declare class PSAR { + constructor(afStart: number, afStep: number, afMax: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array +} +export type KeltnerNode = Keltner +export declare class Keltner { + constructor(emaPeriod: number, atrPeriod: number, multiplier: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number): KeltnerValue | null + batch(high: Array, low: Array, close: Array): Array +} +export type DonchianNode = Donchian +export declare class Donchian { + constructor(period: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number): DonchianValue | null + batch(high: Array, low: Array): Array +} +export type VwapNode = VWAP +export declare class VWAP { + constructor() + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array +} +export type RollingVwapNode = RollingVWAP +export declare class RollingVWAP { + constructor(period: number) + get period(): number + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array +} +export type AoNode = AwesomeOscillator +export declare class AwesomeOscillator { + constructor(fast: number, slow: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array +} +export type AroonNode = Aroon +export declare class Aroon { + constructor(period: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number): AroonValue | null + batch(high: Array, low: Array): Array +} +export type InertiaNode = Inertia +export declare class Inertia { + constructor(rviPeriod: number, linregPeriod: number) + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ConnorsRsiNode = ConnorsRSI +export declare class ConnorsRSI { + constructor(periodRsi: number, periodStreak: number, periodRank: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type LaguerreRsiNode = LaguerreRSI +export declare class LaguerreRSI { + constructor(gamma: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SmiNode = SMI +export declare class SMI { + constructor(period: number, dPeriod: number, d2Period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type KstNode = KST +export declare class KST { + constructor(roc1: number, roc2: number, roc3: number, roc4: number, sma1: number, sma2: number, sma3: number, sma4: number, signal: number) + static classic(): KstNode + update(value: number): KstValue | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PgoNode = PGO +export declare class PGO { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RviNode = RVI +export declare class RVI { + constructor(period: number) + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AwesomeOscillatorHistogramNode = AwesomeOscillatorHistogram +export declare class AwesomeOscillatorHistogram { + constructor(fast: number, slow: number, smaPeriod: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StcNode = STC +export declare class STC { + constructor(fast: number, slow: number, schaffPeriod: number, factor: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ElderImpulseNode = ElderImpulse +export declare class ElderImpulse { + constructor(emaPeriod: number, macdFast: number, macdSlow: number, macdSignal: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ZeroLagMacdNode = ZeroLagMACD +export declare class ZeroLagMACD { + constructor(fast: number, slow: number, signal: number) + update(value: number): ZeroLagMacdValue | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CfoNode = CFO +export declare class CFO { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ApoNode = APO +export declare class APO { + constructor(fast: number, slow: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type KamaNode = KAMA +export declare class KAMA { + constructor(erPeriod: number, fast: number, slow: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(value: number): number | null + batch(prices: Array): Array +} +export type EvwmaNode = EVWMA +export declare class EVWMA { + constructor(period: number) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AlligatorNode = Alligator +export declare class Alligator { + constructor(jaw: number, teeth: number, lips: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number): AlligatorValue | null + batch(high: Array, low: Array): Array +} +export type JmaNode = JMA +export declare class JMA { + constructor(period: number, phase: number, power: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(value: number): number | null + batch(prices: Array): Array +} +export type VidyaNode = VIDYA +export declare class VIDYA { + constructor(period: number, cmoPeriod: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(value: number): number | null + batch(prices: Array): Array +} +export type AlmaNode = ALMA +export declare class ALMA { + constructor(period: number, offset: number, sigma: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(value: number): number | null + batch(prices: Array): Array +} +export type T3Node = T3 +export declare class T3 { + constructor(period: number, v: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TsiNode = TSI +export declare class TSI { + constructor(long: number, short: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PmoNode = PMO +export declare class PMO { + constructor(smoothing1: number, smoothing2: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TiiNode = TII +export declare class TII { + constructor(smaPeriod: number, devPeriod: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AdlNode = ADL +export declare class ADL { + constructor() + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VolumePriceTrendNode = VolumePriceTrend +export declare class VolumePriceTrend { + constructor() + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChaikinMoneyFlowNode = ChaikinMoneyFlow +export declare class ChaikinMoneyFlow { + constructor(period: number) + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChaikinOscillatorNode = ChaikinOscillator +export declare class ChaikinOscillator { + constructor(fast: number, slow: number) + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ForceIndexNode = ForceIndex +export declare class ForceIndex { + constructor(period: number) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type NviNode = NVI +export declare class NVI { + constructor(baseline?: number | undefined | null) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PviNode = PVI +export declare class PVI { + constructor(baseline?: number | undefined | null) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VolumeOscillatorNode = VolumeOscillator +export declare class VolumeOscillator { + constructor(fast: number, slow: number) + update(volume: number): number | null + batch(volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type KvoNode = KVO +export declare class KVO { + constructor(fast: number, slow: number) + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AdOscillatorNode = WilliamsAD +export declare class WilliamsAD { + constructor() + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AnchoredVwapNode = AnchoredVWAP +export declare class AnchoredVWAP { + constructor() + setAnchor(): void + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DemandIndexNode = DemandIndex +export declare class DemandIndex { + constructor(period: number) + update(high: number, low: number, close: number, volume: number): number | null + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TsvNode = TSV +export declare class TSV { + constructor(period: number) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VzoNode = VZO +export declare class VZO { + constructor(period: number) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MarketFacilitationIndexNode = MarketFacilitationIndex +export declare class MarketFacilitationIndex { + constructor() + update(high: number, low: number, volume: number): number | null + batch(high: Array, low: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type EaseOfMovementNode = EaseOfMovement +export declare class EaseOfMovement { + constructor(period: number, divisor: number) + update(high: number, low: number, volume: number): number | null + batch(high: Array, low: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SuperTrendNode = SuperTrend +export declare class SuperTrend { + constructor(atrPeriod: number, multiplier: number) + update(high: number, low: number, close: number): SuperTrendValue | null + /** + * Returns `[value0, direction0, value1, direction1, ...]`, length `2 * n`. + * Warmup positions are `NaN`. + */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChandelierExitNode = ChandelierExit +export declare class ChandelierExit { + constructor(period: number, multiplier: number) + update(high: number, low: number, close: number): ChandelierExitValue | null + /** + * Returns `[long0, short0, long1, short1, ...]`, length `2 * n`. Warmup + * positions are `NaN`. + */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChandeKrollStopNode = ChandeKrollStop +export declare class ChandeKrollStop { + constructor(atrPeriod: number, atrMultiplier: number, stopPeriod: number) + update(high: number, low: number, close: number): ChandeKrollStopValue | null + /** + * Returns `[long0, short0, long1, short1, ...]`, length `2 * n`. Warmup + * positions are `NaN`. + */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AtrTrailingStopNode = AtrTrailingStop +export declare class AtrTrailingStop { + constructor(atrPeriod: number, multiplier: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HiLoActivatorNode = HiLoActivator +export declare class HiLoActivator { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VoltyStopNode = VoltyStop +export declare class VoltyStop { + constructor(atrPeriod: number, multiplier: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type YoyoExitNode = YoyoExit +export declare class YoyoExit { + constructor(atrPeriod: number, multiplier: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number + inTrade(): boolean +} +export type DonchianStopNode = DonchianStop +export declare class DonchianStop { + constructor(period: number) + update(high: number, low: number): DonchianStopValue | null + /** + * Returns `[long0, short0, long1, short1, ...]`, length `2 * n`. Warmup + * positions are `NaN`. + */ + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PercentageTrailingStopNode = PercentageTrailingStop +export declare class PercentageTrailingStop { + constructor(percent: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StepTrailingStopNode = StepTrailingStop +export declare class StepTrailingStop { + constructor(stepSize: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RenkoTrailingStopNode = RenkoTrailingStop +export declare class RenkoTrailingStop { + constructor(blockSize: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TypicalPriceNode = TypicalPrice +export declare class TypicalPrice { + constructor() + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MedianPriceNode = MedianPrice +export declare class MedianPrice { + constructor() + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type WeightedCloseNode = WeightedClose +export declare class WeightedClose { + constructor() + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type LinearRegressionNode = LinearRegression +export declare class LinearRegression { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type LinRegSlopeNode = LinRegSlope +export declare class LinRegSlope { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AcceleratorOscillatorNode = AcceleratorOscillator +export declare class AcceleratorOscillator { + constructor(aoFast: number, aoSlow: number, signalPeriod: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type BalanceOfPowerNode = BalanceOfPower +export declare class BalanceOfPower { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChoppinessIndexNode = ChoppinessIndex +export declare class ChoppinessIndex { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TrueRangeNode = TrueRange +export declare class TrueRange { + constructor() + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ChaikinVolatilityNode = ChaikinVolatility +export declare class ChaikinVolatility { + constructor(emaPeriod: number, rocPeriod: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type YangZhangVolatilityNode = YangZhangVolatility +export declare class YangZhangVolatility { + constructor(period: number, tradingPeriods: number) + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RogersSatchellVolatilityNode = RogersSatchellVolatility +export declare class RogersSatchellVolatility { + constructor(period: number, tradingPeriods: number) + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type GarmanKlassVolatilityNode = GarmanKlassVolatility +export declare class GarmanKlassVolatility { + constructor(period: number, tradingPeriods: number) + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ParkinsonVolatilityNode = ParkinsonVolatility +export declare class ParkinsonVolatility { + constructor(period: number, tradingPeriods: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type LinRegAngleNode = LinRegAngle +export declare class LinRegAngle { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type BollingerBandwidthNode = BollingerBandwidth +export declare class BollingerBandwidth { + constructor(period: number, multiplier: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PercentBNode = PercentB +export declare class PercentB { + constructor(period: number, multiplier: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type NatrNode = NATR +export declare class NATR { + constructor(period: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HistoricalVolatilityNode = HistoricalVolatility +export declare class HistoricalVolatility { + constructor(period: number, tradingPeriods: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AroonOscillatorNode = AroonOscillator +export declare class AroonOscillator { + constructor(period: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type WaveTrendNode = WaveTrend +export declare class WaveTrend { + constructor(channelPeriod: number, averagePeriod: number, signalPeriod: number) + static classic(): WaveTrendNode + update(high: number, low: number, close: number): WaveTrendValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RwiNode = RWI +export declare class RWI { + constructor(period: number) + update(high: number, low: number, close: number): RwiValue | null + /** Returns `[high0, low0, high1, low1, ...]`, length `2 * n`. Warmup is NaN. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VortexNode = Vortex +export declare class Vortex { + constructor(period: number) + update(high: number, low: number, close: number): VortexValue | null + /** Returns `[plus0, minus0, plus1, minus1, ...]`, length `2 * n`. Warmup is NaN. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MassIndexNode = MassIndex +export declare class MassIndex { + constructor(emaPeriod: number, sumPeriod: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StochRsiNode = StochRSI +export declare class StochRSI { + constructor(rsiPeriod: number, stochPeriod: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type UltimateOscillatorNode = UltimateOscillator +export declare class UltimateOscillator { + constructor(short: number, mid: number, long: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PpoNode = PPO +export declare class PPO { + constructor(fast: number, slow: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CoppockNode = Coppock +export declare class Coppock { + constructor(rocLong: number, rocShort: number, wmaPeriod: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VwmaNode = VWMA +export declare class VWMA { + constructor(period: number) + update(close: number, volume: number): number | null + batch(close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MaEnvelopeNode = MaEnvelope +export declare class MaEnvelope { + constructor(period: number, percent: number) + update(value: number): MaEnvelopeValue | null + /** Flat `[upper0, middle0, lower0, upper1, ...]`, length `3 * n`. */ + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AccelerationBandsNode = AccelerationBands +export declare class AccelerationBands { + constructor(period: number, factor: number) + update(high: number, low: number, close: number): AccelerationBandsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StarcBandsNode = StarcBands +export declare class StarcBands { + constructor(smaPeriod: number, atrPeriod: number, multiplier: number) + update(high: number, low: number, close: number): StarcBandsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AtrBandsNode = AtrBands +export declare class AtrBands { + constructor(period: number, multiplier: number) + update(high: number, low: number, close: number): AtrBandsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HurstChannelNode = HurstChannel +export declare class HurstChannel { + constructor(period: number, multiplier: number) + update(high: number, low: number, close: number): HurstChannelValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type LinRegChannelNode = LinRegChannel +export declare class LinRegChannel { + constructor(period: number, multiplier: number) + update(value: number): LinRegChannelValue | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type StandardErrorBandsNode = StandardErrorBands +export declare class StandardErrorBands { + constructor(period: number, multiplier: number) + update(value: number): StandardErrorBandsValue | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DoubleBollingerNode = DoubleBollinger +export declare class DoubleBollinger { + constructor(period: number, kInner: number, kOuter: number) + update(value: number): DoubleBollingerValue | null + /** Flat `[u_o, u_i, m, l_i, l_o, ...]`, length `5 * n`. */ + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TtmSqueezeNode = TtmSqueeze +export declare class TtmSqueeze { + constructor(period: number, bbMult: number, kcMult: number) + update(high: number, low: number, close: number): TtmSqueezeValue | null + /** Flat `[sq0, mom0, sq1, mom1, ...]`, length `2 * n`. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type FractalChaosBandsNode = FractalChaosBands +export declare class FractalChaosBands { + constructor(k: number) + update(high: number, low: number): FractalChaosBandsValue | null + /** Flat `[u0, l0, u1, l1, ...]`, length `2 * n`. */ + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type VwapStdDevBandsNode = VwapStdDevBands +export declare class VwapStdDevBands { + constructor(multiplier: number) + update(high: number, low: number, close: number, volume: number): VwapStdDevBandsValue | null + /** Flat `[u0, m0, l0, sd0, ...]`, length `4 * n`. */ + batch(high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ClassicPivotsNode = ClassicPivots +export declare class ClassicPivots { + constructor() + update(high: number, low: number, close: number): ClassicPivotsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type FibonacciPivotsNode = FibonacciPivots +export declare class FibonacciPivots { + constructor() + update(high: number, low: number, close: number): FibonacciPivotsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CamarillaNode = Camarilla +export declare class Camarilla { + constructor() + update(high: number, low: number, close: number): CamarillaValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type WoodiePivotsNode = WoodiePivots +export declare class WoodiePivots { + constructor() + update(high: number, low: number, close: number): WoodiePivotsValue | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DemarkPivotsNode = DemarkPivots +export declare class DemarkPivots { + constructor() + update(open: number, high: number, low: number, close: number): DemarkPivotsValue | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type WilliamsFractalsNode = WilliamsFractals +export declare class WilliamsFractals { + constructor() + update(high: number, low: number): WilliamsFractalsValue | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ZigZagNode = ZigZag +export declare class ZigZag { + constructor(threshold: number) + update(high: number, low: number): ZigZagValue | null + batch(high: Array, low: Array): Array + get threshold(): number + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdSetupNode = TDSetup +export declare class TDSetup { + constructor(lookback: number, target: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdSequentialNode = TDSequential +export declare class TDSequential { + constructor(setupLookback: number, setupTarget: number, countdownLookback: number, countdownTarget: number) + update(high: number, low: number, close: number): TdSequentialValue | null + /** Batch returns a flat array `[setup0, countdown0, direction0, setup1, ...]`. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdDeMarkerNode = TDDeMarker +export declare class TDDeMarker { + constructor(period: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdReiNode = TDREI +export declare class TDREI { + constructor(period: number) + update(high: number, low: number): number | null + batch(high: Array, low: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdPressureNode = TDPressure +export declare class TDPressure { + constructor(period: number) + update(open: number, high: number, low: number, close: number, volume: number): number | null + batch(open: Array, high: Array, low: Array, close: Array, volume: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdComboNode = TDCombo +export declare class TDCombo { + constructor(setupLookback: number, setupTarget: number, countdownLookback: number, countdownTarget: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdCountdownNode = TDCountdown +export declare class TDCountdown { + constructor(setupLookback: number, setupTarget: number, countdownLookback: number, countdownTarget: number) + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdLinesNode = TDLines +export declare class TDLines { + constructor(lookback: number, target: number) + update(high: number, low: number, close: number): TdLinesValue | null + /** Batch returns a flat array `[resistance0, support0, resistance1, ...]`. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdRangeProjectionNode = TDRangeProjection +export declare class TDRangeProjection { + constructor() + update(open: number, high: number, low: number, close: number): TdRangeProjectionValue | null + /** Batch returns a flat array `[high0, low0, high1, low1, ...]`. */ + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdDifferentialNode = TDDifferential +export declare class TDDifferential { + constructor() + update(high: number, low: number, close: number): number | null + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdOpenNode = TDOpen +export declare class TDOpen { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TdRiskLevelNode = TDRiskLevel +export declare class TDRiskLevel { + constructor(lookback: number, target: number) + update(high: number, low: number, close: number): TdRiskLevelValue | null + /** Batch returns a flat array `[buyRisk0, sellRisk0, buyRisk1, ...]`. */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type InverseFisherTransformNode = InverseFisherTransform +export declare class InverseFisherTransform { + constructor(scale: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DecyclerOscillatorNode = DecyclerOscillator +export declare class DecyclerOscillator { + constructor(fast: number, slow: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RoofingFilterNode = RoofingFilter +export declare class RoofingFilter { + constructor(lpPeriod: number, hpPeriod: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type EmpiricalModeDecompositionNode = EmpiricalModeDecomposition +export declare class EmpiricalModeDecomposition { + constructor(period: number, fraction: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HilbertDominantCycleNode = HilbertDominantCycle +export declare class HilbertDominantCycle { + constructor() + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AdaptiveCycleNode = AdaptiveCycle +export declare class AdaptiveCycle { + constructor() + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SineWaveNode = SineWave +export declare class SineWave { + constructor() + update(value: number): number | null + batch(prices: Array): Array + lead(): number + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MamaNode = MAMA +export declare class MAMA { + constructor(fastLimit: number, slowLimit: number) + update(value: number): MamaValue | null + /** Returns a flat array of length `2 * n`: `[mama0, fama0, mama1, fama1, ...]`. */ + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type FamaNode = FAMA +export declare class FAMA { + constructor(fastLimit: number, slowLimit: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type IchimokuNode = Ichimoku +export declare class Ichimoku { + constructor(tenkanPeriod: number, kijunPeriod: number, senkouBPeriod: number, displacement: number) + update(high: number, low: number, close: number): IchimokuValue | null + /** + * Returns `[tenkan0, kijun0, senkouA0, senkouB0, chikou0, tenkan1, ...]`, + * length `5 * n`. Cells without a defined value are `NaN`. + */ + batch(high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HeikinAshiNode = HeikinAshi +export declare class HeikinAshi { + constructor() + update(open: number, high: number, low: number, close: number): HeikinAshiValue | null + /** Returns `[open0, high0, low0, close0, open1, ...]`, length `4 * n`. */ + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ValueAreaNode = ValueArea +export declare class ValueArea { + constructor(period: number, binCount: number, valueAreaPct: number) + reset(): void + isReady(): boolean + warmupPeriod(): number + update(high: number, low: number, volume: number): ValueAreaValue | null + batch(high: Array, low: Array, volume: Array): Array +} +export type InitialBalanceNode = InitialBalance +export declare class InitialBalance { + constructor(period: number) + reset(): void + isReady(): boolean + isLocked(): boolean + warmupPeriod(): number + update(high: number, low: number): InitialBalanceValue | null + batch(high: Array, low: Array): Array +} +export type OpeningRangeNode = OpeningRange +export declare class OpeningRange { + constructor(period: number) + reset(): void + isReady(): boolean + isLocked(): boolean + warmupPeriod(): number + update(high: number, low: number, close: number): OpeningRangeValue | null + batch(high: Array, low: Array, close: Array): Array +} +export type DojiNode = Doji +export declare class Doji { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HammerNode = Hammer +export declare class Hammer { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type InvertedHammerNode = InvertedHammer +export declare class InvertedHammer { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HangingManNode = HangingMan +export declare class HangingMan { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ShootingStarNode = ShootingStar +export declare class ShootingStar { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type EngulfingNode = Engulfing +export declare class Engulfing { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type HaramiNode = Harami +export declare class Harami { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MorningEveningStarNode = MorningEveningStar +export declare class MorningEveningStar { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ThreeSoldiersOrCrowsNode = ThreeSoldiersOrCrows +export declare class ThreeSoldiersOrCrows { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PiercingDarkCloudNode = PiercingDarkCloud +export declare class PiercingDarkCloud { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MarubozuNode = Marubozu +export declare class Marubozu { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TweezerNode = Tweezer +export declare class Tweezer { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SpinningTopNode = SpinningTop +export declare class SpinningTop { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ThreeInsideNode = ThreeInside +export declare class ThreeInside { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ThreeOutsideNode = ThreeOutside +export declare class ThreeOutside { + constructor() + update(open: number, high: number, low: number, close: number): number | null + batch(open: Array, high: Array, low: Array, close: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SharpeRatioNode = SharpeRatio +export declare class SharpeRatio { + constructor(period: number, riskFree: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type SortinoRatioNode = SortinoRatio +export declare class SortinoRatio { + constructor(period: number, mar: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type CalmarRatioNode = CalmarRatio +export declare class CalmarRatio { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type OmegaRatioNode = OmegaRatio +export declare class OmegaRatio { + constructor(period: number, threshold: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type MaxDrawdownNode = MaxDrawdown +export declare class MaxDrawdown { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AverageDrawdownNode = AverageDrawdown +export declare class AverageDrawdown { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type DrawdownDurationNode = DrawdownDuration +export declare class DrawdownDuration { + constructor() + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type PainIndexNode = PainIndex +export declare class PainIndex { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ValueAtRiskNode = ValueAtRisk +export declare class ValueAtRisk { + constructor(period: number, confidence: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ConditionalValueAtRiskNode = ConditionalValueAtRisk +export declare class ConditionalValueAtRisk { + constructor(period: number, confidence: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type ProfitFactorNode = ProfitFactor +export declare class ProfitFactor { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type GainLossRatioNode = GainLossRatio +export declare class GainLossRatio { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type RecoveryFactorNode = RecoveryFactor +export declare class RecoveryFactor { + constructor() + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type KellyCriterionNode = KellyCriterion +export declare class KellyCriterion { + constructor(period: number) + update(value: number): number | null + batch(prices: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type TreynorRatioNode = TreynorRatio +export declare class TreynorRatio { + constructor(period: number, riskFree: number) + update(asset: number, benchmark: number): number | null + batch(asset: Array, benchmark: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type InformationRatioNode = InformationRatio +export declare class InformationRatio { + constructor(period: number) + update(asset: number, benchmark: number): number | null + batch(asset: Array, benchmark: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} +export type AlphaNode = Alpha +export declare class Alpha { + constructor(period: number, riskFree: number) + update(asset: number, benchmark: number): number | null + batch(asset: Array, benchmark: Array): Array + reset(): void + isReady(): boolean + warmupPeriod(): number +} diff --git a/bindings/node/src/lib.rs b/bindings/node/src/lib.rs index 65106837..c9af2092 100644 --- a/bindings/node/src/lib.rs +++ b/bindings/node/src/lib.rs @@ -22,26 +22,6 @@ fn map_err(e: wc::Error) -> NapiError { NapiError::new(Status::InvalidArg, e.to_string()) } -/// Helper for the scalar-indicator macro only. Scalar `new` functions can fail -/// solely on `period == 0`, which `clamp_period` already rules out, so the -/// `Result` is provably `Ok` here. Candle indicators and the multi-parameter -/// indicators have genuinely fallible parameters and instead use fallible -/// `#[napi(constructor)]`s that return `napi::Result` and throw a JS error. -fn must(r: Result) -> T { - r.expect("wickra: scalar indicator parameter clamped to a valid range") -} - -/// Clamp a period parameter so the underlying indicator never sees zero. JS -/// callers who pass `0` get a window of `1` instead of a thrown exception — -/// effectively a pass-through indicator that still produces valid outputs. -const fn clamp_period(p: u32) -> usize { - if p == 0 { - 1 - } else { - p as usize - } -} - fn flatten(v: Vec>) -> Vec { v.into_iter().map(|x| x.unwrap_or(f64::NAN)).collect() } @@ -64,10 +44,10 @@ macro_rules! node_scalar_indicator { #[napi] impl $wrapper { #[napi(constructor)] - pub fn new(period: u32) -> Self { - Self { - inner: must(<$rust_ty>::new(clamp_period(period))), - } + pub fn new(period: u32) -> napi::Result { + Ok(Self { + inner: <$rust_ty>::new(period as usize).map_err(map_err)?, + }) } #[napi] pub fn update(&mut self, value: f64) -> Option { @@ -137,11 +117,10 @@ node_scalar_indicator!( ); // RviVolatility (Relative Volatility Index, Donald Dorsey). Disambiguated -// from `RVI` = Relative Vigor Index in Family 02. Takes a single `period` -// parameter and additionally rejects `period == 1` (a 1-bar standard -// deviation is always zero), so the `clamp_period`-to-1 strategy from -// `node_scalar_indicator!` would panic via `must`. Hand-rolled fallible -// constructor instead, throws a JS error on bad period. +// from `RVI` = Relative Vigor Index in Family 02. Takes a single `period` and +// rejects both `period == 0` and `period == 1` (a 1-bar standard deviation is +// always zero). Hand-rolled, but behaves like `node_scalar_indicator!`: the +// fallible `new` propagates the core error and throws a JS error on bad period. #[napi(js_name = "RVIVolatility")] pub struct RviVolatilityNode { inner: wc::RviVolatility, @@ -1351,7 +1330,7 @@ impl InertiaNode { #[napi(constructor)] pub fn new(rvi_period: u32, linreg_period: u32) -> napi::Result { Ok(Self { - inner: wc::Inertia::new(clamp_period(rvi_period), clamp_period(linreg_period)) + inner: wc::Inertia::new(rvi_period as usize, linreg_period as usize) .map_err(map_err)?, }) } @@ -1412,9 +1391,9 @@ impl ConnorsRsiNode { pub fn new(period_rsi: u32, period_streak: u32, period_rank: u32) -> napi::Result { Ok(Self { inner: wc::ConnorsRsi::new( - clamp_period(period_rsi), - clamp_period(period_streak), - clamp_period(period_rank), + period_rsi as usize, + period_streak as usize, + period_rank as usize, ) .map_err(map_err)?, }) @@ -1484,12 +1463,8 @@ impl SmiNode { #[napi(constructor)] pub fn new(period: u32, d_period: u32, d2_period: u32) -> napi::Result { Ok(Self { - inner: wc::Smi::new( - clamp_period(period), - clamp_period(d_period), - clamp_period(d2_period), - ) - .map_err(map_err)?, + inner: wc::Smi::new(period as usize, d_period as usize, d2_period as usize) + .map_err(map_err)?, }) } #[napi] @@ -1559,15 +1534,15 @@ impl KstNode { ) -> napi::Result { Ok(Self { inner: wc::Kst::new( - clamp_period(roc1), - clamp_period(roc2), - clamp_period(roc3), - clamp_period(roc4), - clamp_period(sma1), - clamp_period(sma2), - clamp_period(sma3), - clamp_period(sma4), - clamp_period(signal), + roc1 as usize, + roc2 as usize, + roc3 as usize, + roc4 as usize, + sma1 as usize, + sma2 as usize, + sma3 as usize, + sma4 as usize, + signal as usize, ) .map_err(map_err)?, }) @@ -1620,7 +1595,7 @@ impl PgoNode { #[napi(constructor)] pub fn new(period: u32) -> napi::Result { Ok(Self { - inner: wc::Pgo::new(clamp_period(period)).map_err(map_err)?, + inner: wc::Pgo::new(period as usize).map_err(map_err)?, }) } #[napi] @@ -1672,7 +1647,7 @@ impl RviNode { #[napi(constructor)] pub fn new(period: u32) -> napi::Result { Ok(Self { - inner: wc::Rvi::new(clamp_period(period)).map_err(map_err)?, + inner: wc::Rvi::new(period as usize).map_err(map_err)?, }) } #[napi] @@ -1732,9 +1707,9 @@ impl AwesomeOscillatorHistogramNode { pub fn new(fast: u32, slow: u32, sma_period: u32) -> napi::Result { Ok(Self { inner: wc::AwesomeOscillatorHistogram::new( - clamp_period(fast), - clamp_period(slow), - clamp_period(sma_period), + fast as usize, + slow as usize, + sma_period as usize, ) .map_err(map_err)?, }) @@ -1783,13 +1758,8 @@ impl StcNode { #[napi(constructor)] pub fn new(fast: u32, slow: u32, schaff_period: u32, factor: f64) -> napi::Result { Ok(Self { - inner: wc::Stc::new( - clamp_period(fast), - clamp_period(slow), - clamp_period(schaff_period), - factor, - ) - .map_err(map_err)?, + inner: wc::Stc::new(fast as usize, slow as usize, schaff_period as usize, factor) + .map_err(map_err)?, }) } #[napi] @@ -1829,10 +1799,10 @@ impl ElderImpulseNode { ) -> napi::Result { Ok(Self { inner: wc::ElderImpulse::new( - clamp_period(ema_period), - clamp_period(macd_fast), - clamp_period(macd_slow), - clamp_period(macd_signal), + ema_period as usize, + macd_fast as usize, + macd_slow as usize, + macd_signal as usize, ) .map_err(map_err)?, }) @@ -1875,12 +1845,8 @@ impl ZeroLagMacdNode { #[napi(constructor)] pub fn new(fast: u32, slow: u32, signal: u32) -> napi::Result { Ok(Self { - inner: wc::ZeroLagMacd::new( - clamp_period(fast), - clamp_period(slow), - clamp_period(signal), - ) - .map_err(map_err)?, + inner: wc::ZeroLagMacd::new(fast as usize, slow as usize, signal as usize) + .map_err(map_err)?, }) } #[napi] @@ -1927,7 +1893,7 @@ impl CfoNode { #[napi(constructor)] pub fn new(period: u32) -> napi::Result { Ok(Self { - inner: wc::Cfo::new(clamp_period(period)).map_err(map_err)?, + inner: wc::Cfo::new(period as usize).map_err(map_err)?, }) } #[napi] @@ -1961,7 +1927,7 @@ impl ApoNode { #[napi(constructor)] pub fn new(fast: u32, slow: u32) -> napi::Result { Ok(Self { - inner: wc::Apo::new(clamp_period(fast), clamp_period(slow)).map_err(map_err)?, + inner: wc::Apo::new(fast as usize, slow as usize).map_err(map_err)?, }) } #[napi] @@ -2032,7 +1998,7 @@ impl EvwmaNode { #[napi(constructor)] pub fn new(period: u32) -> napi::Result { Ok(Self { - inner: wc::Evwma::new(clamp_period(period)).map_err(map_err)?, + inner: wc::Evwma::new(period as usize).map_err(map_err)?, }) } #[napi] @@ -2088,7 +2054,7 @@ impl AlligatorNode { #[napi(constructor)] pub fn new(jaw: u32, teeth: u32, lips: u32) -> napi::Result { Ok(Self { - inner: wc::Alligator::new(clamp_period(jaw), clamp_period(teeth), clamp_period(lips)) + inner: wc::Alligator::new(jaw as usize, teeth as usize, lips as usize) .map_err(map_err)?, }) } @@ -2146,7 +2112,7 @@ impl JmaNode { #[napi(constructor)] pub fn new(period: u32, phase: f64, power: u32) -> napi::Result { Ok(Self { - inner: wc::Jma::new(clamp_period(period), phase, power).map_err(map_err)?, + inner: wc::Jma::new(period as usize, phase, power).map_err(map_err)?, }) } #[napi] @@ -2182,8 +2148,7 @@ impl VidyaNode { #[napi(constructor)] pub fn new(period: u32, cmo_period: u32) -> napi::Result { Ok(Self { - inner: wc::Vidya::new(clamp_period(period), clamp_period(cmo_period)) - .map_err(map_err)?, + inner: wc::Vidya::new(period as usize, cmo_period as usize).map_err(map_err)?, }) } #[napi] @@ -2219,7 +2184,7 @@ impl AlmaNode { #[napi(constructor)] pub fn new(period: u32, offset: f64, sigma: f64) -> napi::Result { Ok(Self { - inner: wc::Alma::new(clamp_period(period), offset, sigma).map_err(map_err)?, + inner: wc::Alma::new(period as usize, offset, sigma).map_err(map_err)?, }) } #[napi]