voly 0.0.73__tar.gz → 0.0.74__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voly
3
- Version: 0.0.73
3
+ Version: 0.0.74
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "voly"
7
- version = "0.0.73"
7
+ version = "0.0.74"
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.73"
63
+ python_version = "0.0.74"
64
64
  warn_return_any = true
65
65
  warn_unused_configs = true
66
66
  disallow_untyped_defs = true
@@ -361,16 +361,16 @@ class VolyClient:
361
361
  - return_domain: str Domain for x-axis values ('log_moneyness', 'moneyness', 'strikes', 'delta')
362
362
 
363
363
  Returns:
364
- - Tuple of (iv_surface, x_surface)
364
+ - Surface. Dict composed of (iv_surface, x_surface)
365
365
  """
366
366
  # Generate the surface
367
- iv_surface, x_surface = get_iv_surface(
367
+ surface = get_iv_surface(
368
368
  fit_results=fit_results,
369
369
  log_moneyness_params=log_moneyness_params,
370
370
  return_domain=return_domain
371
371
  )
372
372
 
373
- return {'iv_surface': iv_surface, 'x_surface': x_surface}
373
+ return surface
374
374
 
375
375
  @staticmethod
376
376
  def plot_model(fit_results: pd.DataFrame,
@@ -393,7 +393,11 @@ class VolyClient:
393
393
  plots = {}
394
394
 
395
395
  # Generate IV surface and domain
396
- iv_surface, x_surface = get_iv_surface(fit_results, log_moneyness_params, return_domain)
396
+ surface = get_iv_surface(fit_results, log_moneyness_params, return_domain)
397
+
398
+ # Get iv_surface and x_surface from the return value
399
+ iv_surface = surface['iv_surface']
400
+ x_surface = surface['x_surface']
397
401
 
398
402
  # Plot volatility smiles
399
403
  plots['smiles'] = plot_all_smiles(
@@ -28,7 +28,7 @@ def plot_volatility_smile(x_domain: np.ndarray,
28
28
  Plot volatility smile for a single expiry.
29
29
 
30
30
  Parameters:
31
- - x_domain: Array of x-axis values (log_moneyness, moneyness, strikes, delta)
31
+ - x_domain: Array of x-axis values in the specified domain
32
32
  - iv_array: Implied volatility values
33
33
  - option_chain: Optional market data for comparison
34
34
  - maturity: Maturity name for filtering market data
@@ -37,8 +37,6 @@ def plot_volatility_smile(x_domain: np.ndarray,
37
37
  Returns:
38
38
  - Plotly figure
39
39
  """
40
- fig = go.Figure()
41
-
42
40
  # Map domain types to axis labels
43
41
  domain_labels = {
44
42
  'log_moneyness': 'Log Moneyness',
@@ -47,6 +45,8 @@ def plot_volatility_smile(x_domain: np.ndarray,
47
45
  'delta': 'Call Delta'
48
46
  }
49
47
 
48
+ fig = go.Figure()
49
+
50
50
  # Add model curve
51
51
  fig.add_trace(
52
52
  go.Scatter(
@@ -63,37 +63,20 @@ def plot_volatility_smile(x_domain: np.ndarray,
63
63
  maturity_data = option_chain[option_chain['maturity_name'] == maturity]
64
64
 
65
65
  if not maturity_data.empty:
66
- # For market data, use log_moneyness by default as x-axis
67
- market_x = maturity_data['log_moneyness']
68
-
69
- # If domain is not log_moneyness, convert market data to match the domain
70
- if domain_type == 'moneyness':
71
- market_x = np.exp(market_x)
72
- elif domain_type == 'strikes':
73
- s = maturity_data['underlying_price'].iloc[0]
74
- market_x = s / np.exp(market_x)
75
- elif domain_type == 'delta':
76
- # For delta, we'd need more complex conversion - skip market data for this domain
77
- market_x = None
78
-
79
- # Add bid and ask IVs if the domain type allows
80
- if domain_type != 'delta' and market_x is not None:
81
- for iv_type in ['bid_iv', 'ask_iv']:
82
- if iv_type in maturity_data.columns:
83
- fig.add_trace(
84
- go.Scatter(
85
- x=market_x,
86
- y=maturity_data[iv_type] * 100, # Convert to percentage
87
- mode='markers',
88
- name=iv_type.replace('_', ' ').upper(),
89
- marker=dict(size=8, symbol='circle', opacity=0.7)
90
- )
66
+ # Add bid and ask IVs if available
67
+ for iv_type in ['bid_iv', 'ask_iv']:
68
+ if iv_type in maturity_data.columns:
69
+ fig.add_trace(
70
+ go.Scatter(
71
+ x=maturity_data['log_moneyness'],
72
+ y=maturity_data[iv_type] * 100, # Convert to percentage
73
+ mode='markers',
74
+ name=iv_type.replace('_', ' ').upper(),
75
+ marker=dict(size=8, symbol='circle', opacity=0.7)
91
76
  )
77
+ )
92
78
 
93
- dte_value = maturity_data['dtm'].iloc[0]
94
-
95
- # Update layout with DTE
96
- title = f'Vol Smile for {maturity} (DTE: {dte_value:.1f})'
79
+ title = f'Vol Smile for {maturity} (DTE: {maturity_data["dtm"].iloc[0]:.1f})'
97
80
  else:
98
81
  title = f'Vol Smile for {maturity}'
99
82
  else:
@@ -165,8 +148,8 @@ def plot_raw_parameters(fit_results: pd.DataFrame) -> go.Figure:
165
148
  maturity_names = fit_results.index
166
149
 
167
150
  # Create hover text with maturity info
168
- tick_labels = [f"{m} (DTE: {fit_results.loc[m, 'dtm']:.1f}"
169
- for m in maturity_names]
151
+ tick_labels = [f"{m} (DTE: {fit_results.loc[m, 'dtm']:.1f}, YTE: {fit_results.loc[m, 'ytm']:.4f})"
152
+ for m in maturity_names]
170
153
 
171
154
  # Plot each parameter
172
155
  for i, param in enumerate(param_names):
@@ -230,7 +213,7 @@ def plot_jw_parameters(fit_results: pd.DataFrame) -> go.Figure:
230
213
 
231
214
  # Create hover text with maturity info
232
215
  tick_labels = [f"{m} (DTE: {fit_results.loc[m, 'dtm']:.1f}, YTE: {fit_results.loc[m, 'ytm']:.4f})"
233
- for m in maturity_names]
216
+ for m in maturity_names]
234
217
 
235
218
  # Plot each parameter
236
219
  for i, param in enumerate(param_names):
@@ -378,53 +361,31 @@ def plot_3d_surface(x_surface: Dict[str, np.ndarray],
378
361
  # Default to sequential values
379
362
  maturity_values = list(range(len(maturity_names)))
380
363
 
381
- # For domains with uniform x values across maturities (like log_moneyness, moneyness)
382
- # we can use standard surface plot
383
- if domain_type in ['log_moneyness', 'moneyness']:
384
- # Create mesh grid
385
- X, Y = np.meshgrid(list(x_surface.values())[0], maturity_values)
386
- Z = np.array([iv_surface[m] * 100 for m in maturity_names]) # Convert to percentage
387
-
388
- # Create figure
389
- fig = go.Figure(data=[
390
- go.Surface(
391
- z=Z,
392
- x=X,
393
- y=Y,
394
- colorscale=custom_blue_scale,
395
- contours_z=dict(
396
- show=True,
397
- usecolormap=True,
398
- highlightcolor="#0080FF",
399
- project_z=True
400
- )
401
- )
402
- ])
364
+ # Create 3D surface using lines for each maturity
365
+ fig = go.Figure()
403
366
 
404
- # For domains that might have different x values per maturity (like strikes, delta)
405
- # we need to use a different approach
406
- else:
407
- # Create a 3D scatter plot with lines
408
- fig = go.Figure()
409
-
410
- # For each maturity, create a curve
411
- for i, maturity in enumerate(maturity_names):
412
- x_values = x_surface[maturity]
413
- z_values = iv_surface[maturity] * 100 # Convert to percentage
414
- y_values = np.full_like(x_values, maturity_values[i])
415
-
416
- # Add a line for this maturity
417
- fig.add_trace(go.Scatter3d(
418
- x=x_values,
419
- y=y_values,
420
- z=z_values,
421
- mode='lines',
422
- line=dict(
423
- color=f'rgb({30 + 225 * (i / len(maturity_names))}, {30 + 150 * (i / len(maturity_names))}, {200 - 170 * (i / len(maturity_names))})',
424
- width=5
425
- ),
426
- name=maturity
427
- ))
367
+ # Add a line for each maturity
368
+ for i, maturity in enumerate(maturity_names):
369
+ x_values = x_surface[maturity]
370
+ z_values = iv_surface[maturity] * 100 # Convert to percentage
371
+ y_values = np.full_like(x_values, maturity_values[i])
372
+
373
+ # Color based on maturity (blue to light blue gradient)
374
+ color_intensity = i / max(1, len(maturity_names) - 1)
375
+ color = f'rgb({int(30 + 170*color_intensity)}, {int(120 + 80*color_intensity)}, {int(220 - 120*color_intensity)})'
376
+
377
+ # Add trace
378
+ fig.add_trace(go.Scatter3d(
379
+ x=x_values,
380
+ y=y_values,
381
+ z=z_values,
382
+ mode='lines',
383
+ name=maturity,
384
+ line=dict(
385
+ color=color,
386
+ width=5
387
+ )
388
+ ))
428
389
 
429
390
  # Update layout
430
391
  fig.update_layout(
@@ -433,12 +394,7 @@ def plot_3d_surface(x_surface: Dict[str, np.ndarray],
433
394
  scene=dict(
434
395
  xaxis_title=domain_labels.get(domain_type, 'X Domain'),
435
396
  yaxis_title='Days to Expiry',
436
- zaxis_title='Implied Volatility (%)',
437
- aspectmode='manual',
438
- aspectratio=dict(x=1.5, y=1, z=1),
439
- camera=dict(
440
- eye=dict(x=1.5, y=-1.5, z=1)
441
- )
397
+ zaxis_title='Implied Volatility (%)'
442
398
  ),
443
399
  margin=dict(l=65, r=50, b=65, t=90)
444
400
  )
@@ -238,4 +238,4 @@ def get_iv_surface(fit_results: pd.DataFrame,
238
238
  ytm=ytm
239
239
  )
240
240
 
241
- return iv_surface, x_surface
241
+ return {'iv_surface': iv_surface, 'x_surface': x_surface}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voly
3
- Version: 0.0.73
3
+ Version: 0.0.74
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
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