@fullstackcraftllc/floe 0.0.13 → 0.0.14
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 +7 -7
- package/dist/client/brokers/TradierClient.js +7 -6
- 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 +4 -2
- package/dist/index.js +27 -1
- 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/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,182 @@
|
|
|
1
|
+
import { IVSurface, ExposurePerExpiry } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Regime classification based on IV level and surface characteristics
|
|
4
|
+
*/
|
|
5
|
+
export type MarketRegime = 'calm' | 'normal' | 'stressed' | 'crisis';
|
|
6
|
+
/**
|
|
7
|
+
* Parameters derived from the IV surface itself (no external data needed)
|
|
8
|
+
*/
|
|
9
|
+
export interface RegimeParams {
|
|
10
|
+
/** ATM implied volatility (as decimal, e.g., 0.18 for 18%) */
|
|
11
|
+
atmIV: number;
|
|
12
|
+
/** Implied spot-vol correlation derived from skew */
|
|
13
|
+
impliedSpotVolCorr: number;
|
|
14
|
+
/** Implied vol-of-vol derived from smile curvature */
|
|
15
|
+
impliedVolOfVol: number;
|
|
16
|
+
/** Regime classification */
|
|
17
|
+
regime: MarketRegime;
|
|
18
|
+
/** Expected daily spot move (as decimal) */
|
|
19
|
+
expectedDailySpotMove: number;
|
|
20
|
+
/** Expected daily vol move (as decimal) */
|
|
21
|
+
expectedDailyVolMove: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Normalized exposure at a single strike
|
|
25
|
+
*/
|
|
26
|
+
export interface NormalizedExposure {
|
|
27
|
+
strike: number;
|
|
28
|
+
rawGamma: number;
|
|
29
|
+
rawVanna: number;
|
|
30
|
+
rawCharm: number;
|
|
31
|
+
effectiveGamma: number;
|
|
32
|
+
effectiveVanna: number;
|
|
33
|
+
effectiveCharm: number;
|
|
34
|
+
totalEffective: number;
|
|
35
|
+
dominant: 'gamma' | 'vanna' | 'charm';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Aggregate normalized exposure metrics
|
|
39
|
+
*/
|
|
40
|
+
export interface NormalizedExposureSummary {
|
|
41
|
+
spot: number;
|
|
42
|
+
expiration: number;
|
|
43
|
+
regimeParams: RegimeParams;
|
|
44
|
+
strikeExposures: NormalizedExposure[];
|
|
45
|
+
totalEffectiveGamma: number;
|
|
46
|
+
totalEffectiveVanna: number;
|
|
47
|
+
totalEffectiveCharm: number;
|
|
48
|
+
totalEffective: number;
|
|
49
|
+
dominantGreek: 'gamma' | 'vanna' | 'charm';
|
|
50
|
+
weights: {
|
|
51
|
+
gamma: number;
|
|
52
|
+
vanna: number;
|
|
53
|
+
charm: number;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Hedging pressure at a (spot, time) coordinate
|
|
58
|
+
*/
|
|
59
|
+
export interface HedgingPressure {
|
|
60
|
+
spot: number;
|
|
61
|
+
timeToExpiry: number;
|
|
62
|
+
hoursRemaining: number;
|
|
63
|
+
gammaFlow: number;
|
|
64
|
+
vannaFlow: number;
|
|
65
|
+
charmFlow: number;
|
|
66
|
+
netPressure: number;
|
|
67
|
+
effectivePressure: number;
|
|
68
|
+
direction: 'supportive' | 'resistive' | 'neutral';
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Grid cell for pressure visualization
|
|
72
|
+
*/
|
|
73
|
+
export interface PressureGridCell {
|
|
74
|
+
spot: number;
|
|
75
|
+
hoursRemaining: number;
|
|
76
|
+
pressure: HedgingPressure;
|
|
77
|
+
spotGradient: number;
|
|
78
|
+
timeGradient: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Key levels derived from pressure field
|
|
82
|
+
*/
|
|
83
|
+
export interface KeyLevels {
|
|
84
|
+
support: number[];
|
|
85
|
+
resistance: number[];
|
|
86
|
+
pinning: number[];
|
|
87
|
+
gammaFlip: number | null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Path of least resistance analysis
|
|
91
|
+
*/
|
|
92
|
+
export interface PathOfLeastResistance {
|
|
93
|
+
direction: 'up' | 'down' | 'pin';
|
|
94
|
+
targetSpot: number;
|
|
95
|
+
confidence: number;
|
|
96
|
+
rationale: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Complete pressure grid
|
|
100
|
+
*/
|
|
101
|
+
export interface PressureGrid {
|
|
102
|
+
symbol: string;
|
|
103
|
+
expiration: number;
|
|
104
|
+
currentSpot: number;
|
|
105
|
+
timestamp: number;
|
|
106
|
+
regime: MarketRegime;
|
|
107
|
+
spotRange: {
|
|
108
|
+
min: number;
|
|
109
|
+
max: number;
|
|
110
|
+
step: number;
|
|
111
|
+
};
|
|
112
|
+
timeRange: {
|
|
113
|
+
min: number;
|
|
114
|
+
max: number;
|
|
115
|
+
step: number;
|
|
116
|
+
};
|
|
117
|
+
cells: PressureGridCell[][];
|
|
118
|
+
keyLevels: KeyLevels;
|
|
119
|
+
pathOfLeastResistance: PathOfLeastResistance;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* IV pressure at a specific strike
|
|
123
|
+
*/
|
|
124
|
+
export interface StrikeIVPressure {
|
|
125
|
+
strike: number;
|
|
126
|
+
currentIV: number;
|
|
127
|
+
vannaIVPressure: number;
|
|
128
|
+
vommaIVPressure: number;
|
|
129
|
+
vetaIVPressure: number;
|
|
130
|
+
netIVPressure: number;
|
|
131
|
+
liquidityScore: number;
|
|
132
|
+
expectedIVMove: number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* IV surface evolution prediction
|
|
136
|
+
*/
|
|
137
|
+
export interface IVSurfaceEvolution {
|
|
138
|
+
currentSurface: IVSurface;
|
|
139
|
+
predictedSurface: IVSurface;
|
|
140
|
+
strikePressures: StrikeIVPressure[];
|
|
141
|
+
netSurfacePressure: number;
|
|
142
|
+
atmIVMove: number;
|
|
143
|
+
skewChange: number;
|
|
144
|
+
curvatureChange: number;
|
|
145
|
+
confidence: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Cascade simulation step
|
|
149
|
+
*/
|
|
150
|
+
export interface CascadeStep {
|
|
151
|
+
step: number;
|
|
152
|
+
spot: number;
|
|
153
|
+
ivSurface: IVSurface;
|
|
154
|
+
exposures: ExposurePerExpiry;
|
|
155
|
+
regime: MarketRegime;
|
|
156
|
+
ivPressure: number;
|
|
157
|
+
spotPressure: number;
|
|
158
|
+
cumulativeIVMove: number;
|
|
159
|
+
cumulativeSpotMove: number;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Full cascade simulation result
|
|
163
|
+
*/
|
|
164
|
+
export interface CascadeSimulation {
|
|
165
|
+
initial: CascadeStep;
|
|
166
|
+
steps: CascadeStep[];
|
|
167
|
+
terminal: CascadeStep;
|
|
168
|
+
outcome: 'converged' | 'diverged' | 'oscillating';
|
|
169
|
+
insight: string;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Configuration for IV path prediction
|
|
173
|
+
*/
|
|
174
|
+
export interface IVPathConfig {
|
|
175
|
+
spotMoveScenario: number;
|
|
176
|
+
timeStepHours: number;
|
|
177
|
+
cascadeIterations: number;
|
|
178
|
+
cascadeDampening: number;
|
|
179
|
+
ivImpactPerMillion: number;
|
|
180
|
+
ivFloor: number;
|
|
181
|
+
ivCeiling: number;
|
|
182
|
+
}
|
|
@@ -9,8 +9,9 @@ exports.getUnderlyingFromOptionRoot = exports.OPTION_ROOT_TO_UNDERLYING = void 0
|
|
|
9
9
|
exports.OPTION_ROOT_TO_UNDERLYING = {
|
|
10
10
|
'SPXW': 'SPX', // SPX Weekly options
|
|
11
11
|
'SPXPM': 'SPX', // SPX PM-settled options
|
|
12
|
-
'NDXP': 'NDX', // NDX
|
|
12
|
+
'NDXP': 'NDX', // NDXP is Tradier's NDX options root
|
|
13
13
|
'RUTW': 'RUT', // RUT Weekly options
|
|
14
|
+
'DJXW': 'DJX', // DJX Weekly options
|
|
14
15
|
// Add more as needed
|
|
15
16
|
};
|
|
16
17
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fullstackcraftllc/floe",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Production-ready options analytics toolkit. Normalize broker data structures and calculate Black-Scholes, Greeks, and exposures with a clean, type-safe API. Built for trading platforms and fintech applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|