@fullstackcraftllc/floe 0.0.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/LICENSE-COMMERCIAL +74 -0
- package/LICENSE-MIT +27 -0
- package/LICENSE.md +65 -0
- package/README.md +272 -0
- package/dist/adapters/index.d.ts +52 -0
- package/dist/adapters/index.js +132 -0
- package/dist/blackscholes/index.d.ts +73 -0
- package/dist/blackscholes/index.js +266 -0
- package/dist/exposure/index.d.ts +35 -0
- package/dist/exposure/index.js +212 -0
- package/dist/greeks/index.d.ts +29 -0
- package/dist/greeks/index.js +107 -0
- package/dist/impliedpdf/index.d.ts +0 -0
- package/dist/impliedpdf/index.js +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +56 -0
- package/dist/types/index.d.ts +228 -0
- package/dist/types/index.js +14 -0
- package/dist/utils/statistics.d.ts +18 -0
- package/dist/utils/statistics.js +32 -0
- package/dist/volatility/index.d.ts +37 -0
- package/dist/volatility/index.js +163 -0
- package/dist/volatility/smoothing.d.ts +17 -0
- package/dist/volatility/smoothing.js +171 -0
- package/package.json +55 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Commercial License Agreement
|
|
2
|
+
|
|
3
|
+
**Full Stack Craft LLC - floe Commercial License**
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2025 Full Stack Craft LLC
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Grant of License
|
|
10
|
+
|
|
11
|
+
Subject to the terms and conditions of this agreement and payment of applicable license fees, Full Stack Craft LLC ("Licensor") grants you ("Licensee") a non-exclusive, non-transferable license to use the floe software ("Software") for commercial purposes.
|
|
12
|
+
|
|
13
|
+
## Permitted Uses
|
|
14
|
+
|
|
15
|
+
This Commercial License permits:
|
|
16
|
+
- Use in commercial, proprietary, and closed-source applications
|
|
17
|
+
- Integration into SaaS platforms and trading systems
|
|
18
|
+
- Deployment in production environments serving customers
|
|
19
|
+
- Use in revenue-generating applications
|
|
20
|
+
- No requirement to disclose source code
|
|
21
|
+
|
|
22
|
+
## Restrictions
|
|
23
|
+
|
|
24
|
+
Licensee may not:
|
|
25
|
+
- Redistribute or resell the Software as a standalone product
|
|
26
|
+
- Remove or modify license notices or attributions
|
|
27
|
+
- Use the Software in a way that competes directly with Licensor's business
|
|
28
|
+
- Sublicense the Software to third parties
|
|
29
|
+
|
|
30
|
+
## Support and Updates
|
|
31
|
+
|
|
32
|
+
Commercial License includes:
|
|
33
|
+
- Email support (response within 48 business hours)
|
|
34
|
+
- Access to software updates and bug fixes
|
|
35
|
+
- Security patches and vulnerability fixes
|
|
36
|
+
|
|
37
|
+
**Enterprise tier additionally includes:**
|
|
38
|
+
- Priority support with SLA guarantees
|
|
39
|
+
- Custom broker integrations
|
|
40
|
+
- Dedicated support channel
|
|
41
|
+
- Implementation assistance
|
|
42
|
+
|
|
43
|
+
## Fees
|
|
44
|
+
|
|
45
|
+
License fees are based on the tier selected:
|
|
46
|
+
- **Developer**: $149/month or $1,490/year
|
|
47
|
+
- **Professional**: $499/month or $4,990/year
|
|
48
|
+
- **Enterprise**: Custom pricing based on requirements
|
|
49
|
+
|
|
50
|
+
Contact hi@fullstackcraft.com for current pricing.
|
|
51
|
+
|
|
52
|
+
## Term and Termination
|
|
53
|
+
|
|
54
|
+
This license is effective upon payment and continues for the subscription period. Failure to pay renewal fees will result in termination of the license. Upon termination, Licensee must cease all use of the Software.
|
|
55
|
+
|
|
56
|
+
## Warranty Disclaimer
|
|
57
|
+
|
|
58
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
59
|
+
|
|
60
|
+
## Limitation of Liability
|
|
61
|
+
|
|
62
|
+
IN NO EVENT SHALL LICENSOR BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE.
|
|
63
|
+
|
|
64
|
+
## Governing Law
|
|
65
|
+
|
|
66
|
+
This Agreement shall be governed by the laws of the State of Delaware, United States.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
**To obtain a Commercial License:**
|
|
71
|
+
- Email: hi@fullstackcraft.com
|
|
72
|
+
- Website: https://fullstackcraft.com/floe/pricing
|
|
73
|
+
|
|
74
|
+
Full Stack Craft LLC
|
package/LICENSE-MIT
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Full Stack Craft LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
IMPORTANT: This MIT License only applies to individual and non-commercial use.
|
|
26
|
+
For commercial use, a Commercial License is required.
|
|
27
|
+
See LICENSE.md for details.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Dual License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Full Stack Craft LLC
|
|
4
|
+
|
|
5
|
+
This software is available under two licenses. Choose the one that best fits your use case:
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. MIT License (For Individual/Non-Commercial Use)
|
|
10
|
+
|
|
11
|
+
**This license applies to:**
|
|
12
|
+
- Individual developers using floe for personal projects
|
|
13
|
+
- Educational and academic purposes
|
|
14
|
+
- Open-source projects (must remain open-source)
|
|
15
|
+
- Non-profit organizations
|
|
16
|
+
- Evaluation and testing purposes
|
|
17
|
+
|
|
18
|
+
See [LICENSE-MIT](LICENSE-MIT) for full terms.
|
|
19
|
+
|
|
20
|
+
**Free to use** - No payment required for individual, non-commercial use.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. Commercial License (For Business/Commercial Use)
|
|
25
|
+
|
|
26
|
+
**This license is required for:**
|
|
27
|
+
- Any business or commercial entity using floe in production
|
|
28
|
+
- SaaS applications and trading platforms
|
|
29
|
+
- Proprietary software and closed-source projects
|
|
30
|
+
- Fintech applications serving customers
|
|
31
|
+
- Any revenue-generating use of this software
|
|
32
|
+
|
|
33
|
+
**Pricing:**
|
|
34
|
+
- Contact us at: **hi@fullstackcraft.com**
|
|
35
|
+
- Visit: **https://fullstackcraft.com/floe/pricing**
|
|
36
|
+
|
|
37
|
+
The Commercial License includes:
|
|
38
|
+
- Permission to use in commercial/proprietary applications
|
|
39
|
+
- No requirement to disclose source code
|
|
40
|
+
- Priority support and bug fixes
|
|
41
|
+
- SLA guarantees (Enterprise tier)
|
|
42
|
+
- Custom broker integrations (Enterprise tier)
|
|
43
|
+
|
|
44
|
+
See [LICENSE-COMMERCIAL](LICENSE-COMMERCIAL) for full terms.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## How to Choose
|
|
49
|
+
|
|
50
|
+
**Use MIT License if:**
|
|
51
|
+
- You're an individual developer working on personal projects
|
|
52
|
+
- You're building an open-source project that will remain open-source
|
|
53
|
+
- You're a student or academic using this for research/education
|
|
54
|
+
|
|
55
|
+
**Use Commercial License if:**
|
|
56
|
+
- You're a business using this in production
|
|
57
|
+
- You're building a commercial product or service
|
|
58
|
+
- You're generating revenue using this software
|
|
59
|
+
- You need support, SLAs, or custom integrations
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Questions?
|
|
64
|
+
|
|
65
|
+
Contact us at **hi@fullstackcraft.com** for licensing questions.
|
package/README.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# `floe`
|
|
2
|
+
|
|
3
|
+
Browser-only TypeScript functions for calculating Black-Scholes, Greeks, and dealer exposures with a clean, type-safe API. Built for use in trading platforms and fintech applications.
|
|
4
|
+
|
|
5
|
+
The same library that is used in Full Stack Craft's various fintech products including [The Wheel Screener](https://wheelscreener.com), [LEAPS Screener](https://leapsscreener.com), [Option Screener](https://option-screener.com), [AMT JOY](https://amtjoy.com), and [VannaCharm](https://vannacharm.com).
|
|
6
|
+
|
|
7
|
+
## 📋 Dual License
|
|
8
|
+
|
|
9
|
+
**This project is dual-licensed:**
|
|
10
|
+
|
|
11
|
+
- ✅ **MIT License** - Free for individuals, personal projects, and non-commercial use
|
|
12
|
+
- 💼 **Commercial License** - Required for businesses and commercial applications
|
|
13
|
+
|
|
14
|
+
[Read full licensing details](LICENSE.md) | [Get Commercial License](mailto:hi@fullstackcraft.com)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- 🎯 **Black-Scholes Pricing** - Fast, accurate options pricing
|
|
21
|
+
- 📊 **Greeks Calculations** - Delta, gamma, theta, vega, rho
|
|
22
|
+
- 🔄 **Dealer Exposure Metrics** - GEX, VEX, and CEX exposures
|
|
23
|
+
- 🔌 **Broker-Agnostic** - Normalize data from any broker
|
|
24
|
+
- 💪 **Type-Safe** - Full TypeScript support
|
|
25
|
+
- ⚡ **Zero Dependencies** - Lightweight and fast
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @fullstackcraftllc/floe
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
Nearly everything in `floe` revolves around the `NormalizedOption` interface, which provides a consistent way to represent options data regardless of the broker source:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
/**
|
|
39
|
+
* Normalized option data structure (broker-agnostic)
|
|
40
|
+
*/
|
|
41
|
+
export interface NormalizedOption {
|
|
42
|
+
/** Underlying symbol */
|
|
43
|
+
symbol: string;
|
|
44
|
+
/** Strike price */
|
|
45
|
+
strike: number;
|
|
46
|
+
/** Expiration date (ISO 8601) */
|
|
47
|
+
expiration: string;
|
|
48
|
+
/** Option type */
|
|
49
|
+
optionType: OptionType;
|
|
50
|
+
/** Current bid price */
|
|
51
|
+
bid: number;
|
|
52
|
+
/** Current ask price */
|
|
53
|
+
ask: number;
|
|
54
|
+
/** Last traded price */
|
|
55
|
+
last: number;
|
|
56
|
+
/** Trading volume */
|
|
57
|
+
volume: number;
|
|
58
|
+
/** Open interest */
|
|
59
|
+
openInterest: number;
|
|
60
|
+
/** Implied volatility (as decimal) */
|
|
61
|
+
impliedVolatility: number;
|
|
62
|
+
/** Pre-calculated Greeks (optional) */
|
|
63
|
+
greeks?: Greeks;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { blackScholes, calculateGreeks, calculateGEX } from '@fullstackcraftllc/floe';
|
|
69
|
+
|
|
70
|
+
// Calculate option price
|
|
71
|
+
const price = blackScholes({
|
|
72
|
+
spot: 100,
|
|
73
|
+
strike: 105,
|
|
74
|
+
timeToExpiry: 0.25,
|
|
75
|
+
volatility: 0.20,
|
|
76
|
+
riskFreeRate: 0.05,
|
|
77
|
+
optionType: 'call'
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Calculate Greeks
|
|
81
|
+
const greeks = calculateGreeks({
|
|
82
|
+
spot: 100,
|
|
83
|
+
strike: 105,
|
|
84
|
+
timeToExpiry: 0.25,
|
|
85
|
+
volatility: 0.20,
|
|
86
|
+
riskFreeRate: 0.05,
|
|
87
|
+
optionType: 'call'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const normalizedOptions = [
|
|
91
|
+
{
|
|
92
|
+
symbol: 'AAPL',
|
|
93
|
+
strike: 105,
|
|
94
|
+
expiration: '2025-12-20',
|
|
95
|
+
optionType: 'call',
|
|
96
|
+
bid: 2.50,
|
|
97
|
+
ask: 2.60,
|
|
98
|
+
last: 2.55,
|
|
99
|
+
volume: 150,
|
|
100
|
+
openInterest: 2000,
|
|
101
|
+
impliedVolatility: 0.22
|
|
102
|
+
},
|
|
103
|
+
// ...more options
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const gexData = calculateGEX(normalizedOptions, 100, 100);
|
|
107
|
+
|
|
108
|
+
console.log('Option Price:', price);
|
|
109
|
+
console.log('Delta:', greeks.delta);
|
|
110
|
+
console.log('Gamma:', greeks.gamma);
|
|
111
|
+
console.log('Net Gamma:', gexData.netGamma);
|
|
112
|
+
console.log('Strike of Max Gamma:', gexData.maxPositiveStrike);
|
|
113
|
+
console.log('Strike of Min Gamma:', gexData.maxNegativeStrike);
|
|
114
|
+
console.log('Zero Gamma Level:', gexData.zeroGammaLevel);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Broker Normalization
|
|
118
|
+
|
|
119
|
+
Floe provides adapters for normalizing options data from multiple brokers:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { normalizeTastyworksData } from '@fullstackcraftllc/floe';
|
|
123
|
+
|
|
124
|
+
// Tastyworks data
|
|
125
|
+
const normalizedOptions = normalizeTastyworksData(rawTastyData);
|
|
126
|
+
|
|
127
|
+
// Now both use the same interface
|
|
128
|
+
normalizedOptions.forEach(option => {
|
|
129
|
+
const greeks = calculateGreeks(option);
|
|
130
|
+
console.log(greeks);
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## For Devs - Example / Documentation Site
|
|
135
|
+
|
|
136
|
+
The website at [fullstackcraft.github.io/floe](https://fullstackcraft.github.io/floe) contains live code examples and documentation and is here locally at `./site`. It is a static site build with Next.js.
|
|
137
|
+
|
|
138
|
+
## API Documentation
|
|
139
|
+
|
|
140
|
+
### Black-Scholes Pricing
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
blackScholes(params: BlackScholesParams): number
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Calculate option price using Black-Scholes model.
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
- `spot`: Current price of underlying asset
|
|
150
|
+
- `strike`: Strike price of option
|
|
151
|
+
- `timeToExpiry`: Time to expiration in years
|
|
152
|
+
- `volatility`: Implied volatility (annualized)
|
|
153
|
+
- `riskFreeRate`: Risk-free interest rate (annualized)
|
|
154
|
+
- `optionType`: 'call' | 'put'
|
|
155
|
+
- `dividendYield?`: Dividend yield (optional, default 0)
|
|
156
|
+
|
|
157
|
+
### Greeks Calculation
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
calculateGreeks(params: BlackScholesParams): Greeks
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Calculate all Greeks for an option.
|
|
164
|
+
|
|
165
|
+
**Returns:**
|
|
166
|
+
- `delta`: Rate of change of option price with respect to underlying price
|
|
167
|
+
- `gamma`: Rate of change of delta with respect to underlying price
|
|
168
|
+
- `theta`: Rate of change of option price with respect to time
|
|
169
|
+
- `vega`: Rate of change of option price with respect to volatility
|
|
170
|
+
- `rho`: Rate of change of option price with respect to interest rate
|
|
171
|
+
|
|
172
|
+
### Estimate Implied Volatility Surface
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
estimateIVSurface(options: NormalizedOption[], spot: number): IVSurface
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Dealer Exposure Metrics
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
calculateGEX(options: NormalizedOption[]): GEXMetrics
|
|
182
|
+
calculateVanna(options: NormalizedOption[]): VannaMetrics
|
|
183
|
+
calculateCharm(options: NormalizedOption[]): CharmMetrics
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Notional Intraday Dealer Exposure Metrics
|
|
187
|
+
|
|
188
|
+
This process assume that dealer inventory consists of the previously reported open interest at t=0 (09:30AM EST), and that all options volume is bought or sold at market price based on the NBBO at the time of the trade. This is a simplification and may not reflect actual dealer inventory changes throughout the day.
|
|
189
|
+
|
|
190
|
+
Note that the nature of this calculation requires continuous intraday data including time-stamped trades and quotes to accurately model dealer inventory changes.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
calculateIntradayGEX(trades: Trade[], quotes: Quote[], initialOpenInterest: Map<string, number>, spotPrices: Map<string, number>): IntradayGEXMetrics
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Calculate dealer exposure metrics across an options chain.
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
**Free for Individuals** - Use the MIT License for personal, educational, and non-commercial projects.
|
|
201
|
+
|
|
202
|
+
**Commercial License Required** - Businesses and commercial applications must obtain a commercial license.
|
|
203
|
+
|
|
204
|
+
See [LICENSE.md](LICENSE.md) for full details.
|
|
205
|
+
|
|
206
|
+
**Need a Commercial License?** Contact us at [hi@fullstackcraft.com](mailto:hi@fullstackcraft.com)
|
|
207
|
+
|
|
208
|
+
## Pricing
|
|
209
|
+
|
|
210
|
+
### Individual (MIT License)
|
|
211
|
+
**$0/month** - Free forever
|
|
212
|
+
- ✅ Personal projects
|
|
213
|
+
- ✅ Open-source projects
|
|
214
|
+
- ✅ Educational use
|
|
215
|
+
- ✅ Community support
|
|
216
|
+
|
|
217
|
+
### Developer (Commercial)
|
|
218
|
+
**$149/month** or **$1,490/year**
|
|
219
|
+
- ✅ Commercial use
|
|
220
|
+
- ✅ Up to 100K calculations/month
|
|
221
|
+
- ✅ Email support
|
|
222
|
+
- ✅ All broker integrations
|
|
223
|
+
|
|
224
|
+
### Professional (Commercial)
|
|
225
|
+
**$499/month** or **$4,990/year**
|
|
226
|
+
- ✅ Unlimited calculations
|
|
227
|
+
- ✅ Priority support
|
|
228
|
+
- ✅ SLA guarantees
|
|
229
|
+
- ✅ Custom integrations
|
|
230
|
+
|
|
231
|
+
### Enterprise (Commercial)
|
|
232
|
+
**Custom pricing**
|
|
233
|
+
- ✅ White-label options
|
|
234
|
+
- ✅ Dedicated support
|
|
235
|
+
- ✅ On-premise deployment
|
|
236
|
+
- ✅ Custom broker adapters
|
|
237
|
+
|
|
238
|
+
[Contact hi@fullstackcraft.com for Enterprise pricing](mailto:hi@fullstackcraft.com)
|
|
239
|
+
|
|
240
|
+
## Documentation
|
|
241
|
+
|
|
242
|
+
Full documentation coming soon at [fullstackcraft.github.io/floe](https://fullstackcraft.github.io/floe)
|
|
243
|
+
|
|
244
|
+
## Support
|
|
245
|
+
|
|
246
|
+
- **Email:** hi@fullstackcraft.com
|
|
247
|
+
- **Bug Reports:** [GitHub Issues](https://github.com/FullStackCraft/floe/issues)
|
|
248
|
+
- **Discussions:** [GitHub Discussions](https://github.com/FullStackCraft/floe/discussions)
|
|
249
|
+
|
|
250
|
+
## Contributing
|
|
251
|
+
|
|
252
|
+
Contributions welcome! Please open an issue or PR.
|
|
253
|
+
|
|
254
|
+
By contributing, you agree that your contributions will be licensed under the same dual-license terms.
|
|
255
|
+
|
|
256
|
+
## Roadmap
|
|
257
|
+
|
|
258
|
+
- [ ] Homepage / documentation site
|
|
259
|
+
- [ ] Volatility surface estimation with a variety of interpolation methods
|
|
260
|
+
- [ ] Implied PDF calculations
|
|
261
|
+
- [ ] Tradier integration, normalization, and docs
|
|
262
|
+
- [ ] TradeStation integration, normalization, and docs
|
|
263
|
+
- [ ] Interactive Brokers integration, normalization, and docs
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
## Credits
|
|
267
|
+
|
|
268
|
+
Built with ❤️ by [Full Stack Craft LLC](https://fullstackcraft.com)
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
**© 2025 Full Stack Craft LLC** - All rights reserved.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RawOptionData, OptionChain, BrokerAdapter } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Generic adapter that maps common field names
|
|
4
|
+
* This is a fallback adapter when broker-specific adapters are not available
|
|
5
|
+
*/
|
|
6
|
+
export declare const genericAdapter: BrokerAdapter;
|
|
7
|
+
/**
|
|
8
|
+
* Schwab-specific adapter for Schwab API responses
|
|
9
|
+
*/
|
|
10
|
+
export declare const schwabAdapter: BrokerAdapter;
|
|
11
|
+
/**
|
|
12
|
+
* Interactive Brokers adapter
|
|
13
|
+
*/
|
|
14
|
+
export declare const ibkrAdapter: BrokerAdapter;
|
|
15
|
+
/**
|
|
16
|
+
* TD Ameritrade / Schwab TDA API adapter
|
|
17
|
+
*/
|
|
18
|
+
export declare const tdaAdapter: BrokerAdapter;
|
|
19
|
+
/**
|
|
20
|
+
* Map of broker names to their adapters
|
|
21
|
+
*/
|
|
22
|
+
export declare const brokerAdapters: Record<string, BrokerAdapter>;
|
|
23
|
+
/**
|
|
24
|
+
* Get adapter for a specific broker
|
|
25
|
+
* @param brokerName - Name of the broker
|
|
26
|
+
* @returns Broker adapter function
|
|
27
|
+
*/
|
|
28
|
+
export declare function getAdapter(brokerName: string): BrokerAdapter;
|
|
29
|
+
/**
|
|
30
|
+
* Create an option chain from raw broker data
|
|
31
|
+
*
|
|
32
|
+
* @param symbol - Underlying symbol (e.g., 'SPY')
|
|
33
|
+
* @param spot - Current spot price of the underlying
|
|
34
|
+
* @param riskFreeRate - Risk-free interest rate (as decimal, e.g., 0.05 for 5%)
|
|
35
|
+
* @param dividendYield - Dividend yield (as decimal, e.g., 0.02 for 2%)
|
|
36
|
+
* @param rawOptions - Array of raw option data from broker
|
|
37
|
+
* @param broker - Broker name for adapter selection (default: 'generic')
|
|
38
|
+
* @returns Complete option chain with market context
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const chain = createOptionChain(
|
|
43
|
+
* 'SPY',
|
|
44
|
+
* 450.50,
|
|
45
|
+
* 0.05,
|
|
46
|
+
* 0.02,
|
|
47
|
+
* rawOptionsFromBroker,
|
|
48
|
+
* 'schwab'
|
|
49
|
+
* );
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function createOptionChain(symbol: string, spot: number, riskFreeRate: number, dividendYield: number, rawOptions: RawOptionData[], broker?: string): OptionChain;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.brokerAdapters = exports.tdaAdapter = exports.ibkrAdapter = exports.schwabAdapter = exports.genericAdapter = void 0;
|
|
4
|
+
exports.getAdapter = getAdapter;
|
|
5
|
+
exports.createOptionChain = createOptionChain;
|
|
6
|
+
/**
|
|
7
|
+
* Generic adapter that maps common field names
|
|
8
|
+
* This is a fallback adapter when broker-specific adapters are not available
|
|
9
|
+
*/
|
|
10
|
+
const genericAdapter = (data) => {
|
|
11
|
+
return {
|
|
12
|
+
strike: Number(data.strike || data.strikePrice || 0),
|
|
13
|
+
expiration: data.expiration || data.expirationDate || '',
|
|
14
|
+
expirationTimestamp: data.expirationTimestamp || new Date(data.expiration || data.expirationDate).getTime(),
|
|
15
|
+
optionType: (data.optionType || data.putCall || '').toLowerCase() === 'call' ? 'call' : 'put',
|
|
16
|
+
bid: Number(data.bid || 0),
|
|
17
|
+
ask: Number(data.ask || 0),
|
|
18
|
+
mark: Number(data.mark || (data.bid + data.ask) / 2 || 0),
|
|
19
|
+
last: Number(data.last || data.lastPrice || 0),
|
|
20
|
+
volume: Number(data.volume || 0),
|
|
21
|
+
openInterest: Number(data.openInterest || 0),
|
|
22
|
+
impliedVolatility: Number(data.impliedVolatility || data.iv || 0),
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.genericAdapter = genericAdapter;
|
|
26
|
+
/**
|
|
27
|
+
* Schwab-specific adapter for Schwab API responses
|
|
28
|
+
*/
|
|
29
|
+
const schwabAdapter = (data) => {
|
|
30
|
+
return {
|
|
31
|
+
strike: Number(data.strikePrice || 0),
|
|
32
|
+
expiration: data.expirationDate || '',
|
|
33
|
+
expirationTimestamp: new Date(data.expirationDate).getTime(),
|
|
34
|
+
optionType: (data.putCall || '').toLowerCase() === 'call' ? 'call' : 'put',
|
|
35
|
+
bid: Number(data.bid || 0),
|
|
36
|
+
ask: Number(data.ask || 0),
|
|
37
|
+
mark: Number(data.mark || 0),
|
|
38
|
+
last: Number(data.last || 0),
|
|
39
|
+
volume: Number(data.totalVolume || 0),
|
|
40
|
+
openInterest: Number(data.openInterest || 0),
|
|
41
|
+
impliedVolatility: Number(data.volatility || 0),
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
exports.schwabAdapter = schwabAdapter;
|
|
45
|
+
/**
|
|
46
|
+
* Interactive Brokers adapter
|
|
47
|
+
*/
|
|
48
|
+
const ibkrAdapter = (data) => {
|
|
49
|
+
return {
|
|
50
|
+
strike: Number(data.strike || 0),
|
|
51
|
+
expiration: data.lastTradeDateOrContractMonth || '',
|
|
52
|
+
expirationTimestamp: new Date(data.lastTradeDateOrContractMonth).getTime(),
|
|
53
|
+
optionType: (data.right || '').toLowerCase() === 'c' ? 'call' : 'put',
|
|
54
|
+
bid: Number(data.bid || 0),
|
|
55
|
+
ask: Number(data.ask || 0),
|
|
56
|
+
mark: Number(data.mark || (data.bid + data.ask) / 2 || 0),
|
|
57
|
+
last: Number(data.lastTradedPrice || 0),
|
|
58
|
+
volume: Number(data.volume || 0),
|
|
59
|
+
openInterest: Number(data.openInterest || 0),
|
|
60
|
+
impliedVolatility: Number(data.impliedVolatility || 0),
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
exports.ibkrAdapter = ibkrAdapter;
|
|
64
|
+
/**
|
|
65
|
+
* TD Ameritrade / Schwab TDA API adapter
|
|
66
|
+
*/
|
|
67
|
+
const tdaAdapter = (data) => {
|
|
68
|
+
return {
|
|
69
|
+
strike: Number(data.strikePrice || 0),
|
|
70
|
+
expiration: data.expirationDate || '',
|
|
71
|
+
expirationTimestamp: data.expirationDate ? new Date(data.expirationDate).getTime() : 0,
|
|
72
|
+
optionType: (data.putCall || '').toLowerCase() === 'call' ? 'call' : 'put',
|
|
73
|
+
bid: Number(data.bid || 0),
|
|
74
|
+
ask: Number(data.ask || 0),
|
|
75
|
+
mark: Number(data.mark || 0),
|
|
76
|
+
last: Number(data.last || 0),
|
|
77
|
+
volume: Number(data.totalVolume || 0),
|
|
78
|
+
openInterest: Number(data.openInterest || 0),
|
|
79
|
+
impliedVolatility: Number(data.volatility || 0),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
exports.tdaAdapter = tdaAdapter;
|
|
83
|
+
/**
|
|
84
|
+
* Map of broker names to their adapters
|
|
85
|
+
*/
|
|
86
|
+
exports.brokerAdapters = {
|
|
87
|
+
generic: exports.genericAdapter,
|
|
88
|
+
schwab: exports.schwabAdapter,
|
|
89
|
+
ibkr: exports.ibkrAdapter,
|
|
90
|
+
tda: exports.tdaAdapter,
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Get adapter for a specific broker
|
|
94
|
+
* @param brokerName - Name of the broker
|
|
95
|
+
* @returns Broker adapter function
|
|
96
|
+
*/
|
|
97
|
+
function getAdapter(brokerName) {
|
|
98
|
+
return exports.brokerAdapters[brokerName.toLowerCase()] || exports.genericAdapter;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Create an option chain from raw broker data
|
|
102
|
+
*
|
|
103
|
+
* @param symbol - Underlying symbol (e.g., 'SPY')
|
|
104
|
+
* @param spot - Current spot price of the underlying
|
|
105
|
+
* @param riskFreeRate - Risk-free interest rate (as decimal, e.g., 0.05 for 5%)
|
|
106
|
+
* @param dividendYield - Dividend yield (as decimal, e.g., 0.02 for 2%)
|
|
107
|
+
* @param rawOptions - Array of raw option data from broker
|
|
108
|
+
* @param broker - Broker name for adapter selection (default: 'generic')
|
|
109
|
+
* @returns Complete option chain with market context
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const chain = createOptionChain(
|
|
114
|
+
* 'SPY',
|
|
115
|
+
* 450.50,
|
|
116
|
+
* 0.05,
|
|
117
|
+
* 0.02,
|
|
118
|
+
* rawOptionsFromBroker,
|
|
119
|
+
* 'schwab'
|
|
120
|
+
* );
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
function createOptionChain(symbol, spot, riskFreeRate, dividendYield, rawOptions, broker = 'generic') {
|
|
124
|
+
const adapter = getAdapter(broker);
|
|
125
|
+
return {
|
|
126
|
+
symbol,
|
|
127
|
+
spot,
|
|
128
|
+
riskFreeRate,
|
|
129
|
+
dividendYield,
|
|
130
|
+
options: rawOptions.map(adapter),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BlackScholesParams, Greeks, OptionType } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate option price using Black-Scholes model
|
|
4
|
+
*
|
|
5
|
+
* @param params - Black-Scholes parameters
|
|
6
|
+
* @returns Option price
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const price = blackScholes({
|
|
11
|
+
* spot: 100,
|
|
12
|
+
* strike: 105,
|
|
13
|
+
* timeToExpiry: 0.25,
|
|
14
|
+
* volatility: 0.20,
|
|
15
|
+
* riskFreeRate: 0.05,
|
|
16
|
+
* optionType: 'call'
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function blackScholes(params: BlackScholesParams): number;
|
|
21
|
+
/**
|
|
22
|
+
* Calculate complete option Greeks using Black-Scholes-Merton model
|
|
23
|
+
* Includes all first, second, and third-order Greeks
|
|
24
|
+
*
|
|
25
|
+
* @param params - Black-Scholes parameters
|
|
26
|
+
* @returns Complete Greeks including price
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const greeks = calculateGreeks({
|
|
31
|
+
* spot: 100,
|
|
32
|
+
* strike: 105,
|
|
33
|
+
* timeToExpiry: 0.25,
|
|
34
|
+
* volatility: 0.20,
|
|
35
|
+
* riskFreeRate: 0.05,
|
|
36
|
+
* optionType: 'call'
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function calculateGreeks(params: BlackScholesParams): Greeks;
|
|
41
|
+
/**
|
|
42
|
+
* Calculate implied volatility using bisection method
|
|
43
|
+
*
|
|
44
|
+
* @param price - Observed option price
|
|
45
|
+
* @param spot - Current spot price
|
|
46
|
+
* @param strike - Strike price
|
|
47
|
+
* @param riskFreeRate - Risk-free interest rate (as decimal)
|
|
48
|
+
* @param dividendYield - Dividend yield (as decimal)
|
|
49
|
+
* @param timeToExpiry - Time to expiration in years
|
|
50
|
+
* @param optionType - 'call' or 'put'
|
|
51
|
+
* @returns Implied volatility as a percentage (e.g., 20.0 for 20%)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const iv = calculateImpliedVolatility(5.50, 100, 105, 0.05, 0, 0.25, 'call');
|
|
56
|
+
* console.log(`IV: ${iv}%`);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function calculateImpliedVolatility(price: number, spot: number, strike: number, riskFreeRate: number, dividendYield: number, timeToExpiry: number, optionType: OptionType): number;
|
|
60
|
+
/**
|
|
61
|
+
* Get milliseconds until expiration
|
|
62
|
+
*
|
|
63
|
+
* @param expirationTimestamp - Expiration timestamp in milliseconds
|
|
64
|
+
* @returns Milliseconds until expiration
|
|
65
|
+
*/
|
|
66
|
+
export declare function getMillisecondsToExpiration(expirationTimestamp: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get time to expiration in years
|
|
69
|
+
*
|
|
70
|
+
* @param expirationTimestamp - Expiration timestamp in milliseconds
|
|
71
|
+
* @returns Time to expiration in years
|
|
72
|
+
*/
|
|
73
|
+
export declare function getTimeToExpirationInYears(expirationTimestamp: number): number;
|