@ebowwa/quant-rust 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +161 -0
  2. package/bun-ffi.d.ts +54 -0
  3. package/dist/index.js +576 -0
  4. package/dist/src/index.d.ts +324 -0
  5. package/dist/src/index.d.ts.map +1 -0
  6. package/dist/types/index.d.ts +403 -0
  7. package/dist/types/index.d.ts.map +1 -0
  8. package/native/README.md +62 -0
  9. package/native/darwin-arm64/libquant_rust.dylib +0 -0
  10. package/package.json +70 -0
  11. package/scripts/postinstall.cjs +85 -0
  12. package/src/ffi.rs +496 -0
  13. package/src/index.ts +1073 -0
  14. package/src/indicators/ma.rs +222 -0
  15. package/src/indicators/mod.rs +18 -0
  16. package/src/indicators/momentum.rs +353 -0
  17. package/src/indicators/sr.rs +195 -0
  18. package/src/indicators/trend.rs +351 -0
  19. package/src/indicators/volatility.rs +270 -0
  20. package/src/indicators/volume.rs +213 -0
  21. package/src/lib.rs +130 -0
  22. package/src/patterns/breakout.rs +431 -0
  23. package/src/patterns/chart.rs +772 -0
  24. package/src/patterns/mod.rs +394 -0
  25. package/src/patterns/sr.rs +423 -0
  26. package/src/prediction/amm.rs +338 -0
  27. package/src/prediction/arbitrage.rs +230 -0
  28. package/src/prediction/calibration.rs +317 -0
  29. package/src/prediction/kelly.rs +232 -0
  30. package/src/prediction/lmsr.rs +194 -0
  31. package/src/prediction/mod.rs +59 -0
  32. package/src/prediction/odds.rs +229 -0
  33. package/src/prediction/pnl.rs +254 -0
  34. package/src/prediction/risk.rs +228 -0
  35. package/src/risk/beta.rs +257 -0
  36. package/src/risk/drawdown.rs +256 -0
  37. package/src/risk/leverage.rs +201 -0
  38. package/src/risk/mod.rs +388 -0
  39. package/src/risk/portfolio.rs +287 -0
  40. package/src/risk/ratios.rs +290 -0
  41. package/src/risk/sizing.rs +194 -0
  42. package/src/risk/var.rs +222 -0
  43. package/src/stats/cdf.rs +257 -0
  44. package/src/stats/correlation.rs +225 -0
  45. package/src/stats/distribution.rs +194 -0
  46. package/src/stats/hypothesis.rs +177 -0
  47. package/src/stats/matrix.rs +346 -0
  48. package/src/stats/mod.rs +257 -0
  49. package/src/stats/regression.rs +239 -0
  50. package/src/stats/rolling.rs +193 -0
  51. package/src/stats/timeseries.rs +263 -0
  52. package/src/types.rs +224 -0
  53. package/src/utils/mod.rs +215 -0
  54. package/src/utils/normalize.rs +192 -0
  55. package/src/utils/price.rs +167 -0
  56. package/src/utils/quantiles.rs +177 -0
  57. package/src/utils/returns.rs +158 -0
  58. package/src/utils/rolling.rs +97 -0
  59. package/src/utils/stats.rs +154 -0
  60. package/types/index.ts +513 -0
@@ -0,0 +1,97 @@
1
+ //! Rolling Window Operations Module
2
+ //!
3
+ //! Sliding window calculations for time series analysis
4
+
5
+ use super::stats::{mean, std_dev, max, min};
6
+
7
+ /// Apply a function over a sliding window
8
+ ///
9
+ /// Returns an empty vector if the array is shorter than the window size.
10
+ pub fn rolling<T, F>(arr: &[f64], window: usize, f: F) -> Vec<T>
11
+ where
12
+ F: Fn(&[f64]) -> T,
13
+ {
14
+ if arr.len() < window || window == 0 {
15
+ return Vec::new();
16
+ }
17
+
18
+ let result_len = arr.len() - window + 1;
19
+ let mut result = Vec::with_capacity(result_len);
20
+
21
+ for i in 0..result_len {
22
+ let slice = &arr[i..i + window];
23
+ result.push(f(slice));
24
+ }
25
+
26
+ result
27
+ }
28
+
29
+ /// Rolling mean (Simple Moving Average)
30
+ pub fn rolling_mean(arr: &[f64], period: usize) -> Vec<f64> {
31
+ rolling(arr, period, mean)
32
+ }
33
+
34
+ /// Rolling standard deviation (sample)
35
+ pub fn rolling_std_dev(arr: &[f64], period: usize) -> Vec<f64> {
36
+ rolling(arr, period, |slice| std_dev(slice, false))
37
+ }
38
+
39
+ /// Rolling minimum
40
+ pub fn rolling_min(arr: &[f64], period: usize) -> Vec<f64> {
41
+ rolling(arr, period, min)
42
+ }
43
+
44
+ /// Rolling maximum
45
+ pub fn rolling_max(arr: &[f64], period: usize) -> Vec<f64> {
46
+ rolling(arr, period, max)
47
+ }
48
+
49
+ /// Rolling sum
50
+ pub fn rolling_sum(arr: &[f64], period: usize) -> Vec<f64> {
51
+ rolling(arr, period, |slice| slice.iter().sum())
52
+ }
53
+
54
+ /// Rolling variance (sample)
55
+ pub fn rolling_variance(arr: &[f64], period: usize) -> Vec<f64> {
56
+ use super::stats::variance;
57
+ rolling(arr, period, |slice| variance(slice, false))
58
+ }
59
+
60
+ #[cfg(test)]
61
+ mod tests {
62
+ use super::*;
63
+
64
+ #[test]
65
+ fn test_rolling() {
66
+ let data = [1.0, 2.0, 3.0, 4.0, 5.0];
67
+ let result: Vec<f64> = rolling(&data, 3, |s| s.iter().sum());
68
+ assert_eq!(result, vec![6.0, 9.0, 12.0]);
69
+ }
70
+
71
+ #[test]
72
+ fn test_rolling_mean() {
73
+ let data = [1.0, 2.0, 3.0, 4.0, 5.0];
74
+ let result = rolling_mean(&data, 3);
75
+ assert_eq!(result.len(), 3);
76
+ assert!((result[0] - 2.0).abs() < 1e-10);
77
+ assert!((result[1] - 3.0).abs() < 1e-10);
78
+ assert!((result[2] - 4.0).abs() < 1e-10);
79
+ }
80
+
81
+ #[test]
82
+ fn test_rolling_empty() {
83
+ let data = [1.0, 2.0];
84
+ let result = rolling_mean(&data, 5);
85
+ assert!(result.is_empty());
86
+ }
87
+
88
+ #[test]
89
+ fn test_rolling_min_max() {
90
+ let data = [5.0, 3.0, 8.0, 2.0, 9.0, 1.0];
91
+ let min_result = rolling_min(&data, 3);
92
+ let max_result = rolling_max(&data, 3);
93
+
94
+ assert_eq!(min_result, vec![3.0, 2.0, 2.0, 1.0]);
95
+ assert_eq!(max_result, vec![8.0, 8.0, 9.0, 9.0]);
96
+ }
97
+ }
@@ -0,0 +1,154 @@
1
+ //! Array Statistics Module
2
+ //!
3
+ //! Common statistical functions for quantitative analysis
4
+
5
+ /// Calculate the sum of an array
6
+ pub fn sum(arr: &[f64]) -> f64 {
7
+ arr.iter().sum()
8
+ }
9
+
10
+ /// Calculate the mean (average) of an array
11
+ pub fn mean(arr: &[f64]) -> f64 {
12
+ if arr.is_empty() {
13
+ return 0.0;
14
+ }
15
+ sum(arr) / arr.len() as f64
16
+ }
17
+
18
+ /// Calculate the median of an array
19
+ pub fn median(arr: &[f64]) -> f64 {
20
+ if arr.is_empty() {
21
+ return 0.0;
22
+ }
23
+
24
+ let mut sorted: Vec<f64> = arr.to_vec();
25
+ sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
26
+
27
+ let mid = sorted.len() / 2;
28
+ if sorted.len() % 2 != 0 {
29
+ sorted[mid]
30
+ } else {
31
+ (sorted[mid - 1] + sorted[mid]) / 2.0
32
+ }
33
+ }
34
+
35
+ /// Calculate the mode of an array
36
+ pub fn mode(arr: &[f64]) -> f64 {
37
+ if arr.is_empty() {
38
+ return 0.0;
39
+ }
40
+
41
+ use std::collections::HashMap;
42
+ let mut frequency: HashMap<u64, usize> = HashMap::new();
43
+
44
+ // Use bit representation for hashing floats
45
+ for &val in arr {
46
+ let key = val.to_bits();
47
+ *frequency.entry(key).or_insert(0) += 1;
48
+ }
49
+
50
+ let mut max_freq = 0;
51
+ let mut mode_val = arr[0];
52
+
53
+ for (&key, &freq) in &frequency {
54
+ if freq > max_freq {
55
+ max_freq = freq;
56
+ mode_val = f64::from_bits(key);
57
+ }
58
+ }
59
+
60
+ mode_val
61
+ }
62
+
63
+ /// Calculate variance
64
+ /// population: true for population variance, false for sample variance
65
+ pub fn variance(arr: &[f64], population: bool) -> f64 {
66
+ if arr.is_empty() {
67
+ return 0.0;
68
+ }
69
+
70
+ let avg = mean(arr);
71
+ let sum_sq_diff: f64 = arr.iter().map(|&val| (val - avg).powi(2)).sum();
72
+
73
+ let divisor = if population {
74
+ arr.len() as f64
75
+ } else {
76
+ (arr.len() - 1) as f64
77
+ };
78
+
79
+ sum_sq_diff / divisor
80
+ }
81
+
82
+ /// Calculate standard deviation
83
+ /// population: true for population std dev, false for sample std dev
84
+ pub fn std_dev(arr: &[f64], population: bool) -> f64 {
85
+ variance(arr, population).sqrt()
86
+ }
87
+
88
+ /// Calculate the minimum value
89
+ pub fn min(arr: &[f64]) -> f64 {
90
+ if arr.is_empty() {
91
+ return 0.0;
92
+ }
93
+ arr.iter().cloned().fold(f64::INFINITY, f64::min)
94
+ }
95
+
96
+ /// Calculate the maximum value
97
+ pub fn max(arr: &[f64]) -> f64 {
98
+ if arr.is_empty() {
99
+ return 0.0;
100
+ }
101
+ arr.iter().cloned().fold(f64::NEG_INFINITY, f64::max)
102
+ }
103
+
104
+ /// Calculate the range (max - min)
105
+ pub fn range(arr: &[f64]) -> f64 {
106
+ max(arr) - min(arr)
107
+ }
108
+
109
+ #[cfg(test)]
110
+ mod tests {
111
+ use super::*;
112
+
113
+ #[test]
114
+ fn test_sum() {
115
+ assert_eq!(sum(&[1.0, 2.0, 3.0, 4.0, 5.0]), 15.0);
116
+ assert_eq!(sum(&[]), 0.0);
117
+ }
118
+
119
+ #[test]
120
+ fn test_mean() {
121
+ assert_eq!(mean(&[1.0, 2.0, 3.0, 4.0, 5.0]), 3.0);
122
+ assert_eq!(mean(&[]), 0.0);
123
+ }
124
+
125
+ #[test]
126
+ fn test_median() {
127
+ assert_eq!(median(&[1.0, 2.0, 3.0, 4.0, 5.0]), 3.0);
128
+ assert_eq!(median(&[1.0, 2.0, 3.0, 4.0]), 2.5);
129
+ assert_eq!(median(&[]), 0.0);
130
+ }
131
+
132
+ #[test]
133
+ fn test_variance() {
134
+ let data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
135
+ // Population variance
136
+ assert!((variance(&data, true) - 4.0).abs() < 1e-10);
137
+ // Sample variance
138
+ assert!((variance(&data, false) - 4.571428571).abs() < 1e-6);
139
+ }
140
+
141
+ #[test]
142
+ fn test_std_dev() {
143
+ let data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
144
+ assert!((std_dev(&data, true) - 2.0).abs() < 1e-10);
145
+ }
146
+
147
+ #[test]
148
+ fn test_min_max_range() {
149
+ let data = [1.0, 5.0, 3.0, 9.0, 2.0];
150
+ assert_eq!(min(&data), 1.0);
151
+ assert_eq!(max(&data), 9.0);
152
+ assert_eq!(range(&data), 8.0);
153
+ }
154
+ }