garch 1.2.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +191 -26
- package/build/index.cjs +2039 -275
- package/build/index.mjs +2023 -276
- package/package.json +53 -48
- package/types.d.ts +347 -12
package/package.json
CHANGED
|
@@ -1,48 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "garch",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "GARCH and EGARCH volatility models for TypeScript",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"build"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"rollup
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "garch",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "GARCH and EGARCH volatility models for TypeScript",
|
|
5
|
+
"funding": {
|
|
6
|
+
"type": "individual",
|
|
7
|
+
"url": "http://paypal.me/tripolskypetr"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://backtest-kit.github.io/documents/article_07_ai_news_trading_signals.html",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./build/index.cjs",
|
|
12
|
+
"module": "./build/index.mjs",
|
|
13
|
+
"types": "./types.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./types.d.ts",
|
|
17
|
+
"import": "./build/index.mjs",
|
|
18
|
+
"require": "./build/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"build",
|
|
23
|
+
"types.d.ts",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "rollup -c",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"prepublishOnly": "npm run build"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"garch",
|
|
34
|
+
"egarch",
|
|
35
|
+
"volatility",
|
|
36
|
+
"finance",
|
|
37
|
+
"econometrics",
|
|
38
|
+
"time-series"
|
|
39
|
+
],
|
|
40
|
+
"author": "",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
44
|
+
"@types/node": "^20.10.0",
|
|
45
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
46
|
+
"rollup": "^4.57.1",
|
|
47
|
+
"rollup-plugin-dts": "^6.3.0",
|
|
48
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
49
|
+
"tslib": "^2.8.1",
|
|
50
|
+
"typescript": "^5.3.0",
|
|
51
|
+
"vitest": "^1.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/types.d.ts
CHANGED
|
@@ -68,6 +68,25 @@ interface HarRvParams {
|
|
|
68
68
|
annualizedVol: number;
|
|
69
69
|
r2: number;
|
|
70
70
|
df: number;
|
|
71
|
+
/** true when the regression runs on ln RV (betas live in log space). */
|
|
72
|
+
logSpec?: boolean;
|
|
73
|
+
/** Residual variance of the log-RV regression (lognormal bias correction). */
|
|
74
|
+
residualLogVar?: number;
|
|
75
|
+
}
|
|
76
|
+
interface RealizedGarchParams {
|
|
77
|
+
omega: number;
|
|
78
|
+
beta: number;
|
|
79
|
+
gamma: number;
|
|
80
|
+
/** Measurement-equation intercept: ln RV_t = ξ + ln σ²_t + τ₁z + τ₂(z²−1) + u. */
|
|
81
|
+
xi: number;
|
|
82
|
+
tau1: number;
|
|
83
|
+
tau2: number;
|
|
84
|
+
/** Std of the measurement noise u — how much the model trusts RV. */
|
|
85
|
+
sigmaU: number;
|
|
86
|
+
persistence: number;
|
|
87
|
+
unconditionalVariance: number;
|
|
88
|
+
annualizedVol: number;
|
|
89
|
+
df: number;
|
|
71
90
|
}
|
|
72
91
|
interface NoVaSParams {
|
|
73
92
|
weights: number[];
|
|
@@ -83,6 +102,7 @@ interface NoVaSParams {
|
|
|
83
102
|
interface OptimizerResult {
|
|
84
103
|
x: number[];
|
|
85
104
|
fx: number;
|
|
105
|
+
/** Iterations of the winning Nelder-Mead run (not summed across multi-start restarts). */
|
|
86
106
|
iterations: number;
|
|
87
107
|
converged: boolean;
|
|
88
108
|
}
|
|
@@ -115,6 +135,8 @@ declare class Garch {
|
|
|
115
135
|
fit(options?: {
|
|
116
136
|
maxIter?: number;
|
|
117
137
|
tol?: number;
|
|
138
|
+
forgetting?: number;
|
|
139
|
+
warmStart?: GarchParams;
|
|
118
140
|
}): CalibrationResult<GarchParams>;
|
|
119
141
|
/**
|
|
120
142
|
* Calculate conditional variance series given parameters
|
|
@@ -168,11 +190,24 @@ declare class Egarch {
|
|
|
168
190
|
fit(options?: {
|
|
169
191
|
maxIter?: number;
|
|
170
192
|
tol?: number;
|
|
193
|
+
forgetting?: number;
|
|
194
|
+
warmStart?: EgarchParams;
|
|
171
195
|
}): CalibrationResult<EgarchParams>;
|
|
172
196
|
/**
|
|
173
197
|
* Calculate conditional variance series given parameters
|
|
174
198
|
*/
|
|
175
199
|
getVarianceSeries(params: EgarchParams): number[];
|
|
200
|
+
/**
|
|
201
|
+
* Mean drift of the magnitude term under the fitted dynamics.
|
|
202
|
+
*
|
|
203
|
+
* With RV magnitude, E[√(RV/σ²)] ≠ E[|z|]: the in-sample recursion
|
|
204
|
+
* carries a mean offset α·m̄ per step that ω absorbed during fitting.
|
|
205
|
+
* A multi-step forecast that drops the α term entirely would therefore
|
|
206
|
+
* converge to a level systematically below the fitted dynamics.
|
|
207
|
+
* Returns m̄ = mean(magnitude − E|z|) over the sample (0 for prices-only
|
|
208
|
+
* input, where magnitude = |z| and the offset is sampling noise).
|
|
209
|
+
*/
|
|
210
|
+
magnitudeDrift(params: EgarchParams): number;
|
|
176
211
|
/**
|
|
177
212
|
* Forecast variance forward
|
|
178
213
|
*
|
|
@@ -200,6 +235,13 @@ interface HarRvOptions {
|
|
|
200
235
|
shortLag?: number;
|
|
201
236
|
mediumLag?: number;
|
|
202
237
|
longLag?: number;
|
|
238
|
+
/**
|
|
239
|
+
* Regress ln RV instead of RV levels (log-HAR, Corsi). Positivity comes
|
|
240
|
+
* for free (no 1e-20 clamps on negative predictions), residuals are far
|
|
241
|
+
* closer to homoskedastic, and single RV prints stop dominating the OLS.
|
|
242
|
+
* Predictions are bias-corrected: E[RV] = exp(ŷ + σ²_ε/2).
|
|
243
|
+
*/
|
|
244
|
+
logSpec?: boolean;
|
|
203
245
|
}
|
|
204
246
|
/**
|
|
205
247
|
* HAR-RV model (Corsi, 2009)
|
|
@@ -223,6 +265,8 @@ declare class HarRv {
|
|
|
223
265
|
private shortLag;
|
|
224
266
|
private mediumLag;
|
|
225
267
|
private longLag;
|
|
268
|
+
private logSpec;
|
|
269
|
+
private lnRv;
|
|
226
270
|
constructor(data: Candle[] | number[], options?: HarRvOptions);
|
|
227
271
|
/**
|
|
228
272
|
* Calibrate HAR-RV via OLS.
|
|
@@ -230,6 +274,7 @@ declare class HarRv {
|
|
|
230
274
|
fit(): CalibrationResult<HarRvParams>;
|
|
231
275
|
/**
|
|
232
276
|
* Internal: compute variance series from beta vector.
|
|
277
|
+
* For the log spec the prediction is E[RV] = exp(ŷ + σ²_ε/2).
|
|
233
278
|
*/
|
|
234
279
|
private getVarianceSeriesInternal;
|
|
235
280
|
/**
|
|
@@ -240,7 +285,8 @@ declare class HarRv {
|
|
|
240
285
|
* Forecast variance forward.
|
|
241
286
|
*
|
|
242
287
|
* Uses iterative substitution: each forecast step feeds back
|
|
243
|
-
* into the rolling RV components for subsequent steps
|
|
288
|
+
* into the rolling RV components for subsequent steps (point forecasts
|
|
289
|
+
* of ln RV for the log spec, bias-corrected on output).
|
|
244
290
|
*/
|
|
245
291
|
forecast(params: HarRvParams, steps?: number): VolatilityForecast;
|
|
246
292
|
/**
|
|
@@ -270,7 +316,7 @@ interface GjrGarchOptions {
|
|
|
270
316
|
* where:
|
|
271
317
|
* - ω (omega) > 0: constant term
|
|
272
318
|
* - α (alpha) ≥ 0: symmetric shock response
|
|
273
|
-
* - γ (gamma) ≥
|
|
319
|
+
* - γ (gamma) ≥ −α: asymmetric leverage coefficient (negative = inverted leverage)
|
|
274
320
|
* - β (beta) ≥ 0: persistence
|
|
275
321
|
* - I(r<0) = 1 when return is negative, 0 otherwise
|
|
276
322
|
* - Stationarity: α + γ/2 + β < 1
|
|
@@ -290,6 +336,8 @@ declare class GjrGarch {
|
|
|
290
336
|
fit(options?: {
|
|
291
337
|
maxIter?: number;
|
|
292
338
|
tol?: number;
|
|
339
|
+
forgetting?: number;
|
|
340
|
+
warmStart?: GjrGarchParams;
|
|
293
341
|
}): CalibrationResult<GjrGarchParams>;
|
|
294
342
|
/**
|
|
295
343
|
* Calculate conditional variance series given parameters
|
|
@@ -313,6 +361,63 @@ declare class GjrGarch {
|
|
|
313
361
|
*/
|
|
314
362
|
declare function calibrateGjrGarch(data: Candle[] | number[], options?: GjrGarchOptions): CalibrationResult<GjrGarchParams>;
|
|
315
363
|
|
|
364
|
+
interface RealizedGarchOptions {
|
|
365
|
+
periodsPerYear?: number;
|
|
366
|
+
maxIter?: number;
|
|
367
|
+
tol?: number;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Realized GARCH(1,1) (Hansen, Huang & Shek, 2012), log-linear, φ = 1.
|
|
371
|
+
*
|
|
372
|
+
* r_t = σ_t·z_t, z_t ~ standardized t(df)
|
|
373
|
+
* ln σ²_t = ω + β·ln σ²_{t−1} + γ·ln RV_{t−1}
|
|
374
|
+
* ln RV_t = ξ + ln σ²_t + τ₁·z_t + τ₂·(z²_t − 1) + u_t, u_t ~ N(0, σ²_u)
|
|
375
|
+
*
|
|
376
|
+
* Unlike the RV-in-place-of-ε² hybrids, the measurement equation estimates
|
|
377
|
+
* the bias (ξ) and noise (σ_u) of the realized measure inside the joint
|
|
378
|
+
* likelihood: RV information is weighted by how trustworthy it actually is,
|
|
379
|
+
* and leverage enters through τ₁. Stationarity: β + γ < 1 (with φ = 1).
|
|
380
|
+
*/
|
|
381
|
+
declare class RealizedGarch {
|
|
382
|
+
private returns;
|
|
383
|
+
private lnRv;
|
|
384
|
+
private periodsPerYear;
|
|
385
|
+
private initialVariance;
|
|
386
|
+
constructor(data: Candle[] | number[], options?: RealizedGarchOptions);
|
|
387
|
+
/**
|
|
388
|
+
* Calibrate by joint MLE over returns and the realized measure.
|
|
389
|
+
*/
|
|
390
|
+
fit(options?: {
|
|
391
|
+
maxIter?: number;
|
|
392
|
+
tol?: number;
|
|
393
|
+
forgetting?: number;
|
|
394
|
+
warmStart?: RealizedGarchParams;
|
|
395
|
+
}): CalibrationResult<RealizedGarchParams>;
|
|
396
|
+
/**
|
|
397
|
+
* Conditional variance series (data scale). σ²_t is driven by RV_{t−1}
|
|
398
|
+
* through the log recursion — no look-ahead.
|
|
399
|
+
*/
|
|
400
|
+
getVarianceSeries(params: RealizedGarchParams): number[];
|
|
401
|
+
/**
|
|
402
|
+
* Forecast variance forward. One step uses the actual last RV; further
|
|
403
|
+
* steps substitute E[ln RV_t] = ξ + ln σ²_t, giving the reduced recursion
|
|
404
|
+
* ln σ²_{t+h} = (ω + γξ) + (β + γ)·ln σ²_{t+h−1}.
|
|
405
|
+
*/
|
|
406
|
+
forecast(params: RealizedGarchParams, steps?: number): VolatilityForecast;
|
|
407
|
+
/**
|
|
408
|
+
* Get the return series.
|
|
409
|
+
*/
|
|
410
|
+
getReturns(): number[];
|
|
411
|
+
/**
|
|
412
|
+
* Get initial variance estimate.
|
|
413
|
+
*/
|
|
414
|
+
getInitialVariance(): number;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Convenience function to calibrate Realized GARCH from candles or prices.
|
|
418
|
+
*/
|
|
419
|
+
declare function calibrateRealizedGarch(data: Candle[] | number[], options?: RealizedGarchOptions): CalibrationResult<RealizedGarchParams>;
|
|
420
|
+
|
|
316
421
|
interface NoVaSOptions {
|
|
317
422
|
periodsPerYear?: number;
|
|
318
423
|
lags?: number;
|
|
@@ -352,6 +457,7 @@ declare class NoVaS {
|
|
|
352
457
|
fit(options?: {
|
|
353
458
|
maxIter?: number;
|
|
354
459
|
tol?: number;
|
|
460
|
+
warmWeights?: number[];
|
|
355
461
|
}): CalibrationResult<NoVaSParams>;
|
|
356
462
|
/**
|
|
357
463
|
* Internal: compute variance series from D² weight vector.
|
|
@@ -384,6 +490,15 @@ declare class NoVaS {
|
|
|
384
490
|
*/
|
|
385
491
|
declare function calibrateNoVaS(data: Candle[] | number[], options?: NoVaSOptions): CalibrationResult<NoVaSParams>;
|
|
386
492
|
|
|
493
|
+
/**
|
|
494
|
+
* Validate OHLC integrity. Garbage candles (NaN, non-positive prices,
|
|
495
|
+
* high < low) otherwise propagate silently as NaN through every estimator.
|
|
496
|
+
*/
|
|
497
|
+
declare function validateCandles(candles: Candle[]): void;
|
|
498
|
+
/**
|
|
499
|
+
* Linear-interpolation quantile of a pre-sorted (ascending) sample.
|
|
500
|
+
*/
|
|
501
|
+
declare function empiricalQuantile(sortedAsc: number[], p: number): number;
|
|
387
502
|
/**
|
|
388
503
|
* Calculate log returns from candles
|
|
389
504
|
*/
|
|
@@ -472,6 +587,28 @@ declare function studentTNegLL(returns: number[], varianceSeries: number[], df:
|
|
|
472
587
|
* Converges to √(2/π) as df → ∞ (Gaussian limit).
|
|
473
588
|
*/
|
|
474
589
|
declare function expectedAbsStudentT(df: number): number;
|
|
590
|
+
/**
|
|
591
|
+
* Regularized incomplete beta function I_x(a, b).
|
|
592
|
+
*/
|
|
593
|
+
declare function incompleteBeta(x: number, a: number, b: number): number;
|
|
594
|
+
/**
|
|
595
|
+
* CDF of the (raw, unstandardized) Student-t distribution with df degrees
|
|
596
|
+
* of freedom: P(T ≤ t).
|
|
597
|
+
*/
|
|
598
|
+
declare function studentTCdf(t: number, df: number): number;
|
|
599
|
+
/**
|
|
600
|
+
* Two-sided quantile of the STANDARDIZED Student-t distribution
|
|
601
|
+
* (unit variance). The t-analog of probit(): returns z such that
|
|
602
|
+
* P(|Z| ≤ z) = confidence when Z ~ t(df) scaled to variance 1.
|
|
603
|
+
*
|
|
604
|
+
* This is what price corridors must use when the model was fitted with
|
|
605
|
+
* Student-t innovations: with fat tails (small df) the Gaussian probit
|
|
606
|
+
* makes 68% bands too wide and 99% bands dangerously narrow.
|
|
607
|
+
*
|
|
608
|
+
* Falls back to probit() for df > 1000 (where the difference from the
|
|
609
|
+
* Gaussian quantile is < 0.3% even at 99%) or df ≤ 2 (variance undefined).
|
|
610
|
+
*/
|
|
611
|
+
declare function studentTProbit(confidence: number, df: number): number;
|
|
475
612
|
/**
|
|
476
613
|
* 1D grid search for optimal df that minimizes Student-t neg-LL.
|
|
477
614
|
* Used by HAR-RV and NoVaS where df is profiled after main optimization.
|
|
@@ -497,33 +634,199 @@ declare function qlike(varianceSeries: number[], rv: number[]): number;
|
|
|
497
634
|
declare function probit(confidence: number): number;
|
|
498
635
|
|
|
499
636
|
type CandleInterval = '1m' | '3m' | '5m' | '15m' | '30m' | '1h' | '2h' | '4h' | '6h' | '8h';
|
|
637
|
+
type WarningCode = 'LOW_SAMPLE' | 'NOT_CONVERGED' | 'HIGH_PERSISTENCE' | 'DEGENERATE_VARIANCE' | 'RESIDUAL_AUTOCORRELATION' | 'DATA_GAPS' | 'INTERVAL_MISMATCH';
|
|
638
|
+
interface PredictionWarning {
|
|
639
|
+
code: WarningCode;
|
|
640
|
+
/** Plain-language explanation with a suggested action. */
|
|
641
|
+
message: string;
|
|
642
|
+
/** true when this warning alone makes the forecast unreliable. */
|
|
643
|
+
critical: boolean;
|
|
644
|
+
}
|
|
500
645
|
interface PredictionResult {
|
|
646
|
+
/** Reference price used to compute the corridor (last close or the value passed as `currentPrice`). */
|
|
501
647
|
currentPrice: number;
|
|
648
|
+
/** One-period (or cumulative) volatility estimate, as a decimal log-return standard deviation (e.g. `0.012` = 1.2%). */
|
|
502
649
|
sigma: number;
|
|
650
|
+
/** Upward expected move in price units: `upperPrice - currentPrice`. */
|
|
503
651
|
move: number;
|
|
652
|
+
/** Upward expected move in percent (0–100 scale, e.g. `1.21` means 1.21%). Equal to `(exp(z·σ) - 1) * 100`. */
|
|
504
653
|
movePercent: number;
|
|
654
|
+
/** Upper price band: `currentPrice · exp(+z·σ)`. */
|
|
505
655
|
upperPrice: number;
|
|
656
|
+
/** Lower price band: `currentPrice · exp(-z·σ)`. Always positive. */
|
|
506
657
|
lowerPrice: number;
|
|
507
|
-
|
|
658
|
+
/** Top-weight member of the volatility model combination (selected by out-of-sample QLIKE). */
|
|
659
|
+
modelType: 'garch' | 'egarch' | 'gjr-garch' | 'realized-garch' | 'har-rv' | 'novas';
|
|
660
|
+
/** Student-t degrees of freedom profiled on scale-corrected residuals. */
|
|
661
|
+
df: number;
|
|
662
|
+
/**
|
|
663
|
+
* Average corridor multiplier, (zScoreUp + zScoreDown) / 2 — kept for
|
|
664
|
+
* backward compatibility. The bands themselves are asymmetric; use
|
|
665
|
+
* zScoreUp/zScoreDown to reconstruct them exactly.
|
|
666
|
+
*/
|
|
667
|
+
zScore: number;
|
|
668
|
+
/** Upper-tail multiplier: `upperPrice = currentPrice · exp(+zScoreUp · sigma)`. */
|
|
669
|
+
zScoreUp: number;
|
|
670
|
+
/** Lower-tail multiplier: `lowerPrice = currentPrice · exp(−zScoreDown · sigma)`. */
|
|
671
|
+
zScoreDown: number;
|
|
672
|
+
/** `true` when no critical warning fired (model converged, persistence < 0.999, Ljung-Box p ≥ 0.05, non-degenerate variance). */
|
|
508
673
|
reliable: boolean;
|
|
674
|
+
/**
|
|
675
|
+
* Everything the pipeline noticed, in plain language: why `reliable` is
|
|
676
|
+
* false (critical warnings) plus non-critical data quality notes.
|
|
677
|
+
*/
|
|
678
|
+
warnings: PredictionWarning[];
|
|
679
|
+
/** Combination weights per model family (out-of-sample QLIKE softmax), summing to 1. */
|
|
680
|
+
modelWeights: Partial<Record<PredictionResult['modelType'], number>>;
|
|
681
|
+
/** `true` when a significant diurnal volatility profile was detected and removed before fitting. */
|
|
682
|
+
seasonalityDetected: boolean;
|
|
683
|
+
}
|
|
684
|
+
interface PredictOptions {
|
|
685
|
+
/** Reference price for the corridor; defaults to the last close. */
|
|
686
|
+
currentPrice?: number | null;
|
|
687
|
+
/** Two-sided probability in (0,1). Default ≈0.6827 (±1σ). */
|
|
688
|
+
confidence?: number;
|
|
689
|
+
}
|
|
690
|
+
interface DataIssue {
|
|
691
|
+
code: 'TOO_FEW_CANDLES' | 'INVALID_OHLC' | 'UNSORTED' | 'DUPLICATE_TIMESTAMPS' | 'LOW_SAMPLE' | 'DATA_GAPS' | 'INTERVAL_MISMATCH' | 'FLAT_CANDLES';
|
|
692
|
+
message: string;
|
|
693
|
+
severity: 'error' | 'warning';
|
|
694
|
+
}
|
|
695
|
+
interface DataReport {
|
|
696
|
+
/** false when any error-severity issue is present (predict would throw). */
|
|
697
|
+
ok: boolean;
|
|
698
|
+
issues: DataIssue[];
|
|
699
|
+
recommendedCandles: number;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Pre-flight data check with plain-language, actionable messages: run it on
|
|
703
|
+
* a new data source before wiring it into predict. Errors are conditions
|
|
704
|
+
* predict would throw on; warnings degrade quality but do not block.
|
|
705
|
+
*/
|
|
706
|
+
declare function checkData(candles: Candle[], interval: CandleInterval): DataReport;
|
|
707
|
+
interface Seasonality {
|
|
708
|
+
/** Variance factor per intraday bucket, sample-weighted mean 1. */
|
|
709
|
+
factors: number[];
|
|
710
|
+
/** Bucket of return index t (i.e. candle t+1); also valid for future t. */
|
|
711
|
+
bucketOfReturn: (t: number) => number;
|
|
509
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* Diurnal variance profile from per-candle Parkinson RV.
|
|
715
|
+
*
|
|
716
|
+
* Intraday markets have a strong time-of-day volatility pattern (sessions,
|
|
717
|
+
* funding, weekends). A GARCH-family fit smears it into average persistence,
|
|
718
|
+
* so corridors are systematically too narrow in active hours and too wide in
|
|
719
|
+
* quiet ones. Factors are estimated per intraday bucket (≤24 per day, bars
|
|
720
|
+
* grouped for sub-hour intervals), circularly smoothed, shrunk toward 1 by
|
|
721
|
+
* bucket support, and gated by a χ² significance test against the RV
|
|
722
|
+
* sampling noise (inflated for volatility clustering) — pure-GARCH data
|
|
723
|
+
* without seasonality returns null and the pipeline is unchanged.
|
|
724
|
+
*
|
|
725
|
+
* Timestamps (ms or s), when present on every candle, anchor buckets to
|
|
726
|
+
* real time of day and survive gaps; otherwise buckets are positional and
|
|
727
|
+
* assume contiguous bars.
|
|
728
|
+
*/
|
|
729
|
+
declare function computeSeasonality(candles: Candle[], interval: CandleInterval): Seasonality | null;
|
|
730
|
+
/**
|
|
731
|
+
* Rescale each candle's log-moves by 1/√f(bucket) so the deseasonalized
|
|
732
|
+
* series has a flat diurnal profile. Gaps (open vs prev close) are scaled
|
|
733
|
+
* with the same factor; OHLC ordering is preserved (monotone log map).
|
|
734
|
+
*/
|
|
735
|
+
declare function deseasonalizeCandles(candles: Candle[], season: Seasonality): Candle[];
|
|
736
|
+
/**
|
|
737
|
+
* Cached calibration state threaded between rolling refits: previous
|
|
738
|
+
* optima become warm starts with a reduced multi-start budget, and the
|
|
739
|
+
* HAR spec search collapses to the previously selected configuration.
|
|
740
|
+
*/
|
|
741
|
+
interface WarmState {
|
|
742
|
+
garch?: GarchParams;
|
|
743
|
+
garchForget?: GarchParams;
|
|
744
|
+
egarch?: EgarchParams;
|
|
745
|
+
gjr?: GjrGarchParams;
|
|
746
|
+
rgarch?: RealizedGarchParams;
|
|
747
|
+
harLags?: [number, number, number];
|
|
748
|
+
harLog?: boolean;
|
|
749
|
+
novasWeights?: number[];
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Stateful predictor for rolling use (bots, backtests): each subsequent
|
|
753
|
+
* predict/predictRange warm-starts every optimizer from the previous
|
|
754
|
+
* window's optimum with a reduced multi-start budget — same math, a
|
|
755
|
+
* fraction of the cost. State is per-instrument: do not share one
|
|
756
|
+
* predictor across symbols.
|
|
757
|
+
*/
|
|
758
|
+
declare function createPredictor(interval: CandleInterval): {
|
|
759
|
+
predict: (candles: Candle[], currentPriceOrOptions?: number | null | PredictOptions, confidence?: number) => PredictionResult;
|
|
760
|
+
predictRange: (candles: Candle[], steps: number, currentPriceOrOptions?: number | null | PredictOptions, confidence?: number) => PredictionResult;
|
|
761
|
+
};
|
|
510
762
|
/**
|
|
511
763
|
* Forecast expected price range for t+1 (next candle).
|
|
512
764
|
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
765
|
+
* Combines all volatility models weighted by out-of-sample QLIKE,
|
|
766
|
+
* deseasonalizes the diurnal variance profile when one is present,
|
|
767
|
+
* rescales the variance to the return scale (Var(r/σ) = 1), and builds
|
|
768
|
+
* bands P·exp(±z·σ) where z is calibrated on the data itself: the
|
|
769
|
+
* empirical |z| quantile of the standardized residuals blended with the
|
|
770
|
+
* fitted Student-t quantile as the tail runs out of observations (see
|
|
771
|
+
* corridorZ). Empirical coverage tracks the requested confidence without
|
|
772
|
+
* assuming a distributional shape.
|
|
515
773
|
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
516
|
-
* Common values: 0.90
|
|
774
|
+
* Common values: 0.90, 0.95, 0.99.
|
|
517
775
|
*/
|
|
518
|
-
declare function predict(candles: Candle[], interval: CandleInterval,
|
|
776
|
+
declare function predict(candles: Candle[], interval: CandleInterval, currentPriceOrOptions?: number | null | PredictOptions, confidence?: number): PredictionResult;
|
|
519
777
|
/**
|
|
520
778
|
* Forecast expected price range over multiple candles.
|
|
521
779
|
*
|
|
522
|
-
* Cumulative σ = √(σ₁² + σ₂² + ... + σₙ²) — total expected move over N
|
|
523
|
-
*
|
|
780
|
+
* Cumulative σ = √(σ₁² + σ₂² + ... + σₙ²) — total expected move over N
|
|
781
|
+
* periods, with each step's variance carrying its own seasonal factor.
|
|
782
|
+
* Uses log-normal price bands P·exp(±z·σ) where z is calibrated at the
|
|
783
|
+
* requested horizon: the empirical quantile of |h-step standardized sums|
|
|
784
|
+
* from the sample itself, blended with the model-implied quantile simulated
|
|
785
|
+
* through the fitted recursions (volatility feedback and fat-tail decay
|
|
786
|
+
* included).
|
|
524
787
|
* @param confidence — two-sided probability in (0,1). Default ≈0.6827 (±1σ).
|
|
788
|
+
* @param steps — horizon in candles, 1 ≤ steps ≤ candles.length.
|
|
789
|
+
*/
|
|
790
|
+
declare function predictRange(candles: Candle[], interval: CandleInterval, steps: number, currentPriceOrOptions?: number | null | PredictOptions, confidence?: number): PredictionResult;
|
|
791
|
+
interface BacktestStats {
|
|
792
|
+
/** Number of test candles whose close landed inside the predicted corridor. */
|
|
793
|
+
hits: number;
|
|
794
|
+
/** Number of walk-forward predictions made. */
|
|
795
|
+
total: number;
|
|
796
|
+
/** Empirical coverage in percent (0–100). Compare against `confidence · 100`. */
|
|
797
|
+
hitRate: number;
|
|
798
|
+
/** Statistical judgment of the coverage against the nominal confidence (Kupiec POF test). */
|
|
799
|
+
verdict: 'well-calibrated' | 'too-narrow' | 'too-wide' | 'inconclusive';
|
|
800
|
+
/** Kupiec test p-value: probability of a coverage gap this large under correct calibration. */
|
|
801
|
+
pValue: number;
|
|
802
|
+
/** Plain-language interpretation of the verdict with the numbers filled in. */
|
|
803
|
+
message: string;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Kupiec (1995) proportion-of-failures test: is the observed hit rate
|
|
807
|
+
* statistically consistent with the nominal confidence, given how many
|
|
808
|
+
* walk-forward points there are? A raw hitRate of 63% vs nominal 68% means
|
|
809
|
+
* nothing without n — this answers "failure or noise" directly.
|
|
810
|
+
*/
|
|
811
|
+
declare function kupiecTest(hits: number, total: number, confidence: number): Pick<BacktestStats, 'verdict' | 'pValue' | 'message'>;
|
|
812
|
+
/**
|
|
813
|
+
* Walk-forward calibration statistics for predict.
|
|
814
|
+
*
|
|
815
|
+
* Refits the model on a rolling window (75% of candles, min MIN_CANDLES)
|
|
816
|
+
* and checks whether the next close lands inside the predicted corridor.
|
|
817
|
+
* A well-calibrated tool has hitRate ≈ confidence·100.
|
|
818
|
+
*
|
|
819
|
+
* Every refit costs a full multi-model calibration, so by default the test
|
|
820
|
+
* points are subsampled to at most ~100 refits (stride grows with the test
|
|
821
|
+
* span). Pass `stride: 1` to evaluate every candle when runtime is not a
|
|
822
|
+
* concern, or any positive stride to control the trade-off yourself.
|
|
823
|
+
* Throws if not enough candles for the given interval.
|
|
824
|
+
* @param confidence — two-sided probability in (0,1) for the prediction band.
|
|
825
|
+
* Default ≈0.6827 (±1σ).
|
|
525
826
|
*/
|
|
526
|
-
declare function
|
|
827
|
+
declare function backtestStats(candles: Candle[], interval: CandleInterval, confidence?: number, options?: {
|
|
828
|
+
stride?: number;
|
|
829
|
+
}): BacktestStats;
|
|
527
830
|
/**
|
|
528
831
|
* Walk-forward backtest of predict.
|
|
529
832
|
*
|
|
@@ -536,6 +839,30 @@ declare function predictRange(candles: Candle[], interval: CandleInterval, steps
|
|
|
536
839
|
*/
|
|
537
840
|
declare function backtest(candles: Candle[], interval: CandleInterval, confidence?: number, requiredPercent?: number): boolean;
|
|
538
841
|
|
|
842
|
+
/**
|
|
843
|
+
* Typed error hierarchy so bot code can branch on error class instead of
|
|
844
|
+
* parsing message strings.
|
|
845
|
+
*
|
|
846
|
+
* try { predict(candles, '1h') }
|
|
847
|
+
* catch (e) {
|
|
848
|
+
* if (e instanceof NotEnoughDataError) await fetchMoreCandles();
|
|
849
|
+
* else if (e instanceof BadDataError) alertDataPipeline(e.message);
|
|
850
|
+
* else throw e;
|
|
851
|
+
* }
|
|
852
|
+
*/
|
|
853
|
+
declare class GarchError extends Error {
|
|
854
|
+
constructor(message: string);
|
|
855
|
+
}
|
|
856
|
+
/** The sample is too short for the requested interval/model. Fetch more candles. */
|
|
857
|
+
declare class NotEnoughDataError extends GarchError {
|
|
858
|
+
}
|
|
859
|
+
/** The candles themselves are broken: invalid OHLC, unsorted or duplicated timestamps. Fix the data pipeline. */
|
|
860
|
+
declare class BadDataError extends GarchError {
|
|
861
|
+
}
|
|
862
|
+
/** A call argument is out of range or of the wrong shape (interval, confidence, steps, currentPrice). Fix the call site. */
|
|
863
|
+
declare class InvalidArgumentError extends GarchError {
|
|
864
|
+
}
|
|
865
|
+
|
|
539
866
|
declare function nelderMead(fn: (x: number[]) => number, x0: number[], options?: {
|
|
540
867
|
maxIter?: number;
|
|
541
868
|
tol?: number;
|
|
@@ -548,7 +875,15 @@ declare function nelderMeadMultiStart(fn: (x: number[]) => number, x0: number[],
|
|
|
548
875
|
maxIter?: number;
|
|
549
876
|
tol?: number;
|
|
550
877
|
restarts?: number;
|
|
878
|
+
/**
|
|
879
|
+
* Additional explicit starting points, each run through a full NM pass.
|
|
880
|
+
* The perturbation restarts below scale x0 multiplicatively, so they
|
|
881
|
+
* preserve its shape — basins whose shape differs from x0 (e.g. far-lag
|
|
882
|
+
* weight structures) are unreachable from x0 alone and must be seeded
|
|
883
|
+
* explicitly.
|
|
884
|
+
*/
|
|
885
|
+
extraStarts?: number[][];
|
|
551
886
|
}): OptimizerResult;
|
|
552
887
|
|
|
553
|
-
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 };
|
|
554
|
-
export type { CalibrationResult, Candle, CandleInterval, EgarchOptions, EgarchParams, GarchOptions, GarchParams, GjrGarchOptions, GjrGarchParams, HarRvOptions, HarRvParams, LeverageStats, NoVaSOptions, NoVaSParams, OptimizerResult, PredictionResult, VolatilityForecast };
|
|
888
|
+
export { BadDataError, EXPECTED_ABS_NORMAL, Egarch, Garch, GarchError, GjrGarch, HarRv, InvalidArgumentError, NoVaS, NotEnoughDataError, RealizedGarch, backtest, backtestStats, calculateReturns, calculateReturnsFromPrices, calibrateEgarch, calibrateGarch, calibrateGjrGarch, calibrateHarRv, calibrateNoVaS, calibrateRealizedGarch, checkData, checkLeverageEffect, computeSeasonality, createPredictor, deseasonalizeCandles, empiricalQuantile, expectedAbsStudentT, garmanKlassVariance, incompleteBeta, kupiecTest, ljungBox, logGamma, nelderMead, nelderMeadMultiStart, perCandleParkinson, predict, predictRange, probit, profileStudentTDf, qlike, sampleVariance, sampleVarianceWithMean, studentTCdf, studentTNegLL, studentTProbit, validateCandles, yangZhangVariance };
|
|
889
|
+
export type { BacktestStats, CalibrationResult, Candle, CandleInterval, DataIssue, DataReport, EgarchOptions, EgarchParams, GarchOptions, GarchParams, GjrGarchOptions, GjrGarchParams, HarRvOptions, HarRvParams, LeverageStats, NoVaSOptions, NoVaSParams, OptimizerResult, PredictOptions, PredictionResult, PredictionWarning, RealizedGarchOptions, RealizedGarchParams, Seasonality, VolatilityForecast, WarmState, WarningCode };
|