@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
package/dist/index.js ADDED
@@ -0,0 +1,576 @@
1
+ // @bun
2
+ // src/index.ts
3
+ import { dlopen, FFIType, ptr } from "bun:ffi";
4
+ import { join, dirname } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { existsSync } from "fs";
7
+
8
+ // types/index.ts
9
+ var Signal;
10
+ ((Signal2) => {
11
+ Signal2[Signal2["StrongBuy"] = 2] = "StrongBuy";
12
+ Signal2[Signal2["Buy"] = 1] = "Buy";
13
+ Signal2[Signal2["Neutral"] = 0] = "Neutral";
14
+ Signal2[Signal2["Sell"] = -1] = "Sell";
15
+ Signal2[Signal2["StrongSell"] = -2] = "StrongSell";
16
+ })(Signal ||= {});
17
+ var CandlePattern;
18
+ ((CandlePattern2) => {
19
+ CandlePattern2["Doji"] = "Doji";
20
+ CandlePattern2["Hammer"] = "Hammer";
21
+ CandlePattern2["InvertedHammer"] = "InvertedHammer";
22
+ CandlePattern2["BullishEngulfing"] = "BullishEngulfing";
23
+ CandlePattern2["BearishEngulfing"] = "BearishEngulfing";
24
+ CandlePattern2["MorningStar"] = "MorningStar";
25
+ CandlePattern2["EveningStar"] = "EveningStar";
26
+ CandlePattern2["ThreeWhiteSoldiers"] = "ThreeWhiteSoldiers";
27
+ CandlePattern2["ThreeBlackCrows"] = "ThreeBlackCrows";
28
+ CandlePattern2["ShootingStar"] = "ShootingStar";
29
+ CandlePattern2["HangingMan"] = "HangingMan";
30
+ })(CandlePattern ||= {});
31
+ function calculateEdge(yourProbability, marketPrice) {
32
+ const edge = yourProbability - marketPrice;
33
+ return {
34
+ edge,
35
+ has_edge: edge > 0,
36
+ edge_percent: edge * 100
37
+ };
38
+ }
39
+ function positionSizeFixedFractional(capital, riskPercent, entryPrice, stopLoss) {
40
+ const riskAmount = capital * riskPercent;
41
+ const riskPerShare = Math.abs(entryPrice - stopLoss);
42
+ const shares = riskPerShare > 0 ? Math.floor(riskAmount / riskPerShare) : 0;
43
+ const positionSize = shares * entryPrice;
44
+ return {
45
+ position_size: positionSize,
46
+ shares,
47
+ risk_amount: riskAmount,
48
+ entry_price: entryPrice,
49
+ stop_loss: stopLoss
50
+ };
51
+ }
52
+
53
+ // src/index.ts
54
+ var __dirname2 = dirname(fileURLToPath(import.meta.url));
55
+ function getNativeLibPath() {
56
+ const platform = process.platform;
57
+ const arch = process.arch;
58
+ const libName = (() => {
59
+ switch (platform) {
60
+ case "darwin":
61
+ return "libquant_rust.dylib";
62
+ case "linux":
63
+ return "libquant_rust.so";
64
+ case "win32":
65
+ return "quant_rust.dll";
66
+ default:
67
+ throw new Error(`Unsupported platform: ${platform}`);
68
+ }
69
+ })();
70
+ const possiblePaths = [
71
+ join(__dirname2, "..", "native", `${platform}-${arch}`, libName),
72
+ join(__dirname2, "..", "target", "release", libName),
73
+ join(__dirname2, "..", "..", "target", "release", libName),
74
+ join(__dirname2, "..", "..", "..", "target", "release", libName)
75
+ ];
76
+ for (const p of possiblePaths) {
77
+ if (existsSync(p)) {
78
+ return p;
79
+ }
80
+ }
81
+ throw new Error(`Could not find quant_rust library for ${platform}-${arch}. ` + `Please run 'cargo build --release' or ensure prebuilt binaries are in native/${platform}-${arch}/`);
82
+ }
83
+ var libPath = getNativeLibPath();
84
+ var symbols = {
85
+ quant_version: {
86
+ returns: FFIType.cstring,
87
+ args: []
88
+ },
89
+ quant_last_error: {
90
+ returns: FFIType.cstring,
91
+ args: []
92
+ },
93
+ quant_clear_error: {
94
+ returns: FFIType.void,
95
+ args: []
96
+ },
97
+ quant_ohlcv_new: {
98
+ returns: FFIType.cstring,
99
+ args: [FFIType.i64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64]
100
+ },
101
+ quant_amm_new: {
102
+ returns: FFIType.cstring,
103
+ args: [FFIType.f64, FFIType.f64, FFIType.f64]
104
+ },
105
+ quant_amm_calculate_cost: {
106
+ returns: FFIType.cstring,
107
+ args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64]
108
+ },
109
+ quant_amm_price_impact: {
110
+ returns: FFIType.cstring,
111
+ args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64]
112
+ },
113
+ quant_lmsr_price: {
114
+ returns: FFIType.cstring,
115
+ args: [FFIType.f64, FFIType.f64, FFIType.f64]
116
+ },
117
+ quant_lmsr_cost: {
118
+ returns: FFIType.cstring,
119
+ args: [FFIType.f64, FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64]
120
+ },
121
+ quant_kelly_criterion: {
122
+ returns: FFIType.cstring,
123
+ args: [FFIType.f64, FFIType.f64, FFIType.f64]
124
+ },
125
+ quant_detect_arbitrage: {
126
+ returns: FFIType.cstring,
127
+ args: [FFIType.f64, FFIType.f64]
128
+ },
129
+ quant_convert_odds: {
130
+ returns: FFIType.cstring,
131
+ args: [FFIType.f64, FFIType.i32]
132
+ },
133
+ quant_mean: {
134
+ returns: FFIType.f64,
135
+ args: [FFIType.ptr, FFIType.usize]
136
+ },
137
+ quant_std_dev: {
138
+ returns: FFIType.f64,
139
+ args: [FFIType.ptr, FFIType.usize]
140
+ },
141
+ quant_variance: {
142
+ returns: FFIType.f64,
143
+ args: [FFIType.ptr, FFIType.usize]
144
+ },
145
+ quant_correlation: {
146
+ returns: FFIType.f64,
147
+ args: [FFIType.ptr, FFIType.ptr, FFIType.usize]
148
+ },
149
+ quant_free_string: {
150
+ returns: FFIType.void,
151
+ args: [FFIType.ptr]
152
+ }
153
+ };
154
+ var lib = dlopen(libPath, symbols);
155
+ function parseJsonResponse(response) {
156
+ if (!response) {
157
+ const error = lib.symbols.quant_last_error();
158
+ throw new Error(error || "Unknown error from quant-rust");
159
+ }
160
+ try {
161
+ return JSON.parse(response);
162
+ } catch (e) {
163
+ throw new Error(`Failed to parse JSON response: ${response}`);
164
+ }
165
+ }
166
+ function createFloat64Ptr(data) {
167
+ const buffer = new Float64Array(data);
168
+ return { buffer, ptr: ptr(buffer) };
169
+ }
170
+ function getVersion() {
171
+ return lib.symbols.quant_version();
172
+ }
173
+ function clearError() {
174
+ lib.symbols.quant_clear_error();
175
+ }
176
+ function getLibraryPath() {
177
+ return libPath;
178
+ }
179
+ function createOHLCV(timestamp, open, high, low, close, volume) {
180
+ const response = lib.symbols.quant_ohlcv_new(BigInt(timestamp), open, high, low, close, volume);
181
+ return parseJsonResponse(response);
182
+ }
183
+ function createAMM(poolYes, poolNo, fee) {
184
+ const response = lib.symbols.quant_amm_new(poolYes, poolNo, fee);
185
+ return parseJsonResponse(response);
186
+ }
187
+ function ammCalculateCost(poolYes, poolNo, outcome, shares) {
188
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
189
+ const response = lib.symbols.quant_amm_calculate_cost(poolYes, poolNo, buyYes, shares);
190
+ const result = parseJsonResponse(response);
191
+ return Math.abs(result.cost);
192
+ }
193
+ function ammCalculateCostFull(poolYes, poolNo, outcome, shares) {
194
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
195
+ const response = lib.symbols.quant_amm_calculate_cost(poolYes, poolNo, buyYes, shares);
196
+ const result = parseJsonResponse(response);
197
+ return {
198
+ cost: Math.abs(result.cost),
199
+ avg_price: Math.abs(result.avg_price)
200
+ };
201
+ }
202
+ function ammPriceImpact(poolYes, poolNo, outcome, shares) {
203
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
204
+ const response = lib.symbols.quant_amm_price_impact(poolYes, poolNo, buyYes, shares);
205
+ return parseJsonResponse(response);
206
+ }
207
+ var amm_buy_cost = ammCalculateCost;
208
+ var amm_calculate_cost = ammCalculateCost;
209
+ var amm_price_impact = ammPriceImpact;
210
+ function lmsrPrice(yesShares, noShares, b) {
211
+ const response = lib.symbols.quant_lmsr_price(yesShares, noShares, b);
212
+ return parseJsonResponse(response);
213
+ }
214
+ function lmsrCost(yesShares, noShares, b, outcome, shares) {
215
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
216
+ const response = lib.symbols.quant_lmsr_cost(yesShares, noShares, b, buyYes, shares);
217
+ return parseJsonResponse(response);
218
+ }
219
+ function lmsrCalculate(yesShares, noShares, liquidityParam, operation, outcome, sharesToBuy) {
220
+ if (operation === "price") {
221
+ return lmsrPrice(yesShares, noShares, liquidityParam);
222
+ } else {
223
+ if (sharesToBuy === undefined) {
224
+ throw new Error("sharesToBuy is required for cost operation");
225
+ }
226
+ return lmsrCost(yesShares, noShares, liquidityParam, outcome === "yes", sharesToBuy);
227
+ }
228
+ }
229
+ function kellyCriterion(yourProbability, marketPrice, bankroll) {
230
+ const response = lib.symbols.quant_kelly_criterion(yourProbability, marketPrice, bankroll);
231
+ return parseJsonResponse(response);
232
+ }
233
+ var kelly_criterion = kellyCriterion;
234
+ function detectArbitrage(yesPrice, noPrice) {
235
+ const response = lib.symbols.quant_detect_arbitrage(yesPrice, noPrice);
236
+ const result = parseJsonResponse(response);
237
+ return { ...result, profit: result.profit_per_share };
238
+ }
239
+ var detect_arbitrage = detectArbitrage;
240
+ function convertOdds(value, fromType, toType) {
241
+ const typeMap = {
242
+ probability: 0,
243
+ decimal: 1,
244
+ american: 2
245
+ };
246
+ const response = lib.symbols.quant_convert_odds(value, typeMap[fromType]);
247
+ const result = parseJsonResponse(response);
248
+ if (toType) {
249
+ switch (toType) {
250
+ case "probability":
251
+ return result.probability;
252
+ case "decimal":
253
+ return result.decimal_odds;
254
+ case "american":
255
+ return result.american_odds;
256
+ default:
257
+ return result;
258
+ }
259
+ }
260
+ return result;
261
+ }
262
+ var convert_odds = convertOdds;
263
+ function mean(data) {
264
+ if (data.length === 0)
265
+ return NaN;
266
+ const { buffer, ptr: dataPtr } = createFloat64Ptr(data);
267
+ return lib.symbols.quant_mean(dataPtr, data.length);
268
+ }
269
+ function stdDev(data) {
270
+ if (data.length === 0)
271
+ return NaN;
272
+ const { buffer, ptr: dataPtr } = createFloat64Ptr(data);
273
+ return lib.symbols.quant_std_dev(dataPtr, data.length);
274
+ }
275
+ function variance(data) {
276
+ if (data.length === 0)
277
+ return NaN;
278
+ const { buffer, ptr: dataPtr } = createFloat64Ptr(data);
279
+ return lib.symbols.quant_variance(dataPtr, data.length);
280
+ }
281
+ function correlation(x, y) {
282
+ if (x.length === 0 || y.length === 0 || x.length !== y.length)
283
+ return NaN;
284
+ const { buffer: bufferX, ptr: ptrX } = createFloat64Ptr(x);
285
+ const { buffer: bufferY, ptr: ptrY } = createFloat64Ptr(y);
286
+ return lib.symbols.quant_correlation(ptrX, ptrY, x.length);
287
+ }
288
+ var std_dev = stdDev;
289
+ function sma(prices, period) {
290
+ if (prices.length < period || period <= 0)
291
+ return [];
292
+ const result = [];
293
+ for (let i = period - 1;i < prices.length; i++) {
294
+ let sum = 0;
295
+ for (let j = i - period + 1;j <= i; j++) {
296
+ sum += prices[j];
297
+ }
298
+ result.push(sum / period);
299
+ }
300
+ return result;
301
+ }
302
+ function ema(prices, period) {
303
+ if (prices.length < period || period <= 0)
304
+ return [];
305
+ const multiplier = 2 / (period + 1);
306
+ const result = [];
307
+ let prevEma = prices.slice(0, period).reduce((a, b) => a + b, 0) / period;
308
+ result.push(prevEma);
309
+ for (let i = period;i < prices.length; i++) {
310
+ const currentEma = (prices[i] - prevEma) * multiplier + prevEma;
311
+ result.push(currentEma);
312
+ prevEma = currentEma;
313
+ }
314
+ return result;
315
+ }
316
+ function rsi(prices, period = 14) {
317
+ if (prices.length < period + 1 || period <= 0)
318
+ return [];
319
+ const gains = [];
320
+ const losses = [];
321
+ for (let i = 1;i < prices.length; i++) {
322
+ const change = prices[i] - prices[i - 1];
323
+ gains.push(change > 0 ? change : 0);
324
+ losses.push(change < 0 ? Math.abs(change) : 0);
325
+ }
326
+ let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
327
+ let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
328
+ const result = [];
329
+ if (avgLoss === 0) {
330
+ result.push(100);
331
+ } else {
332
+ const rs = avgGain / avgLoss;
333
+ result.push(100 - 100 / (1 + rs));
334
+ }
335
+ for (let i = period;i < gains.length; i++) {
336
+ avgGain = (avgGain * (period - 1) + gains[i]) / period;
337
+ avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
338
+ if (avgLoss === 0) {
339
+ result.push(100);
340
+ } else {
341
+ const rs = avgGain / avgLoss;
342
+ result.push(100 - 100 / (1 + rs));
343
+ }
344
+ }
345
+ return result;
346
+ }
347
+ function macd(prices, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
348
+ if (prices.length < slowPeriod) {
349
+ return { macd: [], signal: [], histogram: [] };
350
+ }
351
+ const fastEma = ema(prices, fastPeriod);
352
+ const slowEma = ema(prices, slowPeriod);
353
+ const offset = slowPeriod - fastPeriod;
354
+ const macdLine = [];
355
+ for (let i = 0;i < slowEma.length; i++) {
356
+ if (i + offset < fastEma.length) {
357
+ macdLine.push(fastEma[i + offset] - slowEma[i]);
358
+ }
359
+ }
360
+ const signalLine = ema(macdLine, signalPeriod);
361
+ const signalOffset = signalPeriod - 1;
362
+ const histogram = [];
363
+ for (let i = 0;i < signalLine.length; i++) {
364
+ if (i + signalOffset < macdLine.length) {
365
+ histogram.push(macdLine[i + signalOffset] - signalLine[i]);
366
+ }
367
+ }
368
+ return {
369
+ macd: macdLine.slice(signalOffset, signalOffset + histogram.length),
370
+ signal: signalLine,
371
+ histogram
372
+ };
373
+ }
374
+ function calculateVar(returns, confidenceLevel = 0.95) {
375
+ if (returns.length === 0) {
376
+ return { var: 0, cvar: 0, confidence_level: confidenceLevel };
377
+ }
378
+ const sorted = [...returns].sort((a, b) => a - b);
379
+ const index = Math.floor((1 - confidenceLevel) * returns.length);
380
+ const clampedIndex = Math.min(index, sorted.length - 1);
381
+ const varValue = -sorted[clampedIndex];
382
+ const tailReturns = sorted.slice(0, clampedIndex + 1);
383
+ const cvar = tailReturns.length > 0 ? -tailReturns.reduce((a, b) => a + b, 0) / tailReturns.length : varValue;
384
+ return { var: varValue, cvar, confidence_level: confidenceLevel };
385
+ }
386
+ function calculateDrawdown(equityCurve) {
387
+ if (equityCurve.length < 2) {
388
+ return { max_drawdown: 0, max_duration: 0, current_drawdown: 0, recovery_factor: 0 };
389
+ }
390
+ let maxDrawdown = 0;
391
+ let maxDuration = 0;
392
+ let peak = equityCurve[0];
393
+ let lastPeakIdx = 0;
394
+ for (let i = 0;i < equityCurve.length; i++) {
395
+ const equity = equityCurve[i];
396
+ if (equity > peak) {
397
+ peak = equity;
398
+ lastPeakIdx = i;
399
+ } else {
400
+ const duration = i - lastPeakIdx;
401
+ const drawdown = (peak - equity) / peak;
402
+ if (drawdown > maxDrawdown) {
403
+ maxDrawdown = drawdown;
404
+ maxDuration = duration;
405
+ }
406
+ }
407
+ }
408
+ const currentDrawdown = peak > 0 ? (peak - equityCurve[equityCurve.length - 1]) / peak : 0;
409
+ const totalReturn = equityCurve[0] > 0 ? (equityCurve[equityCurve.length - 1] - equityCurve[0]) / equityCurve[0] : 0;
410
+ const recoveryFactor = maxDrawdown > 0 ? totalReturn / maxDrawdown : Infinity;
411
+ return {
412
+ max_drawdown: maxDrawdown,
413
+ max_duration: maxDuration,
414
+ current_drawdown: currentDrawdown,
415
+ recovery_factor: recoveryFactor
416
+ };
417
+ }
418
+ function calculateSharpeRatio(returns, riskFreeRate = 0.04, periodsPerYear = 252) {
419
+ if (returns.length === 0) {
420
+ return 0;
421
+ }
422
+ const avgReturn = returns.reduce((a, b) => a + b, 0) / returns.length;
423
+ const stdDev2 = Math.sqrt(returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / returns.length);
424
+ if (stdDev2 === 0) {
425
+ return 0;
426
+ }
427
+ const excessReturn = avgReturn - riskFreeRate / periodsPerYear;
428
+ const sharpeRatio = excessReturn / stdDev2;
429
+ const annualizedSharpe = sharpeRatio * Math.sqrt(periodsPerYear);
430
+ return annualizedSharpe;
431
+ }
432
+ function calculateSharpeRatioFull(returns, riskFreeRate = 0.04, periodsPerYear = 252) {
433
+ if (returns.length === 0) {
434
+ return { sharpe_ratio: 0, annualized_sharpe: 0, risk_free_rate: riskFreeRate, avg_return: 0, std_dev: 0 };
435
+ }
436
+ const avgReturn = returns.reduce((a, b) => a + b, 0) / returns.length;
437
+ const stdDev2 = Math.sqrt(returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / returns.length);
438
+ if (stdDev2 === 0) {
439
+ return { sharpe_ratio: 0, annualized_sharpe: 0, risk_free_rate: riskFreeRate, avg_return: avgReturn, std_dev: 0 };
440
+ }
441
+ const excessReturn = avgReturn - riskFreeRate / periodsPerYear;
442
+ const sharpeRatio = excessReturn / stdDev2;
443
+ const annualizedSharpe = sharpeRatio * Math.sqrt(periodsPerYear);
444
+ return {
445
+ sharpe_ratio: sharpeRatio,
446
+ annualized_sharpe: annualizedSharpe,
447
+ risk_free_rate: riskFreeRate,
448
+ avg_return: avgReturn,
449
+ std_dev: stdDev2
450
+ };
451
+ }
452
+ var calculate_var = calculateVar;
453
+ var calculate_drawdown = calculateDrawdown;
454
+ var calculate_sharpe_ratio = calculateSharpeRatio;
455
+ var sharpeRatio = calculateSharpeRatio;
456
+ function calculateSortinoRatio(returns, riskFreeRate = 0.04, periodsPerYear = 252) {
457
+ if (returns.length === 0)
458
+ return 0;
459
+ const avgReturn = returns.reduce((a, b) => a + b, 0) / returns.length;
460
+ const target = riskFreeRate / periodsPerYear;
461
+ const downsideReturns = returns.filter((r) => r < target);
462
+ const downsideVariance = downsideReturns.length > 0 ? downsideReturns.reduce((sum, r) => sum + Math.pow(r - target, 2), 0) / returns.length : 0;
463
+ const downsideDev = Math.sqrt(downsideVariance);
464
+ if (downsideDev === 0)
465
+ return Infinity;
466
+ const excessReturn = avgReturn - target;
467
+ return excessReturn / downsideDev * Math.sqrt(periodsPerYear);
468
+ }
469
+ function calculateBetaAlpha(assetReturns, benchmarkReturns) {
470
+ if (assetReturns.length === 0 || benchmarkReturns.length === 0 || assetReturns.length !== benchmarkReturns.length) {
471
+ return { beta: 0, alpha: 0 };
472
+ }
473
+ const n = assetReturns.length;
474
+ const avgAsset = assetReturns.reduce((a, b) => a + b, 0) / n;
475
+ const avgBench = benchmarkReturns.reduce((a, b) => a + b, 0) / n;
476
+ const cov = assetReturns.reduce((sum, a, i) => sum + (a - avgAsset) * (benchmarkReturns[i] - avgBench), 0) / n;
477
+ const varBench = benchmarkReturns.reduce((sum, r) => sum + Math.pow(r - avgBench, 2), 0) / n;
478
+ if (varBench === 0)
479
+ return { beta: 0, alpha: 0 };
480
+ const beta = cov / varBench;
481
+ const alpha = avgAsset - beta * avgBench;
482
+ return { beta, alpha };
483
+ }
484
+ var calculate_sortino_ratio = calculateSortinoRatio;
485
+ var calculate_beta_alpha = calculateBetaAlpha;
486
+ var src_default = {
487
+ getVersion,
488
+ clearError,
489
+ getLibraryPath,
490
+ createOHLCV,
491
+ createAMM,
492
+ ammCalculateCost,
493
+ ammCalculateCostFull,
494
+ ammPriceImpact,
495
+ amm_buy_cost,
496
+ amm_calculate_cost,
497
+ amm_price_impact,
498
+ lmsrPrice,
499
+ lmsrCost,
500
+ lmsrCalculate,
501
+ kellyCriterion,
502
+ kelly_criterion,
503
+ detectArbitrage,
504
+ detect_arbitrage,
505
+ convertOdds,
506
+ convert_odds,
507
+ mean,
508
+ stdDev,
509
+ std_dev,
510
+ variance,
511
+ correlation,
512
+ sma,
513
+ ema,
514
+ rsi,
515
+ macd,
516
+ calculateVar,
517
+ calculate_var,
518
+ calculateDrawdown,
519
+ calculate_drawdown,
520
+ calculateSharpeRatio,
521
+ calculateSharpeRatioFull,
522
+ calculate_sharpe_ratio,
523
+ sharpeRatio,
524
+ calculateSortinoRatio,
525
+ calculate_sortino_ratio,
526
+ calculateBetaAlpha,
527
+ calculate_beta_alpha
528
+ };
529
+ export {
530
+ variance,
531
+ std_dev,
532
+ stdDev,
533
+ sma,
534
+ sharpeRatio,
535
+ rsi,
536
+ positionSizeFixedFractional,
537
+ mean,
538
+ macd,
539
+ lmsrPrice,
540
+ lmsrCost,
541
+ lmsrCalculate,
542
+ kelly_criterion,
543
+ kellyCriterion,
544
+ getVersion,
545
+ getLibraryPath,
546
+ ema,
547
+ detect_arbitrage,
548
+ detectArbitrage,
549
+ src_default as default,
550
+ createOHLCV,
551
+ createAMM,
552
+ correlation,
553
+ convert_odds,
554
+ convertOdds,
555
+ clearError,
556
+ calculate_var,
557
+ calculate_sortino_ratio,
558
+ calculate_sharpe_ratio,
559
+ calculate_drawdown,
560
+ calculate_beta_alpha,
561
+ calculateVar,
562
+ calculateSortinoRatio,
563
+ calculateSharpeRatioFull,
564
+ calculateSharpeRatio,
565
+ calculateEdge,
566
+ calculateDrawdown,
567
+ calculateBetaAlpha,
568
+ amm_price_impact,
569
+ amm_calculate_cost,
570
+ amm_buy_cost,
571
+ ammPriceImpact,
572
+ ammCalculateCostFull,
573
+ ammCalculateCost,
574
+ Signal,
575
+ CandlePattern
576
+ };