@fullstackcraftllc/floe 0.0.13 → 0.0.15
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 +8 -8
- package/dist/client/FloeClient.d.ts +5 -1
- package/dist/client/FloeClient.js +54 -0
- package/dist/client/brokers/IBKRClient.d.ts +324 -0
- package/dist/client/brokers/IBKRClient.js +797 -0
- package/dist/client/brokers/TradierClient.js +7 -6
- package/dist/hedgeflow/charm.d.ts +23 -0
- package/dist/hedgeflow/charm.js +113 -0
- package/dist/hedgeflow/curve.d.ts +27 -0
- package/dist/hedgeflow/curve.js +315 -0
- package/dist/hedgeflow/index.d.ts +33 -0
- package/dist/hedgeflow/index.js +52 -0
- package/dist/hedgeflow/regime.d.ts +7 -0
- package/dist/hedgeflow/regime.js +99 -0
- package/dist/hedgeflow/types.d.ts +185 -0
- package/dist/hedgeflow/types.js +2 -0
- package/dist/impliedpdf/adjusted.d.ts +173 -0
- package/dist/impliedpdf/adjusted.js +500 -0
- package/dist/impliedpdf/index.d.ts +1 -0
- package/dist/impliedpdf/index.js +10 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +27 -1
- package/dist/iv/index.d.ts +52 -0
- package/dist/iv/index.js +287 -0
- package/dist/iv/types.d.ts +40 -0
- package/dist/iv/types.js +2 -0
- package/dist/pressure/grid.d.ts +14 -0
- package/dist/pressure/grid.js +220 -0
- package/dist/pressure/index.d.ts +5 -0
- package/dist/pressure/index.js +22 -0
- package/dist/pressure/ivpath.d.ts +31 -0
- package/dist/pressure/ivpath.js +304 -0
- package/dist/pressure/normalize.d.ts +6 -0
- package/dist/pressure/normalize.js +76 -0
- package/dist/pressure/regime.d.ts +7 -0
- package/dist/pressure/regime.js +99 -0
- package/dist/pressure/types.d.ts +182 -0
- package/dist/pressure/types.js +2 -0
- package/dist/rv/index.d.ts +26 -0
- package/dist/rv/index.js +81 -0
- package/dist/rv/types.d.ts +32 -0
- package/dist/rv/types.js +2 -0
- package/dist/utils/indexOptions.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveRegimeParams = deriveRegimeParams;
|
|
4
|
+
exports.interpolateIVAtStrike = interpolateIVAtStrike;
|
|
5
|
+
/**
|
|
6
|
+
* Derive regime parameters from the IV surface
|
|
7
|
+
*/
|
|
8
|
+
function deriveRegimeParams(ivSurface, spot) {
|
|
9
|
+
const { strikes, smoothedIVs } = ivSurface;
|
|
10
|
+
const atmIV = interpolateIVAtStrike(strikes, smoothedIVs, spot) / 100;
|
|
11
|
+
const skew = calculateSkewAtSpot(strikes, smoothedIVs, spot);
|
|
12
|
+
const impliedSpotVolCorr = skewToCorrelation(skew);
|
|
13
|
+
const curvature = calculateCurvatureAtSpot(strikes, smoothedIVs, spot);
|
|
14
|
+
const impliedVolOfVol = curvatureToVolOfVol(curvature, atmIV);
|
|
15
|
+
const regime = ivToRegime(atmIV);
|
|
16
|
+
const expectedDailySpotMove = atmIV / Math.sqrt(252);
|
|
17
|
+
const expectedDailyVolMove = impliedVolOfVol / Math.sqrt(252);
|
|
18
|
+
return {
|
|
19
|
+
atmIV,
|
|
20
|
+
impliedSpotVolCorr,
|
|
21
|
+
impliedVolOfVol,
|
|
22
|
+
regime,
|
|
23
|
+
expectedDailySpotMove,
|
|
24
|
+
expectedDailyVolMove,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function skewToCorrelation(skew) {
|
|
28
|
+
const SKEW_TO_CORR_SCALE = 0.15;
|
|
29
|
+
return Math.max(-0.95, Math.min(0.5, skew * SKEW_TO_CORR_SCALE));
|
|
30
|
+
}
|
|
31
|
+
function curvatureToVolOfVol(curvature, atmIV) {
|
|
32
|
+
const VOL_OF_VOL_SCALE = 2.0;
|
|
33
|
+
return Math.sqrt(Math.abs(curvature)) * VOL_OF_VOL_SCALE * atmIV;
|
|
34
|
+
}
|
|
35
|
+
function ivToRegime(atmIV) {
|
|
36
|
+
if (atmIV < 0.15)
|
|
37
|
+
return 'calm';
|
|
38
|
+
if (atmIV < 0.20)
|
|
39
|
+
return 'normal';
|
|
40
|
+
if (atmIV < 0.35)
|
|
41
|
+
return 'stressed';
|
|
42
|
+
return 'crisis';
|
|
43
|
+
}
|
|
44
|
+
function interpolateIVAtStrike(strikes, ivs, targetStrike) {
|
|
45
|
+
if (strikes.length === 0 || ivs.length === 0)
|
|
46
|
+
return 20;
|
|
47
|
+
if (strikes.length === 1)
|
|
48
|
+
return ivs[0];
|
|
49
|
+
let lower = 0;
|
|
50
|
+
let upper = strikes.length - 1;
|
|
51
|
+
for (let i = 0; i < strikes.length - 1; i++) {
|
|
52
|
+
if (strikes[i] <= targetStrike && strikes[i + 1] >= targetStrike) {
|
|
53
|
+
lower = i;
|
|
54
|
+
upper = i + 1;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (targetStrike <= strikes[0])
|
|
59
|
+
return ivs[0];
|
|
60
|
+
if (targetStrike >= strikes[strikes.length - 1])
|
|
61
|
+
return ivs[ivs.length - 1];
|
|
62
|
+
const t = (targetStrike - strikes[lower]) / (strikes[upper] - strikes[lower]);
|
|
63
|
+
return ivs[lower] + t * (ivs[upper] - ivs[lower]);
|
|
64
|
+
}
|
|
65
|
+
function calculateSkewAtSpot(strikes, ivs, spot) {
|
|
66
|
+
if (strikes.length < 2)
|
|
67
|
+
return 0;
|
|
68
|
+
let lowerIdx = 0;
|
|
69
|
+
let upperIdx = strikes.length - 1;
|
|
70
|
+
for (let i = 0; i < strikes.length - 1; i++) {
|
|
71
|
+
if (strikes[i] <= spot && strikes[i + 1] >= spot) {
|
|
72
|
+
lowerIdx = i;
|
|
73
|
+
upperIdx = i + 1;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const dIV = ivs[upperIdx] - ivs[lowerIdx];
|
|
78
|
+
const dK = strikes[upperIdx] - strikes[lowerIdx];
|
|
79
|
+
return dK > 0 ? (dIV / dK) * spot : 0;
|
|
80
|
+
}
|
|
81
|
+
function calculateCurvatureAtSpot(strikes, ivs, spot) {
|
|
82
|
+
if (strikes.length < 3)
|
|
83
|
+
return 0;
|
|
84
|
+
let centerIdx = 0;
|
|
85
|
+
for (let i = 0; i < strikes.length; i++) {
|
|
86
|
+
if (Math.abs(strikes[i] - spot) < Math.abs(strikes[centerIdx] - spot)) {
|
|
87
|
+
centerIdx = i;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (centerIdx === 0 || centerIdx === strikes.length - 1)
|
|
91
|
+
return 0;
|
|
92
|
+
const h = (strikes[centerIdx + 1] - strikes[centerIdx - 1]) / 2;
|
|
93
|
+
if (h <= 0)
|
|
94
|
+
return 0;
|
|
95
|
+
const ivMinus = ivs[centerIdx - 1];
|
|
96
|
+
const iv = ivs[centerIdx];
|
|
97
|
+
const ivPlus = ivs[centerIdx + 1];
|
|
98
|
+
return ((ivPlus - 2 * iv + ivMinus) / (h * h)) * spot * spot;
|
|
99
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regime classification based on IV level and surface characteristics
|
|
3
|
+
*/
|
|
4
|
+
export type MarketRegime = 'calm' | 'normal' | 'stressed' | 'crisis';
|
|
5
|
+
/**
|
|
6
|
+
* Parameters derived from the IV surface itself (no external data needed)
|
|
7
|
+
*/
|
|
8
|
+
export interface RegimeParams {
|
|
9
|
+
/** ATM implied volatility (as decimal, e.g., 0.18 for 18%) */
|
|
10
|
+
atmIV: number;
|
|
11
|
+
/** Implied spot-vol correlation derived from skew */
|
|
12
|
+
impliedSpotVolCorr: number;
|
|
13
|
+
/** Implied vol-of-vol derived from smile curvature */
|
|
14
|
+
impliedVolOfVol: number;
|
|
15
|
+
/** Regime classification */
|
|
16
|
+
regime: MarketRegime;
|
|
17
|
+
/** Expected daily spot move (as decimal) */
|
|
18
|
+
expectedDailySpotMove: number;
|
|
19
|
+
/** Expected daily vol move (as decimal) */
|
|
20
|
+
expectedDailyVolMove: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for the hedge impulse curve computation
|
|
24
|
+
*/
|
|
25
|
+
export interface HedgeImpulseConfig {
|
|
26
|
+
/** Price grid range as percentage of spot (e.g. 3 for ±3%). Default: 3 */
|
|
27
|
+
rangePercent?: number;
|
|
28
|
+
/** Price grid step as percentage of spot (e.g. 0.05 for 0.05%). Default: 0.05 */
|
|
29
|
+
stepPercent?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Gaussian kernel width in number of strike spacings.
|
|
32
|
+
* Auto-detected from the option chain's strike spacing.
|
|
33
|
+
* Default: 2 (i.e. lambda = 2 * modal strike spacing)
|
|
34
|
+
*/
|
|
35
|
+
kernelWidthStrikes?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Hedge impulse value at a single price level
|
|
39
|
+
*
|
|
40
|
+
* The hedge impulse H(S) represents the net dealer delta hedge change
|
|
41
|
+
* per unit spot move if price were at S. It combines gamma and vanna
|
|
42
|
+
* via the empirical spot-vol coupling:
|
|
43
|
+
*
|
|
44
|
+
* H(S) = Gamma(S) - (k / S) * Vanna(S)
|
|
45
|
+
*
|
|
46
|
+
* where k is derived from the IV surface skew slope.
|
|
47
|
+
*/
|
|
48
|
+
export interface HedgeImpulsePoint {
|
|
49
|
+
/** Price level */
|
|
50
|
+
price: number;
|
|
51
|
+
/** Smoothed gamma exposure at this price level (kernel-weighted from strikes) */
|
|
52
|
+
gamma: number;
|
|
53
|
+
/** Smoothed vanna exposure at this price level (kernel-weighted from strikes) */
|
|
54
|
+
vanna: number;
|
|
55
|
+
/** Combined hedge impulse: gamma - (k/S) * vanna */
|
|
56
|
+
impulse: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A zero crossing of the hedge impulse curve
|
|
60
|
+
*/
|
|
61
|
+
export interface ZeroCrossing {
|
|
62
|
+
/** Price at which the crossing occurs (interpolated) */
|
|
63
|
+
price: number;
|
|
64
|
+
/** Direction: 'rising' means impulse goes from negative to positive */
|
|
65
|
+
direction: 'rising' | 'falling';
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A local extremum (basin or peak) of the hedge impulse curve
|
|
69
|
+
*/
|
|
70
|
+
export interface ImpulseExtremum {
|
|
71
|
+
/** Price at the extremum */
|
|
72
|
+
price: number;
|
|
73
|
+
/** Impulse value at the extremum */
|
|
74
|
+
impulse: number;
|
|
75
|
+
/** 'basin' = positive local max (attractor), 'peak' = negative local min (accelerator) */
|
|
76
|
+
type: 'basin' | 'peak';
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Directional asymmetry analysis around current spot
|
|
80
|
+
*/
|
|
81
|
+
export interface DirectionalAsymmetry {
|
|
82
|
+
/** Integrated impulse from spot to spot + integrationRange */
|
|
83
|
+
upside: number;
|
|
84
|
+
/** Integrated impulse from spot to spot - integrationRange */
|
|
85
|
+
downside: number;
|
|
86
|
+
/** Integration range used (percentage of spot) */
|
|
87
|
+
integrationRangePercent: number;
|
|
88
|
+
/** Which side has more negative impulse (= path of least resistance) */
|
|
89
|
+
bias: 'up' | 'down' | 'neutral';
|
|
90
|
+
/** Ratio of |upside| to |downside| impulse. >1 means upside is larger magnitude */
|
|
91
|
+
asymmetryRatio: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Regime classification based on the impulse curve shape
|
|
95
|
+
*/
|
|
96
|
+
export type ImpulseRegime = 'pinned' | 'expansion' | 'squeeze-up' | 'squeeze-down' | 'neutral';
|
|
97
|
+
/**
|
|
98
|
+
* Complete hedge impulse curve result
|
|
99
|
+
*/
|
|
100
|
+
export interface HedgeImpulseCurve {
|
|
101
|
+
/** Current spot price */
|
|
102
|
+
spot: number;
|
|
103
|
+
/** Expiration timestamp */
|
|
104
|
+
expiration: number;
|
|
105
|
+
/** Timestamp when this curve was computed */
|
|
106
|
+
computedAt: number;
|
|
107
|
+
/** Spot-vol coupling coefficient derived from IV surface */
|
|
108
|
+
spotVolCoupling: number;
|
|
109
|
+
/** Kernel width used (in price units) */
|
|
110
|
+
kernelWidth: number;
|
|
111
|
+
/** Strike spacing detected from the option chain */
|
|
112
|
+
strikeSpacing: number;
|
|
113
|
+
/** The full curve of impulse values across the price grid */
|
|
114
|
+
curve: HedgeImpulsePoint[];
|
|
115
|
+
/** Impulse value at current spot (interpolated) */
|
|
116
|
+
impulseAtSpot: number;
|
|
117
|
+
/** Slope of the impulse curve at current spot (dH/dS) */
|
|
118
|
+
slopeAtSpot: number;
|
|
119
|
+
/** Zero crossings of the impulse curve */
|
|
120
|
+
zeroCrossings: ZeroCrossing[];
|
|
121
|
+
/** Local extrema (basins = attractors, peaks = accelerators) */
|
|
122
|
+
extrema: ImpulseExtremum[];
|
|
123
|
+
/** Directional asymmetry analysis */
|
|
124
|
+
asymmetry: DirectionalAsymmetry;
|
|
125
|
+
/** Regime classification */
|
|
126
|
+
regime: ImpulseRegime;
|
|
127
|
+
/** Nearest attractor (positive impulse basin) above spot, if any */
|
|
128
|
+
nearestAttractorAbove: number | null;
|
|
129
|
+
/** Nearest attractor (positive impulse basin) below spot, if any */
|
|
130
|
+
nearestAttractorBelow: number | null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Configuration for charm integral computation
|
|
134
|
+
*/
|
|
135
|
+
export interface CharmIntegralConfig {
|
|
136
|
+
/** Time step for the integral in minutes. Default: 15 */
|
|
137
|
+
timeStepMinutes?: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Charm integral at a single time bucket
|
|
141
|
+
*/
|
|
142
|
+
export interface CharmBucket {
|
|
143
|
+
/** Minutes remaining to expiry at start of this bucket */
|
|
144
|
+
minutesRemaining: number;
|
|
145
|
+
/** Instantaneous CEX at this time */
|
|
146
|
+
instantaneousCEX: number;
|
|
147
|
+
/** Cumulative CEX from now to this time */
|
|
148
|
+
cumulativeCEX: number;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Complete charm integral result
|
|
152
|
+
*/
|
|
153
|
+
export interface CharmIntegral {
|
|
154
|
+
/** Current spot price */
|
|
155
|
+
spot: number;
|
|
156
|
+
/** Expiration timestamp */
|
|
157
|
+
expiration: number;
|
|
158
|
+
/** Timestamp when this was computed */
|
|
159
|
+
computedAt: number;
|
|
160
|
+
/** Minutes remaining from computation time to expiry */
|
|
161
|
+
minutesRemaining: number;
|
|
162
|
+
/** Total charm integral from now to close (cumulative expected delta change) */
|
|
163
|
+
totalCharmToClose: number;
|
|
164
|
+
/** Direction: positive = net buying pressure from charm, negative = net selling */
|
|
165
|
+
direction: 'buying' | 'selling' | 'neutral';
|
|
166
|
+
/** Bucketed charm integral curve for visualization */
|
|
167
|
+
buckets: CharmBucket[];
|
|
168
|
+
/** Per-strike charm breakdown (for understanding what drives the integral) */
|
|
169
|
+
strikeContributions: Array<{
|
|
170
|
+
strike: number;
|
|
171
|
+
charmExposure: number;
|
|
172
|
+
fractionOfTotal: number;
|
|
173
|
+
}>;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Complete hedge flow analysis combining impulse curve and charm integral
|
|
177
|
+
*/
|
|
178
|
+
export interface HedgeFlowAnalysis {
|
|
179
|
+
/** The instantaneous hedge impulse curve (left panel) */
|
|
180
|
+
impulseCurve: HedgeImpulseCurve;
|
|
181
|
+
/** The charm integral to close (right panel) */
|
|
182
|
+
charmIntegral: CharmIntegral;
|
|
183
|
+
/** Regime params derived from IV surface */
|
|
184
|
+
regimeParams: RegimeParams;
|
|
185
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { ImpliedProbabilityDistribution, getProbabilityInRange, getCumulativeProbability, getQuantile } from './index';
|
|
2
|
+
import { ExposurePerExpiry, NormalizedOption } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for exposure-based PDF adjustments
|
|
5
|
+
*/
|
|
6
|
+
export interface ExposureAdjustmentConfig {
|
|
7
|
+
/** Gamma adjustment settings */
|
|
8
|
+
gamma: {
|
|
9
|
+
/** Enable gamma-based kurtosis adjustment */
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
/** Strength of attractor effect at +GEX strikes (0-1) */
|
|
12
|
+
attractorStrength: number;
|
|
13
|
+
/** Strength of repellent effect at -GEX strikes (0-1) */
|
|
14
|
+
repellentStrength: number;
|
|
15
|
+
/** Minimum absolute GEX to consider significant (in dollars) */
|
|
16
|
+
threshold: number;
|
|
17
|
+
/** Decay rate for influence distance (higher = more localized) */
|
|
18
|
+
decayRate: number;
|
|
19
|
+
};
|
|
20
|
+
/** Vanna adjustment settings */
|
|
21
|
+
vanna: {
|
|
22
|
+
/** Enable vanna-based tail adjustment */
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
/** Spot-vol beta: IV change per 1% spot move (typically -2 to -4 for indices) */
|
|
25
|
+
spotVolBeta: number;
|
|
26
|
+
/** Maximum tail fattening multiplier */
|
|
27
|
+
maxTailMultiplier: number;
|
|
28
|
+
/** Number of feedback iterations to simulate */
|
|
29
|
+
feedbackIterations: number;
|
|
30
|
+
};
|
|
31
|
+
/** Charm adjustment settings */
|
|
32
|
+
charm: {
|
|
33
|
+
/** Enable charm-based mean shift */
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
/** Time horizon multiplier ('intraday' = 0.25, 'daily' = 1.0, 'weekly' = 5.0) */
|
|
36
|
+
timeHorizon: 'intraday' | 'daily' | 'weekly';
|
|
37
|
+
/** Scaling factor for mean shift */
|
|
38
|
+
shiftScale: number;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result of exposure-adjusted PDF calculation
|
|
43
|
+
*/
|
|
44
|
+
export interface AdjustedPDFResult {
|
|
45
|
+
/** Original market-implied distribution */
|
|
46
|
+
baseline: ImpliedProbabilityDistribution;
|
|
47
|
+
/** Exposure-adjusted distribution */
|
|
48
|
+
adjusted: ImpliedProbabilityDistribution;
|
|
49
|
+
/** Gamma modifier applied at each strike (multiplicative) */
|
|
50
|
+
gammaModifiers: number[];
|
|
51
|
+
/** Vanna modifier applied at each strike (multiplicative) */
|
|
52
|
+
vannaModifiers: number[];
|
|
53
|
+
/** Charm-induced mean shift (in price units) */
|
|
54
|
+
charmShift: number;
|
|
55
|
+
/** Comparison metrics between baseline and adjusted */
|
|
56
|
+
comparison: PDFComparison;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Comparison metrics between baseline and adjusted PDFs
|
|
60
|
+
*/
|
|
61
|
+
export interface PDFComparison {
|
|
62
|
+
/** Shift in expected value */
|
|
63
|
+
meanShift: number;
|
|
64
|
+
/** Shift as percentage of spot */
|
|
65
|
+
meanShiftPercent: number;
|
|
66
|
+
/** Change in standard deviation */
|
|
67
|
+
stdDevChange: number;
|
|
68
|
+
/** Change in tail skew ratio */
|
|
69
|
+
tailSkewChange: number;
|
|
70
|
+
/** 5th percentile: baseline vs adjusted */
|
|
71
|
+
leftTail: {
|
|
72
|
+
baseline: number;
|
|
73
|
+
adjusted: number;
|
|
74
|
+
ratio: number;
|
|
75
|
+
};
|
|
76
|
+
/** 95th percentile: baseline vs adjusted */
|
|
77
|
+
rightTail: {
|
|
78
|
+
baseline: number;
|
|
79
|
+
adjusted: number;
|
|
80
|
+
ratio: number;
|
|
81
|
+
};
|
|
82
|
+
/** Dominant adjustment factor */
|
|
83
|
+
dominantFactor: 'gamma' | 'vanna' | 'charm' | 'none';
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Default configuration tuned for SPX-like indices
|
|
87
|
+
*/
|
|
88
|
+
export declare const DEFAULT_ADJUSTMENT_CONFIG: ExposureAdjustmentConfig;
|
|
89
|
+
/**
|
|
90
|
+
* Configuration for low volatility / grinding markets
|
|
91
|
+
*/
|
|
92
|
+
export declare const LOW_VOL_CONFIG: ExposureAdjustmentConfig;
|
|
93
|
+
/**
|
|
94
|
+
* Configuration for high volatility / crisis markets
|
|
95
|
+
*/
|
|
96
|
+
export declare const CRISIS_CONFIG: ExposureAdjustmentConfig;
|
|
97
|
+
/**
|
|
98
|
+
* Configuration for OPEX week
|
|
99
|
+
*/
|
|
100
|
+
export declare const OPEX_CONFIG: ExposureAdjustmentConfig;
|
|
101
|
+
/**
|
|
102
|
+
* Estimate an exposure-adjusted implied probability distribution.
|
|
103
|
+
*
|
|
104
|
+
* This function takes the standard market-implied PDF (Breeden-Litzenberger)
|
|
105
|
+
* and adjusts it based on dealer Greek exposures to produce a "mechanically-informed"
|
|
106
|
+
* probability distribution that accounts for:
|
|
107
|
+
*
|
|
108
|
+
* - **Gamma**: Creates "sticky" zones (+GEX) where price pins, and "slippery" zones
|
|
109
|
+
* (-GEX) where price accelerates through
|
|
110
|
+
* - **Vanna**: Fattens tails based on the IV-spot feedback loop (selloffs spike IV,
|
|
111
|
+
* which forces more selling via negative vanna)
|
|
112
|
+
* - **Charm**: Shifts the mean based on predictable delta decay over time
|
|
113
|
+
*
|
|
114
|
+
* @param symbol - Underlying ticker symbol
|
|
115
|
+
* @param underlyingPrice - Current spot price
|
|
116
|
+
* @param callOptions - Call options for a single expiry
|
|
117
|
+
* @param exposures - Exposure metrics from calculateGammaVannaCharmExposures()
|
|
118
|
+
* @param config - Adjustment configuration (uses defaults if not provided)
|
|
119
|
+
* @returns Baseline and adjusted PDFs with comparison metrics
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* // Get exposures first
|
|
124
|
+
* const allExposures = calculateGammaVannaCharmExposures(chain, ivSurfaces);
|
|
125
|
+
* const expiryExposures = allExposures.find(e => e.expiration === targetExpiry);
|
|
126
|
+
*
|
|
127
|
+
* // Calculate adjusted PDF
|
|
128
|
+
* const result = estimateExposureAdjustedPDF(
|
|
129
|
+
* 'SPX',
|
|
130
|
+
* 4520,
|
|
131
|
+
* callOptionsForExpiry,
|
|
132
|
+
* expiryExposures
|
|
133
|
+
* );
|
|
134
|
+
*
|
|
135
|
+
* // Compare probabilities
|
|
136
|
+
* const target = 4400;
|
|
137
|
+
* const baselineProb = getCumulativeProbability(result.baseline, target);
|
|
138
|
+
* const adjustedProb = getCumulativeProbability(result.adjusted, target);
|
|
139
|
+
* console.log(`Market says ${baselineProb}% chance of ${target}`);
|
|
140
|
+
* console.log(`Flow-adjusted: ${adjustedProb}% chance`);
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export declare function estimateExposureAdjustedPDF(symbol: string, underlyingPrice: number, callOptions: NormalizedOption[], exposures: ExposurePerExpiry, config?: Partial<ExposureAdjustmentConfig>): AdjustedPDFResult | {
|
|
144
|
+
success: false;
|
|
145
|
+
error: string;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Get the "edge" - the difference between market-implied and flow-adjusted
|
|
149
|
+
* probability of reaching a price level.
|
|
150
|
+
*
|
|
151
|
+
* Positive edge means the market is underpricing the probability of reaching that level.
|
|
152
|
+
* Negative edge means the market is overpricing it.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* const result = estimateExposureAdjustedPDF(...);
|
|
157
|
+
* const edge = getEdgeAtPrice(result, 4400);
|
|
158
|
+
* console.log(`Edge at 4400: ${(edge * 100).toFixed(2)}%`);
|
|
159
|
+
* // Output: "Edge at 4400: 2.35%"
|
|
160
|
+
* // Meaning: flow mechanics suggest 2.35% higher probability than market prices
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export declare function getEdgeAtPrice(result: AdjustedPDFResult, price: number): number;
|
|
164
|
+
/**
|
|
165
|
+
* Get price levels where the adjustment is most significant
|
|
166
|
+
*/
|
|
167
|
+
export declare function getSignificantAdjustmentLevels(result: AdjustedPDFResult, threshold?: number): Array<{
|
|
168
|
+
strike: number;
|
|
169
|
+
baselineProb: number;
|
|
170
|
+
adjustedProb: number;
|
|
171
|
+
edge: number;
|
|
172
|
+
}>;
|
|
173
|
+
export { getProbabilityInRange, getCumulativeProbability, getQuantile };
|