Skip to content

Commit 1afc2ec

Browse files
authored
Merge pull request #70 from chemardes/feature/adding-more-tests
FEATURE: adding tests
2 parents 26c0bde + 6a19b69 commit 1afc2ec

File tree

5 files changed

+103
-7
lines changed

5 files changed

+103
-7
lines changed

pdesolvers/optionspricing/monte_carlo.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def plot_price_paths(self, closing_prices=None, export=False):
159159
raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.")
160160

161161
plt.rcParams['font.family'] = 'monospace'
162-
plt.rcParams['font.size'] = 10
162+
plt.rcParams['font.size'] = 18
163163

164164
t = self.__generate_grid()
165165

@@ -193,7 +193,7 @@ def plot_distribution_of_final_prices(self, export=False):
193193
raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.")
194194

195195
plt.rcParams['font.family'] = 'monospace'
196-
plt.rcParams['font.size'] = 10
196+
plt.rcParams['font.size'] = 18
197197

198198
final_prices = self.__S[:, -1]
199199

@@ -205,7 +205,8 @@ def plot_distribution_of_final_prices(self, export=False):
205205

206206
if export:
207207
plt.savefig("monte_carlo_prices.pdf", format="pdf", bbox_inches="tight", pad_inches=0.2)
208-
plt.show()
208+
209+
plt.show()
209210

210211
def plot_distribution_of_payoff(self, export=False):
211212
"""
@@ -217,7 +218,7 @@ def plot_distribution_of_payoff(self, export=False):
217218
raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.")
218219

219220
plt.rcParams['font.family'] = 'monospace'
220-
plt.rcParams['font.size'] = 10
221+
plt.rcParams['font.size'] = 18
221222

222223
plt.figure(figsize=(10, 6))
223224
plt.hist(self.__payoff, bins=50, edgecolor='darkblue', alpha=0.5, color='blue', density=True)
@@ -244,7 +245,7 @@ def plot_convergence_analysis(self, analytical_solution, num_simulations_list=No
244245
errors = self.get_benchmark_errors(analytical_solution, num_simulations_list, export=export)
245246

246247
plt.rcParams['font.family'] = 'monospace'
247-
plt.rcParams['font.size'] = 10
248+
plt.rcParams['font.size'] = 18
248249

249250
fig, ax = plt.subplots(figsize=(10,6))
250251
ax.plot(num_simulations_list, errors, 'bo-', linewidth=2)

pdesolvers/tests/test_options_pricing.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from unittest.mock import patch
44

55
from pdesolvers.optionspricing.monte_carlo import MonteCarloPricing
6+
from pdesolvers.optionspricing.black_scholes_formula import BlackScholesFormula
67
from pdesolvers.enums.enums import OptionType, Greeks
78

89
@pytest.fixture
@@ -17,6 +18,16 @@ def mc_pricing_params():
1718
'sim': 5
1819
}
1920

21+
@pytest.fixture
22+
def bs_pricing_params():
23+
return {
24+
'S0': 100.0,
25+
'strike_price': 100.0,
26+
'r': 0.05,
27+
'sigma': 0.2,
28+
'expiry': 1.0
29+
}
30+
2031
class TestMonteCarlo:
2132

2233
@patch('pdesolvers.optionspricing.monte_carlo.MonteCarloPricing.simulate_gbm')
@@ -83,11 +94,51 @@ def test_check_simulate_gbm_initial_values(self, mc_pricing_params):
8394

8495
assert (results[:,0] == mc_pricing_params['S0']).all()
8596

86-
def test_check_get_execution_time_raises_exception_when_no_simulation_is_run(self, mc_pricing_params):
97+
def test_check_get_execution_time_raises_error_when_no_simulation_is_run(self, mc_pricing_params):
8798

8899
test_mc = MonteCarloPricing(
89100
OptionType.EUROPEAN_CALL, **mc_pricing_params
90101
)
91102

92103
with pytest.raises(RuntimeError, match="Execution time is not available because the simulation has not been run yet."):
93104
test_mc.get_execution_time()
105+
106+
def test_check_plot_payoff_raises_error_when_no_simulation_is_run(self, mc_pricing_params):
107+
108+
test_mc = MonteCarloPricing(
109+
OptionType.EUROPEAN_CALL, **mc_pricing_params
110+
)
111+
112+
with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."):
113+
test_mc.plot_distribution_of_payoff()
114+
115+
def test_check_plot_price_distribution_raises_error_when_no_simulation_is_run(self, mc_pricing_params):
116+
117+
test_mc = MonteCarloPricing(
118+
OptionType.EUROPEAN_CALL, **mc_pricing_params
119+
)
120+
121+
with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."):
122+
test_mc.plot_distribution_of_final_prices()
123+
124+
def test_check_plot_price_paths_raises_error_when_no_simulation_is_run(self, mc_pricing_params):
125+
126+
test_mc = MonteCarloPricing(
127+
OptionType.EUROPEAN_CALL, **mc_pricing_params
128+
)
129+
130+
with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."):
131+
test_mc.plot_price_paths()
132+
133+
def test_check_plot_convergence_raises_error_when_no_list_supplied(self, mc_pricing_params, bs_pricing_params):
134+
135+
test_mc = MonteCarloPricing(
136+
OptionType.EUROPEAN_CALL, **mc_pricing_params
137+
)
138+
139+
results = test_mc.simulate_gbm()
140+
141+
price = BlackScholesFormula(OptionType.EUROPEAN_CALL, **bs_pricing_params)
142+
143+
with pytest.raises(ValueError, match="Number of simulations need to be defined."):
144+
test_mc.plot_convergence_analysis(price)

playground/brownian_motion.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def plot(self):
4343
t = self.__generate_grid()
4444
B = self.__get_paths()
4545

46+
plt.rcParams['font.family'] = 'monospace'
47+
plt.rcParams['font.size'] = 18
48+
4649
plt.figure(figsize=(10,6))
4750
for i in range(self.__sim):
4851
plt.plot(t, B[i], color='grey', alpha=0.3)
@@ -55,7 +58,7 @@ def plot(self):
5558

5659

5760
def main():
58-
BrownianMotion(T=1, time_steps=365, sim=200).simulate_bm().plot()
61+
BrownianMotion(T=1, time_steps=365, sim=100).simulate_bm().plot()
5962

6063
if __name__ == "__main__":
6164
main()

playground/export.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
mv /Users/chemardes/Documents/repos/PDESolvers/playground/brownian_plot.pdf /Users/chemardes/Documents/school/gpu-project/report/GPU-Accelerated\ Solution\ for\ BSE/figures/

playground/plot_results_csv.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import numpy as np
2+
import pandas as pd
3+
import matplotlib.pyplot as plt
4+
import os
5+
6+
def plot_option_surface(file_path):
7+
# Expand file path if using ~
8+
file_path = os.path.expanduser(file_path)
9+
10+
# Load data
11+
df = pd.read_csv(file_path, header=None)
12+
print(f"Data shape: {df.shape}")
13+
14+
# Process data
15+
grid_data = df.values.T
16+
17+
# Create coordinate grids
18+
price_grid = np.linspace(0, 300, grid_data.shape[0])
19+
time_grid = np.linspace(0, 1, grid_data.shape[1])
20+
X, Y = np.meshgrid(time_grid, price_grid)
21+
22+
# Create plot
23+
fig = plt.figure(figsize=(10, 6))
24+
ax = fig.add_subplot(111, projection='3d')
25+
surf = ax.plot_surface(X, Y, grid_data, cmap='viridis')
26+
27+
# Add labels and colorbar
28+
ax.set_xlabel('Time')
29+
ax.set_ylabel('Asset Price')
30+
ax.set_zlabel('Option Value')
31+
ax.set_title('Option Value Surface Plot')
32+
fig.colorbar(surf, shrink=0.5, aspect=5)
33+
34+
return fig, ax
35+
36+
if __name__ == "__main__":
37+
fig, ax = plot_option_surface('~/Downloads/out.csv')
38+
plt.show()

0 commit comments

Comments
 (0)