voly 0.0.180__py3-none-any.whl → 0.0.182__py3-none-any.whl
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.
- voly/client.py +2 -5
- voly/core/charts.py +1 -1
- voly/core/fit.py +8 -10
- {voly-0.0.180.dist-info → voly-0.0.182.dist-info}/METADATA +1 -1
- {voly-0.0.180.dist-info → voly-0.0.182.dist-info}/RECORD +8 -8
- {voly-0.0.180.dist-info → voly-0.0.182.dist-info}/WHEEL +0 -0
- {voly-0.0.180.dist-info → voly-0.0.182.dist-info}/licenses/LICENSE +0 -0
- {voly-0.0.180.dist-info → voly-0.0.182.dist-info}/top_level.txt +0 -0
voly/client.py
CHANGED
@@ -165,14 +165,12 @@ class VolyClient:
|
|
165
165
|
# -------------------------------------------------------------------------
|
166
166
|
|
167
167
|
@staticmethod
|
168
|
-
def fit_model(option_chain: pd.DataFrame
|
169
|
-
domain_params: Tuple[float, float, int] = (-2, 2, 1000)) -> pd.DataFrame:
|
168
|
+
def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
|
170
169
|
"""
|
171
170
|
Fit a volatility model to market data using the improved SVI approach.
|
172
171
|
|
173
172
|
Parameters:
|
174
173
|
- option_chain: DataFrame with option market data
|
175
|
-
- domain_params: Tuple of (min, max, num_points) for the log-moneyness grid
|
176
174
|
|
177
175
|
Returns:
|
178
176
|
- DataFrame with fit results including arbitrage checks
|
@@ -181,8 +179,7 @@ class VolyClient:
|
|
181
179
|
|
182
180
|
# Fit the model
|
183
181
|
fit_results = fit_model(
|
184
|
-
option_chain=option_chain
|
185
|
-
domain_params=domain_params
|
182
|
+
option_chain=option_chain
|
186
183
|
)
|
187
184
|
|
188
185
|
return fit_results
|
voly/core/charts.py
CHANGED
voly/core/fit.py
CHANGED
@@ -19,14 +19,12 @@ warnings.filterwarnings("ignore")
|
|
19
19
|
|
20
20
|
|
21
21
|
@catch_exception
|
22
|
-
def fit_model(option_chain: pd.DataFrame
|
23
|
-
domain_params: Tuple[float, float, int] = (-2, 2, 1000)) -> pd.DataFrame:
|
22
|
+
def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
|
24
23
|
"""
|
25
24
|
Fit a volatility model to market data.
|
26
25
|
|
27
26
|
Parameters:
|
28
27
|
- option_chain: DataFrame with market data
|
29
|
-
- domain_params: Tuple of (min, max, num_points) for the log-moneyness grid
|
30
28
|
|
31
29
|
Returns:
|
32
30
|
- DataFrame with all fit results and performance metrics as columns, maturity_names as index
|
@@ -130,7 +128,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
130
128
|
usd_min_strike = np.exp(log_min_strike) * s
|
131
129
|
|
132
130
|
# Butterfly arbitrage check
|
133
|
-
k_range = np.linspace(min(k), max(k),
|
131
|
+
k_range = np.linspace(min(k), max(k), 200)
|
134
132
|
w_k = lambda k: SVIModel.svi(k, a_scaled, b_scaled, m, rho, sigma)
|
135
133
|
w_prime = lambda k: b_scaled * (rho + (k - m) / np.sqrt((k - m) ** 2 + sigma ** 2))
|
136
134
|
w_double_prime = lambda k: b_scaled * sigma ** 2 / ((k - m) ** 2 + sigma ** 2) ** (3 / 2)
|
@@ -147,7 +145,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
147
145
|
# Log result
|
148
146
|
status = f'{GREEN}SUCCESS{RESET}' if not np.isnan(params[0]) else f'{RED}FAILED{RESET}'
|
149
147
|
logger.info(f'Optimization for {maturity_name}: {status}')
|
150
|
-
logger.info("
|
148
|
+
logger.info("================================================")
|
151
149
|
|
152
150
|
results_data['s'].append(float(s))
|
153
151
|
results_data['u'].append(float(u))
|
@@ -191,7 +189,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
191
189
|
|
192
190
|
# Calendar arbitrage check (pre-correction)
|
193
191
|
logger.info("\nChecking calendar arbitrage (pre-correction)...")
|
194
|
-
k_grid = np.linspace(
|
192
|
+
k_grid = np.linspace(-2, 2, 200)
|
195
193
|
sorted_maturities = sorted(params_dict.keys(), key=lambda x: params_dict[x][0])
|
196
194
|
calendar_arbitrage_free = True
|
197
195
|
|
@@ -211,7 +209,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
211
209
|
k_market = np.log(K / s)
|
212
210
|
mask = ~np.isnan(k_market)
|
213
211
|
k_check = np.unique(
|
214
|
-
np.concatenate([k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]),
|
212
|
+
np.concatenate([k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), 200)]))
|
215
213
|
|
216
214
|
for k_val in k_check:
|
217
215
|
w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
|
@@ -281,7 +279,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
281
279
|
|
282
280
|
# Update butterfly arbitrage check
|
283
281
|
butterfly_arbitrage_free = True
|
284
|
-
k_range = np.linspace(min(k), max(k),
|
282
|
+
k_range = np.linspace(min(k), max(k), 200)
|
285
283
|
w_k = lambda k: SVIModel.svi(k, a_scaled, b_scaled, m, rho, sigma)
|
286
284
|
w_prime = lambda k: b_scaled * (rho + (k - m) / np.sqrt((k - m) ** 2 + sigma ** 2))
|
287
285
|
w_double_prime = lambda k: b_scaled * sigma ** 2 / ((k - m) ** 2 + sigma ** 2) ** (3 / 2)
|
@@ -324,7 +322,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
324
322
|
|
325
323
|
# Calendar arbitrage check (post-correction)
|
326
324
|
logger.info("\nChecking calendar arbitrage (post-correction)...")
|
327
|
-
calendar_arbitrage_free = True
|
325
|
+
calendar_arbitrage_free = False # Should be True
|
328
326
|
for i in range(len(sorted_maturities) - 1):
|
329
327
|
mat1, mat2 = sorted_maturities[i], sorted_maturities[i + 1]
|
330
328
|
t1, params1 = params_dict[mat1]
|
@@ -341,7 +339,7 @@ def fit_model(option_chain: pd.DataFrame,
|
|
341
339
|
k_market = np.log(K / s)
|
342
340
|
mask = ~np.isnan(k_market)
|
343
341
|
k_check = np.unique(np.concatenate(
|
344
|
-
[k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]),
|
342
|
+
[k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), 200)]))
|
345
343
|
|
346
344
|
for k_val in k_check:
|
347
345
|
w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
|
@@ -1,20 +1,20 @@
|
|
1
1
|
voly/__init__.py,sha256=8xyDk7rFCn_MOD5hxuv5cxxKZvBVRiSIM7TgaMPpwpw,211
|
2
|
-
voly/client.py,sha256=
|
2
|
+
voly/client.py,sha256=dPyRRmZ_Gvo1zCZMo9eFOx2oaYocmkOt71fzdmOXFyM,14387
|
3
3
|
voly/exceptions.py,sha256=PBsbn1vNMvKcCJwwJ4lBO6glD85jo1h2qiEmD7ArAjs,92
|
4
4
|
voly/formulas.py,sha256=JnEs6G0wlfRNH6X_YEJMe2RtLH-ryhzufjsim73Bj3c,11176
|
5
5
|
voly/models.py,sha256=wxqf9T4D2ORO7g3KcwxUL0E78fG69W29xqer3ccoUXo,6994
|
6
6
|
voly/core/__init__.py,sha256=bu6fS2I1Pj9fPPnl-zY3L7NqrZSY5Zy6NY2uMUvdhKs,183
|
7
|
-
voly/core/charts.py,sha256=
|
7
|
+
voly/core/charts.py,sha256=2S-BfCo30aj1_xlNLqF-za5rQWxF_mWKIdtdOe5bgbw,12735
|
8
8
|
voly/core/data.py,sha256=9v9iuE2XdIIlzoRAB7q1ol7YghBzBsPGAiwZ11oDuis,13650
|
9
|
-
voly/core/fit.py,sha256=
|
9
|
+
voly/core/fit.py,sha256=erZsfHuzpPclhDs8DXAl-7AR3xQT1HnxeCFAW3el7b4,17693
|
10
10
|
voly/core/hd.py,sha256=UFAyLncNUHivpPAcko6IK1bC55mudVtdlRFfXp63HXE,14771
|
11
11
|
voly/core/interpolate.py,sha256=JkK172-FXyhesW3hY4pEeuJWG3Bugq7QZXbeKoRpLuo,5305
|
12
12
|
voly/core/rnd.py,sha256=GoC3m1Q46Wnk5tV_mstr-3_aktHeue6BBLh4DQTciW0,13307
|
13
13
|
voly/utils/__init__.py,sha256=E05mWatyC-PDOsCxQV1p5Xi1IgpOomxrNURyCx_gB-w,200
|
14
14
|
voly/utils/density.py,sha256=q0fX4im9TGwMCZ32Hzdv8CNh56KnJo8bmG5w0gVWZH8,5879
|
15
15
|
voly/utils/logger.py,sha256=4-_2bVJmq17Q0d7Rd2mPg1AeR8gxv6EPvcmBDMFWcSM,1744
|
16
|
-
voly-0.0.
|
17
|
-
voly-0.0.
|
18
|
-
voly-0.0.
|
19
|
-
voly-0.0.
|
20
|
-
voly-0.0.
|
16
|
+
voly-0.0.182.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
|
17
|
+
voly-0.0.182.dist-info/METADATA,sha256=H6IjaszSVd7Mv34a1ZKG-utmlUbrH4FkoWJ8ZJnohWU,4115
|
18
|
+
voly-0.0.182.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
19
|
+
voly-0.0.182.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
|
20
|
+
voly-0.0.182.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|