diff --git a/pdesolvers/optionspricing/monte_carlo.py b/pdesolvers/optionspricing/monte_carlo.py index a6c4504..6704b9c 100644 --- a/pdesolvers/optionspricing/monte_carlo.py +++ b/pdesolvers/optionspricing/monte_carlo.py @@ -159,7 +159,7 @@ def plot_price_paths(self, closing_prices=None, export=False): raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.") plt.rcParams['font.family'] = 'monospace' - plt.rcParams['font.size'] = 10 + plt.rcParams['font.size'] = 18 t = self.__generate_grid() @@ -193,7 +193,7 @@ def plot_distribution_of_final_prices(self, export=False): raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.") plt.rcParams['font.family'] = 'monospace' - plt.rcParams['font.size'] = 10 + plt.rcParams['font.size'] = 18 final_prices = self.__S[:, -1] @@ -205,7 +205,8 @@ def plot_distribution_of_final_prices(self, export=False): if export: plt.savefig("monte_carlo_prices.pdf", format="pdf", bbox_inches="tight", pad_inches=0.2) - plt.show() + + plt.show() def plot_distribution_of_payoff(self, export=False): """ @@ -217,7 +218,7 @@ def plot_distribution_of_payoff(self, export=False): raise RuntimeError("Plots cannot be generated because the simulation has not been run yet.") plt.rcParams['font.family'] = 'monospace' - plt.rcParams['font.size'] = 10 + plt.rcParams['font.size'] = 18 plt.figure(figsize=(10, 6)) 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 errors = self.get_benchmark_errors(analytical_solution, num_simulations_list, export=export) plt.rcParams['font.family'] = 'monospace' - plt.rcParams['font.size'] = 10 + plt.rcParams['font.size'] = 18 fig, ax = plt.subplots(figsize=(10,6)) ax.plot(num_simulations_list, errors, 'bo-', linewidth=2) diff --git a/pdesolvers/tests/test_options_pricing.py b/pdesolvers/tests/test_options_pricing.py index 99f2f8d..7e72a35 100644 --- a/pdesolvers/tests/test_options_pricing.py +++ b/pdesolvers/tests/test_options_pricing.py @@ -3,6 +3,7 @@ from unittest.mock import patch from pdesolvers.optionspricing.monte_carlo import MonteCarloPricing +from pdesolvers.optionspricing.black_scholes_formula import BlackScholesFormula from pdesolvers.enums.enums import OptionType, Greeks @pytest.fixture @@ -17,6 +18,16 @@ def mc_pricing_params(): 'sim': 5 } +@pytest.fixture +def bs_pricing_params(): + return { + 'S0': 100.0, + 'strike_price': 100.0, + 'r': 0.05, + 'sigma': 0.2, + 'expiry': 1.0 + } + class TestMonteCarlo: @patch('pdesolvers.optionspricing.monte_carlo.MonteCarloPricing.simulate_gbm') @@ -83,7 +94,7 @@ def test_check_simulate_gbm_initial_values(self, mc_pricing_params): assert (results[:,0] == mc_pricing_params['S0']).all() - def test_check_get_execution_time_raises_exception_when_no_simulation_is_run(self, mc_pricing_params): + def test_check_get_execution_time_raises_error_when_no_simulation_is_run(self, mc_pricing_params): test_mc = MonteCarloPricing( OptionType.EUROPEAN_CALL, **mc_pricing_params @@ -91,3 +102,43 @@ def test_check_get_execution_time_raises_exception_when_no_simulation_is_run(sel with pytest.raises(RuntimeError, match="Execution time is not available because the simulation has not been run yet."): test_mc.get_execution_time() + + def test_check_plot_payoff_raises_error_when_no_simulation_is_run(self, mc_pricing_params): + + test_mc = MonteCarloPricing( + OptionType.EUROPEAN_CALL, **mc_pricing_params + ) + + with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."): + test_mc.plot_distribution_of_payoff() + + def test_check_plot_price_distribution_raises_error_when_no_simulation_is_run(self, mc_pricing_params): + + test_mc = MonteCarloPricing( + OptionType.EUROPEAN_CALL, **mc_pricing_params + ) + + with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."): + test_mc.plot_distribution_of_final_prices() + + def test_check_plot_price_paths_raises_error_when_no_simulation_is_run(self, mc_pricing_params): + + test_mc = MonteCarloPricing( + OptionType.EUROPEAN_CALL, **mc_pricing_params + ) + + with pytest.raises(RuntimeError, match="Plots cannot be generated because the simulation has not been run yet."): + test_mc.plot_price_paths() + + def test_check_plot_convergence_raises_error_when_no_list_supplied(self, mc_pricing_params, bs_pricing_params): + + test_mc = MonteCarloPricing( + OptionType.EUROPEAN_CALL, **mc_pricing_params + ) + + results = test_mc.simulate_gbm() + + price = BlackScholesFormula(OptionType.EUROPEAN_CALL, **bs_pricing_params) + + with pytest.raises(ValueError, match="Number of simulations need to be defined."): + test_mc.plot_convergence_analysis(price) diff --git a/playground/brownian_motion.py b/playground/brownian_motion.py index 06196ed..90a3b81 100644 --- a/playground/brownian_motion.py +++ b/playground/brownian_motion.py @@ -43,6 +43,9 @@ def plot(self): t = self.__generate_grid() B = self.__get_paths() + plt.rcParams['font.family'] = 'monospace' + plt.rcParams['font.size'] = 18 + plt.figure(figsize=(10,6)) for i in range(self.__sim): plt.plot(t, B[i], color='grey', alpha=0.3) @@ -55,7 +58,7 @@ def plot(self): def main(): - BrownianMotion(T=1, time_steps=365, sim=200).simulate_bm().plot() + BrownianMotion(T=1, time_steps=365, sim=100).simulate_bm().plot() if __name__ == "__main__": main() \ No newline at end of file diff --git a/playground/export.sh b/playground/export.sh new file mode 100644 index 0000000..8604583 --- /dev/null +++ b/playground/export.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +mv /Users/chemardes/Documents/repos/PDESolvers/playground/brownian_plot.pdf /Users/chemardes/Documents/school/gpu-project/report/GPU-Accelerated\ Solution\ for\ BSE/figures/ \ No newline at end of file diff --git a/playground/plot_results_csv.py b/playground/plot_results_csv.py new file mode 100644 index 0000000..792b26e --- /dev/null +++ b/playground/plot_results_csv.py @@ -0,0 +1,38 @@ +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +import os + +def plot_option_surface(file_path): + # Expand file path if using ~ + file_path = os.path.expanduser(file_path) + + # Load data + df = pd.read_csv(file_path, header=None) + print(f"Data shape: {df.shape}") + + # Process data + grid_data = df.values.T + + # Create coordinate grids + price_grid = np.linspace(0, 300, grid_data.shape[0]) + time_grid = np.linspace(0, 1, grid_data.shape[1]) + X, Y = np.meshgrid(time_grid, price_grid) + + # Create plot + fig = plt.figure(figsize=(10, 6)) + ax = fig.add_subplot(111, projection='3d') + surf = ax.plot_surface(X, Y, grid_data, cmap='viridis') + + # Add labels and colorbar + ax.set_xlabel('Time') + ax.set_ylabel('Asset Price') + ax.set_zlabel('Option Value') + ax.set_title('Option Value Surface Plot') + fig.colorbar(surf, shrink=0.5, aspect=5) + + return fig, ax + +if __name__ == "__main__": + fig, ax = plot_option_surface('~/Downloads/out.csv') + plt.show() \ No newline at end of file