orderflow-metrics 0.24.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 (134) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/LICENSE +21 -0
  3. package/README.md +556 -0
  4. package/dist/bars.d.ts +67 -0
  5. package/dist/bars.d.ts.map +1 -0
  6. package/dist/bars.js +92 -0
  7. package/dist/bars.js.map +1 -0
  8. package/dist/classify.d.ts +25 -0
  9. package/dist/classify.d.ts.map +1 -0
  10. package/dist/classify.js +57 -0
  11. package/dist/classify.js.map +1 -0
  12. package/dist/covariance.d.ts +37 -0
  13. package/dist/covariance.d.ts.map +1 -0
  14. package/dist/covariance.js +72 -0
  15. package/dist/covariance.js.map +1 -0
  16. package/dist/efficiency.d.ts +24 -0
  17. package/dist/efficiency.d.ts.map +1 -0
  18. package/dist/efficiency.js +65 -0
  19. package/dist/efficiency.js.map +1 -0
  20. package/dist/entropy.d.ts +40 -0
  21. package/dist/entropy.d.ts.map +1 -0
  22. package/dist/entropy.js +73 -0
  23. package/dist/entropy.js.map +1 -0
  24. package/dist/execution.d.ts +40 -0
  25. package/dist/execution.d.ts.map +1 -0
  26. package/dist/execution.js +64 -0
  27. package/dist/execution.js.map +1 -0
  28. package/dist/fairvalue.d.ts +19 -0
  29. package/dist/fairvalue.d.ts.map +1 -0
  30. package/dist/fairvalue.js +27 -0
  31. package/dist/fairvalue.js.map +1 -0
  32. package/dist/hurst.d.ts +23 -0
  33. package/dist/hurst.d.ts.map +1 -0
  34. package/dist/hurst.js +71 -0
  35. package/dist/hurst.js.map +1 -0
  36. package/dist/imbalance.d.ts +12 -0
  37. package/dist/imbalance.d.ts.map +1 -0
  38. package/dist/imbalance.js +19 -0
  39. package/dist/imbalance.js.map +1 -0
  40. package/dist/impact.d.ts +59 -0
  41. package/dist/impact.d.ts.map +1 -0
  42. package/dist/impact.js +63 -0
  43. package/dist/impact.js.map +1 -0
  44. package/dist/index.d.ts +39 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +25 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/jumps.d.ts +33 -0
  49. package/dist/jumps.d.ts.map +1 -0
  50. package/dist/jumps.js +63 -0
  51. package/dist/jumps.js.map +1 -0
  52. package/dist/liquidity.d.ts +18 -0
  53. package/dist/liquidity.d.ts.map +1 -0
  54. package/dist/liquidity.js +22 -0
  55. package/dist/liquidity.js.map +1 -0
  56. package/dist/moments.d.ts +20 -0
  57. package/dist/moments.d.ts.map +1 -0
  58. package/dist/moments.js +48 -0
  59. package/dist/moments.js.map +1 -0
  60. package/dist/ofi.d.ts +22 -0
  61. package/dist/ofi.d.ts.map +1 -0
  62. package/dist/ofi.js +25 -0
  63. package/dist/ofi.js.map +1 -0
  64. package/dist/online.d.ts +101 -0
  65. package/dist/online.d.ts.map +1 -0
  66. package/dist/online.js +205 -0
  67. package/dist/online.js.map +1 -0
  68. package/dist/orderbook.d.ts +30 -0
  69. package/dist/orderbook.d.ts.map +1 -0
  70. package/dist/orderbook.js +66 -0
  71. package/dist/orderbook.js.map +1 -0
  72. package/dist/rangevol.d.ts +40 -0
  73. package/dist/rangevol.d.ts.map +1 -0
  74. package/dist/rangevol.js +101 -0
  75. package/dist/rangevol.js.map +1 -0
  76. package/dist/scheduling.d.ts +19 -0
  77. package/dist/scheduling.d.ts.map +1 -0
  78. package/dist/scheduling.js +45 -0
  79. package/dist/scheduling.js.map +1 -0
  80. package/dist/semivar.d.ts +49 -0
  81. package/dist/semivar.d.ts.map +1 -0
  82. package/dist/semivar.js +59 -0
  83. package/dist/semivar.js.map +1 -0
  84. package/dist/shortfall.d.ts +42 -0
  85. package/dist/shortfall.d.ts.map +1 -0
  86. package/dist/shortfall.js +32 -0
  87. package/dist/shortfall.js.map +1 -0
  88. package/dist/simulate.d.ts +29 -0
  89. package/dist/simulate.d.ts.map +1 -0
  90. package/dist/simulate.js +36 -0
  91. package/dist/simulate.js.map +1 -0
  92. package/dist/spreadest.d.ts +38 -0
  93. package/dist/spreadest.d.ts.map +1 -0
  94. package/dist/spreadest.js +68 -0
  95. package/dist/spreadest.js.map +1 -0
  96. package/dist/types.d.ts +24 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +9 -0
  99. package/dist/types.js.map +1 -0
  100. package/dist/volatility.d.ts +21 -0
  101. package/dist/volatility.d.ts.map +1 -0
  102. package/dist/volatility.js +33 -0
  103. package/dist/volatility.js.map +1 -0
  104. package/dist/vpin.d.ts +38 -0
  105. package/dist/vpin.d.ts.map +1 -0
  106. package/dist/vpin.js +81 -0
  107. package/dist/vpin.js.map +1 -0
  108. package/package.json +70 -0
  109. package/src/bars.ts +141 -0
  110. package/src/classify.ts +59 -0
  111. package/src/covariance.ts +72 -0
  112. package/src/efficiency.ts +64 -0
  113. package/src/entropy.ts +67 -0
  114. package/src/execution.ts +100 -0
  115. package/src/fairvalue.ts +33 -0
  116. package/src/hurst.ts +77 -0
  117. package/src/imbalance.ts +25 -0
  118. package/src/impact.ts +99 -0
  119. package/src/index.ts +87 -0
  120. package/src/jumps.ts +61 -0
  121. package/src/liquidity.ts +29 -0
  122. package/src/moments.ts +45 -0
  123. package/src/ofi.ts +46 -0
  124. package/src/online.ts +228 -0
  125. package/src/orderbook.ts +76 -0
  126. package/src/rangevol.ts +108 -0
  127. package/src/scheduling.ts +50 -0
  128. package/src/semivar.ts +67 -0
  129. package/src/shortfall.ts +69 -0
  130. package/src/simulate.ts +68 -0
  131. package/src/spreadest.ts +75 -0
  132. package/src/types.ts +26 -0
  133. package/src/volatility.ts +36 -0
  134. package/src/vpin.ts +98 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Range-based volatility estimators from OHLC candles.
3
+ *
4
+ * Close-to-close realized volatility (see `volatility`) throws away most of each
5
+ * bar — it reads only the close. But the open, high, and low carry information
6
+ * too, and using them yields far more efficient volatility estimates from the
7
+ * same data. Four classic estimators, in increasing order of what they use:
8
+ *
9
+ * - Parkinson (1980): the high-low range only.
10
+ * - Garman-Klass (1980): adds the open and close.
11
+ * - Rogers-Satchell (1991): drift-independent (correct under a trending mean).
12
+ * - Yang-Zhang (2000): drift-independent and robust to overnight jumps.
13
+ *
14
+ * Each returns the estimated volatility (standard deviation) *per bar*. To
15
+ * annualize, multiply the variance by the number of bars per year, or the
16
+ * volatility by its square root. Prices must be strictly positive.
17
+ */
18
+ const LN2 = Math.LN2;
19
+ /** Parkinson (1980) high-low volatility. Returns 0 for an empty input. */
20
+ export function parkinsonVolatility(bars) {
21
+ const n = bars.length;
22
+ if (n === 0)
23
+ return 0;
24
+ let s = 0;
25
+ for (const b of bars) {
26
+ const hl = Math.log(b.high / b.low);
27
+ s += hl * hl;
28
+ }
29
+ return Math.sqrt(s / (4 * LN2) / n);
30
+ }
31
+ /** Garman-Klass (1980) OHLC volatility. Returns 0 for an empty input. */
32
+ export function garmanKlassVolatility(bars) {
33
+ const n = bars.length;
34
+ if (n === 0)
35
+ return 0;
36
+ let s = 0;
37
+ for (const b of bars) {
38
+ const hl = Math.log(b.high / b.low);
39
+ const co = Math.log(b.close / b.open);
40
+ s += 0.5 * hl * hl - (2 * LN2 - 1) * co * co;
41
+ }
42
+ const v = s / n;
43
+ return v > 0 ? Math.sqrt(v) : 0;
44
+ }
45
+ /**
46
+ * Rogers-Satchell (1991) drift-independent OHLC volatility. Correct even when
47
+ * the price has a non-zero mean drift. Returns 0 for an empty input.
48
+ */
49
+ export function rogersSatchellVolatility(bars) {
50
+ const n = bars.length;
51
+ if (n === 0)
52
+ return 0;
53
+ let s = 0;
54
+ for (const b of bars) {
55
+ s +=
56
+ Math.log(b.high / b.close) * Math.log(b.high / b.open) +
57
+ Math.log(b.low / b.close) * Math.log(b.low / b.open);
58
+ }
59
+ const v = s / n;
60
+ return v > 0 ? Math.sqrt(v) : 0;
61
+ }
62
+ /**
63
+ * Yang-Zhang (2000) volatility: a minimum-variance combination of overnight,
64
+ * open-to-close, and Rogers-Satchell variances that is both drift-independent
65
+ * and robust to opening jumps. Uses each bar's open relative to the previous
66
+ * close, so it needs at least three bars; returns 0 otherwise.
67
+ */
68
+ export function yangZhangVolatility(bars) {
69
+ const n = bars.length;
70
+ if (n < 3)
71
+ return 0;
72
+ const overnight = [];
73
+ const openClose = [];
74
+ let rs = 0;
75
+ for (let i = 1; i < n; i++) {
76
+ const prev = bars[i - 1];
77
+ const b = bars[i];
78
+ overnight.push(Math.log(b.open / prev.close));
79
+ openClose.push(Math.log(b.close / b.open));
80
+ rs +=
81
+ Math.log(b.high / b.close) * Math.log(b.high / b.open) +
82
+ Math.log(b.low / b.close) * Math.log(b.low / b.open);
83
+ }
84
+ const m = overnight.length;
85
+ const mean = (a) => a.reduce((x, y) => x + y, 0) / a.length;
86
+ const ob = mean(overnight);
87
+ const cb = mean(openClose);
88
+ let so = 0;
89
+ let sc = 0;
90
+ for (let i = 0; i < m; i++) {
91
+ so += (overnight[i] - ob) ** 2;
92
+ sc += (openClose[i] - cb) ** 2;
93
+ }
94
+ so /= m - 1;
95
+ sc /= m - 1;
96
+ const rsv = rs / m;
97
+ const k = 0.34 / (1.34 + (m + 1) / (m - 1));
98
+ const v = so + k * sc + (1 - k) * rsv;
99
+ return v > 0 ? Math.sqrt(v) : 0;
100
+ }
101
+ //# sourceMappingURL=rangevol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rangevol.js","sourceRoot":"","sources":["../src/rangevol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Execution scheduling: split a parent order into child slices.
3
+ *
4
+ * `twap` spreads size evenly across a fixed number of slices (time-weighted).
5
+ * `pov` participates at a fixed fraction of each interval's volume
6
+ * (percentage-of-volume). Both return the child sizes; sizes may be fractional.
7
+ */
8
+ /**
9
+ * TWAP: split ``totalSize`` into ``slices`` equal child orders. The sizes sum
10
+ * exactly to ``totalSize`` (any floating residual lands in the last slice).
11
+ */
12
+ export declare function twap(totalSize: number, slices: number): number[];
13
+ /**
14
+ * POV: for each interval, trade ``rate`` × that interval's volume, capped by
15
+ * the size still remaining. Returns per-interval child sizes; their sum is the
16
+ * filled amount (less than ``totalSize`` if the volume was insufficient).
17
+ */
18
+ export declare function pov(totalSize: number, intervalVolumes: readonly number[], rate: number): number[];
19
+ //# sourceMappingURL=scheduling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../src/scheduling.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAYhE;AAED;;;;GAIG;AACH,wBAAgB,GAAG,CACjB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAcV"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Execution scheduling: split a parent order into child slices.
3
+ *
4
+ * `twap` spreads size evenly across a fixed number of slices (time-weighted).
5
+ * `pov` participates at a fixed fraction of each interval's volume
6
+ * (percentage-of-volume). Both return the child sizes; sizes may be fractional.
7
+ */
8
+ /**
9
+ * TWAP: split ``totalSize`` into ``slices`` equal child orders. The sizes sum
10
+ * exactly to ``totalSize`` (any floating residual lands in the last slice).
11
+ */
12
+ export function twap(totalSize, slices) {
13
+ if (slices < 1 || !Number.isInteger(slices)) {
14
+ throw new Error("slices must be a positive integer");
15
+ }
16
+ const out = [];
17
+ let allocated = 0;
18
+ for (let i = 1; i <= slices; i++) {
19
+ const target = (totalSize * i) / slices;
20
+ out.push(target - allocated);
21
+ allocated = target;
22
+ }
23
+ return out;
24
+ }
25
+ /**
26
+ * POV: for each interval, trade ``rate`` × that interval's volume, capped by
27
+ * the size still remaining. Returns per-interval child sizes; their sum is the
28
+ * filled amount (less than ``totalSize`` if the volume was insufficient).
29
+ */
30
+ export function pov(totalSize, intervalVolumes, rate) {
31
+ const r = Math.max(0, rate);
32
+ const out = [];
33
+ let remaining = totalSize;
34
+ for (const vol of intervalVolumes) {
35
+ if (remaining <= 0) {
36
+ out.push(0);
37
+ continue;
38
+ }
39
+ const child = Math.min(remaining, r * Math.max(0, vol));
40
+ out.push(child);
41
+ remaining -= child;
42
+ }
43
+ return out;
44
+ }
45
+ //# sourceMappingURL=scheduling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduling.js","sourceRoot":"","sources":["../src/scheduling.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,SAAiB,EAAE,MAAc;IACpD,IAAI,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;QAC7B,SAAS,GAAG,MAAM,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,GAAG,CACjB,SAAiB,EACjB,eAAkC,EAClC,IAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,SAAS,GAAG,SAAS,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACxD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,SAAS,IAAI,KAAK,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Realized semivariance and signed jump variation
3
+ * (Barndorff-Nielsen, Kinnebrock & Shephard, 2010; Patton & Shephard, 2015).
4
+ *
5
+ * Realized variance (RV = Σ rᵢ²) treats an up-move and a down-move of equal
6
+ * size as identical risk. But most traders care far more about the downside.
7
+ * Realized semivariance splits RV by the *sign* of each return:
8
+ *
9
+ * RS⁺ = Σ rᵢ² · 1{rᵢ > 0} (upside)
10
+ * RS⁻ = Σ rᵢ² · 1{rᵢ < 0} (downside)
11
+ * RS⁺ + RS⁻ = RV (zero returns contribute to neither)
12
+ *
13
+ * The two halves carry different information: RS⁻ (bad volatility) is the part
14
+ * that predicts future risk and demands a premium, while RS⁺ (good volatility)
15
+ * behaves quite differently. Their difference is the *signed* jump variation,
16
+ * which — unlike ordinary jump variation — keeps the direction of jump risk:
17
+ *
18
+ * signed jump variation = RS⁺ − RS⁻
19
+ *
20
+ * A positive value means upside moves dominate; a negative value means the
21
+ * series is downside-heavy. Each function takes a return series.
22
+ */
23
+ /** Upside / downside decomposition of realized variance. Both are ≥ 0. */
24
+ export interface Semivariance {
25
+ /** RS⁺ = Σ rᵢ² over strictly positive returns. */
26
+ upside: number;
27
+ /** RS⁻ = Σ rᵢ² over strictly negative returns. */
28
+ downside: number;
29
+ }
30
+ /**
31
+ * Realized semivariance: splits realized variance into the sum of squared
32
+ * positive returns (upside) and squared negative returns (downside). Zero
33
+ * returns are ignored, so `upside + downside` equals realized variance. An
34
+ * empty series returns { upside: 0, downside: 0 }.
35
+ */
36
+ export declare function realizedSemivariance(returns: readonly number[]): Semivariance;
37
+ /**
38
+ * Downside variance ratio: RS⁻ / (RS⁺ + RS⁻), the share of realized variance
39
+ * coming from negative returns, in [0, 1]. Returns 0 when realized variance is
40
+ * 0 (or the series is empty). A value above 0.5 marks a downside-heavy window.
41
+ */
42
+ export declare function downsideVarianceRatio(returns: readonly number[]): number;
43
+ /**
44
+ * Signed jump variation: RS⁺ − RS⁻ (Patton & Shephard, 2015). Positive when
45
+ * upside moves dominate, negative when downside moves dominate; unlike jump
46
+ * variation it can take either sign. Returns 0 for an empty series.
47
+ */
48
+ export declare function signedJumpVariation(returns: readonly number[]): number;
49
+ //# sourceMappingURL=semivar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semivar.d.ts","sourceRoot":"","sources":["../src/semivar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAQ7E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGtE"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Realized semivariance and signed jump variation
3
+ * (Barndorff-Nielsen, Kinnebrock & Shephard, 2010; Patton & Shephard, 2015).
4
+ *
5
+ * Realized variance (RV = Σ rᵢ²) treats an up-move and a down-move of equal
6
+ * size as identical risk. But most traders care far more about the downside.
7
+ * Realized semivariance splits RV by the *sign* of each return:
8
+ *
9
+ * RS⁺ = Σ rᵢ² · 1{rᵢ > 0} (upside)
10
+ * RS⁻ = Σ rᵢ² · 1{rᵢ < 0} (downside)
11
+ * RS⁺ + RS⁻ = RV (zero returns contribute to neither)
12
+ *
13
+ * The two halves carry different information: RS⁻ (bad volatility) is the part
14
+ * that predicts future risk and demands a premium, while RS⁺ (good volatility)
15
+ * behaves quite differently. Their difference is the *signed* jump variation,
16
+ * which — unlike ordinary jump variation — keeps the direction of jump risk:
17
+ *
18
+ * signed jump variation = RS⁺ − RS⁻
19
+ *
20
+ * A positive value means upside moves dominate; a negative value means the
21
+ * series is downside-heavy. Each function takes a return series.
22
+ */
23
+ /**
24
+ * Realized semivariance: splits realized variance into the sum of squared
25
+ * positive returns (upside) and squared negative returns (downside). Zero
26
+ * returns are ignored, so `upside + downside` equals realized variance. An
27
+ * empty series returns { upside: 0, downside: 0 }.
28
+ */
29
+ export function realizedSemivariance(returns) {
30
+ let upside = 0;
31
+ let downside = 0;
32
+ for (const r of returns) {
33
+ if (r > 0)
34
+ upside += r * r;
35
+ else if (r < 0)
36
+ downside += r * r;
37
+ }
38
+ return { upside, downside };
39
+ }
40
+ /**
41
+ * Downside variance ratio: RS⁻ / (RS⁺ + RS⁻), the share of realized variance
42
+ * coming from negative returns, in [0, 1]. Returns 0 when realized variance is
43
+ * 0 (or the series is empty). A value above 0.5 marks a downside-heavy window.
44
+ */
45
+ export function downsideVarianceRatio(returns) {
46
+ const { upside, downside } = realizedSemivariance(returns);
47
+ const total = upside + downside;
48
+ return total > 0 ? downside / total : 0;
49
+ }
50
+ /**
51
+ * Signed jump variation: RS⁺ − RS⁻ (Patton & Shephard, 2015). Positive when
52
+ * upside moves dominate, negative when downside moves dominate; unlike jump
53
+ * variation it can take either sign. Returns 0 for an empty series.
54
+ */
55
+ export function signedJumpVariation(returns) {
56
+ const { upside, downside } = realizedSemivariance(returns);
57
+ return upside - downside;
58
+ }
59
+ //# sourceMappingURL=semivar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semivar.js","sourceRoot":"","sources":["../src/semivar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA0B;IAC7D,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;aACtB,IAAI,CAAC,GAAG,CAAC;YAAE,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA0B;IAC9D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA0B;IAC5D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC3D,OAAO,MAAM,GAAG,QAAQ,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Implementation shortfall and arrival slippage.
3
+ *
4
+ * Perold's (1988) "implementation shortfall" measures the all-in cost of turning
5
+ * a paper decision into real fills. It splits into the cost paid on the shares
6
+ * you actually executed (vs the price when you decided), the opportunity cost of
7
+ * the shares you failed to execute as the price drifted away, and fees. Arrival
8
+ * slippage is the simpler, per-order version against the arrival mid.
9
+ *
10
+ * Sign convention: buys are +1, sells are -1. All costs are returned as
11
+ * *positive = worse* (a shortfall), in the input price/quantity units.
12
+ */
13
+ import type { Side } from "./types.ts";
14
+ export interface ShortfallResult {
15
+ /** Cost on executed shares vs the decision price. */
16
+ execution: number;
17
+ /** Opportunity cost of unexecuted shares as the price drifted. */
18
+ opportunity: number;
19
+ /** Explicit fees / commissions. */
20
+ fees: number;
21
+ /** execution + opportunity + fees. Positive = shortfall (cost). */
22
+ total: number;
23
+ }
24
+ /**
25
+ * Implementation shortfall of an order, decomposed into execution cost,
26
+ * opportunity cost, and fees.
27
+ *
28
+ * @param decisionPrice price when the trade was decided (the paper benchmark)
29
+ * @param avgExecPrice volume-weighted average price actually paid/received
30
+ * @param executedQty shares actually filled
31
+ * @param targetQty shares originally intended
32
+ * @param finalPrice price at the end of trading (for the unfilled remainder)
33
+ * @param fees explicit costs (default 0)
34
+ */
35
+ export declare function implementationShortfall(side: Side, decisionPrice: number, avgExecPrice: number, executedQty: number, targetQty: number, finalPrice: number, fees?: number): ShortfallResult;
36
+ /**
37
+ * Arrival slippage in basis points: signed cost of the average execution price
38
+ * against the arrival price. Positive = adverse (paid up on a buy / sold low on
39
+ * a sell). Returns 0 when the arrival price is 0.
40
+ */
41
+ export declare function arrivalSlippageBps(side: Side, arrivalPrice: number, avgExecPrice: number): number;
42
+ //# sourceMappingURL=shortfall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortfall.d.ts","sourceRoot":"","sources":["../src/shortfall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvC,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,SAAI,GACP,eAAe,CAMjB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GACnB,MAAM,CAGR"}
@@ -0,0 +1,32 @@
1
+ function dir(side) {
2
+ return side === "buy" ? 1 : -1;
3
+ }
4
+ /**
5
+ * Implementation shortfall of an order, decomposed into execution cost,
6
+ * opportunity cost, and fees.
7
+ *
8
+ * @param decisionPrice price when the trade was decided (the paper benchmark)
9
+ * @param avgExecPrice volume-weighted average price actually paid/received
10
+ * @param executedQty shares actually filled
11
+ * @param targetQty shares originally intended
12
+ * @param finalPrice price at the end of trading (for the unfilled remainder)
13
+ * @param fees explicit costs (default 0)
14
+ */
15
+ export function implementationShortfall(side, decisionPrice, avgExecPrice, executedQty, targetQty, finalPrice, fees = 0) {
16
+ const d = dir(side);
17
+ const execution = d * (avgExecPrice - decisionPrice) * executedQty;
18
+ const unexecuted = Math.max(0, targetQty - executedQty);
19
+ const opportunity = d * (finalPrice - decisionPrice) * unexecuted;
20
+ return { execution, opportunity, fees, total: execution + opportunity + fees };
21
+ }
22
+ /**
23
+ * Arrival slippage in basis points: signed cost of the average execution price
24
+ * against the arrival price. Positive = adverse (paid up on a buy / sold low on
25
+ * a sell). Returns 0 when the arrival price is 0.
26
+ */
27
+ export function arrivalSlippageBps(side, arrivalPrice, avgExecPrice) {
28
+ if (arrivalPrice === 0)
29
+ return 0;
30
+ return ((dir(side) * (avgExecPrice - arrivalPrice)) / arrivalPrice) * 10_000;
31
+ }
32
+ //# sourceMappingURL=shortfall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortfall.js","sourceRoot":"","sources":["../src/shortfall.ts"],"names":[],"mappings":"AAcA,SAAS,GAAG,CAAC,IAAU;IACrB,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAaD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAU,EACV,aAAqB,EACrB,YAAoB,EACpB,WAAmB,EACnB,SAAiB,EACjB,UAAkB,EAClB,IAAI,GAAG,CAAC;IAER,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,YAAY,GAAG,aAAa,CAAC,GAAG,WAAW,CAAC;IACnE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,aAAa,CAAC,GAAG,UAAU,CAAC;IAClE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAU,EACV,YAAoB,EACpB,YAAoB;IAEpB,IAAI,YAAY,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,MAAM,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Market-order simulation against a reconstructed order book.
3
+ *
4
+ * Sweep the book with a market order and see what you'd actually get: the
5
+ * volume-weighted fill price, slippage vs the starting mid, and any size the
6
+ * book was too thin to fill. Read-only — the book is not mutated.
7
+ */
8
+ import { OrderBook } from "./orderbook.ts";
9
+ export interface Fill {
10
+ price: number;
11
+ size: number;
12
+ }
13
+ export interface MarketOrderResult {
14
+ filledSize: number;
15
+ remainingSize: number;
16
+ /** volume-weighted average fill price, or null if nothing filled */
17
+ avgPrice: number | null;
18
+ notional: number;
19
+ /** cost vs the mid at start, in basis points (positive = adverse); null if unknown */
20
+ slippageBps: number | null;
21
+ fills: Fill[];
22
+ }
23
+ /**
24
+ * Simulate a market order. A ``buy`` consumes asks from best (lowest) upward;
25
+ * a ``sell`` consumes bids from best (highest) downward. Stops when filled or
26
+ * the book runs out (``remainingSize`` > 0).
27
+ */
28
+ export declare function simulateMarketOrder(book: OrderBook, side: "buy" | "sell", size: number): MarketOrderResult;
29
+ //# sourceMappingURL=simulate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulate.d.ts","sourceRoot":"","sources":["../src/simulate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,KAAK,GAAG,MAAM,EACpB,IAAI,EAAE,MAAM,GACX,iBAAiB,CAiCnB"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Simulate a market order. A ``buy`` consumes asks from best (lowest) upward;
3
+ * a ``sell`` consumes bids from best (highest) downward. Stops when filled or
4
+ * the book runs out (``remainingSize`` > 0).
5
+ */
6
+ export function simulateMarketOrder(book, side, size) {
7
+ const startMid = book.mid();
8
+ const levels = book.depth(side === "buy" ? "ask" : "bid", Number.MAX_SAFE_INTEGER);
9
+ const fills = [];
10
+ let remaining = size;
11
+ let notional = 0;
12
+ for (const level of levels) {
13
+ if (remaining <= 0)
14
+ break;
15
+ const take = Math.min(remaining, level.size);
16
+ fills.push({ price: level.price, size: take });
17
+ notional += level.price * take;
18
+ remaining -= take;
19
+ }
20
+ const filled = size - remaining;
21
+ const avgPrice = filled > 0 ? notional / filled : null;
22
+ let slippageBps = null;
23
+ if (avgPrice !== null && startMid !== null && startMid !== 0) {
24
+ const raw = side === "buy" ? avgPrice - startMid : startMid - avgPrice;
25
+ slippageBps = (raw / startMid) * 10_000;
26
+ }
27
+ return {
28
+ filledSize: filled,
29
+ remainingSize: remaining,
30
+ avgPrice,
31
+ notional,
32
+ slippageBps,
33
+ fills,
34
+ };
35
+ }
36
+ //# sourceMappingURL=simulate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulate.js","sourceRoot":"","sources":["../src/simulate.ts"],"names":[],"mappings":"AAyBA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAe,EACf,IAAoB,EACpB,IAAY;IAEZ,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAEnF,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,QAAQ,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAC/B,SAAS,IAAI,IAAI,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvD,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACvE,WAAW,GAAG,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,MAAM,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,aAAa,EAAE,SAAS;QACxB,QAAQ;QACR,QAAQ;QACR,WAAW;QACX,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Bid-ask spread estimators from daily OHLC data.
3
+ *
4
+ * When all you have is low-frequency bars — daily high, low, and close — you can
5
+ * still back out an estimate of the effective bid-ask spread. Two well-known,
6
+ * dependency-free estimators:
7
+ *
8
+ * - Corwin & Schultz (2012): the high-low range over two consecutive periods
9
+ * reflects both fundamental volatility and the bid-ask bounce. The bounce can
10
+ * be isolated because volatility scales with the time interval while the
11
+ * spread does not.
12
+ * - Abdi & Ranaldo (2017): compares each close to the mid-point of the current
13
+ * and the next period's high-low range; their covariance recovers the spread.
14
+ *
15
+ * Both return a *proportional* spread (a fraction of price, e.g. 0.01 = 100 bps).
16
+ * Negative estimates — noise when the true spread is close to zero — are floored
17
+ * at 0. Prices must be strictly positive.
18
+ */
19
+ export interface Ohlc {
20
+ high: number;
21
+ low: number;
22
+ close: number;
23
+ }
24
+ /**
25
+ * Corwin-Schultz (2012) high-low proportional spread estimate, averaged over all
26
+ * consecutive bar pairs. Per-pair negative estimates are set to 0 before
27
+ * averaging (as recommended in the paper). Returns 0 for fewer than two bars.
28
+ */
29
+ export declare function corwinSchultz(bars: Ohlc[]): number;
30
+ /**
31
+ * Abdi-Ranaldo (2017) proportional spread estimate from close, high, and low.
32
+ * Uses the covariance of each log-close with the mid-range of the current and
33
+ * next bar: S = sqrt(max(4 · E[(c_t − η_t)(c_t − η_{t+1})], 0)), where
34
+ * η = (log high + log low) / 2. Returns 0 for fewer than two bars or when the
35
+ * estimate is negative.
36
+ */
37
+ export declare function abdiRanaldo(bars: Ohlc[]): number;
38
+ //# sourceMappingURL=spreadest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spreadest.d.ts","sourceRoot":"","sources":["../src/spreadest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,CAmBlD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,CAahD"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Bid-ask spread estimators from daily OHLC data.
3
+ *
4
+ * When all you have is low-frequency bars — daily high, low, and close — you can
5
+ * still back out an estimate of the effective bid-ask spread. Two well-known,
6
+ * dependency-free estimators:
7
+ *
8
+ * - Corwin & Schultz (2012): the high-low range over two consecutive periods
9
+ * reflects both fundamental volatility and the bid-ask bounce. The bounce can
10
+ * be isolated because volatility scales with the time interval while the
11
+ * spread does not.
12
+ * - Abdi & Ranaldo (2017): compares each close to the mid-point of the current
13
+ * and the next period's high-low range; their covariance recovers the spread.
14
+ *
15
+ * Both return a *proportional* spread (a fraction of price, e.g. 0.01 = 100 bps).
16
+ * Negative estimates — noise when the true spread is close to zero — are floored
17
+ * at 0. Prices must be strictly positive.
18
+ */
19
+ /** 3 - 2√2 ≈ 0.1716, the Corwin-Schultz normalizing constant. */
20
+ const K = 3 - 2 * Math.SQRT2;
21
+ /**
22
+ * Corwin-Schultz (2012) high-low proportional spread estimate, averaged over all
23
+ * consecutive bar pairs. Per-pair negative estimates are set to 0 before
24
+ * averaging (as recommended in the paper). Returns 0 for fewer than two bars.
25
+ */
26
+ export function corwinSchultz(bars) {
27
+ if (bars.length < 2)
28
+ return 0;
29
+ let sum = 0;
30
+ let n = 0;
31
+ for (let i = 0; i + 1 < bars.length; i++) {
32
+ const a = bars[i];
33
+ const b = bars[i + 1];
34
+ const hlA = Math.log(a.high / a.low);
35
+ const hlB = Math.log(b.high / b.low);
36
+ const beta = hlA * hlA + hlB * hlB;
37
+ const g = Math.log(Math.max(a.high, b.high) / Math.min(a.low, b.low));
38
+ const gamma = g * g;
39
+ const alpha = (Math.sqrt(2 * beta) - Math.sqrt(beta)) / K - Math.sqrt(gamma / K);
40
+ const s = (2 * (Math.exp(alpha) - 1)) / (1 + Math.exp(alpha));
41
+ sum += s > 0 ? s : 0;
42
+ n++;
43
+ }
44
+ return n === 0 ? 0 : sum / n;
45
+ }
46
+ /**
47
+ * Abdi-Ranaldo (2017) proportional spread estimate from close, high, and low.
48
+ * Uses the covariance of each log-close with the mid-range of the current and
49
+ * next bar: S = sqrt(max(4 · E[(c_t − η_t)(c_t − η_{t+1})], 0)), where
50
+ * η = (log high + log low) / 2. Returns 0 for fewer than two bars or when the
51
+ * estimate is negative.
52
+ */
53
+ export function abdiRanaldo(bars) {
54
+ if (bars.length < 2)
55
+ return 0;
56
+ let sum = 0;
57
+ let n = 0;
58
+ for (let t = 0; t + 1 < bars.length; t++) {
59
+ const c = Math.log(bars[t].close);
60
+ const etaT = (Math.log(bars[t].high) + Math.log(bars[t].low)) / 2;
61
+ const etaN = (Math.log(bars[t + 1].high) + Math.log(bars[t + 1].low)) / 2;
62
+ sum += (c - etaT) * (c - etaN);
63
+ n++;
64
+ }
65
+ const s2 = 4 * (n === 0 ? 0 : sum / n);
66
+ return s2 > 0 ? Math.sqrt(s2) : 0;
67
+ }
68
+ //# sourceMappingURL=spreadest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spreadest.js","sourceRoot":"","sources":["../src/spreadest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Core input types for order-flow metrics.
3
+ *
4
+ * Prices and sizes are plain numbers; timestamps (if provided) are opaque to
5
+ * this library — pass whatever epoch unit your feed uses, we never compare
6
+ * across records.
7
+ */
8
+ export type Side = "buy" | "sell";
9
+ /** Top-of-book (level-1) snapshot. */
10
+ export interface L1Quote {
11
+ ts?: number;
12
+ bidPrice: number;
13
+ bidSize: number;
14
+ askPrice: number;
15
+ askSize: number;
16
+ }
17
+ /** A single executed trade. */
18
+ export interface Trade {
19
+ ts?: number;
20
+ price: number;
21
+ size: number;
22
+ side: Side;
23
+ }
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AAElC,sCAAsC;AACtC,MAAM,WAAW,OAAO;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+BAA+B;AAC/B,MAAM,WAAW,KAAK;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;CACZ"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Core input types for order-flow metrics.
3
+ *
4
+ * Prices and sizes are plain numbers; timestamps (if provided) are opaque to
5
+ * this library — pass whatever epoch unit your feed uses, we never compare
6
+ * across records.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Realized volatility from a return series.
3
+ *
4
+ * Returns are period returns (e.g. log returns between consecutive prints or
5
+ * bars). Realized variance is the sum of squared returns; realized volatility
6
+ * is its square root. Annualized volatility scales the per-period variance by
7
+ * the number of periods in a year (zero-mean convention, standard for
8
+ * high-frequency returns).
9
+ */
10
+ /** Realized variance: Σ rᵢ². */
11
+ export declare function realizedVariance(returns: readonly number[]): number;
12
+ /** Realized volatility over the sample: √(Σ rᵢ²). */
13
+ export declare function realizedVolatility(returns: readonly number[]): number;
14
+ /**
15
+ * Annualized volatility: √( mean(rᵢ²) · periodsPerYear ).
16
+ *
17
+ * ``periodsPerYear`` is how many return periods make up a year (e.g. 252 for
18
+ * daily, 252·390 for 1-minute equity bars). Returns 0 for an empty series.
19
+ */
20
+ export declare function annualizedVolatility(returns: readonly number[], periodsPerYear: number): number;
21
+ //# sourceMappingURL=volatility.d.ts.map