-
Notifications
You must be signed in to change notification settings - Fork 0
/
Variance_Gamma.py
65 lines (49 loc) · 1.76 KB
/
Variance_Gamma.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""
Variance Gamma and NIG simulation.
"""
import numpy as np
class VarianceGamma:
"""
"""
def __init__(self, timestep: int, mu: float, sigma: float, beta: float, start_price: float):
self.timestep = timestep
self.mu = mu
self.sigma = sigma
self.beta = beta
self.start_price = start_price
self.rng = np.random.default_rng()
def generate_path(self, n_path: int):
"""
:param n_path:
:return:
"""
dt = 1. / self.timestep
G = self.rng.gamma(dt / self.beta, self.beta, size=(n_path, self.timestep))
Z = self.rng.standard_normal(size=(n_path, self.timestep))
exponent = self.mu * G + self.sigma * np.sqrt(G) * Z
exponent = np.insert(exponent, 0, 0, axis=1)
log_returns = np.cumsum(exponent, axis=1)
prices = self.start_price * np.exp(log_returns)
return prices
class NormalInverseGaussian:
"""
"""
def __init__(self, timestep: int, delta: float, gamma: float, beta: float, start_price: float):
self.timestep = timestep
self.delta = delta
self.gamma = gamma
self.beta = beta
self.start_price = start_price
self.rng = np.random.default_rng()
def generate_path(self, n_path: int):
"""
:return:
"""
dt = 1. / self.timestep
self.delta *= dt
IG = self.rng.wald(self.delta / self.gamma, self.delta ** 2, size=(n_path, self.timestep))
exponent = self.beta * IG + self.rng.standard_normal((n_path, self.timestep)) * np.sqrt(IG)
exponent = np.insert(exponent, 0, 0, axis=1)
log_returns = np.cumsum(exponent, axis=1)
prices = self.start_price * np.exp(log_returns)
return log_returns, prices