Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions pdesolvers/optionspricing/market_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,25 @@ def estimate_metrics(self):
self.__stock_data["Time Diff"] = self.__stock_data.index.to_series().diff().dt.days
self.__stock_data["Z"] = self.__stock_data["Log Returns"] / self.__stock_data["Time Diff"]

sigma = self.__stock_data["Log Returns"].std()
mu = self.__stock_data["Log Returns"].mean()
sigma = self.__stock_data["Log Returns"].std() * np.sqrt(252)
mu = self.__stock_data["Log Returns"].mean() * 252

return sigma, mu

def get_latest_stock_price(self):
if self.__stock_data is None:
raise ValueError("No data available. Call fetch_data first.")

return self.__stock_data["Close"].iloc[-1].item()
return self.__stock_data["Close"].iloc[-1].item()

def get_initial_stock_price(self):
if self.__stock_data is None:
raise ValueError("No data available. Call fetch_data first.")

return self.__stock_data["Close"].iloc[0].item()

def get_closing_prices(self):
if self.__stock_data is None:
raise ValueError("No data available. Call fetch_data first.")

return self.__stock_data["Close"].values
17 changes: 11 additions & 6 deletions pdesolvers/optionspricing/monte_carlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

class MonteCarloPricing:

def __init__(self, option_type: OptionType, S0, strike_price, r, sigma, T, time_steps, sim, seed=None):
def __init__(self, option_type: OptionType, S0, strike_price, mu, sigma, T, time_steps, sim, seed=None):
"""
Initialize the Geometric Brownian Motion model with the given parameters.

Expand All @@ -30,7 +30,7 @@ def __init__(self, option_type: OptionType, S0, strike_price, r, sigma, T, time_
self.__option_type = option_type
self.__S0 = S0
self.__strike_price = strike_price
self.__r = r
self.__mu = mu
self.__sigma = sigma
self.__T = T
self.__time_steps = time_steps
Expand Down Expand Up @@ -60,7 +60,7 @@ def get_monte_carlo_option_price(self):
else:
raise ValueError(f'Unsupported Option Type: {self.__option_type}')

option_price = np.exp(-self.__r * self.__T) * np.mean(self.__payoff)
option_price = np.exp(-self.__mu * self.__T) * np.mean(self.__payoff)

logging.info(f"Option price calculated successfully with {self.__class__.__name__}.")

Expand Down Expand Up @@ -95,7 +95,7 @@ def simulate_gbm(self):
# updates brownian motion
B[i,j] = B[i,j-1] + np.sqrt(dt) * Z[i,j-1]
# calculates stock price based on the incremental difference
S[i,j] = S[i, j-1] * np.exp((self.__r - 0.5*self.__sigma**2)*dt + self.__sigma * (B[i, j] - B[i, j - 1]))
S[i,j] = S[i, j-1] * np.exp((self.__mu - 0.5*self.__sigma**2)*dt + self.__sigma * (B[i, j] - B[i, j - 1]))

end = time.perf_counter()
self.__duration = end - start
Expand Down Expand Up @@ -150,7 +150,7 @@ def __generate_grid(self):

return np.linspace(0, self.__T, self.__time_steps)

def plot_price_paths(self, export=False):
def plot_price_paths(self, closing_prices=None, export=False):
"""
Plot the simulated stock prices for all simulations.
"""
Expand All @@ -171,6 +171,12 @@ def plot_price_paths(self, export=False):
plt.xlabel("Time (Years)")
plt.ylabel("Stock Price")

if closing_prices is not None:
if len(closing_prices) != len(t):
raise ValueError("Length of closing prices does not match the number of time steps in the simulation.")

plt.plot(t , closing_prices, color='red')

if export:
plt.savefig("monte_carlo_prices.pdf", format="pdf", bbox_inches="tight")

Expand Down Expand Up @@ -199,7 +205,6 @@ 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()

def plot_distribution_of_payoff(self, export=False):
Expand Down
6 changes: 3 additions & 3 deletions pdesolvers/tests/test_options_pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def mc_pricing_params():
return {
'S0': 100.0,
'strike_price': 100.0,
'r': 0.05,
'mu': 0.05,
'sigma': 0.2,
'T': 1.0,
'time_steps': 252,
Expand All @@ -31,7 +31,7 @@ def test_get_european_call_option_price(self, mock_simulate_gbm, mc_pricing_para
)

mock_payoffs = np.maximum(np.array([110, 120, 90, 105, 115]) - mc_pricing_params['strike_price'], 0)
expected_price = np.exp(-mc_pricing_params['r'] * mc_pricing_params['T']) * np.mean(mock_payoffs)
expected_price = np.exp(-mc_pricing_params['mu'] * mc_pricing_params['T']) * np.mean(mock_payoffs)

actual_price = test_mc.get_monte_carlo_option_price()

Expand All @@ -49,7 +49,7 @@ def test_get_european_put_option_price(self, mock_simulate_gbm, mc_pricing_param
)

mock_payoffs = np.maximum(mc_pricing_params['strike_price'] - np.array([110, 120, 90, 105, 115]), 0)
expected_price = np.exp(-mc_pricing_params['r'] * mc_pricing_params['T']) * np.mean(mock_payoffs)
expected_price = np.exp(-mc_pricing_params['mu'] * mc_pricing_params['T']) * np.mean(mock_payoffs)

actual_price = test_mc.get_monte_carlo_option_price()

Expand Down