voly 0.0.199__tar.gz → 0.0.201__tar.gz
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-0.0.199/src/voly.egg-info → voly-0.0.201}/PKG-INFO +1 -1
- {voly-0.0.199 → voly-0.0.201}/pyproject.toml +2 -2
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/fit.py +30 -33
- {voly-0.0.199 → voly-0.0.201/src/voly.egg-info}/PKG-INFO +1 -1
- {voly-0.0.199 → voly-0.0.201}/LICENSE +0 -0
- {voly-0.0.199 → voly-0.0.201}/README.md +0 -0
- {voly-0.0.199 → voly-0.0.201}/setup.cfg +0 -0
- {voly-0.0.199 → voly-0.0.201}/setup.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/__init__.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/client.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/__init__.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/charts.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/data.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/hd.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/interpolate.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/core/rnd.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/exceptions.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/formulas.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/models.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/utils/__init__.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/utils/density.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly/utils/logger.py +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly.egg-info/SOURCES.txt +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly.egg-info/dependency_links.txt +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly.egg-info/requires.txt +0 -0
- {voly-0.0.199 → voly-0.0.201}/src/voly.egg-info/top_level.txt +0 -0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "voly"
|
7
|
-
version = "0.0.
|
7
|
+
version = "0.0.201"
|
8
8
|
description = "Options & volatility research package"
|
9
9
|
readme = "README.md"
|
10
10
|
authors = [
|
@@ -60,7 +60,7 @@ line_length = 100
|
|
60
60
|
multi_line_output = 3
|
61
61
|
|
62
62
|
[tool.mypy]
|
63
|
-
python_version = "0.0.
|
63
|
+
python_version = "0.0.201"
|
64
64
|
warn_return_any = true
|
65
65
|
warn_unused_configs = true
|
66
66
|
disallow_untyped_defs = true
|
@@ -32,9 +32,7 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
32
32
|
- num_points: Number of points for k_grid and plotting
|
33
33
|
|
34
34
|
Returns:
|
35
|
-
-
|
36
|
-
results_df: DataFrame with all fit results and performance metrics as columns, maturity_dates as index
|
37
|
-
params_dict: Dictionary mapping maturity_dates to (t, params)
|
35
|
+
- results_df: DataFrame with all fit results and performance metrics as columns, maturity_names as index
|
38
36
|
"""
|
39
37
|
# Start overall timer
|
40
38
|
start_total = time.time()
|
@@ -71,6 +69,7 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
71
69
|
maturity_data_groups = option_chain.groupby('maturity_date')
|
72
70
|
params_dict = {}
|
73
71
|
results_data = {col: [] for col in column_dtypes.keys()}
|
72
|
+
results_data['maturity_name'] = []
|
74
73
|
|
75
74
|
def process_maturity(maturity, maturity_data):
|
76
75
|
"""Process single maturity for SVI calibration."""
|
@@ -94,6 +93,7 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
94
93
|
# Combine cleaned duplicates and unique rows
|
95
94
|
maturity_data = pd.concat([unique_iv, cleaned_duplicated_iv])
|
96
95
|
maturity_date = maturity_data['maturity_date'].iloc[0]
|
96
|
+
maturity_name = maturity_data['maturity_name'].iloc[0]
|
97
97
|
|
98
98
|
t = maturity_data['t'].iloc[0]
|
99
99
|
K = maturity_data['strikes'].values
|
@@ -155,6 +155,7 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
155
155
|
results_data['s'].append(float(s))
|
156
156
|
results_data['t'].append(float(t))
|
157
157
|
results_data['maturity_date'].append(maturity_date)
|
158
|
+
results_data['maturity_name'].append(maturity_name)
|
158
159
|
results_data['a'].append(float(a_scaled) if not np.isnan(params[0]) else np.nan)
|
159
160
|
results_data['b'].append(float(b_scaled) if not np.isnan(params[0]) else np.nan)
|
160
161
|
results_data['m'].append(float(m))
|
@@ -177,7 +178,7 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
177
178
|
results_data['loss'].append(float(loss))
|
178
179
|
results_data['n_points'].append(int(len(k)))
|
179
180
|
|
180
|
-
return
|
181
|
+
return maturity_name
|
181
182
|
|
182
183
|
# Parallel processing of maturities
|
183
184
|
with ThreadPoolExecutor() as executor:
|
@@ -187,7 +188,10 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
187
188
|
future.result()
|
188
189
|
|
189
190
|
# Create results DataFrame
|
190
|
-
results_df = pd.DataFrame(results_data, index=results_data['
|
191
|
+
results_df = pd.DataFrame(results_data, index=results_data['maturity_name'])
|
192
|
+
|
193
|
+
# Map maturity_date to maturity_name for indexing
|
194
|
+
date_to_name = dict(zip(results_data['maturity_date'], results_data['maturity_name']))
|
191
195
|
|
192
196
|
# Convert columns to appropriate types
|
193
197
|
for col, dtype in column_dtypes.items():
|
@@ -231,10 +235,9 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
231
235
|
break
|
232
236
|
|
233
237
|
for mat in sorted_maturities:
|
234
|
-
results_df.at[mat, 'calendar_arbitrage_free'] = calendar_arbitrage_free
|
238
|
+
results_df.at[date_to_name[mat], 'calendar_arbitrage_free'] = calendar_arbitrage_free
|
235
239
|
|
236
240
|
# Calendar arbitrage correction
|
237
|
-
start_correction = time.time()
|
238
241
|
for i in range(1, len(sorted_maturities)):
|
239
242
|
mat2 = sorted_maturities[i]
|
240
243
|
mat1 = sorted_maturities[i - 1]
|
@@ -291,30 +294,26 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
291
294
|
butterfly_arbitrage_free = False
|
292
295
|
break
|
293
296
|
|
294
|
-
results_df.at[mat2, 'a'] = float(a_scaled)
|
295
|
-
results_df.at[mat2, 'b'] = float(b_scaled)
|
296
|
-
results_df.at[mat2, 'm'] = float(m)
|
297
|
-
results_df.at[mat2, 'rho'] = float(rho)
|
298
|
-
results_df.at[mat2, 'sigma'] = float(sigma)
|
299
|
-
results_df.at[mat2, 'nu'] = float(nu)
|
300
|
-
results_df.at[mat2, 'psi'] = float(psi)
|
301
|
-
results_df.at[mat2, 'p'] = float(p)
|
302
|
-
results_df.at[mat2, 'c'] = float(c)
|
303
|
-
results_df.at[mat2, 'nu_tilde'] = float(nu_tilde)
|
304
|
-
results_df.at[mat2, 'rmse'] = float(rmse)
|
305
|
-
results_df.at[mat2, 'mae'] = float(mae)
|
306
|
-
results_df.at[mat2, 'r2'] = float(r2)
|
307
|
-
results_df.at[mat2, 'max_error'] = float(max_error)
|
308
|
-
results_df.at[mat2, 'log_min_strike'] = float(log_min_strike)
|
309
|
-
results_df.at[mat2, 'usd_min_strike'] = float(usd_min_strike)
|
310
|
-
results_df.at[mat2, 'butterfly_arbitrage_free'] = butterfly_arbitrage_free
|
311
|
-
results_df.at[mat2, 'fit_success'] = bool(not np.isnan(a))
|
312
|
-
end_correction = time.time()
|
313
|
-
logger.info(f"Calendar arbitrage correction completed in {end_correction - start_correction:.4f} seconds")
|
297
|
+
results_df.at[date_to_name[mat2], 'a'] = float(a_scaled)
|
298
|
+
results_df.at[date_to_name[mat2], 'b'] = float(b_scaled)
|
299
|
+
results_df.at[date_to_name[mat2], 'm'] = float(m)
|
300
|
+
results_df.at[date_to_name[mat2], 'rho'] = float(rho)
|
301
|
+
results_df.at[date_to_name[mat2], 'sigma'] = float(sigma)
|
302
|
+
results_df.at[date_to_name[mat2], 'nu'] = float(nu)
|
303
|
+
results_df.at[date_to_name[mat2], 'psi'] = float(psi)
|
304
|
+
results_df.at[date_to_name[mat2], 'p'] = float(p)
|
305
|
+
results_df.at[date_to_name[mat2], 'c'] = float(c)
|
306
|
+
results_df.at[date_to_name[mat2], 'nu_tilde'] = float(nu_tilde)
|
307
|
+
results_df.at[date_to_name[mat2], 'rmse'] = float(rmse)
|
308
|
+
results_df.at[date_to_name[mat2], 'mae'] = float(mae)
|
309
|
+
results_df.at[date_to_name[mat2], 'r2'] = float(r2)
|
310
|
+
results_df.at[date_to_name[mat2], 'max_error'] = float(max_error)
|
311
|
+
results_df.at[date_to_name[mat2], 'log_min_strike'] = float(log_min_strike)
|
312
|
+
results_df.at[date_to_name[mat2], 'usd_min_strike'] = float(usd_min_strike)
|
313
|
+
results_df.at[date_to_name[mat2], 'butterfly_arbitrage_free'] = butterfly_arbitrage_free
|
314
|
+
results_df.at[date_to_name[mat2], 'fit_success'] = bool(not np.isnan(a))
|
314
315
|
|
315
316
|
# Calendar arbitrage check (post-correction)
|
316
|
-
logger.info("\nChecking calendar arbitrage (post-correction)...")
|
317
|
-
start_post_check = time.time()
|
318
317
|
calendar_arbitrage_free = True
|
319
318
|
for i in range(len(sorted_maturities) - 1):
|
320
319
|
mat1, mat2 = sorted_maturities[i], sorted_maturities[i + 1]
|
@@ -341,15 +340,13 @@ def fit_model(option_chain: pd.DataFrame, num_points: int = 2000) -> Tuple[pd.Da
|
|
341
340
|
break
|
342
341
|
if not calendar_arbitrage_free:
|
343
342
|
break
|
344
|
-
end_post_check = time.time()
|
345
|
-
logger.info(f"Post-correction calendar arbitrage check completed in {end_post_check - start_post_check:.4f} seconds")
|
346
343
|
|
347
344
|
for mat in sorted_maturities:
|
348
|
-
results_df.at[mat, 'calendar_arbitrage_free'] = calendar_arbitrage_free
|
345
|
+
results_df.at[date_to_name[mat], 'calendar_arbitrage_free'] = calendar_arbitrage_free
|
349
346
|
|
350
347
|
# End overall timer and print total time
|
351
348
|
end_total = time.time()
|
352
|
-
logger.info(f"
|
349
|
+
logger.info(f"Total execution time for the model: {end_total - start_total:.4f} seconds")
|
353
350
|
|
354
351
|
logger.info("Model fitting complete.")
|
355
352
|
return results_df
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|