Skip to content

Commit bdffda5

Browse files
authored
Merge pull request #65 from chemardes/feature/some-minor-changes
FEATURE: changing metric calculations
2 parents e302649 + b0a1325 commit bdffda5

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

pdesolvers/optionspricing/market_data.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,25 @@ def estimate_metrics(self):
2121
self.__stock_data["Time Diff"] = self.__stock_data.index.to_series().diff().dt.days
2222
self.__stock_data["Z"] = self.__stock_data["Log Returns"] / self.__stock_data["Time Diff"]
2323

24-
sigma = self.__stock_data["Log Returns"].std()
25-
mu = self.__stock_data["Log Returns"].mean()
24+
sigma = self.__stock_data["Log Returns"].std() * np.sqrt(252)
25+
mu = self.__stock_data["Log Returns"].mean() * 252
2626

2727
return sigma, mu
2828

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

33-
return self.__stock_data["Close"].iloc[-1].item()
33+
return self.__stock_data["Close"].iloc[-1].item()
34+
35+
def get_initial_stock_price(self):
36+
if self.__stock_data is None:
37+
raise ValueError("No data available. Call fetch_data first.")
38+
39+
return self.__stock_data["Close"].iloc[0].item()
40+
41+
def get_closing_prices(self):
42+
if self.__stock_data is None:
43+
raise ValueError("No data available. Call fetch_data first.")
44+
45+
return self.__stock_data["Close"].values

pdesolvers/optionspricing/monte_carlo.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
class MonteCarloPricing:
1616

17-
def __init__(self, option_type: OptionType, S0, strike_price, r, sigma, T, time_steps, sim, seed=None):
17+
def __init__(self, option_type: OptionType, S0, strike_price, mu, sigma, T, time_steps, sim, seed=None):
1818
"""
1919
Initialize the Geometric Brownian Motion model with the given parameters.
2020
@@ -30,7 +30,7 @@ def __init__(self, option_type: OptionType, S0, strike_price, r, sigma, T, time_
3030
self.__option_type = option_type
3131
self.__S0 = S0
3232
self.__strike_price = strike_price
33-
self.__r = r
33+
self.__mu = mu
3434
self.__sigma = sigma
3535
self.__T = T
3636
self.__time_steps = time_steps
@@ -60,7 +60,7 @@ def get_monte_carlo_option_price(self):
6060
else:
6161
raise ValueError(f'Unsupported Option Type: {self.__option_type}')
6262

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

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

@@ -95,7 +95,7 @@ def simulate_gbm(self):
9595
# updates brownian motion
9696
B[i,j] = B[i,j-1] + np.sqrt(dt) * Z[i,j-1]
9797
# calculates stock price based on the incremental difference
98-
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]))
98+
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]))
9999

100100
end = time.perf_counter()
101101
self.__duration = end - start
@@ -150,7 +150,7 @@ def __generate_grid(self):
150150

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

153-
def plot_price_paths(self, export=False):
153+
def plot_price_paths(self, closing_prices=None, export=False):
154154
"""
155155
Plot the simulated stock prices for all simulations.
156156
"""
@@ -171,6 +171,12 @@ def plot_price_paths(self, export=False):
171171
plt.xlabel("Time (Years)")
172172
plt.ylabel("Stock Price")
173173

174+
if closing_prices is not None:
175+
if len(closing_prices) != len(t):
176+
raise ValueError("Length of closing prices does not match the number of time steps in the simulation.")
177+
178+
plt.plot(t , closing_prices, color='red')
179+
174180
if export:
175181
plt.savefig("monte_carlo_prices.pdf", format="pdf", bbox_inches="tight")
176182

@@ -199,7 +205,6 @@ def plot_distribution_of_final_prices(self, export=False):
199205

200206
if export:
201207
plt.savefig("monte_carlo_prices.pdf", format="pdf", bbox_inches="tight", pad_inches=0.2)
202-
203208
plt.show()
204209

205210
def plot_distribution_of_payoff(self, export=False):

pdesolvers/tests/test_options_pricing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def mc_pricing_params():
1010
return {
1111
'S0': 100.0,
1212
'strike_price': 100.0,
13-
'r': 0.05,
13+
'mu': 0.05,
1414
'sigma': 0.2,
1515
'T': 1.0,
1616
'time_steps': 252,
@@ -31,7 +31,7 @@ def test_get_european_call_option_price(self, mock_simulate_gbm, mc_pricing_para
3131
)
3232

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

3636
actual_price = test_mc.get_monte_carlo_option_price()
3737

@@ -49,7 +49,7 @@ def test_get_european_put_option_price(self, mock_simulate_gbm, mc_pricing_param
4949
)
5050

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

5454
actual_price = test_mc.get_monte_carlo_option_price()
5555

0 commit comments

Comments
 (0)