voly 0.0.78__py3-none-any.whl → 0.0.80__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/charts.py +52 -43
- {voly-0.0.78.dist-info → voly-0.0.80.dist-info}/METADATA +1 -1
- {voly-0.0.78.dist-info → voly-0.0.80.dist-info}/RECORD +6 -6
- {voly-0.0.78.dist-info → voly-0.0.80.dist-info}/LICENSE +0 -0
- {voly-0.0.78.dist-info → voly-0.0.80.dist-info}/WHEEL +0 -0
- {voly-0.0.78.dist-info → voly-0.0.80.dist-info}/top_level.txt +0 -0
voly/core/charts.py
CHANGED
|
@@ -7,6 +7,7 @@ risk-neutral densities, and model fitting results.
|
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
import pandas as pd
|
|
10
|
+
from scipy import interpolate
|
|
10
11
|
from typing import Dict, List, Tuple, Optional, Union, Any
|
|
11
12
|
from voly.utils.logger import logger, catch_exception
|
|
12
13
|
from voly.models import SVIModel
|
|
@@ -150,8 +151,7 @@ def plot_raw_parameters(fit_results: pd.DataFrame) -> go.Figure:
|
|
|
150
151
|
maturity_names = fit_results.index
|
|
151
152
|
|
|
152
153
|
# Create hover text with maturity info
|
|
153
|
-
tick_labels = [f"{m} (DTM: {fit_results.loc[m, 'dtm']:.1f}"
|
|
154
|
-
for m in maturity_names]
|
|
154
|
+
tick_labels = [f"{m} (DTM: {fit_results.loc[m, 'dtm']:.1f}" for m in maturity_names]
|
|
155
155
|
|
|
156
156
|
# Plot each parameter
|
|
157
157
|
for i, param in enumerate(param_names):
|
|
@@ -214,8 +214,7 @@ def plot_jw_parameters(fit_results: pd.DataFrame) -> go.Figure:
|
|
|
214
214
|
maturity_names = fit_results.index
|
|
215
215
|
|
|
216
216
|
# Create hover text with maturity info
|
|
217
|
-
tick_labels = [f"{m} (DTE: {fit_results.loc[m, 'dtm']:.1f}
|
|
218
|
-
for m in maturity_names]
|
|
217
|
+
tick_labels = [f"{m} (DTE: {fit_results.loc[m, 'dtm']:.1f})" for m in maturity_names]
|
|
219
218
|
|
|
220
219
|
# Plot each parameter
|
|
221
220
|
for i, param in enumerate(param_names):
|
|
@@ -227,7 +226,7 @@ def plot_jw_parameters(fit_results: pd.DataFrame) -> go.Figure:
|
|
|
227
226
|
y=fit_results[param],
|
|
228
227
|
mode='lines+markers',
|
|
229
228
|
name=param,
|
|
230
|
-
line=dict(width=2
|
|
229
|
+
line=dict(width=2),
|
|
231
230
|
marker=dict(size=8),
|
|
232
231
|
text=tick_labels,
|
|
233
232
|
hovertemplate="%{text}<br>%{y:.4f}"
|
|
@@ -328,7 +327,7 @@ def plot_fit_performance(fit_results: pd.DataFrame) -> go.Figure:
|
|
|
328
327
|
def plot_3d_surface(x_surface: Dict[str, np.ndarray],
|
|
329
328
|
iv_surface: Dict[str, np.ndarray],
|
|
330
329
|
fit_results: pd.DataFrame = None,
|
|
331
|
-
|
|
330
|
+
return_domain: str = 'log_moneyness') -> go.Figure:
|
|
332
331
|
"""
|
|
333
332
|
Plot 3D implied volatility surface.
|
|
334
333
|
|
|
@@ -336,69 +335,79 @@ def plot_3d_surface(x_surface: Dict[str, np.ndarray],
|
|
|
336
335
|
- x_surface: Dictionary mapping maturity names to x-domain arrays
|
|
337
336
|
- iv_surface: Dictionary mapping maturity names to IV arrays
|
|
338
337
|
- fit_results: Optional DataFrame with maturity information
|
|
339
|
-
-
|
|
338
|
+
- return_domain: Type of x-domain ('log_moneyness', 'moneyness', 'strikes', 'delta')
|
|
340
339
|
|
|
341
340
|
Returns:
|
|
342
341
|
- Plotly figure
|
|
343
342
|
"""
|
|
343
|
+
|
|
344
344
|
# Map domain types to axis labels
|
|
345
345
|
domain_labels = {
|
|
346
346
|
'log_moneyness': 'Log Moneyness',
|
|
347
|
-
'moneyness': 'Moneyness
|
|
347
|
+
'moneyness': 'Moneyness',
|
|
348
348
|
'strikes': 'Strike Price',
|
|
349
|
-
'delta': '
|
|
349
|
+
'delta': 'Delta'
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
#
|
|
353
|
-
custom_blue_scale = [[0, '#60AEFC'], [1, '#002040']]
|
|
354
|
-
|
|
355
|
-
# Get maturity names
|
|
352
|
+
# Get maturity names and sort by DTM
|
|
356
353
|
maturity_names = list(iv_surface.keys())
|
|
357
|
-
|
|
358
|
-
# Get z-axis values (days to expiry)
|
|
359
354
|
if fit_results is not None:
|
|
360
|
-
# Use DTM values from fit_results
|
|
361
355
|
maturity_values = [fit_results.loc[name, 'dtm'] for name in maturity_names]
|
|
356
|
+
# Sort by maturity
|
|
357
|
+
sorted_indices = np.argsort(maturity_values)
|
|
358
|
+
maturity_names = [maturity_names[i] for i in sorted_indices]
|
|
359
|
+
maturity_values = [maturity_values[i] for i in sorted_indices]
|
|
362
360
|
else:
|
|
363
|
-
# Default to sequential values
|
|
364
361
|
maturity_values = list(range(len(maturity_names)))
|
|
365
362
|
|
|
366
|
-
# Create
|
|
367
|
-
|
|
363
|
+
# Create a common x-grid for all maturities
|
|
364
|
+
# Use 100 points between the min and max x-values across all maturities
|
|
365
|
+
all_x = np.concatenate([x_surface[m] for m in maturity_names])
|
|
366
|
+
x_min, x_max = np.min(all_x), np.max(all_x)
|
|
367
|
+
x_grid = np.linspace(x_min, x_max, 100)
|
|
368
|
+
|
|
369
|
+
# Create a matrix for the surface
|
|
370
|
+
z_matrix = np.zeros((len(maturity_names), len(x_grid)))
|
|
368
371
|
|
|
369
|
-
#
|
|
372
|
+
# Fill the matrix with interpolated IV values
|
|
370
373
|
for i, maturity in enumerate(maturity_names):
|
|
371
374
|
x_values = x_surface[maturity]
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
375
|
+
iv_values = iv_surface[maturity] * 100 # Convert to percentage
|
|
376
|
+
|
|
377
|
+
# Create interpolation function
|
|
378
|
+
f = interpolate.interp1d(x_values, iv_values, kind='cubic',
|
|
379
|
+
bounds_error=False, fill_value='extrapolate')
|
|
380
|
+
|
|
381
|
+
# Generate interpolated values for the common x-grid
|
|
382
|
+
z_matrix[i] = f(x_grid)
|
|
383
|
+
|
|
384
|
+
# Create figure with the surface
|
|
385
|
+
fig = go.Figure(data=[go.Surface(
|
|
386
|
+
z=z_matrix,
|
|
387
|
+
x=x_grid,
|
|
388
|
+
y=maturity_values,
|
|
389
|
+
colorscale='Plotly3'
|
|
390
|
+
)])
|
|
391
|
+
|
|
392
|
+
# Add contours
|
|
393
|
+
fig.update_traces(contours_z=dict(
|
|
394
|
+
show=True,
|
|
395
|
+
usecolormap=True,
|
|
396
|
+
highlightcolor="white",
|
|
397
|
+
project_z=True
|
|
398
|
+
))
|
|
391
399
|
|
|
392
400
|
# Update layout
|
|
393
401
|
fig.update_layout(
|
|
394
|
-
title='Implied Volatility
|
|
402
|
+
title='Implied Volatility Surface',
|
|
395
403
|
template='plotly_dark',
|
|
396
404
|
scene=dict(
|
|
397
|
-
xaxis_title=domain_labels.get(
|
|
405
|
+
xaxis_title=domain_labels.get(return_domain, 'X Domain'),
|
|
398
406
|
yaxis_title='Days to Expiry',
|
|
399
|
-
zaxis_title='Implied Volatility (%)'
|
|
407
|
+
zaxis_title='Implied Volatility (%)',
|
|
408
|
+
aspectratio=dict(x=1, y=1, z=0.7)
|
|
400
409
|
),
|
|
401
|
-
|
|
410
|
+
scene_camera_eye=dict(x=1, y=-2, z=0.5)
|
|
402
411
|
)
|
|
403
412
|
|
|
404
413
|
return fig
|
|
@@ -4,15 +4,15 @@ voly/exceptions.py,sha256=PBsbn1vNMvKcCJwwJ4lBO6glD85jo1h2qiEmD7ArAjs,92
|
|
|
4
4
|
voly/formulas.py,sha256=wSbGAH6GuQThT9QyQY4Ud2eUf9fo1YFHglUmP6fNris,11871
|
|
5
5
|
voly/models.py,sha256=LXXIlpXZQEfXTuCngxC8Hd3bWtw6wdXDCSGxTLmHM-c,3659
|
|
6
6
|
voly/core/__init__.py,sha256=bu6fS2I1Pj9fPPnl-zY3L7NqrZSY5Zy6NY2uMUvdhKs,183
|
|
7
|
-
voly/core/charts.py,sha256=
|
|
7
|
+
voly/core/charts.py,sha256=ycZgbPeROYVRMO61auVXCGLmKZA2NwS3vLOsQ9wqCyo,27526
|
|
8
8
|
voly/core/data.py,sha256=JCPD44UDSJqh83jjapAtXVpJEHm8Hq4JC8lVhl5Zb4A,8935
|
|
9
9
|
voly/core/fit.py,sha256=JOr2XjM-I9HtfbyEN0tdGuNCZimQ2ttm4lNUpF-tKb4,9226
|
|
10
10
|
voly/core/interpolate.py,sha256=ztVIePJZOh-CIbn69wkh1JW2rKywNe2FEewRN0zcSAo,8185
|
|
11
11
|
voly/core/rnd.py,sha256=8FTU-Qp9epW9yE4XSOdiFGIRXrGyXqF6mVgZn1NMvxk,11813
|
|
12
12
|
voly/utils/__init__.py,sha256=E05mWatyC-PDOsCxQV1p5Xi1IgpOomxrNURyCx_gB-w,200
|
|
13
13
|
voly/utils/logger.py,sha256=4-_2bVJmq17Q0d7Rd2mPg1AeR8gxv6EPvcmBDMFWcSM,1744
|
|
14
|
-
voly-0.0.
|
|
15
|
-
voly-0.0.
|
|
16
|
-
voly-0.0.
|
|
17
|
-
voly-0.0.
|
|
18
|
-
voly-0.0.
|
|
14
|
+
voly-0.0.80.dist-info/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
|
|
15
|
+
voly-0.0.80.dist-info/METADATA,sha256=nEYbdurZWjd781ZJaCFQgFMxN65_2GRKBk8T5uipNgA,4092
|
|
16
|
+
voly-0.0.80.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
17
|
+
voly-0.0.80.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
|
|
18
|
+
voly-0.0.80.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|