Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
cantaro86
GitHub Repository: cantaro86/Financial-Models-Numerical-Methods
Path: blob/master/src/FMNM/FFT.py
1700 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Mon May 18 20:13:17 2020
5
6
@author: cantaro86
7
"""
8
9
import numpy as np
10
from scipy.fftpack import ifft
11
from scipy.interpolate import interp1d
12
from scipy.integrate import quad
13
from scipy.optimize import fsolve
14
15
16
def fft_Lewis(K, S0, r, T, cf, interp="cubic"):
17
"""
18
K = vector of strike
19
S = spot price scalar
20
cf = characteristic function
21
interp can be cubic or linear
22
"""
23
N = 2**15 # FFT more efficient for N power of 2
24
B = 500 # integration limit
25
dx = B / N
26
x = np.arange(N) * dx # the final value B is excluded
27
28
weight = np.arange(N) # Simpson weights
29
weight = 3 + (-1) ** (weight + 1)
30
weight[0] = 1
31
weight[N - 1] = 1
32
33
dk = 2 * np.pi / B
34
b = N * dk / 2
35
ks = -b + dk * np.arange(N)
36
37
integrand = np.exp(-1j * b * np.arange(N) * dx) * cf(x - 0.5j) * 1 / (x**2 + 0.25) * weight * dx / 3
38
integral_value = np.real(ifft(integrand) * N)
39
40
if interp == "linear":
41
spline_lin = interp1d(ks, integral_value, kind="linear")
42
prices = S0 - np.sqrt(S0 * K) * np.exp(-r * T) / np.pi * spline_lin(np.log(S0 / K))
43
elif interp == "cubic":
44
spline_cub = interp1d(ks, integral_value, kind="cubic")
45
prices = S0 - np.sqrt(S0 * K) * np.exp(-r * T) / np.pi * spline_cub(np.log(S0 / K))
46
return prices
47
48
49
def IV_from_Lewis(K, S0, T, r, cf, disp=False):
50
"""Implied Volatility from the Lewis formula
51
K = strike; S0 = spot stock; T = time to maturity; r = interest rate
52
cf = characteristic function"""
53
k = np.log(S0 / K)
54
55
def obj_fun(sig):
56
integrand = (
57
lambda u: np.real(
58
np.exp(u * k * 1j)
59
* (cf(u - 0.5j) - np.exp(1j * u * r * T + 0.5 * r * T) * np.exp(-0.5 * T * (u**2 + 0.25) * sig**2))
60
)
61
* 1
62
/ (u**2 + 0.25)
63
)
64
int_value = quad(integrand, 1e-15, 2000, limit=2000, full_output=1)[0]
65
return int_value
66
67
X0 = [0.2, 1, 2, 4, 0.0001] # set of initial guess points
68
for x0 in X0:
69
x, _, solved, msg = fsolve(
70
obj_fun,
71
[
72
x0,
73
],
74
full_output=True,
75
xtol=1e-4,
76
)
77
if solved == 1:
78
return x[0]
79
if disp is True:
80
print("Strike", K, msg)
81
return -1
82
83