11import numpy as np
2+ import pdesolvers .utils .utility as utility
3+ import pdesolvers .enums .enums as enum
4+
25from matplotlib import pyplot as plt
36
4- class Solution1D :
7+ class Solution :
58
6- def __init__ (self , result , x_grid , t_grid ):
9+ def __init__ (self , result , x_grid , y_grid , dx , dy ):
710 self .result = result
811 self .x_grid = x_grid
9- self .t_grid = t_grid
12+ self .y_grid = y_grid
13+ self .dx = dx
14+ self .dy = dy
1015
1116 def plot (self ):
1217 """
13- Generates a 3D surface plot of the temperature distribution across a grid of space and time
18+ Generates a 3D surface plot of the option values across a grid of asset prices and time
1419
1520 :return: 3D surface plot
1621 """
1722
18- if self .result is None :
19- raise RuntimeError ("Solution has not been computed - please run the solver." )
20-
21- x_plot , t_plot = np .meshgrid (self .x_grid ,self .t_grid )
23+ X , Y = np .meshgrid (self .x_grid , self .y_grid )
2224
2325 # plotting the 3d surface
2426 fig = plt .figure (figsize = (10 ,6 ))
2527 ax = fig .add_subplot (111 , projection = '3d' )
26- surf = ax .plot_surface (x_plot , t_plot , self .result , cmap = 'viridis' )
28+ surf = ax .plot_surface (X , Y , self .result , cmap = 'viridis' )
2729
28- # set labels and title
29- ax .set_xlabel ('Space' )
30- ax .set_ylabel ('Time' )
31- ax .set_zlabel ('Temperature' )
32- ax .set_title ('3D Surface Plot of 1D Heat Equation' )
30+ self ._set_plot_labels (ax )
3331
3432 fig .colorbar (surf , shrink = 0.5 , aspect = 5 )
3533 plt .show ()
@@ -42,66 +40,93 @@ def get_result(self):
4240 """
4341 return self .result
4442
45- class SolutionBlackScholes :
46- def __init__ (self , result , s_grid , t_grid , delta , gamma , theta ):
47- self .result = result
48- self .s_grid = s_grid
49- self .t_grid = t_grid
50- self .delta = delta
51- self .gamma = gamma
52- self .theta = theta
43+ def _set_plot_labels (self , ax ):
44+ ax .set_xlabel ('X-axis' )
45+ ax .set_ylabel ('Y-axis' )
46+ ax .set_zlabel ('Value' )
47+ ax .set_title ('3D Surface Plot' )
5348
54- def plot (self ):
49+ def __sub__ (self , other ):
5550 """
56- Generates a 3D surface plot of the option values across a grid of asset prices and time
57-
58- :return: 3D surface plot
51+ Compares two solutions by interpolating the sparse grid to the dense grid and computing the difference
52+ :param other: the grid to be compared against
53+ :return: the error (difference) between the two solutions
5954 """
6055
61- X , Y = np .meshgrid (self .t_grid , self .s_grid )
56+ sparser_grid = other
57+ denser_grid = self
6258
63- # plotting the 3d surface
64- fig = plt .figure (figsize = (10 ,6 ))
65- ax = fig .add_subplot (111 , projection = '3d' )
66- surf = ax .plot_surface (X , Y , self .result , cmap = 'viridis' )
59+ if self .x_grid .shape [0 ] < other .x_grid .shape [0 ] and self .y_grid .shape [0 ] < other .y_grid .shape [0 ]:
60+ sparser_grid = self
61+ denser_grid = other
6762
68- ax .set_xlabel ('Time' )
69- ax .set_ylabel ('Asset Price' )
70- ax .set_zlabel ('Option Value' )
71- ax .set_title ('Option Value Surface Plot' )
63+ interpolator_sparse = utility .RBFInterpolator (sparser_grid .result .T , sparser_grid .dx , sparser_grid .dy )
7264
73- fig .colorbar (surf , shrink = 0.5 , aspect = 5 )
74- plt .show ()
65+ diff = 0
7566
76- def get_result (self ):
77- """
78- Gets the grid of computed option prices
67+ for idx_x in range (denser_grid .x_grid .shape [0 ]):
68+ for idx_y in range (denser_grid .y_grid .shape [0 ]):
7969
80- :return: grid result
81- """
82- return self .result
70+ # Points (x, y) of the dense grid
71+ x = denser_grid .x_grid [idx_x ]
72+ y = denser_grid .y_grid [idx_y ]
73+
74+ # Value at (x, y) for the dense grid
75+ val_dense_x_y = denser_grid .result [idx_y , idx_x ]
8376
84- def plot_greek (self , greek_type = 'delta' , time_step = 0 ):
77+ # Interpolate the sparse grid at (x, y)
78+ val_sparse_x_y = interpolator_sparse .interpolate (x , y )
79+
80+ diff = np .max ([diff , np .abs (val_dense_x_y - val_sparse_x_y )])
81+
82+ return diff
83+
84+ class Solution1D (Solution ):
85+
86+ def __init__ (self , result , x_grid , y_grid , dx , dy ):
87+ super ().__init__ (result , x_grid , y_grid , dx , dy )
88+
89+ def _set_plot_labels (self , ax ):
90+ ax .set_xlabel ('Space' )
91+ ax .set_ylabel ('Time' )
92+ ax .set_zlabel ('Temperature' )
93+ ax .set_title ('3D Surface Plot of 1D Heat Equation' )
94+
95+
96+ class SolutionBlackScholes (Solution ):
97+ def __init__ (self , result , x_grid , y_grid , dx , dy , delta , gamma , theta , option_type ):
98+ super ().__init__ (result , x_grid , y_grid , dx , dy )
99+ self .option_type = option_type
100+ self .delta = delta
101+ self .gamma = gamma
102+ self .theta = theta
103+
104+ def plot_greek (self , greek_type = enum .Greeks .DELTA , time_step = 0 ):
85105
86106 greek_types = {
87- 'delta' : {'data' : self .delta , 'title' : 'Delta' },
88- 'gamma' : {'data' : self .gamma , 'title' : 'Gamma' },
89- 'theta' : {'data' : self .theta , 'title' : 'Theta' }
107+ enum . Greeks . DELTA : {'data' : self .delta , 'title' : enum . Greeks . DELTA . value },
108+ enum . Greeks . GAMMA : {'data' : self .gamma , 'title' : enum . Greeks . DELTA . value },
109+ enum . Greeks . THETA : {'data' : self .theta , 'title' : enum . Greeks . DELTA . value }
90110 }
91111
92- if greek_type .lower () not in greek_types :
93- raise ValueError ("Invalid greek type - please choose between delta/gamma/theta." )
112+ # if greek_type.lower() not in greek_types:
113+ # raise ValueError("Invalid greek type - please choose between delta/gamma/theta.")
94114
95- chosen_greek = greek_types [greek_type . lower () ]
115+ chosen_greek = greek_types [greek_type ]
96116 greek_data = chosen_greek ['data' ][:, time_step ]
97117 plt .figure (figsize = (8 , 6 ))
98- plt .plot (self .s_grid , greek_data , label = f"Delta at t={ self .t_grid [time_step ]:.4f} " , color = "blue" )
118+ plt .plot (self .y_grid , greek_data , label = f"Delta at t={ self .x_grid [time_step ]:.4f} " , color = "blue" )
99119
100- plt .title (f"{ chosen_greek ['title' ]} vs. Stock Price at t={ self .t_grid [time_step ]:.4f} " )
120+ plt .title (f"{ chosen_greek ['title' ]} vs. Stock Price at t={ self .x_grid [time_step ]:.4f} " )
101121 plt .xlabel ("Stock Price (S)" )
102122 plt .ylabel (chosen_greek ['title' ])
103123 plt .grid ()
104124 plt .legend ()
105125
106126 plt .show ()
107127
128+ def _set_plot_labels (self , ax ):
129+ ax .set_xlabel ('Time' )
130+ ax .set_ylabel ('Asset Price' )
131+ ax .set_zlabel (f'{ self .option_type .value } Option Value' )
132+ ax .set_title (f'{ self .option_type .value } Option Value Surface Plot' )
0 commit comments