Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
cantaro86
GitHub Repository: cantaro86/Financial-Models-Numerical-Methods
Path: blob/master/src/FMNM/TC_pricer.py
1700 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Mon Jun 10 09:56:25 2019
5
6
@author: cantaro86
7
"""
8
9
from time import time
10
import numpy as np
11
import numpy.matlib
12
import FMNM.cost_utils as cost
13
14
15
class TC_pricer:
16
"""
17
Solver for the option pricing model of Davis-Panas-Zariphopoulou.
18
"""
19
20
def __init__(self, Option_info, Process_info, cost_b=0, cost_s=0, gamma=0.001):
21
"""
22
Option_info: of type Option_param. It contains (S0,K,T)
23
i.e. current price, strike, maturity in years
24
25
Process_info: of type Diffusion_process.
26
It contains (r,mu, sig) i.e. interest rate, drift coefficient, diffusion coeff
27
cost_b: (lambda in the paper) BUY cost
28
cost_s: (mu in the paper) SELL cost
29
gamma: risk avversion coefficient
30
"""
31
32
if Option_info.payoff == "put":
33
raise ValueError("Not implemented for Put Options")
34
35
self.r = Process_info.r # interest rate
36
self.mu = Process_info.mu # drift coefficient
37
self.sig = Process_info.sig # diffusion coefficient
38
self.S0 = Option_info.S0 # current price
39
self.K = Option_info.K # strike
40
self.T = Option_info.T # maturity in years
41
self.cost_b = cost_b # (lambda in the paper) BUY cost
42
self.cost_s = cost_s # (mu in the paper) SELL cost
43
self.gamma = gamma # risk avversion coefficient
44
45
def price(self, N=500, TYPE="writer", Time=False):
46
"""
47
N = number of time steps
48
TYPE writer or buyer
49
Time: Boolean
50
"""
51
t = time() # measures run time
52
np.seterr(all="ignore") # ignore Warning for overflows
53
54
x0 = np.log(self.S0) # current log-price
55
T_vec, dt = np.linspace(0, self.T, N + 1, retstep=True) # vector of time steps and time steps
56
delta = np.exp(-self.r * (self.T - T_vec)) # discount factor
57
dx = self.sig * np.sqrt(dt) # space step1
58
dy = dx # space step2
59
M = int(np.floor(N / 2))
60
y = np.linspace(-M * dy, M * dy, 2 * M + 1)
61
N_y = len(y) # dim of vector y
62
med = np.where(y == 0)[0].item() # point where y==0
63
64
def F(xx, ll, nn):
65
return np.exp(self.gamma * (1 + self.cost_b) * np.exp(xx) * ll / delta[nn])
66
67
def G(xx, mm, nn):
68
return np.exp(-self.gamma * (1 - self.cost_s) * np.exp(xx) * mm / delta[nn])
69
70
for portfolio in ["no_opt", TYPE]:
71
# interates on the zero option and writer/buyer portfolios
72
# Tree nodes at time N
73
x = np.array([x0 + (self.mu - 0.5 * self.sig**2) * dt * N + (2 * i - N) * dx for i in range(N + 1)])
74
75
# Terminal conditions
76
if portfolio == "no_opt":
77
Q = np.exp(-self.gamma * cost.no_opt(x, y, self.cost_b, self.cost_s))
78
elif portfolio == "writer":
79
Q = np.exp(-self.gamma * cost.writer(x, y, self.cost_b, self.cost_s, self.K))
80
elif portfolio == "buyer":
81
Q = np.exp(-self.gamma * cost.buyer(x, y, self.cost_b, self.cost_s, self.K))
82
else:
83
raise ValueError("TYPE can be only writer or buyer")
84
85
for k in range(N - 1, -1, -1):
86
# expectation term
87
Q_new = (Q[:-1, :] + Q[1:, :]) / 2
88
89
# create the logprice vector at time k
90
x = np.array([x0 + (self.mu - 0.5 * self.sig**2) * dt * k + (2 * i - k) * dx for i in range(k + 1)])
91
92
# buy term
93
Buy = np.copy(Q_new)
94
Buy[:, :-1] = np.matlib.repmat(F(x, dy, k), N_y - 1, 1).T * Q_new[:, 1:]
95
96
# sell term
97
Sell = np.copy(Q_new)
98
Sell[:, 1:] = np.matlib.repmat(G(x, dy, k), N_y - 1, 1).T * Q_new[:, :-1]
99
100
# update the Q(:,:,k)
101
Q = np.minimum(np.minimum(Buy, Sell), Q_new)
102
103
if portfolio == "no_opt":
104
Q_no = Q[0, med]
105
else:
106
Q_yes = Q[0, med]
107
108
if TYPE == "writer":
109
price = (delta[0] / self.gamma) * np.log(Q_yes / Q_no)
110
else:
111
price = (delta[0] / self.gamma) * np.log(Q_no / Q_yes)
112
113
if Time is True:
114
elapsed = time() - t
115
return price, elapsed
116
else:
117
return price
118
119