ta-crypto 0.2.3 → 0.3.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 CHANGED
@@ -33,9 +33,13 @@ const vs = vwapSession(high, low, close, volume, [1, 1]);
33
33
  ## Stateful API (streaming)
34
34
 
35
35
  ```ts
36
- import { createRSI, createVWAPSession } from "ta-crypto";
36
+ import { createSMA, createEMA, createRSI, createVWAPSession } from "ta-crypto";
37
37
 
38
+ const sma14 = createSMA(14);
39
+ const ema14 = createEMA(14);
38
40
  const rsi14 = createRSI(14);
41
+ const nextSma = sma14.next(101.25);
42
+ const nextEma = ema14.next(101.25);
39
43
  const nextRsi = rsi14.next(101.25);
40
44
 
41
45
  const vwap = createVWAPSession();
@@ -48,6 +52,33 @@ const nextVwap = vwap.next({
48
52
  });
49
53
  ```
50
54
 
55
+ Websocket-like streaming loop:
56
+
57
+ ```ts
58
+ import { createEMA, createRSI } from "ta-crypto";
59
+
60
+ const ema21 = createEMA(21);
61
+ const rsi14 = createRSI(14);
62
+
63
+ ws.on("message", (tick) => {
64
+ const price = Number(tick.last);
65
+ const e = ema21.next(price);
66
+ const r = rsi14.next(price);
67
+ if (e !== null && r !== null) {
68
+ // strategy signal path
69
+ }
70
+ });
71
+ ```
72
+
73
+ ## Examples
74
+
75
+ Real-world entry points live in `examples/`:
76
+ - `examples/rsi-strategy.ts`
77
+ - `examples/vwap-session.ts`
78
+ - `examples/funding-arbitrage.ts`
79
+
80
+ If you're using ta-crypto in production or experiments, feel free to add your example here.
81
+
51
82
  ## Compatibility
52
83
 
53
84
  `ta-crypto` now ships golden tests (`test/fixtures/golden.json`) to lock behavior across releases.
@@ -75,9 +106,23 @@ Streaming parity:
75
106
 
76
107
  External parity:
77
108
 
78
- | Indicator set | Reference libs | Tolerance |
79
- | --- | --- | --- |
80
- | SMA/EMA/RSI/MACD/BBANDS/ATR/ADX | TA-Lib, pandas-ta, technicalindicators | 1e-8 |
109
+ Policy source: `scripts/compat-policy.json`
110
+
111
+ | Indicator | Burn-in | Tolerance | Blocking refs | Non-blocking refs |
112
+ | --- | --- | --- | --- | --- |
113
+ | SMA(14) | 14 | 1e-10 | TA-Lib, technicalindicators | pandas-ta |
114
+ | EMA(14) | 14 | 1e-10 | TA-Lib, technicalindicators | pandas-ta |
115
+ | RSI(14) | 28 | 5e-2 | TA-Lib, technicalindicators | pandas-ta |
116
+ | MACD(12,26,9) | 80 | 2e-2 | TA-Lib, technicalindicators | pandas-ta |
117
+ | BBANDS(20,2) | 20 | 1e-10 | TA-Lib, technicalindicators | pandas-ta |
118
+ | ATR(14) | 56 | 1.5e-1 | TA-Lib, technicalindicators | pandas-ta |
119
+ | ADX/+DI/-DI(14) | 90 | 1.5 | TA-Lib, technicalindicators | pandas-ta |
120
+
121
+ Warmup and alignment rules:
122
+ - References are left-padded to full series length before comparison.
123
+ - Comparison starts at indicator-specific burn-in and uses only overlapping non-null points.
124
+ - `TA-Lib` and `technicalindicators` are release-blocking checks in CI.
125
+ - `pandas-ta` is telemetry-only (warns when divergent or unavailable by environment).
81
126
 
82
127
  Generate/review vectors:
83
128
 
@@ -149,20 +194,49 @@ Limitations:
149
194
  - Orderflow proxies infer pressure from candle direction and volume; they are not a replacement for L2/L3 order book data.
150
195
  - Different libraries use different warmup conventions; comparisons use overlapping non-null windows.
151
196
 
152
- ## Candle Contracts
197
+ ## Typing and Inputs
198
+
199
+ `ta-crypto` public APIs accept two input styles:
200
+ - Primitive arrays (`number[]`) for low-level control.
201
+ - Candle objects with long keys (`open/high/low/close/volume/time`) or aliases (`o/h/l/c/v/t`).
153
202
 
154
- Use typed candles plus helpers:
203
+ Single-series APIs (for example `sma`, `ema`, `rsi`, `macd`, `bbands`) accept:
204
+
205
+ ```ts
206
+ import { rsi } from "ta-crypto";
207
+
208
+ const close = [101, 102, 103, 104];
209
+ const candles = [{ o: 100, h: 102, l: 99, c: 101, v: 10, t: 1 }];
210
+
211
+ rsi(close, 14);
212
+ rsi(candles, 14); // uses candle close/c
213
+ ```
214
+
215
+ OHLC/OHLCV APIs (for example `vwap`, `stoch`, `atr`, `natr`, `mfi`, `adx`) accept:
216
+
217
+ ```ts
218
+ import { atr, vwap } from "ta-crypto";
219
+
220
+ atr([102, 103], [99, 100], [101, 102], 14);
221
+ atr([{ open: 100, high: 102, low: 99, close: 101, volume: 10 }], 14);
222
+
223
+ vwap([102, 103], [99, 100], [101, 102], [10, 12]);
224
+ vwap([{ o: 100, h: 102, l: 99, c: 101, v: 10 }]);
225
+ ```
226
+
227
+ Helpers:
155
228
 
156
229
  ```ts
157
230
  import { pluckClose, toOHLCV } from "ta-crypto";
158
231
 
159
232
  const close = pluckClose(candles);
160
- const { open, high, low, close: c, volume } = toOHLCV(candles, 0);
233
+ const ohlcv = toOHLCV(candles, 0);
234
+ const ohlcvFromArrays = toOHLCV({ o: [1, 2], h: [3, 4], l: [0, 1], c: [2, 3], v: [5, 6] });
161
235
  ```
162
236
 
163
237
  Validation:
164
- - Multi-series indicators enforce equal lengths (`assertSameLength`).
165
- - Candle helpers validate finite numeric fields with index-specific error messages.
238
+ - Multi-series APIs enforce equal lengths.
239
+ - Numeric inputs are validated as finite numbers with index-aware messages when possible.
166
240
 
167
241
  ## Module Imports
168
242
 
@@ -170,7 +244,7 @@ Validation:
170
244
  import { sma } from "ta-crypto/indicators";
171
245
  import { vwapSession } from "ta-crypto/crypto";
172
246
  import { toOHLCV } from "ta-crypto/candles";
173
- import { createRSI } from "ta-crypto/stateful";
247
+ import { createSMA, createEMA, createRSI } from "ta-crypto/stateful";
174
248
  ```
175
249
 
176
250
  ## Bench (internal baseline, 10k candles)
@@ -191,6 +265,16 @@ Run locally:
191
265
  npm run bench
192
266
  ```
193
267
 
268
+ ## Contributing
269
+
270
+ ta-crypto is open to contributors.
271
+ If you use it, improve it.
272
+ If you miss something, build it.
273
+ If you're learning, this is a great codebase to practice financial math.
274
+
275
+ Start with `CONTRIBUTING.md` and `ROADMAP.md`.
276
+ If you want to contribute but don't know where to start, pick an indicator from the roadmap and add tests comparing with TA-Lib.
277
+
194
278
  ## Release
195
279
 
196
280
  Publications are gated by GitHub Actions:
package/dist/api.d.ts ADDED
@@ -0,0 +1,67 @@
1
+ import type { Candle, OHLCVInput, PriceInput } from "./types.js";
2
+ type OHLCInput = Candle[] | OHLCVInput;
3
+ export declare function sma(input: PriceInput, length?: number): Array<number | null>;
4
+ export declare function ema(input: PriceInput, length?: number): Array<number | null>;
5
+ export declare function rma(input: PriceInput, length?: number): Array<number | null>;
6
+ export declare function bbands(input: PriceInput, length?: number, std?: number): {
7
+ basis: (number | null)[];
8
+ upper: (number | null)[];
9
+ lower: (number | null)[];
10
+ };
11
+ export declare function macd(input: PriceInput, fast?: number, slow?: number, signal?: number): {
12
+ macd: (number | null)[];
13
+ signal: (number | null)[];
14
+ histogram: (number | null)[];
15
+ };
16
+ export declare function rsi(input: PriceInput, length?: number): Array<number | null>;
17
+ export declare function logReturn(input: PriceInput, cumulative?: boolean): Array<number | null>;
18
+ export declare function percentReturn(input: PriceInput, cumulative?: boolean): Array<number | null>;
19
+ export declare function realizedVolatility(input: PriceInput, length?: number, periodsPerYear?: number): Array<number | null>;
20
+ export declare function hl2(high: number[], low: number[]): Array<number | null>;
21
+ export declare function hl2(input: OHLCInput): Array<number | null>;
22
+ export declare function hlc3(high: number[], low: number[], close: number[]): Array<number | null>;
23
+ export declare function hlc3(input: OHLCInput): Array<number | null>;
24
+ export declare function ohlc4(open: number[], high: number[], low: number[], close: number[]): Array<number | null>;
25
+ export declare function ohlc4(input: OHLCInput): Array<number | null>;
26
+ export declare function vwap(high: number[], low: number[], close: number[], volume: number[], length?: number): Array<number | null>;
27
+ export declare function vwap(input: OHLCInput, length?: number): Array<number | null>;
28
+ export declare function stoch(high: number[], low: number[], close: number[], kLength?: number, dLength?: number): {
29
+ k: Array<number | null>;
30
+ d: Array<number | null>;
31
+ };
32
+ export declare function stoch(input: OHLCInput, kLength?: number, dLength?: number): {
33
+ k: Array<number | null>;
34
+ d: Array<number | null>;
35
+ };
36
+ export declare function trueRange(high: number[], low: number[], close: number[]): Array<number | null>;
37
+ export declare function trueRange(input: OHLCInput): Array<number | null>;
38
+ export declare function atr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
39
+ export declare function atr(input: OHLCInput, length?: number): Array<number | null>;
40
+ export declare function natr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
41
+ export declare function natr(input: OHLCInput, length?: number): Array<number | null>;
42
+ export declare function obv(close: number[], volume: number[]): Array<number | null>;
43
+ export declare function obv(input: OHLCInput): Array<number | null>;
44
+ export declare function mfi(high: number[], low: number[], close: number[], volume: number[], length?: number): Array<number | null>;
45
+ export declare function mfi(input: OHLCInput, length?: number): Array<number | null>;
46
+ export declare function adx(high: number[], low: number[], close: number[], length?: number): {
47
+ adx: Array<number | null>;
48
+ plusDI: Array<number | null>;
49
+ minusDI: Array<number | null>;
50
+ };
51
+ export declare function adx(input: OHLCInput, length?: number): {
52
+ adx: Array<number | null>;
53
+ plusDI: Array<number | null>;
54
+ minusDI: Array<number | null>;
55
+ };
56
+ export declare function vwapSession(high: number[], low: number[], close: number[], volume: number[], session: Array<string | number>): Array<number | null>;
57
+ export declare function vwapSession(input: OHLCInput, session: Array<string | number>): Array<number | null>;
58
+ export declare function signedVolume(open: number[], close: number[], volume: number[]): Array<number | null>;
59
+ export declare function signedVolume(input: OHLCInput): Array<number | null>;
60
+ export declare function volumeDelta(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
61
+ export declare function volumeDelta(input: OHLCInput, length?: number): Array<number | null>;
62
+ export declare function orderflowImbalance(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
63
+ export declare function orderflowImbalance(input: OHLCInput, length?: number): Array<number | null>;
64
+ export declare function fundingRateCumulative(values: number[]): Array<number | null>;
65
+ export declare function fundingRateAPR(values: number[], periodsPerYear?: number): Array<number | null>;
66
+ export declare function volatilityRegime(input: PriceInput, length?: number, periodsPerYear?: number, lowZ?: number, highZ?: number): Array<number | null>;
67
+ export {};
package/dist/api.js ADDED
@@ -0,0 +1,241 @@
1
+ import { assertFiniteSeries } from "./core/math.js";
2
+ import { normalizePrice, toOHLCV } from "./candles.js";
3
+ import { sma as coreSma, ema as coreEma, rma as coreRma, hl2 as coreHl2, hlc3 as coreHlc3, ohlc4 as coreOhlc4, vwap as coreVwap, bbands as coreBbands } from "./core/overlap.js";
4
+ import { rsi as coreRsi, macd as coreMacd, stoch as coreStoch } from "./core/momentum.js";
5
+ import { trueRange as coreTrueRange, atr as coreAtr, natr as coreNatr } from "./core/volatility.js";
6
+ import { logReturn as coreLogReturn, percentReturn as corePercentReturn, realizedVolatility as coreRealizedVolatility } from "./core/performance.js";
7
+ import { obv as coreObv, mfi as coreMfi } from "./core/volume.js";
8
+ import { adx as coreAdx } from "./core/trend.js";
9
+ import { vwapSession as coreVwapSession, fundingRateCumulative as coreFundingRateCumulative, fundingRateAPR as coreFundingRateAPR, volatilityRegime as coreVolatilityRegime, signedVolume as coreSignedVolume, volumeDelta as coreVolumeDelta, orderflowImbalance as coreOrderflowImbalance } from "./core/crypto.js";
10
+ function isNumericArray(input) {
11
+ return Array.isArray(input) && (input.length === 0 || typeof input[0] === "number");
12
+ }
13
+ function parseHLC(input, low, close) {
14
+ if (isNumericArray(input)) {
15
+ if (!low || !close) {
16
+ throw new Error("Expected high, low, close arrays or candles/OHLCV object input");
17
+ }
18
+ assertFiniteSeries("high", input);
19
+ assertFiniteSeries("low", low);
20
+ assertFiniteSeries("close", close);
21
+ return { high: input, low, close };
22
+ }
23
+ return toOHLCV(input);
24
+ }
25
+ function parseOHLC(input, high, low, close) {
26
+ if (isNumericArray(input)) {
27
+ if (!high || !low || !close) {
28
+ throw new Error("Expected open, high, low, close arrays or candles/OHLCV object input");
29
+ }
30
+ assertFiniteSeries("open", input);
31
+ assertFiniteSeries("high", high);
32
+ assertFiniteSeries("low", low);
33
+ assertFiniteSeries("close", close);
34
+ return { open: input, high, low, close };
35
+ }
36
+ return toOHLCV(input);
37
+ }
38
+ function parseHLCV(input, low, close, volume) {
39
+ if (isNumericArray(input)) {
40
+ if (!low || !close || !volume) {
41
+ throw new Error("Expected high, low, close, volume arrays or candles/OHLCV object input");
42
+ }
43
+ assertFiniteSeries("high", input);
44
+ assertFiniteSeries("low", low);
45
+ assertFiniteSeries("close", close);
46
+ assertFiniteSeries("volume", volume);
47
+ return { high: input, low, close, volume };
48
+ }
49
+ return toOHLCV(input);
50
+ }
51
+ function parseOCV(input, close, volume) {
52
+ if (isNumericArray(input)) {
53
+ if (!close || !volume) {
54
+ throw new Error("Expected open, close, volume arrays or candles/OHLCV object input");
55
+ }
56
+ assertFiniteSeries("open", input);
57
+ assertFiniteSeries("close", close);
58
+ assertFiniteSeries("volume", volume);
59
+ return { open: input, close, volume };
60
+ }
61
+ return toOHLCV(input);
62
+ }
63
+ export function sma(input, length = 14) {
64
+ return coreSma(normalizePrice(input), length);
65
+ }
66
+ export function ema(input, length = 14) {
67
+ return coreEma(normalizePrice(input), length);
68
+ }
69
+ export function rma(input, length = 14) {
70
+ return coreRma(normalizePrice(input), length);
71
+ }
72
+ export function bbands(input, length = 20, std = 2) {
73
+ return coreBbands(normalizePrice(input), length, std);
74
+ }
75
+ export function macd(input, fast = 12, slow = 26, signal = 9) {
76
+ return coreMacd(normalizePrice(input), fast, slow, signal);
77
+ }
78
+ export function rsi(input, length = 14) {
79
+ return coreRsi(normalizePrice(input), length);
80
+ }
81
+ export function logReturn(input, cumulative = false) {
82
+ return coreLogReturn(normalizePrice(input), cumulative);
83
+ }
84
+ export function percentReturn(input, cumulative = false) {
85
+ return corePercentReturn(normalizePrice(input), cumulative);
86
+ }
87
+ export function realizedVolatility(input, length = 30, periodsPerYear = 365) {
88
+ return coreRealizedVolatility(normalizePrice(input), length, periodsPerYear);
89
+ }
90
+ export function hl2(input, low) {
91
+ if (isNumericArray(input)) {
92
+ if (!low)
93
+ throw new Error("Expected high + low arrays or candles/OHLCV object input");
94
+ return coreHl2(input, low);
95
+ }
96
+ const ohlcv = toOHLCV(input);
97
+ return coreHl2(ohlcv.high, ohlcv.low);
98
+ }
99
+ export function hlc3(input, low, close) {
100
+ const ohlcv = parseHLC(input, low, close);
101
+ return coreHlc3(ohlcv.high, ohlcv.low, ohlcv.close);
102
+ }
103
+ export function ohlc4(input, high, low, close) {
104
+ const ohlcv = parseOHLC(input, high, low, close);
105
+ return coreOhlc4(ohlcv.open, ohlcv.high, ohlcv.low, ohlcv.close);
106
+ }
107
+ export function vwap(input, lowOrLength, close, volume, length) {
108
+ if (isNumericArray(input)) {
109
+ const low = Array.isArray(lowOrLength) ? lowOrLength : undefined;
110
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
111
+ const ohlcv = parseHLCV(input, low, close, volume);
112
+ return coreVwap(ohlcv.high, ohlcv.low, ohlcv.close, ohlcv.volume, resolvedLength);
113
+ }
114
+ const ohlcv = toOHLCV(input);
115
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
116
+ return coreVwap(ohlcv.high, ohlcv.low, ohlcv.close, ohlcv.volume, resolvedLength);
117
+ }
118
+ export function stoch(input, lowOrKLength, closeOrDLength, kLength = 14, dLength = 3) {
119
+ if (isNumericArray(input)) {
120
+ const low = Array.isArray(lowOrKLength) ? lowOrKLength : undefined;
121
+ const close = Array.isArray(closeOrDLength) ? closeOrDLength : undefined;
122
+ const resolvedK = typeof lowOrKLength === "number" ? lowOrKLength : kLength;
123
+ const resolvedD = typeof closeOrDLength === "number" ? closeOrDLength : dLength;
124
+ const ohlcv = parseHLC(input, low, close);
125
+ return coreStoch(ohlcv.high, ohlcv.low, ohlcv.close, resolvedK, resolvedD);
126
+ }
127
+ const resolvedK = typeof lowOrKLength === "number" ? lowOrKLength : kLength;
128
+ const resolvedD = typeof closeOrDLength === "number" ? closeOrDLength : dLength;
129
+ const ohlcv = toOHLCV(input);
130
+ return coreStoch(ohlcv.high, ohlcv.low, ohlcv.close, resolvedK, resolvedD);
131
+ }
132
+ export function trueRange(input, low, close) {
133
+ const ohlcv = parseHLC(input, low, close);
134
+ return coreTrueRange(ohlcv.high, ohlcv.low, ohlcv.close);
135
+ }
136
+ export function atr(input, lowOrLength, close, length = 14) {
137
+ if (isNumericArray(input)) {
138
+ const low = Array.isArray(lowOrLength) ? lowOrLength : undefined;
139
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
140
+ const ohlcv = parseHLC(input, low, close);
141
+ return coreAtr(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
142
+ }
143
+ const ohlcv = toOHLCV(input);
144
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
145
+ return coreAtr(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
146
+ }
147
+ export function natr(input, lowOrLength, close, length = 14) {
148
+ if (isNumericArray(input)) {
149
+ const low = Array.isArray(lowOrLength) ? lowOrLength : undefined;
150
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
151
+ const ohlcv = parseHLC(input, low, close);
152
+ return coreNatr(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
153
+ }
154
+ const ohlcv = toOHLCV(input);
155
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
156
+ return coreNatr(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
157
+ }
158
+ export function obv(input, volume) {
159
+ if (isNumericArray(input)) {
160
+ if (!volume)
161
+ throw new Error("Expected close + volume arrays or candles/OHLCV object input");
162
+ return coreObv(input, volume);
163
+ }
164
+ const ohlcv = toOHLCV(input);
165
+ return coreObv(ohlcv.close, ohlcv.volume);
166
+ }
167
+ export function mfi(input, lowOrLength, close, volume, length = 14) {
168
+ if (isNumericArray(input)) {
169
+ const low = Array.isArray(lowOrLength) ? lowOrLength : undefined;
170
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
171
+ const ohlcv = parseHLCV(input, low, close, volume);
172
+ return coreMfi(ohlcv.high, ohlcv.low, ohlcv.close, ohlcv.volume, resolvedLength);
173
+ }
174
+ const ohlcv = toOHLCV(input);
175
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
176
+ return coreMfi(ohlcv.high, ohlcv.low, ohlcv.close, ohlcv.volume, resolvedLength);
177
+ }
178
+ export function adx(input, lowOrLength, close, length = 14) {
179
+ if (isNumericArray(input)) {
180
+ const low = Array.isArray(lowOrLength) ? lowOrLength : undefined;
181
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
182
+ const ohlcv = parseHLC(input, low, close);
183
+ return coreAdx(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
184
+ }
185
+ const ohlcv = toOHLCV(input);
186
+ const resolvedLength = typeof lowOrLength === "number" ? lowOrLength : length;
187
+ return coreAdx(ohlcv.high, ohlcv.low, ohlcv.close, resolvedLength);
188
+ }
189
+ export function vwapSession(input, lowOrSession, close, volume, session) {
190
+ if (isNumericArray(input)) {
191
+ if (!isNumericArray(lowOrSession)) {
192
+ throw new Error("Expected high, low, close, volume, session arrays");
193
+ }
194
+ if (!session || !close || !volume) {
195
+ throw new Error("Expected high, low, close, volume, session arrays");
196
+ }
197
+ return coreVwapSession(input, lowOrSession, close, volume, session);
198
+ }
199
+ if (!Array.isArray(lowOrSession)) {
200
+ throw new Error("session must be an array");
201
+ }
202
+ const ohlcv = toOHLCV(input);
203
+ return coreVwapSession(ohlcv.high, ohlcv.low, ohlcv.close, ohlcv.volume, lowOrSession);
204
+ }
205
+ export function signedVolume(input, close, volume) {
206
+ const ohlcv = parseOCV(input, close, volume);
207
+ return coreSignedVolume(ohlcv.open, ohlcv.close, ohlcv.volume);
208
+ }
209
+ export function volumeDelta(input, closeOrLength, volume, length = 14) {
210
+ if (isNumericArray(input)) {
211
+ const close = Array.isArray(closeOrLength) ? closeOrLength : undefined;
212
+ const resolvedLength = typeof closeOrLength === "number" ? closeOrLength : length;
213
+ const ohlcv = parseOCV(input, close, volume);
214
+ return coreVolumeDelta(ohlcv.open, ohlcv.close, ohlcv.volume, resolvedLength);
215
+ }
216
+ const ohlcv = toOHLCV(input);
217
+ const resolvedLength = typeof closeOrLength === "number" ? closeOrLength : length;
218
+ return coreVolumeDelta(ohlcv.open, ohlcv.close, ohlcv.volume, resolvedLength);
219
+ }
220
+ export function orderflowImbalance(input, closeOrLength, volume, length = 14) {
221
+ if (isNumericArray(input)) {
222
+ const close = Array.isArray(closeOrLength) ? closeOrLength : undefined;
223
+ const resolvedLength = typeof closeOrLength === "number" ? closeOrLength : length;
224
+ const ohlcv = parseOCV(input, close, volume);
225
+ return coreOrderflowImbalance(ohlcv.open, ohlcv.close, ohlcv.volume, resolvedLength);
226
+ }
227
+ const ohlcv = toOHLCV(input);
228
+ const resolvedLength = typeof closeOrLength === "number" ? closeOrLength : length;
229
+ return coreOrderflowImbalance(ohlcv.open, ohlcv.close, ohlcv.volume, resolvedLength);
230
+ }
231
+ export function fundingRateCumulative(values) {
232
+ assertFiniteSeries("values", values);
233
+ return coreFundingRateCumulative(values);
234
+ }
235
+ export function fundingRateAPR(values, periodsPerYear = 365 * 3) {
236
+ assertFiniteSeries("values", values);
237
+ return coreFundingRateAPR(values, periodsPerYear);
238
+ }
239
+ export function volatilityRegime(input, length = 30, periodsPerYear = 365, lowZ = -0.5, highZ = 0.5) {
240
+ return coreVolatilityRegime(normalizePrice(input), length, periodsPerYear, lowZ, highZ);
241
+ }
package/dist/candles.d.ts CHANGED
@@ -1,15 +1,9 @@
1
- import type { Candle } from "./types.js";
2
- export type OHLCV = {
3
- open: number[];
4
- high: number[];
5
- low: number[];
6
- close: number[];
7
- volume: number[];
8
- time: Array<number | string | Date | undefined>;
9
- };
1
+ import type { Candle, OHLCV, OHLCVInput, PriceInput } from "./types.js";
2
+ export declare function isCandleArray(input: PriceInput | OHLCVInput): input is Candle[];
3
+ export declare function normalizePrice(input: PriceInput, name?: string): number[];
10
4
  export declare function pluckOpen(candles: Candle[]): number[];
11
5
  export declare function pluckHigh(candles: Candle[]): number[];
12
6
  export declare function pluckLow(candles: Candle[]): number[];
13
7
  export declare function pluckClose(candles: Candle[]): number[];
14
8
  export declare function pluckVolume(candles: Candle[], fallback?: number): number[];
15
- export declare function toOHLCV(candles: Candle[], volumeFallback?: number): OHLCV;
9
+ export declare function toOHLCV(input: Candle[] | OHLCVInput, volumeFallback?: number): OHLCV;
package/dist/candles.js CHANGED
@@ -1,36 +1,98 @@
1
- import { assertFiniteSeries } from "./core/math.js";
1
+ import { assertFiniteSeries, assertSameLength, isNum } from "./core/math.js";
2
+ function readField(candle, index, name, alias) {
3
+ const value = candle[name] ?? candle[alias];
4
+ if (!isNum(value)) {
5
+ throw new Error(`candles[${index}].${name} (or .${alias}) must be a finite number`);
6
+ }
7
+ return value;
8
+ }
9
+ function readTime(candle) {
10
+ const value = candle.time ?? candle.t;
11
+ return value;
12
+ }
13
+ function hasOHLCVArrays(input) {
14
+ return "open" in input && "high" in input && "low" in input && "close" in input;
15
+ }
16
+ export function isCandleArray(input) {
17
+ return Array.isArray(input) && input.length > 0 && typeof input[0] !== "number";
18
+ }
19
+ export function normalizePrice(input, name = "values") {
20
+ if (Array.isArray(input) && (input.length === 0 || typeof input[0] === "number")) {
21
+ assertFiniteSeries(name, input);
22
+ return input;
23
+ }
24
+ return pluckClose(input);
25
+ }
2
26
  export function pluckOpen(candles) {
3
- const out = candles.map(c => c.open);
27
+ const out = candles.map((candle, index) => readField(candle, index, "open", "o"));
4
28
  assertFiniteSeries("open", out);
5
29
  return out;
6
30
  }
7
31
  export function pluckHigh(candles) {
8
- const out = candles.map(c => c.high);
32
+ const out = candles.map((candle, index) => readField(candle, index, "high", "h"));
9
33
  assertFiniteSeries("high", out);
10
34
  return out;
11
35
  }
12
36
  export function pluckLow(candles) {
13
- const out = candles.map(c => c.low);
37
+ const out = candles.map((candle, index) => readField(candle, index, "low", "l"));
14
38
  assertFiniteSeries("low", out);
15
39
  return out;
16
40
  }
17
41
  export function pluckClose(candles) {
18
- const out = candles.map(c => c.close);
42
+ const out = candles.map((candle, index) => readField(candle, index, "close", "c"));
19
43
  assertFiniteSeries("close", out);
20
44
  return out;
21
45
  }
22
46
  export function pluckVolume(candles, fallback = 0) {
23
- const out = candles.map(c => (c.volume === undefined ? fallback : c.volume));
47
+ if (!isNum(fallback)) {
48
+ throw new Error("volumeFallback must be a finite number");
49
+ }
50
+ const out = candles.map((candle, index) => {
51
+ const value = candle.volume ?? candle.v;
52
+ const normalized = value === undefined ? fallback : value;
53
+ if (!isNum(normalized)) {
54
+ throw new Error(`candles[${index}].volume (or .v) must be a finite number`);
55
+ }
56
+ return normalized;
57
+ });
24
58
  assertFiniteSeries("volume", out);
25
59
  return out;
26
60
  }
27
- export function toOHLCV(candles, volumeFallback = 0) {
28
- return {
29
- open: pluckOpen(candles),
30
- high: pluckHigh(candles),
31
- low: pluckLow(candles),
32
- close: pluckClose(candles),
33
- volume: pluckVolume(candles, volumeFallback),
34
- time: candles.map(c => c.time)
35
- };
61
+ export function toOHLCV(input, volumeFallback = 0) {
62
+ if (Array.isArray(input)) {
63
+ return {
64
+ open: pluckOpen(input),
65
+ high: pluckHigh(input),
66
+ low: pluckLow(input),
67
+ close: pluckClose(input),
68
+ volume: pluckVolume(input, volumeFallback),
69
+ time: input.map(c => readTime(c))
70
+ };
71
+ }
72
+ if (hasOHLCVArrays(input)) {
73
+ assertFiniteSeries("open", input.open);
74
+ assertFiniteSeries("high", input.high);
75
+ assertFiniteSeries("low", input.low);
76
+ assertFiniteSeries("close", input.close);
77
+ const volume = input.volume ?? new Array(input.close.length).fill(volumeFallback);
78
+ assertFiniteSeries("volume", volume);
79
+ assertSameLength(input.open, input.high, input.low, input.close, volume);
80
+ const time = input.time ?? new Array(input.close.length).fill(undefined);
81
+ if (time.length !== input.close.length) {
82
+ throw new Error(`All series must have the same length (expected ${input.close.length}, got ${time.length})`);
83
+ }
84
+ return { open: input.open, high: input.high, low: input.low, close: input.close, volume, time };
85
+ }
86
+ assertFiniteSeries("open", input.o);
87
+ assertFiniteSeries("high", input.h);
88
+ assertFiniteSeries("low", input.l);
89
+ assertFiniteSeries("close", input.c);
90
+ const volume = input.v ?? new Array(input.c.length).fill(volumeFallback);
91
+ assertFiniteSeries("volume", volume);
92
+ assertSameLength(input.o, input.h, input.l, input.c, volume);
93
+ const time = input.t ?? new Array(input.c.length).fill(undefined);
94
+ if (time.length !== input.c.length) {
95
+ throw new Error(`All series must have the same length (expected ${input.c.length}, got ${time.length})`);
96
+ }
97
+ return { open: input.o, high: input.h, low: input.l, close: input.c, volume, time };
36
98
  }
package/dist/crypto.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./core/crypto.js";
1
+ export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./api.js";
2
2
  export { createVWAPSession } from "./stateful.js";
package/dist/crypto.js CHANGED
@@ -1,2 +1,2 @@
1
- export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./core/crypto.js";
1
+ export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./api.js";
2
2
  export { createVWAPSession } from "./stateful.js";
package/dist/index.d.ts CHANGED
@@ -1,64 +1,83 @@
1
- export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands } from "./core/overlap.js";
2
- export { rsi, macd, stoch } from "./core/momentum.js";
3
- export { trueRange, atr, natr } from "./core/volatility.js";
4
- export { logReturn, percentReturn, realizedVolatility } from "./core/performance.js";
5
- export { obv, mfi } from "./core/volume.js";
6
- export { adx } from "./core/trend.js";
7
- export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./core/crypto.js";
1
+ export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands, rsi, macd, stoch, trueRange, atr, natr, logReturn, percentReturn, realizedVolatility, obv, mfi, adx, vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./api.js";
8
2
  export { pluckOpen, pluckHigh, pluckLow, pluckClose, pluckVolume, toOHLCV } from "./candles.js";
9
- export { createRSI, createVWAPSession } from "./stateful.js";
3
+ export { createSMA, createEMA, createRSI, createVWAPSession } from "./stateful.js";
10
4
  export * from "./types.js";
11
- import * as candles from "./candles.js";
12
5
  import * as stateful from "./stateful.js";
13
6
  export declare const ta: {
7
+ createSMA(period?: number): stateful.StatefulIndicator<number, number | null>;
8
+ createEMA(period?: number): stateful.StatefulIndicator<number, number | null>;
14
9
  createRSI(period?: number): stateful.StatefulIndicator<number, number | null>;
15
10
  createVWAPSession(): stateful.StatefulIndicator<stateful.VWAPSessionInput, number | null>;
11
+ isCandleArray(input: import("./types.js").PriceInput | import("./types.js").OHLCVInput): input is import("./types.js").Candle[];
12
+ normalizePrice(input: import("./types.js").PriceInput, name?: string): number[];
16
13
  pluckOpen(candles: import("./types.js").Candle[]): number[];
17
14
  pluckHigh(candles: import("./types.js").Candle[]): number[];
18
15
  pluckLow(candles: import("./types.js").Candle[]): number[];
19
16
  pluckClose(candles: import("./types.js").Candle[]): number[];
20
17
  pluckVolume(candles: import("./types.js").Candle[], fallback?: number): number[];
21
- toOHLCV(candles: import("./types.js").Candle[], volumeFallback?: number): candles.OHLCV;
22
- vwapSession(high: number[], low: number[], close: number[], volume: number[], session: Array<string | number>): Array<number | null>;
23
- fundingRateCumulative(values: number[]): Array<number | null>;
24
- fundingRateAPR(values: number[], periodsPerYear?: number): Array<number | null>;
25
- volatilityRegime(values: number[], length?: number, periodsPerYear?: number, lowZ?: number, highZ?: number): Array<number | null>;
26
- signedVolume(open: number[], close: number[], volume: number[]): Array<number | null>;
27
- volumeDelta(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
28
- orderflowImbalance(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
29
- adx(high: number[], low: number[], close: number[], length?: number): {
30
- adx: (number | null)[];
31
- plusDI: (number | null)[];
32
- minusDI: (number | null)[];
18
+ toOHLCV(input: import("./types.js").Candle[] | import("./types.js").OHLCVInput, volumeFallback?: number): import("./types.js").OHLCV;
19
+ sma(input: import("./types.js").PriceInput, length?: number): Array<number | null>;
20
+ ema(input: import("./types.js").PriceInput, length?: number): Array<number | null>;
21
+ rma(input: import("./types.js").PriceInput, length?: number): Array<number | null>;
22
+ bbands(input: import("./types.js").PriceInput, length?: number, std?: number): {
23
+ basis: (number | null)[];
24
+ upper: (number | null)[];
25
+ lower: (number | null)[];
33
26
  };
34
- obv(close: number[], volume: number[]): Array<number | null>;
35
- mfi(high: number[], low: number[], close: number[], volume: number[], length?: number): Array<number | null>;
36
- logReturn(values: number[], cumulative?: boolean): Array<number | null>;
37
- percentReturn(values: number[], cumulative?: boolean): Array<number | null>;
38
- realizedVolatility(values: number[], length?: number, periodsPerYear?: number): Array<number | null>;
39
- trueRange(high: number[], low: number[], close: number[]): Array<number | null>;
40
- atr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
41
- natr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
42
- macd(values: number[], fast?: number, slow?: number, signal?: number): {
27
+ macd(input: import("./types.js").PriceInput, fast?: number, slow?: number, signal?: number): {
43
28
  macd: (number | null)[];
44
29
  signal: (number | null)[];
45
30
  histogram: (number | null)[];
46
31
  };
47
- rsi(values: number[], length?: number): Array<number | null>;
48
- stoch(high: number[], low: number[], close: number[], kLength?: number, dLength?: number): {
49
- k: (number | null)[];
50
- d: (number | null)[];
51
- };
52
- sma(values: number[], length?: number): Array<number | null>;
53
- ema(values: number[], length?: number): Array<number | null>;
54
- rma(values: number[], length?: number): Array<number | null>;
32
+ rsi(input: import("./types.js").PriceInput, length?: number): Array<number | null>;
33
+ logReturn(input: import("./types.js").PriceInput, cumulative?: boolean): Array<number | null>;
34
+ percentReturn(input: import("./types.js").PriceInput, cumulative?: boolean): Array<number | null>;
35
+ realizedVolatility(input: import("./types.js").PriceInput, length?: number, periodsPerYear?: number): Array<number | null>;
55
36
  hl2(high: number[], low: number[]): Array<number | null>;
37
+ hl2(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
56
38
  hlc3(high: number[], low: number[], close: number[]): Array<number | null>;
39
+ hlc3(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
57
40
  ohlc4(open: number[], high: number[], low: number[], close: number[]): Array<number | null>;
41
+ ohlc4(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
58
42
  vwap(high: number[], low: number[], close: number[], volume: number[], length?: number): Array<number | null>;
59
- bbands(values: number[], length?: number, std?: number): {
60
- basis: (number | null)[];
61
- upper: (number | null)[];
62
- lower: (number | null)[];
43
+ vwap(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
44
+ stoch(high: number[], low: number[], close: number[], kLength?: number, dLength?: number): {
45
+ k: Array<number | null>;
46
+ d: Array<number | null>;
47
+ };
48
+ stoch(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], kLength?: number, dLength?: number): {
49
+ k: Array<number | null>;
50
+ d: Array<number | null>;
51
+ };
52
+ trueRange(high: number[], low: number[], close: number[]): Array<number | null>;
53
+ trueRange(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
54
+ atr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
55
+ atr(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
56
+ natr(high: number[], low: number[], close: number[], length?: number): Array<number | null>;
57
+ natr(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
58
+ obv(close: number[], volume: number[]): Array<number | null>;
59
+ obv(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
60
+ mfi(high: number[], low: number[], close: number[], volume: number[], length?: number): Array<number | null>;
61
+ mfi(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
62
+ adx(high: number[], low: number[], close: number[], length?: number): {
63
+ adx: Array<number | null>;
64
+ plusDI: Array<number | null>;
65
+ minusDI: Array<number | null>;
66
+ };
67
+ adx(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): {
68
+ adx: Array<number | null>;
69
+ plusDI: Array<number | null>;
70
+ minusDI: Array<number | null>;
63
71
  };
72
+ vwapSession(high: number[], low: number[], close: number[], volume: number[], session: Array<string | number>): Array<number | null>;
73
+ vwapSession(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], session: Array<string | number>): Array<number | null>;
74
+ signedVolume(open: number[], close: number[], volume: number[]): Array<number | null>;
75
+ signedVolume(input: import("./types.js").OHLCVInput | import("./types.js").Candle[]): Array<number | null>;
76
+ volumeDelta(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
77
+ volumeDelta(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
78
+ orderflowImbalance(open: number[], close: number[], volume: number[], length?: number): Array<number | null>;
79
+ orderflowImbalance(input: import("./types.js").OHLCVInput | import("./types.js").Candle[], length?: number): Array<number | null>;
80
+ fundingRateCumulative(values: number[]): Array<number | null>;
81
+ fundingRateAPR(values: number[], periodsPerYear?: number): Array<number | null>;
82
+ volatilityRegime(input: import("./types.js").PriceInput, length?: number, periodsPerYear?: number, lowZ?: number, highZ?: number): Array<number | null>;
64
83
  };
package/dist/index.js CHANGED
@@ -1,30 +1,12 @@
1
- export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands } from "./core/overlap.js";
2
- export { rsi, macd, stoch } from "./core/momentum.js";
3
- export { trueRange, atr, natr } from "./core/volatility.js";
4
- export { logReturn, percentReturn, realizedVolatility } from "./core/performance.js";
5
- export { obv, mfi } from "./core/volume.js";
6
- export { adx } from "./core/trend.js";
7
- export { vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./core/crypto.js";
1
+ export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands, rsi, macd, stoch, trueRange, atr, natr, logReturn, percentReturn, realizedVolatility, obv, mfi, adx, vwapSession, fundingRateCumulative, fundingRateAPR, volatilityRegime, signedVolume, volumeDelta, orderflowImbalance } from "./api.js";
8
2
  export { pluckOpen, pluckHigh, pluckLow, pluckClose, pluckVolume, toOHLCV } from "./candles.js";
9
- export { createRSI, createVWAPSession } from "./stateful.js";
3
+ export { createSMA, createEMA, createRSI, createVWAPSession } from "./stateful.js";
10
4
  export * from "./types.js";
11
- import * as overlap from "./core/overlap.js";
12
- import * as momentum from "./core/momentum.js";
13
- import * as volatility from "./core/volatility.js";
14
- import * as performance from "./core/performance.js";
15
- import * as volume from "./core/volume.js";
16
- import * as trend from "./core/trend.js";
17
- import * as crypto from "./core/crypto.js";
5
+ import * as api from "./api.js";
18
6
  import * as candles from "./candles.js";
19
7
  import * as stateful from "./stateful.js";
20
8
  export const ta = {
21
- ...overlap,
22
- ...momentum,
23
- ...volatility,
24
- ...performance,
25
- ...volume,
26
- ...trend,
27
- ...crypto,
9
+ ...api,
28
10
  ...candles,
29
11
  ...stateful
30
12
  };
@@ -1,6 +1 @@
1
- export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands } from "./core/overlap.js";
2
- export { rsi, macd, stoch } from "./core/momentum.js";
3
- export { trueRange, atr, natr } from "./core/volatility.js";
4
- export { logReturn, percentReturn, realizedVolatility } from "./core/performance.js";
5
- export { obv, mfi } from "./core/volume.js";
6
- export { adx } from "./core/trend.js";
1
+ export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands, rsi, macd, stoch, trueRange, atr, natr, logReturn, percentReturn, realizedVolatility, obv, mfi, adx } from "./api.js";
@@ -1,6 +1 @@
1
- export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands } from "./core/overlap.js";
2
- export { rsi, macd, stoch } from "./core/momentum.js";
3
- export { trueRange, atr, natr } from "./core/volatility.js";
4
- export { logReturn, percentReturn, realizedVolatility } from "./core/performance.js";
5
- export { obv, mfi } from "./core/volume.js";
6
- export { adx } from "./core/trend.js";
1
+ export { sma, ema, rma, hl2, hlc3, ohlc4, vwap, bbands, rsi, macd, stoch, trueRange, atr, natr, logReturn, percentReturn, realizedVolatility, obv, mfi, adx } from "./api.js";
@@ -2,6 +2,8 @@ export type StatefulIndicator<TIn, TOut> = {
2
2
  next(value: TIn): TOut;
3
3
  reset(): void;
4
4
  };
5
+ export declare function createSMA(period?: number): StatefulIndicator<number, number | null>;
6
+ export declare function createEMA(period?: number): StatefulIndicator<number, number | null>;
5
7
  export declare function createRSI(period?: number): StatefulIndicator<number, number | null>;
6
8
  export type VWAPSessionInput = {
7
9
  high: number;
package/dist/stateful.js CHANGED
@@ -1,3 +1,62 @@
1
+ export function createSMA(period = 14) {
2
+ if (period <= 0) {
3
+ throw new Error("period must be > 0");
4
+ }
5
+ const window = [];
6
+ let sum = 0;
7
+ return {
8
+ next(value) {
9
+ if (!Number.isFinite(value)) {
10
+ throw new Error("value must be a finite number");
11
+ }
12
+ window.push(value);
13
+ sum += value;
14
+ if (window.length < period) {
15
+ return null;
16
+ }
17
+ if (window.length > period) {
18
+ sum -= window.shift();
19
+ }
20
+ return sum / period;
21
+ },
22
+ reset() {
23
+ window.length = 0;
24
+ sum = 0;
25
+ }
26
+ };
27
+ }
28
+ export function createEMA(period = 14) {
29
+ if (period <= 0) {
30
+ throw new Error("period must be > 0");
31
+ }
32
+ const k = 2 / (period + 1);
33
+ let seedSum = 0;
34
+ let seedCount = 0;
35
+ let prev = null;
36
+ return {
37
+ next(value) {
38
+ if (!Number.isFinite(value)) {
39
+ throw new Error("value must be a finite number");
40
+ }
41
+ if (prev === null) {
42
+ seedSum += value;
43
+ seedCount += 1;
44
+ if (seedCount < period) {
45
+ return null;
46
+ }
47
+ prev = seedSum / period;
48
+ return prev;
49
+ }
50
+ prev = (value - prev) * k + prev;
51
+ return prev;
52
+ },
53
+ reset() {
54
+ seedSum = 0;
55
+ seedCount = 0;
56
+ prev = null;
57
+ }
58
+ };
59
+ }
1
60
  export function createRSI(period = 14) {
2
61
  if (period <= 0) {
3
62
  throw new Error("period must be > 0");
package/dist/types.d.ts CHANGED
@@ -1,10 +1,38 @@
1
1
  export type NumericSeries = number[];
2
2
  export type Series = Array<number | null>;
3
- export type Candle = {
4
- time?: number | string | Date;
3
+ export type TimeValue = number | string | Date;
4
+ export type CandleObject = {
5
5
  open: number;
6
6
  high: number;
7
7
  low: number;
8
8
  close: number;
9
9
  volume?: number;
10
+ time?: TimeValue;
10
11
  };
12
+ export type CandleAlias = {
13
+ o: number;
14
+ h: number;
15
+ l: number;
16
+ c: number;
17
+ v?: number;
18
+ t?: TimeValue;
19
+ };
20
+ export type Candle = CandleObject | CandleAlias;
21
+ export type OHLCV = {
22
+ open: number[];
23
+ high: number[];
24
+ low: number[];
25
+ close: number[];
26
+ volume: number[];
27
+ time: Array<TimeValue | undefined>;
28
+ };
29
+ export type OHLCVAlias = {
30
+ o: number[];
31
+ h: number[];
32
+ l: number[];
33
+ c: number[];
34
+ v?: number[];
35
+ t?: Array<TimeValue | undefined>;
36
+ };
37
+ export type OHLCVInput = OHLCV | OHLCVAlias;
38
+ export type PriceInput = NumericSeries | Candle[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ta-crypto",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Technical analysis for crypto markets in Node.js",
5
5
  "type": "module",
6
6
  "license": "MIT",