garch 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -22
- package/build/index.cjs +86 -20
- package/build/index.mjs +86 -21
- package/package.json +48 -48
- package/types.d.ts +21 -8
package/README.md
CHANGED
|
@@ -16,9 +16,11 @@ npm install garch
|
|
|
16
16
|
|
|
17
17
|
## API
|
|
18
18
|
|
|
19
|
-
### `predict(candles, interval, currentPrice?)`
|
|
19
|
+
### `predict(candles, interval, currentPrice?, confidence?)`
|
|
20
20
|
|
|
21
|
-
Forecast expected price range for the next candle (t+1). Auto-selects the best model (GARCH, EGARCH, GJR-GARCH, HAR-RV or NoVaS) by QLIKE forecast-error comparison.
|
|
21
|
+
Forecast expected price range for the next candle (t+1). Auto-selects the best model (GARCH, EGARCH, GJR-GARCH, HAR-RV or NoVaS) by QLIKE forecast-error comparison.
|
|
22
|
+
|
|
23
|
+
Uses **log-normal price bands**: `P·exp(±z·σ)`, where `z = probit(confidence)`. This correctly maps log-return volatility back to price space — the corridor is asymmetric (upside > downside in absolute terms) and `lowerPrice` can never go negative.
|
|
22
24
|
|
|
23
25
|
```typescript
|
|
24
26
|
import { predict } from 'garch';
|
|
@@ -26,21 +28,50 @@ import type { Candle } from 'garch';
|
|
|
26
28
|
|
|
27
29
|
const candles: Candle[] = await fetchCandles('BTCUSDT', '4h', 200);
|
|
28
30
|
|
|
31
|
+
// Default: ±1σ band (~68% coverage)
|
|
29
32
|
const result = predict(candles, '4h');
|
|
30
33
|
// {
|
|
31
34
|
// currentPrice: 97500,
|
|
32
|
-
// sigma: 0.012, // 1.2%
|
|
33
|
-
// move:
|
|
34
|
-
// upperPrice:
|
|
35
|
-
// lowerPrice:
|
|
35
|
+
// sigma: 0.012, // 1.2% per-period volatility
|
|
36
|
+
// move: 1177, // upward expected move (upper - current)
|
|
37
|
+
// upperPrice: 98677, // P·exp(+σ) — ceiling
|
|
38
|
+
// lowerPrice: 96337, // P·exp(-σ) — floor
|
|
36
39
|
// modelType: 'egarch',
|
|
37
40
|
// reliable: true
|
|
38
41
|
// }
|
|
39
42
|
|
|
40
|
-
//
|
|
43
|
+
// 95% VaR band (z ≈ 1.96)
|
|
44
|
+
const var95 = predict(candles, '4h', undefined, 0.95);
|
|
45
|
+
|
|
46
|
+
// Custom reference price (e.g. VWAP)
|
|
41
47
|
const result = predict(candles, '4h', vwap);
|
|
42
48
|
```
|
|
43
49
|
|
|
50
|
+
**Confidence → z mapping:**
|
|
51
|
+
|
|
52
|
+
| `confidence` | z-score | Meaning |
|
|
53
|
+
|-------------|---------|---------|
|
|
54
|
+
| 0.6827 (default) | 1.00 | ±1σ, ~68% of moves captured |
|
|
55
|
+
| 0.90 | 1.645 | Moderate VaR |
|
|
56
|
+
| 0.95 | 1.96 | 95% VaR (standard) |
|
|
57
|
+
| 0.99 | 2.576 | Conservative VaR |
|
|
58
|
+
|
|
59
|
+
Any value in (0, 1) is valid — the table above lists common choices, but `probit` computes z for arbitrary confidence.
|
|
60
|
+
|
|
61
|
+
Higher confidence = wider corridor. `sigma` stays the same (it's the model's volatility estimate), only the z-multiplier changes. Example with sigma=1.2% and P=$97,500:
|
|
62
|
+
|
|
63
|
+
| `confidence` | z | upperPrice | lowerPrice | Corridor width |
|
|
64
|
+
|-------------|---|-----------|-----------|----------------|
|
|
65
|
+
| 0.6827 | 1.00 | $98,677 | $96,337 | $2,340 |
|
|
66
|
+
| 0.95 | 1.96 | $99,808 | $95,222 | $4,586 |
|
|
67
|
+
| 0.99 | 2.58 | $100,545 | $94,520 | $6,025 |
|
|
68
|
+
|
|
69
|
+
**When to use which:**
|
|
70
|
+
|
|
71
|
+
- **±1σ (default)** — typical expected move for the next candle. Good for scalping SL/TP targets and assessing whether a move is "normal" or significant
|
|
72
|
+
- **95% VaR** — worst reasonable scenario. Good for risk management, position sizing, and stop-losses that shouldn't be triggered by noise
|
|
73
|
+
- **99% VaR** — extreme tail risk. Good for stress testing and margin calculations
|
|
74
|
+
|
|
44
75
|
**Parameters:**
|
|
45
76
|
|
|
46
77
|
| Parameter | Type | Default | Description |
|
|
@@ -48,6 +79,7 @@ const result = predict(candles, '4h', vwap);
|
|
|
48
79
|
| `candles` | `Candle[]` | required | OHLCV candle data |
|
|
49
80
|
| `interval` | `CandleInterval` | required | Candle timeframe |
|
|
50
81
|
| `currentPrice` | `number` | last close | Reference price to center the corridor |
|
|
82
|
+
| `confidence` | `number` | `0.6827` | Two-sided probability in (0,1). Controls band width via `z = probit(confidence)` |
|
|
51
83
|
|
|
52
84
|
**Returns:** `PredictionResult`
|
|
53
85
|
|
|
@@ -55,9 +87,9 @@ const result = predict(candles, '4h', vwap);
|
|
|
55
87
|
interface PredictionResult {
|
|
56
88
|
currentPrice: number; // Reference price
|
|
57
89
|
sigma: number; // One-period volatility (decimal, e.g. 0.012 = 1.2%)
|
|
58
|
-
move: number; //
|
|
59
|
-
upperPrice: number; //
|
|
60
|
-
lowerPrice: number; //
|
|
90
|
+
move: number; // Upward price move = upperPrice - currentPrice
|
|
91
|
+
upperPrice: number; // P · exp(+z·σ)
|
|
92
|
+
lowerPrice: number; // P · exp(-z·σ)
|
|
61
93
|
modelType: 'garch' | 'egarch' | 'gjr-garch' | 'har-rv' | 'novas'; // Auto-selected model
|
|
62
94
|
reliable: boolean; // Quality flag (convergence + persistence + Ljung-Box)
|
|
63
95
|
}
|
|
@@ -65,9 +97,9 @@ interface PredictionResult {
|
|
|
65
97
|
|
|
66
98
|
---
|
|
67
99
|
|
|
68
|
-
### `predictRange(candles, interval, steps, currentPrice?)`
|
|
100
|
+
### `predictRange(candles, interval, steps, currentPrice?, confidence?)`
|
|
69
101
|
|
|
70
|
-
Forecast cumulative expected price range over multiple candles. Cumulative sigma = sqrt(sigma_1^2 + sigma_2^2 + ... + sigma_n^2). Use for swing trades where you hold across multiple periods.
|
|
102
|
+
Forecast cumulative expected price range over multiple candles. Cumulative sigma = sqrt(sigma_1^2 + sigma_2^2 + ... + sigma_n^2). Uses the same log-normal bands as `predict`. Use for swing trades where you hold across multiple periods.
|
|
71
103
|
|
|
72
104
|
```typescript
|
|
73
105
|
import { predictRange } from 'garch';
|
|
@@ -76,12 +108,15 @@ const range = predictRange(candles, '4h', 5);
|
|
|
76
108
|
// {
|
|
77
109
|
// currentPrice: 97500,
|
|
78
110
|
// sigma: 0.027, // cumulative ~2.7% over 5 candles
|
|
79
|
-
// move:
|
|
80
|
-
// upperPrice:
|
|
81
|
-
// lowerPrice:
|
|
111
|
+
// move: 2669, // upward expected move
|
|
112
|
+
// upperPrice: 100169, // P·exp(+z·σ)
|
|
113
|
+
// lowerPrice: 94901, // P·exp(-z·σ)
|
|
82
114
|
// modelType: 'egarch',
|
|
83
115
|
// reliable: true
|
|
84
116
|
// }
|
|
117
|
+
|
|
118
|
+
// 95% VaR over 5 candles
|
|
119
|
+
const var95 = predictRange(candles, '4h', 5, undefined, 0.95);
|
|
85
120
|
```
|
|
86
121
|
|
|
87
122
|
**Parameters:**
|
|
@@ -92,20 +127,25 @@ const range = predictRange(candles, '4h', 5);
|
|
|
92
127
|
| `interval` | `CandleInterval` | required | Candle timeframe |
|
|
93
128
|
| `steps` | `number` | required | Number of candles to forecast over |
|
|
94
129
|
| `currentPrice` | `number` | last close | Reference price |
|
|
130
|
+
| `confidence` | `number` | `0.6827` | Two-sided probability in (0,1) |
|
|
95
131
|
|
|
96
132
|
**Returns:** `PredictionResult` (same structure as `predict`)
|
|
97
133
|
|
|
98
134
|
---
|
|
99
135
|
|
|
100
|
-
### `backtest(candles, interval, requiredPercent?)`
|
|
136
|
+
### `backtest(candles, interval, confidence?, requiredPercent?)`
|
|
101
137
|
|
|
102
|
-
Walk-forward validation of `predict`. Uses 75% of candles for fitting, 25% for testing. Checks if the model's
|
|
138
|
+
Walk-forward validation of `predict`. Uses 75% of candles for fitting, 25% for testing. Checks if the model's price corridor captures actual price moves at the required hit rate.
|
|
139
|
+
|
|
140
|
+
`confidence` and `requiredPercent` are independent: `confidence` controls the **band width** (via `probit`), `requiredPercent` controls the **pass/fail threshold**.
|
|
103
141
|
|
|
104
142
|
```typescript
|
|
105
143
|
import { backtest } from 'garch';
|
|
106
144
|
|
|
107
|
-
backtest(candles, '4h');
|
|
108
|
-
backtest(candles, '4h',
|
|
145
|
+
backtest(candles, '4h'); // ±1σ band, hit rate >= 68%
|
|
146
|
+
backtest(candles, '4h', 0.95); // 95% VaR band, hit rate >= 68%
|
|
147
|
+
backtest(candles, '4h', 0.95, 90); // 95% VaR band, hit rate >= 90%
|
|
148
|
+
backtest(candles, '4h', undefined, 50); // ±1σ band, hit rate >= 50%
|
|
109
149
|
```
|
|
110
150
|
|
|
111
151
|
**Parameters:**
|
|
@@ -114,7 +154,8 @@ backtest(candles, '4h', 50); // true -- hit rate >= 50% (custom)
|
|
|
114
154
|
|-----------|------|---------|-------------|
|
|
115
155
|
| `candles` | `Candle[]` | required | OHLCV candle data |
|
|
116
156
|
| `interval` | `CandleInterval` | required | Candle timeframe |
|
|
117
|
-
| `
|
|
157
|
+
| `confidence` | `number` | `0.6827` | Two-sided probability in (0,1) for the prediction band |
|
|
158
|
+
| `requiredPercent` | `number` | `68` | Minimum hit rate (0–100) to pass |
|
|
118
159
|
|
|
119
160
|
**Returns:** `boolean`
|
|
120
161
|
|
|
@@ -402,6 +443,69 @@ sigma^2_GK = (1/n) * sum[ 0.5 * ln(H/L)^2 - (2*ln2 - 1) * ln(C/O)^2 ]
|
|
|
402
443
|
|
|
403
444
|
~5x more efficient than close-to-close variance.
|
|
404
445
|
|
|
446
|
+
### Log-Normal Price Bands
|
|
447
|
+
|
|
448
|
+
GARCH models volatility of **log-returns**, not absolute price changes. The correct mapping from log-return volatility back to price space uses the exponential:
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
upperPrice = P · exp(+z · sigma)
|
|
452
|
+
lowerPrice = P · exp(-z · sigma)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
where `z = probit(confidence)` is the z-score corresponding to the desired two-sided confidence level. This produces **asymmetric** bands (upside > downside in absolute terms) and guarantees `lowerPrice > 0`.
|
|
456
|
+
|
|
457
|
+
The previous linear approximation `P · (1 ± sigma)` is a first-order Taylor expansion of `exp(±sigma)`. The difference grows with sigma:
|
|
458
|
+
|
|
459
|
+
| sigma | Linear `1 + sigma` | Exact `exp(sigma)` | Error |
|
|
460
|
+
|-------|--------------------|--------------------|-------|
|
|
461
|
+
| 0.02 | 1.0200 | 1.0202 | ~0.01% |
|
|
462
|
+
| 0.10 | 1.1000 | 1.1052 | ~0.5% |
|
|
463
|
+
| 0.30 | 1.3000 | 1.3499 | ~3.8% |
|
|
464
|
+
|
|
465
|
+
### Probit (Inverse Normal CDF)
|
|
466
|
+
|
|
467
|
+
`probit(confidence)` computes the inverse of the standard normal CDF (Phi^{-1}). It converts a two-sided probability to a z-score:
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
confidence = P(-z < Z < z), Z ~ N(0,1)
|
|
471
|
+
z = probit(confidence)
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
There is no closed-form solution for Phi^{-1} — it is a transcendental equation. The implementation uses **Acklam's rational approximation** (Peter J. Acklam, 2002) with max relative error < 1.15 x 10^{-9}.
|
|
475
|
+
|
|
476
|
+
**Step 1** — convert two-sided confidence to upper-tail probability:
|
|
477
|
+
|
|
478
|
+
```
|
|
479
|
+
p = (1 + confidence) / 2
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Step 2** — piecewise rational approximation over three regions:
|
|
483
|
+
|
|
484
|
+
**Central region** (0.02425 <= p <= 0.97575) — covers ~95% of inputs:
|
|
485
|
+
|
|
486
|
+
```
|
|
487
|
+
q = p - 0.5
|
|
488
|
+
r = q^2
|
|
489
|
+
z = (a1·r^5 + a2·r^4 + a3·r^3 + a4·r^2 + a5·r + a6) · q
|
|
490
|
+
/ (b1·r^5 + b2·r^4 + b3·r^3 + b4·r^2 + b5·r + 1)
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**Tails** (p < 0.02425 or p > 0.97575):
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
q = sqrt(-2·ln(p)) // left tail
|
|
497
|
+
z = (c1·q^5 + ... + c6) / (d1·q^4 + ... + 1)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
For the right tail: `q = sqrt(-2·ln(1-p))`, result is negated. The 16 coefficients (a1–a6, b1–b5, c1–c6, d1–d4) are minimax-optimal rational approximation constants.
|
|
501
|
+
|
|
502
|
+
| `confidence` | `p` | `z` | Meaning |
|
|
503
|
+
|-------------|-----|-----|---------|
|
|
504
|
+
| 0.6827 | 0.8413 | 1.000 | ±1 sigma (default) |
|
|
505
|
+
| 0.90 | 0.9500 | 1.645 | Moderate VaR |
|
|
506
|
+
| 0.95 | 0.9750 | 1.960 | 95% VaR |
|
|
507
|
+
| 0.99 | 0.9950 | 2.576 | Conservative VaR |
|
|
508
|
+
|
|
405
509
|
### Student-t Log-Likelihood
|
|
406
510
|
|
|
407
511
|
All five models use a **Student-t** distribution for log-likelihood computation. Financial return series exhibit fat tails (excess kurtosis), and the Student-t captures this with an additional **degrees of freedom (df)** parameter:
|
|
@@ -452,13 +556,13 @@ where RV_t is Parkinson per-candle realized variance and sigma_t^2 is the model'
|
|
|
452
556
|
|
|
453
557
|
## Tests
|
|
454
558
|
|
|
455
|
-
**
|
|
559
|
+
**932 tests** across **22 test files**. All passing.
|
|
456
560
|
|
|
457
561
|
| Category | Files | Tests | What's covered |
|
|
458
562
|
|----------|-------|-------|----------------|
|
|
459
563
|
| Mathematical formulas | `math.test.ts` | 45 | GARCH/EGARCH variance recursion, log-likelihood, forecast formulas, AIC/BIC, QLIKE, Yang-Zhang, Garman-Klass, Ljung-Box, chi-squared |
|
|
460
564
|
| Math coverage | `math-coverage.test.ts` | 79 | Parkinson formula verification, rv↔returns alignment, H=L fallback, Parkinson-based forecast, candle validation, reliable flag cascade, backtest validity, numerical precision, cross-model consistency, Realized GARCH/EGARCH/GJR-GARCH Candle[] vs number[], perCandleParkinson shared function |
|
|
461
|
-
| Full pipeline coverage | `plan-coverage.test.ts` |
|
|
565
|
+
| Full pipeline coverage | `plan-coverage.test.ts` | 82 | End-to-end: fit, forecast, predict, predictRange, backtest, model selection |
|
|
462
566
|
| GARCH unit | `garch.test.ts` | 10 | Parameter estimation, variance series, forecast convergence, candle vs price input |
|
|
463
567
|
| EGARCH unit | `egarch.test.ts` | 11 | Leverage detection, asymmetric volatility, model comparison |
|
|
464
568
|
| GJR-GARCH unit | `gjr-garch.test.ts` | 86 | Variance recursion (r² and Parkinson), indicator function I(r<0), forecast formula (one-step + multi-step), constraint barriers, computed fields, AIC/BIC numParams=5, estimation properties (perturbation, determinism), numerical stability, degenerate params, Realized path (Candle[] vs number[], flat candles, bad OHLC), options forwarding, immutability, instance isolation, cross-model consistency, scale invariance, property-based fuzz, predict/predictRange/backtest integration |
|
package/build/index.cjs
CHANGED
|
@@ -454,6 +454,61 @@ function qlike(varianceSeries, rv) {
|
|
|
454
454
|
}
|
|
455
455
|
return count > 0 ? sum / count : Infinity;
|
|
456
456
|
}
|
|
457
|
+
/**
|
|
458
|
+
* Inverse standard normal CDF (probit function).
|
|
459
|
+
* Converts a two-sided confidence level (e.g. 0.95) to the corresponding
|
|
460
|
+
* z-score (e.g. 1.96).
|
|
461
|
+
*
|
|
462
|
+
* Uses Acklam's rational approximation (max relative error < 1.15e-9).
|
|
463
|
+
*/
|
|
464
|
+
function probit(confidence) {
|
|
465
|
+
if (confidence <= 0 || confidence >= 1) {
|
|
466
|
+
throw new Error(`confidence must be in (0, 1), got ${confidence}`);
|
|
467
|
+
}
|
|
468
|
+
// Convert two-sided confidence to upper-tail probability
|
|
469
|
+
const p = (1 + confidence) / 2;
|
|
470
|
+
// Acklam's inverse normal approximation
|
|
471
|
+
const a1 = -39.69683028665376;
|
|
472
|
+
const a2 = 2.209460984245205e+02;
|
|
473
|
+
const a3 = -275.9285104469687;
|
|
474
|
+
const a4 = 1.383577518672690e+02;
|
|
475
|
+
const a5 = -30.66479806614716;
|
|
476
|
+
const a6 = 2.506628277459239e+00;
|
|
477
|
+
const b1 = -54.47609879822406;
|
|
478
|
+
const b2 = 1.615858368580409e+02;
|
|
479
|
+
const b3 = -155.6989798598866;
|
|
480
|
+
const b4 = 6.680131188771972e+01;
|
|
481
|
+
const b5 = -13.28068155288572;
|
|
482
|
+
const c1 = -0.007784894002430293;
|
|
483
|
+
const c2 = -0.3223964580411365;
|
|
484
|
+
const c3 = -2.400758277161838;
|
|
485
|
+
const c4 = -2.549732539343734;
|
|
486
|
+
const c5 = 4.374664141464968e+00;
|
|
487
|
+
const c6 = 2.938163982698783e+00;
|
|
488
|
+
const d1 = 7.784695709041462e-03;
|
|
489
|
+
const d2 = 3.224671290700398e-01;
|
|
490
|
+
const d3 = 2.445134137142996e+00;
|
|
491
|
+
const d4 = 3.754408661907416e+00;
|
|
492
|
+
const pLow = 0.02425;
|
|
493
|
+
const pHigh = 1 - pLow;
|
|
494
|
+
let q, r;
|
|
495
|
+
if (p < pLow) {
|
|
496
|
+
q = Math.sqrt(-2 * Math.log(p));
|
|
497
|
+
return (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
|
|
498
|
+
((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
|
|
499
|
+
}
|
|
500
|
+
else if (p <= pHigh) {
|
|
501
|
+
q = p - 0.5;
|
|
502
|
+
r = q * q;
|
|
503
|
+
return (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q /
|
|
504
|
+
(((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1);
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
q = Math.sqrt(-2 * Math.log(1 - p));
|
|
508
|
+
return -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
|
|
509
|
+
((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
457
512
|
|
|
458
513
|
/**
|
|
459
514
|
* GARCH(1,1) model
|
|
@@ -1594,9 +1649,7 @@ function assertMinCandles(candles, interval) {
|
|
|
1594
1649
|
}
|
|
1595
1650
|
}
|
|
1596
1651
|
const recommended = RECOMMENDED_CANDLES[interval];
|
|
1597
|
-
if (candles.length < recommended)
|
|
1598
|
-
console.warn(`[garch] ${interval}: ${candles.length} candles provided, recommend ≥${recommended} for reliable results. Check reliable: true in output.`);
|
|
1599
|
-
}
|
|
1652
|
+
if (candles.length < recommended) ;
|
|
1600
1653
|
}
|
|
1601
1654
|
function fitGarchFamily(candles, periodsPerYear, steps) {
|
|
1602
1655
|
// Fit all three GARCH-family models and pick the best by AIC
|
|
@@ -1722,21 +1775,25 @@ function checkReliable(fit) {
|
|
|
1722
1775
|
/**
|
|
1723
1776
|
* Forecast expected price range for t+1 (next candle).
|
|
1724
1777
|
*
|
|
1725
|
-
* Auto-selects
|
|
1726
|
-
*
|
|
1778
|
+
* Auto-selects the best volatility model via QLIKE.
|
|
1779
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
1780
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
1781
|
+
* Common values: 0.90 → z=1.645, 0.95 → z=1.96, 0.99 → z=2.576.
|
|
1727
1782
|
*/
|
|
1728
|
-
function predict(candles, interval, currentPrice = candles[candles.length - 1].close) {
|
|
1783
|
+
function predict(candles, interval, currentPrice = candles[candles.length - 1].close, confidence = 0.6827) {
|
|
1729
1784
|
assertMinCandles(candles, interval);
|
|
1785
|
+
const z = probit(confidence);
|
|
1730
1786
|
const fit = fitModel(candles, INTERVALS_PER_YEAR[interval], 1);
|
|
1731
1787
|
const sigma = fit.forecast.volatility[0];
|
|
1732
|
-
const
|
|
1788
|
+
const upperPrice = currentPrice * Math.exp(z * sigma);
|
|
1789
|
+
const lowerPrice = currentPrice * Math.exp(-z * sigma);
|
|
1733
1790
|
return {
|
|
1734
1791
|
modelType: fit.modelType,
|
|
1735
1792
|
currentPrice,
|
|
1736
1793
|
sigma,
|
|
1737
|
-
move,
|
|
1738
|
-
upperPrice
|
|
1739
|
-
lowerPrice
|
|
1794
|
+
move: upperPrice - currentPrice,
|
|
1795
|
+
upperPrice,
|
|
1796
|
+
lowerPrice,
|
|
1740
1797
|
reliable: checkReliable(fit),
|
|
1741
1798
|
};
|
|
1742
1799
|
}
|
|
@@ -1744,26 +1801,28 @@ function predict(candles, interval, currentPrice = candles[candles.length - 1].c
|
|
|
1744
1801
|
* Forecast expected price range over multiple candles.
|
|
1745
1802
|
*
|
|
1746
1803
|
* Cumulative σ = √(σ₁² + σ₂² + ... + σₙ²) — total expected move over N periods.
|
|
1747
|
-
*
|
|
1804
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
1805
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
1748
1806
|
*/
|
|
1749
|
-
function predictRange(candles, interval, steps, currentPrice = candles[candles.length - 1].close) {
|
|
1807
|
+
function predictRange(candles, interval, steps, currentPrice = candles[candles.length - 1].close, confidence = 0.6827) {
|
|
1750
1808
|
assertMinCandles(candles, interval);
|
|
1809
|
+
const z = probit(confidence);
|
|
1751
1810
|
const fit = fitModel(candles, INTERVALS_PER_YEAR[interval], steps);
|
|
1752
1811
|
const cumulativeVariance = fit.forecast.variance.reduce((sum, v) => sum + v, 0);
|
|
1753
1812
|
const sigma = Math.sqrt(cumulativeVariance);
|
|
1754
|
-
const
|
|
1813
|
+
const upperPrice = currentPrice * Math.exp(z * sigma);
|
|
1814
|
+
const lowerPrice = currentPrice * Math.exp(-z * sigma);
|
|
1755
1815
|
return {
|
|
1756
1816
|
modelType: fit.modelType,
|
|
1757
1817
|
currentPrice,
|
|
1758
1818
|
sigma,
|
|
1759
|
-
move,
|
|
1760
|
-
upperPrice
|
|
1761
|
-
lowerPrice
|
|
1819
|
+
move: upperPrice - currentPrice,
|
|
1820
|
+
upperPrice,
|
|
1821
|
+
lowerPrice,
|
|
1762
1822
|
reliable: checkReliable(fit),
|
|
1763
1823
|
};
|
|
1764
1824
|
}
|
|
1765
1825
|
// ── Backtest ──────────────────────────────────────────────────
|
|
1766
|
-
const BACKTEST_REQUIRED_PERCENT = 68;
|
|
1767
1826
|
const BACKTEST_WINDOW_RATIO = 0.75;
|
|
1768
1827
|
/**
|
|
1769
1828
|
* Walk-forward backtest of predict.
|
|
@@ -1771,16 +1830,22 @@ const BACKTEST_WINDOW_RATIO = 0.75;
|
|
|
1771
1830
|
* Window is computed automatically: 75% of candles for fitting, 25% for testing.
|
|
1772
1831
|
* Throws if not enough candles for the given interval.
|
|
1773
1832
|
* Returns true if the model's hit rate meets the required threshold.
|
|
1774
|
-
*
|
|
1833
|
+
* @param confidence — two-sided probability in (0,1) for the prediction band.
|
|
1834
|
+
* Default ≈0.6827 (±1σ).
|
|
1835
|
+
* @param requiredPercent — minimum hit rate (0–100) to pass. Default 68.
|
|
1775
1836
|
*/
|
|
1776
|
-
function backtest(candles, interval, requiredPercent =
|
|
1837
|
+
function backtest(candles, interval, confidence = 0.6827, requiredPercent = 68) {
|
|
1777
1838
|
assertMinCandles(candles, interval);
|
|
1839
|
+
if (requiredPercent <= 0)
|
|
1840
|
+
return true;
|
|
1841
|
+
if (requiredPercent >= 100)
|
|
1842
|
+
return false;
|
|
1778
1843
|
const window = Math.max(MIN_CANDLES[interval], Math.floor(candles.length * BACKTEST_WINDOW_RATIO));
|
|
1779
1844
|
let hits = 0;
|
|
1780
1845
|
let total = 0;
|
|
1781
1846
|
for (let i = window; i < candles.length - 1; i++) {
|
|
1782
1847
|
const slice = candles.slice(i - window, i + 1);
|
|
1783
|
-
const predicted = predict(slice, interval);
|
|
1848
|
+
const predicted = predict(slice, interval, slice[slice.length - 1].close, confidence);
|
|
1784
1849
|
const actual = candles[i + 1].close;
|
|
1785
1850
|
if (actual >= predicted.lowerPrice && actual <= predicted.upperPrice) {
|
|
1786
1851
|
hits++;
|
|
@@ -1814,6 +1879,7 @@ exports.nelderMeadMultiStart = nelderMeadMultiStart;
|
|
|
1814
1879
|
exports.perCandleParkinson = perCandleParkinson;
|
|
1815
1880
|
exports.predict = predict;
|
|
1816
1881
|
exports.predictRange = predictRange;
|
|
1882
|
+
exports.probit = probit;
|
|
1817
1883
|
exports.profileStudentTDf = profileStudentTDf;
|
|
1818
1884
|
exports.qlike = qlike;
|
|
1819
1885
|
exports.sampleVariance = sampleVariance;
|
package/build/index.mjs
CHANGED
|
@@ -452,6 +452,61 @@ function qlike(varianceSeries, rv) {
|
|
|
452
452
|
}
|
|
453
453
|
return count > 0 ? sum / count : Infinity;
|
|
454
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Inverse standard normal CDF (probit function).
|
|
457
|
+
* Converts a two-sided confidence level (e.g. 0.95) to the corresponding
|
|
458
|
+
* z-score (e.g. 1.96).
|
|
459
|
+
*
|
|
460
|
+
* Uses Acklam's rational approximation (max relative error < 1.15e-9).
|
|
461
|
+
*/
|
|
462
|
+
function probit(confidence) {
|
|
463
|
+
if (confidence <= 0 || confidence >= 1) {
|
|
464
|
+
throw new Error(`confidence must be in (0, 1), got ${confidence}`);
|
|
465
|
+
}
|
|
466
|
+
// Convert two-sided confidence to upper-tail probability
|
|
467
|
+
const p = (1 + confidence) / 2;
|
|
468
|
+
// Acklam's inverse normal approximation
|
|
469
|
+
const a1 = -39.69683028665376;
|
|
470
|
+
const a2 = 2.209460984245205e+02;
|
|
471
|
+
const a3 = -275.9285104469687;
|
|
472
|
+
const a4 = 1.383577518672690e+02;
|
|
473
|
+
const a5 = -30.66479806614716;
|
|
474
|
+
const a6 = 2.506628277459239e+00;
|
|
475
|
+
const b1 = -54.47609879822406;
|
|
476
|
+
const b2 = 1.615858368580409e+02;
|
|
477
|
+
const b3 = -155.6989798598866;
|
|
478
|
+
const b4 = 6.680131188771972e+01;
|
|
479
|
+
const b5 = -13.28068155288572;
|
|
480
|
+
const c1 = -0.007784894002430293;
|
|
481
|
+
const c2 = -0.3223964580411365;
|
|
482
|
+
const c3 = -2.400758277161838;
|
|
483
|
+
const c4 = -2.549732539343734;
|
|
484
|
+
const c5 = 4.374664141464968e+00;
|
|
485
|
+
const c6 = 2.938163982698783e+00;
|
|
486
|
+
const d1 = 7.784695709041462e-03;
|
|
487
|
+
const d2 = 3.224671290700398e-01;
|
|
488
|
+
const d3 = 2.445134137142996e+00;
|
|
489
|
+
const d4 = 3.754408661907416e+00;
|
|
490
|
+
const pLow = 0.02425;
|
|
491
|
+
const pHigh = 1 - pLow;
|
|
492
|
+
let q, r;
|
|
493
|
+
if (p < pLow) {
|
|
494
|
+
q = Math.sqrt(-2 * Math.log(p));
|
|
495
|
+
return (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
|
|
496
|
+
((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
|
|
497
|
+
}
|
|
498
|
+
else if (p <= pHigh) {
|
|
499
|
+
q = p - 0.5;
|
|
500
|
+
r = q * q;
|
|
501
|
+
return (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q /
|
|
502
|
+
(((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
q = Math.sqrt(-2 * Math.log(1 - p));
|
|
506
|
+
return -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
|
|
507
|
+
((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
455
510
|
|
|
456
511
|
/**
|
|
457
512
|
* GARCH(1,1) model
|
|
@@ -1592,9 +1647,7 @@ function assertMinCandles(candles, interval) {
|
|
|
1592
1647
|
}
|
|
1593
1648
|
}
|
|
1594
1649
|
const recommended = RECOMMENDED_CANDLES[interval];
|
|
1595
|
-
if (candles.length < recommended)
|
|
1596
|
-
console.warn(`[garch] ${interval}: ${candles.length} candles provided, recommend ≥${recommended} for reliable results. Check reliable: true in output.`);
|
|
1597
|
-
}
|
|
1650
|
+
if (candles.length < recommended) ;
|
|
1598
1651
|
}
|
|
1599
1652
|
function fitGarchFamily(candles, periodsPerYear, steps) {
|
|
1600
1653
|
// Fit all three GARCH-family models and pick the best by AIC
|
|
@@ -1720,21 +1773,25 @@ function checkReliable(fit) {
|
|
|
1720
1773
|
/**
|
|
1721
1774
|
* Forecast expected price range for t+1 (next candle).
|
|
1722
1775
|
*
|
|
1723
|
-
* Auto-selects
|
|
1724
|
-
*
|
|
1776
|
+
* Auto-selects the best volatility model via QLIKE.
|
|
1777
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
1778
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
1779
|
+
* Common values: 0.90 → z=1.645, 0.95 → z=1.96, 0.99 → z=2.576.
|
|
1725
1780
|
*/
|
|
1726
|
-
function predict(candles, interval, currentPrice = candles[candles.length - 1].close) {
|
|
1781
|
+
function predict(candles, interval, currentPrice = candles[candles.length - 1].close, confidence = 0.6827) {
|
|
1727
1782
|
assertMinCandles(candles, interval);
|
|
1783
|
+
const z = probit(confidence);
|
|
1728
1784
|
const fit = fitModel(candles, INTERVALS_PER_YEAR[interval], 1);
|
|
1729
1785
|
const sigma = fit.forecast.volatility[0];
|
|
1730
|
-
const
|
|
1786
|
+
const upperPrice = currentPrice * Math.exp(z * sigma);
|
|
1787
|
+
const lowerPrice = currentPrice * Math.exp(-z * sigma);
|
|
1731
1788
|
return {
|
|
1732
1789
|
modelType: fit.modelType,
|
|
1733
1790
|
currentPrice,
|
|
1734
1791
|
sigma,
|
|
1735
|
-
move,
|
|
1736
|
-
upperPrice
|
|
1737
|
-
lowerPrice
|
|
1792
|
+
move: upperPrice - currentPrice,
|
|
1793
|
+
upperPrice,
|
|
1794
|
+
lowerPrice,
|
|
1738
1795
|
reliable: checkReliable(fit),
|
|
1739
1796
|
};
|
|
1740
1797
|
}
|
|
@@ -1742,26 +1799,28 @@ function predict(candles, interval, currentPrice = candles[candles.length - 1].c
|
|
|
1742
1799
|
* Forecast expected price range over multiple candles.
|
|
1743
1800
|
*
|
|
1744
1801
|
* Cumulative σ = √(σ₁² + σ₂² + ... + σₙ²) — total expected move over N periods.
|
|
1745
|
-
*
|
|
1802
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
1803
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
1746
1804
|
*/
|
|
1747
|
-
function predictRange(candles, interval, steps, currentPrice = candles[candles.length - 1].close) {
|
|
1805
|
+
function predictRange(candles, interval, steps, currentPrice = candles[candles.length - 1].close, confidence = 0.6827) {
|
|
1748
1806
|
assertMinCandles(candles, interval);
|
|
1807
|
+
const z = probit(confidence);
|
|
1749
1808
|
const fit = fitModel(candles, INTERVALS_PER_YEAR[interval], steps);
|
|
1750
1809
|
const cumulativeVariance = fit.forecast.variance.reduce((sum, v) => sum + v, 0);
|
|
1751
1810
|
const sigma = Math.sqrt(cumulativeVariance);
|
|
1752
|
-
const
|
|
1811
|
+
const upperPrice = currentPrice * Math.exp(z * sigma);
|
|
1812
|
+
const lowerPrice = currentPrice * Math.exp(-z * sigma);
|
|
1753
1813
|
return {
|
|
1754
1814
|
modelType: fit.modelType,
|
|
1755
1815
|
currentPrice,
|
|
1756
1816
|
sigma,
|
|
1757
|
-
move,
|
|
1758
|
-
upperPrice
|
|
1759
|
-
lowerPrice
|
|
1817
|
+
move: upperPrice - currentPrice,
|
|
1818
|
+
upperPrice,
|
|
1819
|
+
lowerPrice,
|
|
1760
1820
|
reliable: checkReliable(fit),
|
|
1761
1821
|
};
|
|
1762
1822
|
}
|
|
1763
1823
|
// ── Backtest ──────────────────────────────────────────────────
|
|
1764
|
-
const BACKTEST_REQUIRED_PERCENT = 68;
|
|
1765
1824
|
const BACKTEST_WINDOW_RATIO = 0.75;
|
|
1766
1825
|
/**
|
|
1767
1826
|
* Walk-forward backtest of predict.
|
|
@@ -1769,16 +1828,22 @@ const BACKTEST_WINDOW_RATIO = 0.75;
|
|
|
1769
1828
|
* Window is computed automatically: 75% of candles for fitting, 25% for testing.
|
|
1770
1829
|
* Throws if not enough candles for the given interval.
|
|
1771
1830
|
* Returns true if the model's hit rate meets the required threshold.
|
|
1772
|
-
*
|
|
1831
|
+
* @param confidence — two-sided probability in (0,1) for the prediction band.
|
|
1832
|
+
* Default ≈0.6827 (±1σ).
|
|
1833
|
+
* @param requiredPercent — minimum hit rate (0–100) to pass. Default 68.
|
|
1773
1834
|
*/
|
|
1774
|
-
function backtest(candles, interval, requiredPercent =
|
|
1835
|
+
function backtest(candles, interval, confidence = 0.6827, requiredPercent = 68) {
|
|
1775
1836
|
assertMinCandles(candles, interval);
|
|
1837
|
+
if (requiredPercent <= 0)
|
|
1838
|
+
return true;
|
|
1839
|
+
if (requiredPercent >= 100)
|
|
1840
|
+
return false;
|
|
1776
1841
|
const window = Math.max(MIN_CANDLES[interval], Math.floor(candles.length * BACKTEST_WINDOW_RATIO));
|
|
1777
1842
|
let hits = 0;
|
|
1778
1843
|
let total = 0;
|
|
1779
1844
|
for (let i = window; i < candles.length - 1; i++) {
|
|
1780
1845
|
const slice = candles.slice(i - window, i + 1);
|
|
1781
|
-
const predicted = predict(slice, interval);
|
|
1846
|
+
const predicted = predict(slice, interval, slice[slice.length - 1].close, confidence);
|
|
1782
1847
|
const actual = candles[i + 1].close;
|
|
1783
1848
|
if (actual >= predicted.lowerPrice && actual <= predicted.upperPrice) {
|
|
1784
1849
|
hits++;
|
|
@@ -1788,4 +1853,4 @@ function backtest(candles, interval, requiredPercent = BACKTEST_REQUIRED_PERCENT
|
|
|
1788
1853
|
return (hits / total) * 100 >= requiredPercent;
|
|
1789
1854
|
}
|
|
1790
1855
|
|
|
1791
|
-
export { EXPECTED_ABS_NORMAL, Egarch, Garch, GjrGarch, HarRv, NoVaS, backtest, calculateReturns, calculateReturnsFromPrices, calibrateEgarch, calibrateGarch, calibrateGjrGarch, calibrateHarRv, calibrateNoVaS, checkLeverageEffect, expectedAbsStudentT, garmanKlassVariance, ljungBox, logGamma, nelderMead, nelderMeadMultiStart, perCandleParkinson, predict, predictRange, profileStudentTDf, qlike, sampleVariance, sampleVarianceWithMean, studentTNegLL, yangZhangVariance };
|
|
1856
|
+
export { EXPECTED_ABS_NORMAL, Egarch, Garch, GjrGarch, HarRv, NoVaS, backtest, calculateReturns, calculateReturnsFromPrices, calibrateEgarch, calibrateGarch, calibrateGjrGarch, calibrateHarRv, calibrateNoVaS, checkLeverageEffect, expectedAbsStudentT, garmanKlassVariance, ljungBox, logGamma, nelderMead, nelderMeadMultiStart, perCandleParkinson, predict, predictRange, probit, profileStudentTDf, qlike, sampleVariance, sampleVarianceWithMean, studentTNegLL, yangZhangVariance };
|
package/package.json
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "garch",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "GARCH and EGARCH volatility models for TypeScript",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./build/index.cjs",
|
|
7
|
-
"module": "./build/index.mjs",
|
|
8
|
-
"types": "./types.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./types.d.ts",
|
|
12
|
-
"import": "./build/index.mjs",
|
|
13
|
-
"require": "./build/index.cjs"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"build",
|
|
18
|
-
"types.d.ts",
|
|
19
|
-
"README.md"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "rollup -c",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"test:watch": "vitest",
|
|
25
|
-
"prepublishOnly": "npm run build"
|
|
26
|
-
},
|
|
27
|
-
"keywords": [
|
|
28
|
-
"garch",
|
|
29
|
-
"egarch",
|
|
30
|
-
"volatility",
|
|
31
|
-
"finance",
|
|
32
|
-
"econometrics",
|
|
33
|
-
"time-series"
|
|
34
|
-
],
|
|
35
|
-
"author": "",
|
|
36
|
-
"license": "MIT",
|
|
37
|
-
"devDependencies": {
|
|
38
|
-
"@rollup/plugin-typescript": "^12.3.0",
|
|
39
|
-
"@types/node": "^20.10.0",
|
|
40
|
-
"@vitest/coverage-v8": "^1.6.1",
|
|
41
|
-
"rollup": "^4.57.1",
|
|
42
|
-
"rollup-plugin-dts": "^6.3.0",
|
|
43
|
-
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
44
|
-
"tslib": "^2.8.1",
|
|
45
|
-
"typescript": "^5.3.0",
|
|
46
|
-
"vitest": "^1.0.0"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "garch",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "GARCH and EGARCH volatility models for TypeScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./build/index.cjs",
|
|
7
|
+
"module": "./build/index.mjs",
|
|
8
|
+
"types": "./types.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./types.d.ts",
|
|
12
|
+
"import": "./build/index.mjs",
|
|
13
|
+
"require": "./build/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"build",
|
|
18
|
+
"types.d.ts",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "rollup -c",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"garch",
|
|
29
|
+
"egarch",
|
|
30
|
+
"volatility",
|
|
31
|
+
"finance",
|
|
32
|
+
"econometrics",
|
|
33
|
+
"time-series"
|
|
34
|
+
],
|
|
35
|
+
"author": "",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
39
|
+
"@types/node": "^20.10.0",
|
|
40
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
41
|
+
"rollup": "^4.57.1",
|
|
42
|
+
"rollup-plugin-dts": "^6.3.0",
|
|
43
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
44
|
+
"tslib": "^2.8.1",
|
|
45
|
+
"typescript": "^5.3.0",
|
|
46
|
+
"vitest": "^1.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/types.d.ts
CHANGED
|
@@ -487,6 +487,14 @@ declare function profileStudentTDf(returns: number[], varianceSeries: number[]):
|
|
|
487
487
|
* of how the model was calibrated (MLE, OLS, D², etc.).
|
|
488
488
|
*/
|
|
489
489
|
declare function qlike(varianceSeries: number[], rv: number[]): number;
|
|
490
|
+
/**
|
|
491
|
+
* Inverse standard normal CDF (probit function).
|
|
492
|
+
* Converts a two-sided confidence level (e.g. 0.95) to the corresponding
|
|
493
|
+
* z-score (e.g. 1.96).
|
|
494
|
+
*
|
|
495
|
+
* Uses Acklam's rational approximation (max relative error < 1.15e-9).
|
|
496
|
+
*/
|
|
497
|
+
declare function probit(confidence: number): number;
|
|
490
498
|
|
|
491
499
|
type CandleInterval = '1m' | '3m' | '5m' | '15m' | '30m' | '1h' | '2h' | '4h' | '6h' | '8h';
|
|
492
500
|
interface PredictionResult {
|
|
@@ -501,26 +509,31 @@ interface PredictionResult {
|
|
|
501
509
|
/**
|
|
502
510
|
* Forecast expected price range for t+1 (next candle).
|
|
503
511
|
*
|
|
504
|
-
* Auto-selects
|
|
505
|
-
*
|
|
512
|
+
* Auto-selects the best volatility model via QLIKE.
|
|
513
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
514
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
515
|
+
* Common values: 0.90 → z=1.645, 0.95 → z=1.96, 0.99 → z=2.576.
|
|
506
516
|
*/
|
|
507
|
-
declare function predict(candles: Candle[], interval: CandleInterval, currentPrice?: number): PredictionResult;
|
|
517
|
+
declare function predict(candles: Candle[], interval: CandleInterval, currentPrice?: number, confidence?: number): PredictionResult;
|
|
508
518
|
/**
|
|
509
519
|
* Forecast expected price range over multiple candles.
|
|
510
520
|
*
|
|
511
521
|
* Cumulative σ = √(σ₁² + σ₂² + ... + σₙ²) — total expected move over N periods.
|
|
512
|
-
*
|
|
522
|
+
* Uses log-normal price bands: P·exp(±z·σ), where z = probit(confidence).
|
|
523
|
+
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
513
524
|
*/
|
|
514
|
-
declare function predictRange(candles: Candle[], interval: CandleInterval, steps: number, currentPrice?: number): PredictionResult;
|
|
525
|
+
declare function predictRange(candles: Candle[], interval: CandleInterval, steps: number, currentPrice?: number, confidence?: number): PredictionResult;
|
|
515
526
|
/**
|
|
516
527
|
* Walk-forward backtest of predict.
|
|
517
528
|
*
|
|
518
529
|
* Window is computed automatically: 75% of candles for fitting, 25% for testing.
|
|
519
530
|
* Throws if not enough candles for the given interval.
|
|
520
531
|
* Returns true if the model's hit rate meets the required threshold.
|
|
521
|
-
*
|
|
532
|
+
* @param confidence — two-sided probability in (0,1) for the prediction band.
|
|
533
|
+
* Default ≈0.6827 (±1σ).
|
|
534
|
+
* @param requiredPercent — minimum hit rate (0–100) to pass. Default 68.
|
|
522
535
|
*/
|
|
523
|
-
declare function backtest(candles: Candle[], interval: CandleInterval, requiredPercent?: number): boolean;
|
|
536
|
+
declare function backtest(candles: Candle[], interval: CandleInterval, confidence?: number, requiredPercent?: number): boolean;
|
|
524
537
|
|
|
525
538
|
declare function nelderMead(fn: (x: number[]) => number, x0: number[], options?: {
|
|
526
539
|
maxIter?: number;
|
|
@@ -536,5 +549,5 @@ declare function nelderMeadMultiStart(fn: (x: number[]) => number, x0: number[],
|
|
|
536
549
|
restarts?: number;
|
|
537
550
|
}): OptimizerResult;
|
|
538
551
|
|
|
539
|
-
export { EXPECTED_ABS_NORMAL, Egarch, Garch, GjrGarch, HarRv, NoVaS, backtest, calculateReturns, calculateReturnsFromPrices, calibrateEgarch, calibrateGarch, calibrateGjrGarch, calibrateHarRv, calibrateNoVaS, checkLeverageEffect, expectedAbsStudentT, garmanKlassVariance, ljungBox, logGamma, nelderMead, nelderMeadMultiStart, perCandleParkinson, predict, predictRange, profileStudentTDf, qlike, sampleVariance, sampleVarianceWithMean, studentTNegLL, yangZhangVariance };
|
|
552
|
+
export { EXPECTED_ABS_NORMAL, Egarch, Garch, GjrGarch, HarRv, NoVaS, backtest, calculateReturns, calculateReturnsFromPrices, calibrateEgarch, calibrateGarch, calibrateGjrGarch, calibrateHarRv, calibrateNoVaS, checkLeverageEffect, expectedAbsStudentT, garmanKlassVariance, ljungBox, logGamma, nelderMead, nelderMeadMultiStart, perCandleParkinson, predict, predictRange, probit, profileStudentTDf, qlike, sampleVariance, sampleVarianceWithMean, studentTNegLL, yangZhangVariance };
|
|
540
553
|
export type { CalibrationResult, Candle, CandleInterval, EgarchOptions, EgarchParams, GarchOptions, GarchParams, GjrGarchOptions, GjrGarchParams, HarRvOptions, HarRvParams, LeverageStats, NoVaSOptions, NoVaSParams, OptimizerResult, PredictionResult, VolatilityForecast };
|