voly 0.0.186__py3-none-any.whl → 0.0.189__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/core/fit.py CHANGED
@@ -37,11 +37,8 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
37
37
  # Define column names and their data types
38
38
  column_dtypes = {
39
39
  's': float,
40
- 'u': float,
41
40
  't': float,
42
41
  'r': float,
43
- 'oi': float,
44
- 'volume': float,
45
42
  'maturity_date': 'datetime64[ns]',
46
43
  'a': float,
47
44
  'b': float,
@@ -67,6 +64,7 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
67
64
  }
68
65
 
69
66
  s = option_chain['index_price'].iloc[0]
67
+ unique_ts = sorted(option_chain['t'].unique())
70
68
  maturity_names = [option_chain[option_chain['t'] == t]['maturity_name'].iloc[0] for t in unique_ts]
71
69
  groups = option_chain.groupby('maturity_date')
72
70
  params_dict = {}
@@ -94,7 +92,6 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
94
92
 
95
93
  # Combine cleaned duplicates and unique rows
96
94
  maturity_data = pd.concat([unique_iv, cleaned_duplicated_iv])
97
- #maturity_name = maturity_data['maturity_name'].iloc[0]
98
95
  maturity_date = maturity_data['maturity_date'].iloc[0]
99
96
 
100
97
  t = group['t'].iloc[0]
@@ -113,10 +110,7 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
113
110
  nu = psi = p = c = nu_tilde = np.nan
114
111
  rmse = mae = r2 = max_error = np.nan
115
112
  butterfly_arbitrage_free = True
116
- u = s # Assume underlying_price is index_price
117
113
  r = maturity_data['interest_rate'].iloc[0] if 'interest_rate' in maturity_data.columns else 0
118
- oi = maturity_data['open_interest'].sum() if 'open_interest' in maturity_data.columns else 0
119
- volume = maturity_data['volume'].sum() if 'volume' in maturity_data.columns else 0
120
114
  log_min_strike = usd_min_strike = np.nan
121
115
 
122
116
  if len(k) > 5:
@@ -165,11 +159,8 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
165
159
 
166
160
  # Store results
167
161
  results_data['s'].append(float(s))
168
- results_data['u'].append(float(u))
169
162
  results_data['t'].append(float(t))
170
163
  results_data['r'].append(float(r))
171
- results_data['oi'].append(float(oi))
172
- results_data['volume'].append(float(volume))
173
164
  results_data['maturity_date'].append(maturity_date)
174
165
  results_data['a'].append(float(a_scaled) if not np.isnan(params[0]) else np.nan)
175
166
  results_data['b'].append(float(b_scaled) if not np.isnan(params[0]) else np.nan)
@@ -370,3 +361,60 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame:
370
361
 
371
362
  logger.info("Model fitting complete.")
372
363
  return results_df
364
+
365
+
366
+ @catch_exception
367
+ def get_iv_surface(model_results: pd.DataFrame,
368
+ domain_params: Tuple[float, float, int] = (-1.5, 1.5, 1000),
369
+ return_domain: str = 'log_moneyness') -> Tuple[Dict[str, np.ndarray], Dict[str, np.ndarray]]:
370
+ """
371
+ Generate implied volatility surface using optimized SVI parameters.
372
+
373
+ Works with both regular fit_results and interpolated_results dataframes.
374
+
375
+ Parameters:
376
+ - model_results: DataFrame from fit_model() or interpolate_model(). Maturity names or DTM as Index
377
+ - domain_params: Tuple of (min, max, num_points) for the log-moneyness array
378
+ - return_domain: Domain for x-axis values ('log_moneyness', 'moneyness', 'returns', 'strikes', 'delta')
379
+
380
+ Returns:
381
+ - Tuple of (iv_surface, x_surface)
382
+ iv_surface: Dictionary mapping maturity/dtm names to IV arrays
383
+ x_surface: Dictionary mapping maturity/dtm names to requested x domain arrays
384
+ """
385
+ # Check if required columns are present
386
+ required_columns = ['a', 'b', 'm', 'rho', 'sigma', 't']
387
+ missing_columns = [col for col in required_columns if col not in model_results.columns]
388
+ if missing_columns:
389
+ raise VolyError(f"Required columns missing in model_results: {missing_columns}")
390
+
391
+ # Generate implied volatility surface in log-moneyness domain
392
+ LM = np.linspace(domain_params[0], domain_params[1], domain_params[2])
393
+
394
+ iv_surface = {}
395
+ x_surface = {}
396
+
397
+ # Process each maturity/dtm
398
+ for i in model_results.index:
399
+ # Calculate SVI total implied variance and convert to IV
400
+ params = [
401
+ model_results.loc[i, 'a'],
402
+ model_results.loc[i, 'b'],
403
+ model_results.loc[i, 'm'],
404
+ model_results.loc[i, 'rho'],
405
+ model_results.loc[i, 'sigma']
406
+ ]
407
+ s = model_results.loc[i, 's']
408
+ r = model_results.loc[i, 'r']
409
+ t = model_results.loc[i, 't']
410
+
411
+ # Calculate implied volatility
412
+ w = np.array([SVIModel.svi(x, *params) for x in LM])
413
+ o = np.sqrt(w / t)
414
+ iv_surface[i] = o
415
+
416
+ # Calculate x domain for this maturity/dtm
417
+ x = get_domain(domain_params, s, r, o, t, return_domain)
418
+ x_surface[i] = x
419
+
420
+ return iv_surface, x_surface
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voly
3
- Version: 0.0.186
3
+ Version: 0.0.189
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
@@ -6,15 +6,15 @@ voly/models.py,sha256=2aNGsF3joCx4jGbiF8m0zxEW_nvcSBERSYPSKCXV3us,7019
6
6
  voly/core/__init__.py,sha256=bu6fS2I1Pj9fPPnl-zY3L7NqrZSY5Zy6NY2uMUvdhKs,183
7
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=pfGRzycJ9WERHc-nIowpWQQ8nZbGHlOlRDUxgkkfvnY,15448
9
+ voly/core/fit.py,sha256=cHd4SmdsjSKnllH-g_pU7_L8N9dSl07Q6tsqDjd2jNA,17217
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.186.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
17
- voly-0.0.186.dist-info/METADATA,sha256=GUbTWWjdupPDNj3wHCYQ5b5qu0hmHWNsO8KPXRKpAW8,4115
18
- voly-0.0.186.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
19
- voly-0.0.186.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
20
- voly-0.0.186.dist-info/RECORD,,
16
+ voly-0.0.189.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
17
+ voly-0.0.189.dist-info/METADATA,sha256=Tz2ZLYVNWXtm9123NubqXctsRkv0j2gteQRLw0S2SCg,4115
18
+ voly-0.0.189.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
19
+ voly-0.0.189.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
20
+ voly-0.0.189.dist-info/RECORD,,
File without changes