Skip to content
All library documents

Plotting Black–Scholes Vanna Across Spot and Volatility

Article Quant Q&A · Author: John_maddon

Summary

The document explains how to visualize Black–Scholes Vanna, the sensitivity of an option’s value to changes in both the underlying price and volatility. The central task is to evaluate Vanna over every pair drawn from two input ranges, rather than matching the first spot value only with the first volatility value, and so on. One answer uses Cartesian products to generate paired inputs and displays the results as a three-dimensional scatter plot. Another builds two-dimensional grids with a mesh operation, evaluates the Vanna formula across the grids, and presents the output as a contour plot or a three-dimensional surface.

The examples clarify that a grid-based surface is useful for seeing how the Greek varies jointly across the two dimensions, while a scatter plot is another way to inspect those combinations. One response also corrects a variable-name typo in the supplied formula. The material is a plotting example rather than a derivation or validation of the Vanna formula, and it does not compare the visualizations or discuss numerical edge cases.

Key ideas

  • Evaluating paired arrays element by element does not cover every spot and volatility combination.
  • A Cartesian product can generate all pairs for a scatter plot.
  • A mesh grid supports evaluating a Greek across a two-dimensional parameter surface.
  • Contour plots and surface plots show different views of the same grid of Vanna values.

Tags

Full text
# Mixed greeks in Python - How plot the following


# Mixed greeks in Python - How plot the following












I am interested about greeks with Black-Scholes. In this case, I have the python formula to compute the greek called "Vanna", that is: $\frac{\partial^2 P}{\partial \sigma \partial S}$ the sensitivity of option value P with respect to a joint movement in underlying and volatility.

Now, let's consider the following example, with S = [100,120] a list of 50 equispaced points and $\sigma$ = [0.05,0.7] another list of 50 equispaced points, in the code below I am able to generate the plot of this greek, with respect each element of S and $\sigma$, i.e. with respect the first element of S and first element of $\sigma$ list, after that with respect to the second element of both list, till the last element of both list.

My question is: How can I take all the possible combinations, between these 2 lists? Maybe it can be done with a 3-dimensional plot? How can I do this in Python?

```
import numpy as np
import matplotlib.pyplot as plt
underlying = np.linspace(100,120,50)
K = 100
T = 1
r = 0
sigma = np.linspace(0.05,0.7,50)
def Vanna_(S, K, T, r, sigma):
    lista = []
    d1 = (np.log(S / K) + (r + 1/2 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    d2 = d1-vol*T**(1/2)
    return (1 / np.sqrt(2 * np.pi) * S  * np.exp(-d1 ** 2 * 1/2) * np.sqrt(T))/S * (1- d1/(sigma*np.sqrt(T)))
plt.plot(Vanna_(underlying, K, T, r, sigma))
```

## Answer by David Duarte (score 8, accepted)

https://quant.stackexchange.com/a/68165

Something like this?

```
from mpl_toolkits import mplot3d
from itertools import product

S = np.linspace(100,120)
vols = np.linspace(0.05,0.7)
combs = list(product(S, vols))

values = [Vanna_(underlying, K, T, r, sigma) for underlying, sigma in combs]
x, y = np.hsplit(np.array(combs), 2)

fig = plt.figure()
ax = plt.axes(projection="3d")
ax.scatter3D(x, y, values, c=values);
```

## Answer by lehalle (score 7)

https://quant.stackexchange.com/a/68169

Here is another solution using `Plotly`.

First of all let me correct a typo in your code

```
def Vanna_(S, K, T, r, sigma):
    lista = []
    d1 = (np.log(S / K) + (r + 1/2 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    d2 = d1-sigma*T**(1/2)
    return (1 / np.sqrt(2 * np.pi) * S  * np.exp(-d1 ** 2 * 1/2) * np.sqrt(T))/S * (1- d1/(sigma*np.sqrt(T)))
```

Then let me use pandas to format the result

```
import numpy as np
import pandas

K = 100
T = 1
r = 0

underlying_1d = np.linspace(100,120,25)
sigma_1d     = np.linspace(0.05,0.3,50)

underlying, sigma = np.meshgrid(underlying_1d, sigma_1d)

Vanna_df = pandas.DataFrame(
    Vanna_(underlying, K, T, r, sigma),
    columns=underlying_1d,
    index=sigma_1d
    )
Vanna_df.index.name  = 'volatility'
Vanna_df.columns.name = 'Strike'
Vanna_df.iloc[:10,:10]
```

Now a contourplot

```
import plotly.graph_objects as go

fig = go.Figure(data =
    go.Contour(
        z=Vanna_df.values,
        x=underlying_1d,
        y=sigma_1d
    ))
fig.update_layout(title='Vanna', autosize=False, 
                  xaxis_title='volatility', yaxis_title='strike',
                  width=700, height=500)
fig.show()
```

and your surface plot

```
import plotly.graph_objects as go

fig = go.Figure(data =
    go.Surface(
        z=Vanna_df.values,
        x=underlying_1d,
        y=sigma_1d
    ))
fig.update_traces(contours_z=dict(show=True, usecolormap=True,
                                  highlightcolor="limegreen", project_z=True))

fig.update_layout(title='Vanna', autosize=False,
                  width=700, height=500)
fig.show()
```

(Note: it is not my habit to post code on `quant.stackexchange` but I am training myself to use `Plotly` nowadays...)

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.