1
$\begingroup$

I am trying to calibrate SVI model using the following code

import numpy as np
from scipy import optimize
from matplotlib import pyplot as plt
spot = 1.3444
forward = 1.342782
t = 30 / 365.0
vols = np.array([9.420, 9.772, 9.237, 10.144, 9.196, 10.724, 9.265, 11.161, 9.390, 11.908, 9.751]) / 100
strikes = np.array([1.34342148, 1.35800697, 1.32950654, 1.37006384, 1.31948358, 1.38700437, 1.30670715,
                    1.39978993, 1.29765089, 1.42124726, 1.28287975])
total_implied_variance = t * vols ** 2

def sviraw(k, param):
    a = param[0];
    b = param[1];
    m = param[2];
    rho = param[3];
    sigma = param[4];

    totalvariance = a + b * (rho * (k - m) + np.sqrt((k - m)** 2 + sigma**2));
    return totalvariance



def targetfunction(x):
    value=0
    for i in range(11):
        model_total_implied_variance = sviraw(np.log(strikes[i] / forward), x);
        value =value+(total_implied_variance[i]  - model_total_implied_variance) ** 2;
    return value**0.5

bound = [(1e-5, max(total_implied_variance)),(1e-3, 0.99),(min(strikes), max(strikes)),(-0.99, 0.99),(1e-3, 0.99)]
result = optimize.differential_evolution(targetfunction,bound,tol=1e-8)
x=result.x

K = np.linspace(-0.5, 0.5, 60)

newVols = [np.sqrt(sviraw(logmoneyness, x)/t) for logmoneyness in K]
plt.plot(np.log(strikes / forward), vols, marker='o', linestyle='none', label='market')
plt.plot(K, newVols, label='SVI')
plt.title("vol curve")

plt.grid()
plt.legend()
plt.show()

But I am getting the following curve that does not fit the input. enter image description here

$\endgroup$

1 Answer 1

2
$\begingroup$

I'd probably use a different solver, e.g. use BFGS in scipy:

result = optimize.minimize(targetfunction, bound, tol=1e-8, method="BFGS")

That seems to do the job. I don't know much about scipy.optimize.differential_evolution but it seems to fail minimising your loss function.

enter image description here

$\endgroup$
2
  • $\begingroup$ Thank you for your answer. the minimizer you have used needs some starting point which are not available. Morever I have used your correction but I did not have the same shape as yours $\endgroup$
    – User2089
    Commented Jan 14, 2023 at 13:20
  • 1
    $\begingroup$ I randomly selected the initial guess, in this case it just happened to be the first 5 elements from bound. You can use e.g. x_0 = [0, max(total_implied_variance), 0, 1, min(strikes)] but a better approach would be using e.g. what Le Floc'h (2014). $\endgroup$
    – oronimbus
    Commented Jan 14, 2023 at 16:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.