@hardlydifficult/math 1.0.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.
Files changed (41) hide show
  1. package/dist/RingBuffer.d.ts +17 -0
  2. package/dist/RingBuffer.d.ts.map +1 -0
  3. package/dist/RingBuffer.js +63 -0
  4. package/dist/RingBuffer.js.map +1 -0
  5. package/dist/RollingVwap.d.ts +12 -0
  6. package/dist/RollingVwap.d.ts.map +1 -0
  7. package/dist/RollingVwap.js +37 -0
  8. package/dist/RollingVwap.js.map +1 -0
  9. package/dist/SlopeTracker.d.ts +10 -0
  10. package/dist/SlopeTracker.d.ts.map +1 -0
  11. package/dist/SlopeTracker.js +36 -0
  12. package/dist/SlopeTracker.js.map +1 -0
  13. package/dist/VwapTracker.d.ts +13 -0
  14. package/dist/VwapTracker.d.ts.map +1 -0
  15. package/dist/VwapTracker.js +37 -0
  16. package/dist/VwapTracker.js.map +1 -0
  17. package/dist/WindowedChange.d.ts +11 -0
  18. package/dist/WindowedChange.d.ts.map +1 -0
  19. package/dist/WindowedChange.js +46 -0
  20. package/dist/WindowedChange.js.map +1 -0
  21. package/dist/bookImbalance.d.ts +6 -0
  22. package/dist/bookImbalance.d.ts.map +1 -0
  23. package/dist/bookImbalance.js +38 -0
  24. package/dist/bookImbalance.js.map +1 -0
  25. package/dist/clamp.d.ts +3 -0
  26. package/dist/clamp.d.ts.map +1 -0
  27. package/dist/clamp.js +8 -0
  28. package/dist/clamp.js.map +1 -0
  29. package/dist/index.d.ts +10 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +23 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/linearRegression.d.ts +7 -0
  34. package/dist/linearRegression.d.ts.map +1 -0
  35. package/dist/linearRegression.js +32 -0
  36. package/dist/linearRegression.js.map +1 -0
  37. package/dist/trend.d.ts +4 -0
  38. package/dist/trend.d.ts.map +1 -0
  39. package/dist/trend.js +14 -0
  40. package/dist/trend.js.map +1 -0
  41. package/package.json +34 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare class RingBuffer<T> {
5
+ readonly capacity: number;
6
+ private readonly buffer;
7
+ private head;
8
+ private count;
9
+ constructor(capacity: number);
10
+ push(item: T): void;
11
+ get length(): number;
12
+ toArray(): T[];
13
+ first(): T | undefined;
14
+ last(): T | undefined;
15
+ clear(): void;
16
+ }
17
+ //# sourceMappingURL=RingBuffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RingBuffer.d.ts","sourceRoot":"","sources":["../src/RingBuffer.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAU,CAAC,CAAC;IAKX,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAJrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAK;gBAEG,QAAQ,EAAE,MAAM;IAOrC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAQnB,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,OAAO,IAAI,CAAC,EAAE;IAed,KAAK,IAAI,CAAC,GAAG,SAAS;IAQtB,IAAI,IAAI,CAAC,GAAG,SAAS;IAOrB,KAAK,IAAI,IAAI;CAKd"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RingBuffer = void 0;
4
+ /**
5
+ *
6
+ */
7
+ class RingBuffer {
8
+ capacity;
9
+ buffer;
10
+ head = 0;
11
+ count = 0;
12
+ constructor(capacity) {
13
+ this.capacity = capacity;
14
+ if (capacity < 1) {
15
+ throw new Error("RingBuffer capacity must be >= 1");
16
+ }
17
+ this.buffer = new Array(capacity);
18
+ }
19
+ push(item) {
20
+ this.buffer[this.head] = item;
21
+ this.head = (this.head + 1) % this.capacity;
22
+ if (this.count < this.capacity) {
23
+ this.count++;
24
+ }
25
+ }
26
+ get length() {
27
+ return this.count;
28
+ }
29
+ toArray() {
30
+ if (this.count === 0) {
31
+ return [];
32
+ }
33
+ const start = this.count < this.capacity ? 0 : this.head;
34
+ const result = [];
35
+ for (let i = 0; i < this.count; i++) {
36
+ const item = this.buffer[(start + i) % this.capacity];
37
+ if (item !== undefined) {
38
+ result.push(item);
39
+ }
40
+ }
41
+ return result;
42
+ }
43
+ first() {
44
+ if (this.count === 0) {
45
+ return undefined;
46
+ }
47
+ const start = this.count < this.capacity ? 0 : this.head;
48
+ return this.buffer[start];
49
+ }
50
+ last() {
51
+ if (this.count === 0) {
52
+ return undefined;
53
+ }
54
+ return this.buffer[(this.head - 1 + this.capacity) % this.capacity];
55
+ }
56
+ clear() {
57
+ this.head = 0;
58
+ this.count = 0;
59
+ this.buffer.fill(undefined);
60
+ }
61
+ }
62
+ exports.RingBuffer = RingBuffer;
63
+ //# sourceMappingURL=RingBuffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RingBuffer.js","sourceRoot":"","sources":["../src/RingBuffer.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,UAAU;IAKA;IAJJ,MAAM,CAAoB;IACnC,IAAI,GAAG,CAAC,CAAC;IACT,KAAK,GAAG,CAAC,CAAC;IAElB,YAAqB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QACnC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAgB,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC,IAAO;QACV,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC5C,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACzD,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACzD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtE,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;CACF;AA3DD,gCA2DC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare class RollingVwap {
5
+ private readonly buffer;
6
+ private readonly windowMs;
7
+ constructor(windowMs: number, capacity?: number);
8
+ addTrade(ts: number, price: number, size: number): this;
9
+ get value(): number;
10
+ valueAt(now: number): number;
11
+ }
12
+ //# sourceMappingURL=RollingVwap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RollingVwap.d.ts","sourceRoot":"","sources":["../src/RollingVwap.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAS;IAK/C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKvD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;CAa7B"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RollingVwap = void 0;
4
+ const RingBuffer_js_1 = require("./RingBuffer.js");
5
+ /**
6
+ *
7
+ */
8
+ class RollingVwap {
9
+ buffer;
10
+ windowMs;
11
+ constructor(windowMs, capacity = 50_000) {
12
+ this.windowMs = windowMs;
13
+ this.buffer = new RingBuffer_js_1.RingBuffer(capacity);
14
+ }
15
+ addTrade(ts, price, size) {
16
+ this.buffer.push({ ts, price, size });
17
+ return this;
18
+ }
19
+ get value() {
20
+ return this.valueAt(Date.now());
21
+ }
22
+ valueAt(now) {
23
+ const arr = this.buffer.toArray();
24
+ let pv = 0;
25
+ let v = 0;
26
+ for (let i = arr.length - 1; i >= 0; i--) {
27
+ if (now - arr[i].ts > this.windowMs) {
28
+ break;
29
+ }
30
+ pv += arr[i].price * arr[i].size;
31
+ v += arr[i].size;
32
+ }
33
+ return v > 0 ? pv / v : 0;
34
+ }
35
+ }
36
+ exports.RollingVwap = RollingVwap;
37
+ //# sourceMappingURL=RollingVwap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RollingVwap.js","sourceRoot":"","sources":["../src/RollingVwap.ts"],"names":[],"mappings":";;;AAAA,mDAA6C;AAQ7C;;GAEG;AACH,MAAa,WAAW;IACL,MAAM,CAA0B;IAChC,QAAQ,CAAS;IAElC,YAAY,QAAgB,EAAE,QAAQ,GAAG,MAAM;QAC7C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,0BAAU,CAAc,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,QAAQ,CAAC,EAAU,EAAE,KAAa,EAAE,IAAY;QAC9C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACpC,MAAM;YACR,CAAC;YACD,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACjC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;CACF;AA/BD,kCA+BC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare class SlopeTracker {
5
+ private readonly buffer;
6
+ constructor(capacity?: number);
7
+ addSample(ts: number, value: number): this;
8
+ slope(windowMs: number): number;
9
+ }
10
+ //# sourceMappingURL=SlopeTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlopeTracker.d.ts","sourceRoot":"","sources":["../src/SlopeTracker.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAE1C,QAAQ,SAAM;IAI1B,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAkBhC"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlopeTracker = void 0;
4
+ const linearRegression_js_1 = require("./linearRegression.js");
5
+ const RingBuffer_js_1 = require("./RingBuffer.js");
6
+ /**
7
+ *
8
+ */
9
+ class SlopeTracker {
10
+ buffer;
11
+ constructor(capacity = 600) {
12
+ this.buffer = new RingBuffer_js_1.RingBuffer(capacity);
13
+ }
14
+ addSample(ts, value) {
15
+ this.buffer.push({ ts, value });
16
+ return this;
17
+ }
18
+ slope(windowMs) {
19
+ const arr = this.buffer.toArray();
20
+ if (arr.length < 2) {
21
+ return 0;
22
+ }
23
+ const cutoff = arr[arr.length - 1].ts - windowMs;
24
+ const windowSamples = [];
25
+ for (let i = arr.length - 1; i >= 0; i--) {
26
+ if (arr[i].ts < cutoff) {
27
+ break;
28
+ }
29
+ windowSamples.push({ t: arr[i].ts, v: arr[i].value });
30
+ }
31
+ windowSamples.reverse();
32
+ return (0, linearRegression_js_1.computeSlope)(windowSamples);
33
+ }
34
+ }
35
+ exports.SlopeTracker = SlopeTracker;
36
+ //# sourceMappingURL=SlopeTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlopeTracker.js","sourceRoot":"","sources":["../src/SlopeTracker.ts"],"names":[],"mappings":";;;AAAA,+DAAkE;AAClE,mDAA6C;AAO7C;;GAEG;AACH,MAAa,YAAY;IACN,MAAM,CAA+B;IAEtD,YAAY,QAAQ,GAAG,GAAG;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,0BAAU,CAAmB,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,EAAU,EAAE,KAAa;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAAgB;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC;QACjD,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;gBACvB,MAAM;YACR,CAAC;YACD,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,aAAa,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,IAAA,kCAAY,EAAC,aAAa,CAAC,CAAC;IACrC,CAAC;CACF;AA9BD,oCA8BC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare class VwapTracker {
5
+ private sumPV;
6
+ private sumV;
7
+ private sumPV2;
8
+ addTrade(price: number, size: number): this;
9
+ reset(): this;
10
+ get value(): number;
11
+ zScore(currentPrice: number): number;
12
+ }
13
+ //# sourceMappingURL=VwapTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VwapTracker.d.ts","sourceRoot":"","sources":["../src/VwapTracker.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IAEnB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAO3C,KAAK,IAAI,IAAI;IAOb,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;CASrC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VwapTracker = void 0;
4
+ /**
5
+ *
6
+ */
7
+ class VwapTracker {
8
+ sumPV = 0;
9
+ sumV = 0;
10
+ sumPV2 = 0;
11
+ addTrade(price, size) {
12
+ this.sumPV += price * size;
13
+ this.sumV += size;
14
+ this.sumPV2 += price * price * size;
15
+ return this;
16
+ }
17
+ reset() {
18
+ this.sumPV = 0;
19
+ this.sumV = 0;
20
+ this.sumPV2 = 0;
21
+ return this;
22
+ }
23
+ get value() {
24
+ return this.sumV > 0 ? this.sumPV / this.sumV : 0;
25
+ }
26
+ zScore(currentPrice) {
27
+ const vwap = this.value;
28
+ if (vwap === 0 || this.sumV === 0 || currentPrice === 0) {
29
+ return 0;
30
+ }
31
+ const variance = this.sumPV2 / this.sumV - vwap * vwap;
32
+ const sigma = variance > 0 ? Math.sqrt(variance) : 0;
33
+ return sigma > 0 ? (currentPrice - vwap) / sigma : 0;
34
+ }
35
+ }
36
+ exports.VwapTracker = VwapTracker;
37
+ //# sourceMappingURL=VwapTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VwapTracker.js","sourceRoot":"","sources":["../src/VwapTracker.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,WAAW;IACd,KAAK,GAAG,CAAC,CAAC;IACV,IAAI,GAAG,CAAC,CAAC;IACT,MAAM,GAAG,CAAC,CAAC;IAEnB,QAAQ,CAAC,KAAa,EAAE,IAAY;QAClC,IAAI,CAAC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,IAAI,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,YAAoB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QACvD,MAAM,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;CACF;AAhCD,kCAgCC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare class WindowedChange {
5
+ private readonly buffer;
6
+ private readonly windowMs;
7
+ constructor(windowMs: number, capacity?: number);
8
+ addSample(ts: number, value: number): this;
9
+ get change(): number;
10
+ }
11
+ //# sourceMappingURL=WindowedChange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WindowedChange.d.ts","sourceRoot":"","sources":["../src/WindowedChange.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAM;IAK5C,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1C,IAAI,MAAM,IAAI,MAAM,CA2BnB;CACF"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WindowedChange = void 0;
4
+ const RingBuffer_js_1 = require("./RingBuffer.js");
5
+ /**
6
+ *
7
+ */
8
+ class WindowedChange {
9
+ buffer;
10
+ windowMs;
11
+ constructor(windowMs, capacity = 240) {
12
+ this.windowMs = windowMs;
13
+ this.buffer = new RingBuffer_js_1.RingBuffer(capacity);
14
+ }
15
+ addSample(ts, value) {
16
+ this.buffer.push({ ts, value });
17
+ return this;
18
+ }
19
+ get change() {
20
+ const arr = this.buffer.toArray();
21
+ if (arr.length < 2) {
22
+ return 0;
23
+ }
24
+ const latest = arr[arr.length - 1];
25
+ const cutoff = latest.ts - this.windowMs;
26
+ let oldest;
27
+ for (const sample of arr) {
28
+ if (sample.ts <= cutoff) {
29
+ oldest = sample;
30
+ }
31
+ else {
32
+ break;
33
+ }
34
+ }
35
+ if (!oldest || oldest.value === 0) {
36
+ const first = arr[0];
37
+ if (first.value === 0) {
38
+ return 0;
39
+ }
40
+ return (latest.value - first.value) / first.value;
41
+ }
42
+ return (latest.value - oldest.value) / oldest.value;
43
+ }
44
+ }
45
+ exports.WindowedChange = WindowedChange;
46
+ //# sourceMappingURL=WindowedChange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WindowedChange.js","sourceRoot":"","sources":["../src/WindowedChange.ts"],"names":[],"mappings":";;;AAAA,mDAA6C;AAO7C;;GAEG;AACH,MAAa,cAAc;IACR,MAAM,CAA+B;IACrC,QAAQ,CAAS;IAElC,YAAY,QAAgB,EAAE,QAAQ,GAAG,GAAG;QAC1C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,0BAAU,CAAmB,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,EAAU,EAAE,KAAa;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM;QACR,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEzC,IAAI,MAAoC,CAAC;QACzC,KAAK,MAAM,MAAM,IAAI,GAAG,EAAE,CAAC;YACzB,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;gBACxB,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC;YACX,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACpD,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACtD,CAAC;CACF;AA1CD,wCA0CC"}
@@ -0,0 +1,6 @@
1
+ export type Level = readonly [price: number, size: number];
2
+ /** Top-of-book imbalance: (bidSize - askSize) / (bidSize + askSize). */
3
+ export declare function bookImbalance(bidSize: number, askSize: number): number;
4
+ /** Depth-weighted imbalance within ±depthPct of mid price. */
5
+ export declare function depthImbalance(bids: readonly Level[], asks: readonly Level[], depthPct: number): number;
6
+ //# sourceMappingURL=bookImbalance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bookImbalance.d.ts","sourceRoot":"","sources":["../src/bookImbalance.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAE3D,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,KAAK,EAAE,EACtB,IAAI,EAAE,SAAS,KAAK,EAAE,EACtB,QAAQ,EAAE,MAAM,GACf,MAAM,CA+BR"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bookImbalance = bookImbalance;
4
+ exports.depthImbalance = depthImbalance;
5
+ /** Top-of-book imbalance: (bidSize - askSize) / (bidSize + askSize). */
6
+ function bookImbalance(bidSize, askSize) {
7
+ const total = bidSize + askSize;
8
+ return total > 0 ? (bidSize - askSize) / total : 0;
9
+ }
10
+ /** Depth-weighted imbalance within ±depthPct of mid price. */
11
+ function depthImbalance(bids, asks, depthPct) {
12
+ if (bids.length === 0 || asks.length === 0) {
13
+ return 0;
14
+ }
15
+ const mid = (bids[0][0] + asks[0][0]) / 2;
16
+ if (mid <= 0) {
17
+ return 0;
18
+ }
19
+ const lower = mid * (1 - depthPct);
20
+ const upper = mid * (1 + depthPct);
21
+ let sumBid = 0;
22
+ for (const [px, sz] of bids) {
23
+ if (px < lower) {
24
+ break;
25
+ }
26
+ sumBid += sz;
27
+ }
28
+ let sumAsk = 0;
29
+ for (const [px, sz] of asks) {
30
+ if (px > upper) {
31
+ break;
32
+ }
33
+ sumAsk += sz;
34
+ }
35
+ const total = sumBid + sumAsk;
36
+ return total > 0 ? (sumBid - sumAsk) / total : 0;
37
+ }
38
+ //# sourceMappingURL=bookImbalance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bookImbalance.js","sourceRoot":"","sources":["../src/bookImbalance.ts"],"names":[],"mappings":";;AAGA,sCAGC;AAGD,wCAmCC;AA1CD,wEAAwE;AACxE,SAAgB,aAAa,CAAC,OAAe,EAAE,OAAe;IAC5D,MAAM,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;IAChC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,8DAA8D;AAC9D,SAAgB,cAAc,CAC5B,IAAsB,EACtB,IAAsB,EACtB,QAAgB;IAEhB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACb,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IAEnC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;YACf,MAAM;QACR,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;YACf,MAAM;QACR,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Constrain a value to the inclusive [min, max] range. */
2
+ export declare function clamp(value: number, min: number, max: number): number;
3
+ //# sourceMappingURL=clamp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clamp.d.ts","sourceRoot":"","sources":["../src/clamp.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
package/dist/clamp.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clamp = clamp;
4
+ /** Constrain a value to the inclusive [min, max] range. */
5
+ function clamp(value, min, max) {
6
+ return Math.min(Math.max(value, min), max);
7
+ }
8
+ //# sourceMappingURL=clamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clamp.js","sourceRoot":"","sources":["../src/clamp.ts"],"names":[],"mappings":";;AACA,sBAEC;AAHD,2DAA2D;AAC3D,SAAgB,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { RingBuffer } from "./RingBuffer.js";
2
+ export { type Sample, computeSlope } from "./linearRegression.js";
3
+ export { clamp } from "./clamp.js";
4
+ export { type TrendLabel, classifyTrend } from "./trend.js";
5
+ export { type Level, bookImbalance, depthImbalance } from "./bookImbalance.js";
6
+ export { VwapTracker } from "./VwapTracker.js";
7
+ export { RollingVwap } from "./RollingVwap.js";
8
+ export { SlopeTracker } from "./SlopeTracker.js";
9
+ export { WindowedChange } from "./WindowedChange.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,MAAM,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,KAAK,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WindowedChange = exports.SlopeTracker = exports.RollingVwap = exports.VwapTracker = exports.depthImbalance = exports.bookImbalance = exports.classifyTrend = exports.clamp = exports.computeSlope = exports.RingBuffer = void 0;
4
+ var RingBuffer_js_1 = require("./RingBuffer.js");
5
+ Object.defineProperty(exports, "RingBuffer", { enumerable: true, get: function () { return RingBuffer_js_1.RingBuffer; } });
6
+ var linearRegression_js_1 = require("./linearRegression.js");
7
+ Object.defineProperty(exports, "computeSlope", { enumerable: true, get: function () { return linearRegression_js_1.computeSlope; } });
8
+ var clamp_js_1 = require("./clamp.js");
9
+ Object.defineProperty(exports, "clamp", { enumerable: true, get: function () { return clamp_js_1.clamp; } });
10
+ var trend_js_1 = require("./trend.js");
11
+ Object.defineProperty(exports, "classifyTrend", { enumerable: true, get: function () { return trend_js_1.classifyTrend; } });
12
+ var bookImbalance_js_1 = require("./bookImbalance.js");
13
+ Object.defineProperty(exports, "bookImbalance", { enumerable: true, get: function () { return bookImbalance_js_1.bookImbalance; } });
14
+ Object.defineProperty(exports, "depthImbalance", { enumerable: true, get: function () { return bookImbalance_js_1.depthImbalance; } });
15
+ var VwapTracker_js_1 = require("./VwapTracker.js");
16
+ Object.defineProperty(exports, "VwapTracker", { enumerable: true, get: function () { return VwapTracker_js_1.VwapTracker; } });
17
+ var RollingVwap_js_1 = require("./RollingVwap.js");
18
+ Object.defineProperty(exports, "RollingVwap", { enumerable: true, get: function () { return RollingVwap_js_1.RollingVwap; } });
19
+ var SlopeTracker_js_1 = require("./SlopeTracker.js");
20
+ Object.defineProperty(exports, "SlopeTracker", { enumerable: true, get: function () { return SlopeTracker_js_1.SlopeTracker; } });
21
+ var WindowedChange_js_1 = require("./WindowedChange.js");
22
+ Object.defineProperty(exports, "WindowedChange", { enumerable: true, get: function () { return WindowedChange_js_1.WindowedChange; } });
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,6DAAkE;AAA5C,mHAAA,YAAY,OAAA;AAClC,uCAAmC;AAA1B,iGAAA,KAAK,OAAA;AACd,uCAA4D;AAAlC,yGAAA,aAAa,OAAA;AACvC,uDAA+E;AAA1D,iHAAA,aAAa,OAAA;AAAE,kHAAA,cAAc,OAAA;AAClD,mDAA+C;AAAtC,6GAAA,WAAW,OAAA;AACpB,mDAA+C;AAAtC,6GAAA,WAAW,OAAA;AACpB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
@@ -0,0 +1,7 @@
1
+ export interface Sample {
2
+ readonly t: number;
3
+ readonly v: number;
4
+ }
5
+ /** Least-squares regression slope over time-series samples. */
6
+ export declare function computeSlope(samples: readonly Sample[]): number;
7
+ //# sourceMappingURL=linearRegression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linearRegression.d.ts","sourceRoot":"","sources":["../src/linearRegression.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CA8B/D"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeSlope = computeSlope;
4
+ /** Least-squares regression slope over time-series samples. */
5
+ function computeSlope(samples) {
6
+ if (samples.length < 2) {
7
+ return 0;
8
+ }
9
+ const t0 = samples[0].t;
10
+ const n = samples.length;
11
+ let sumT = 0;
12
+ let sumV = 0;
13
+ for (let i = 0; i < n; i++) {
14
+ sumT += (samples[i].t - t0) / 1000;
15
+ sumV += samples[i].v;
16
+ }
17
+ const meanT = sumT / n;
18
+ const meanV = sumV / n;
19
+ let num = 0;
20
+ let den = 0;
21
+ for (let i = 0; i < n; i++) {
22
+ const dt = (samples[i].t - t0) / 1000 - meanT;
23
+ const dv = samples[i].v - meanV;
24
+ num += dt * dv;
25
+ den += dt * dt;
26
+ }
27
+ if (den === 0) {
28
+ return 0;
29
+ }
30
+ return num / den;
31
+ }
32
+ //# sourceMappingURL=linearRegression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linearRegression.js","sourceRoot":"","sources":["../src/linearRegression.ts"],"names":[],"mappings":";;AAMA,oCA8BC;AA/BD,+DAA+D;AAC/D,SAAgB,YAAY,CAAC,OAA0B;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAEzB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;QACnC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC;IAEvB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;QAC9C,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAChC,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;QACf,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,CAAC;AACnB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type TrendLabel = "up" | "down" | "flat";
2
+ /** Classify a value as up/down/flat against a symmetric threshold. */
3
+ export declare function classifyTrend(value: number, threshold: number): TrendLabel;
4
+ //# sourceMappingURL=trend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend.d.ts","sourceRoot":"","sources":["../src/trend.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAQ1E"}
package/dist/trend.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classifyTrend = classifyTrend;
4
+ /** Classify a value as up/down/flat against a symmetric threshold. */
5
+ function classifyTrend(value, threshold) {
6
+ if (value > threshold) {
7
+ return "up";
8
+ }
9
+ if (value < -threshold) {
10
+ return "down";
11
+ }
12
+ return "flat";
13
+ }
14
+ //# sourceMappingURL=trend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend.js","sourceRoot":"","sources":["../src/trend.ts"],"names":[],"mappings":";;AAGA,sCAQC;AATD,sEAAsE;AACtE,SAAgB,aAAa,CAAC,KAAa,EAAE,SAAiB;IAC5D,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@hardlydifficult/math",
3
+ "version": "1.0.0",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "test:coverage": "vitest run --coverage",
14
+ "lint": "tsc --noEmit",
15
+ "clean": "node --eval \"fs.rmSync('dist', { recursive: true, force: true })\""
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "5.9.3",
19
+ "vitest": "4.0.18",
20
+ "@vitest/coverage-v8": "4.0.18"
21
+ },
22
+ "engines": {
23
+ "node": ">=20.19.0"
24
+ },
25
+ "type": "commonjs",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "require": "./dist/index.js",
31
+ "default": "./dist/index.js"
32
+ }
33
+ }
34
+ }