STOXX Europe 600 Option Pricing Using Monte Carlo Methods

Finsinyur
The Startup
Published in
9 min readDec 6, 2020
Photo by Mathias Konrath on Unsplash

Hello there!

This is my first attempt to apply what I have learned from WorldQuant University’s Masters’ in Finance Engineering, and I’d like to start with pricing a vanilla call option using computational finance methods. As there are many things I’m still trying to learn, I would love to hear your feedback and suggestions on making a more realistic option pricing model! :)

In this article, I chose the STOXX Europe 600 Index as the underlying. I will first introduce the index, followed by reviewing its performance in 2020, and finally applying the Monte-Carlo simulation to derive a price based on some assumptions I made.

So, what is STOXX Europe 600?

According to Qontigo, the index provider, the STOXX Europe 600 index (SXXP) has “… a fixed number of 600 components,… represents large, mid and small capitalization companies across 17 countries of the European region: Austria, Belgium, Denmark, Finland, France, Germany, Ireland, Italy, Luxembourg, the Netherlands, Norway, Poland, Portugal, Spain, Sweden, Switzerland, and the United Kingdom”. In short, it is a broad-based index much like the popular S&P 500 Index of the US. Some interesting companies in the index are as follows:

Figure 1. Top 10 companies in STOXX Europe 600 Index

So what makes up the STOXX Europe 600? As part of a data visualization project, I have explored the building blocks of the index. Here, I took the data source from Qontigo’s website, which you may also try out by signing up for an account.

Figure 2. Left: Top 5 countries’ weightage. Right: Bubble plot of constituents by countries.

As we can see from Figure 2 (left), the top 5 countries that dominated the STOXX Europe 600 are Great Britain, France, Switzerland, Germany, and the Netherlands. These 5 represent near 77% of the index.

To present the countries on a map with bubble plots to show their relative importance, I employed plotly.express (for visualization) and geopy (for coordinates). The below code snippet shows how this is done, which resulted in the chart in Figure 2 (right).

# Import essential libraries for plotting geo map
import plotly.express as px
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="geo_test")
all_countries = SXXP_constituents['Country'].unique()
geo_dict = []def retrieve_coords(country):
# function to retrive country's coordinates
loc = geolocator.geocode(country)
return (loc.latitude, loc.longitude)
for country in all_countries:
geo_info = {}
coords = retrieve_coords(country)
geo_info['Country'] = country
geo_info['Latitude'] = coords[0]
geo_info['Longitude'] = coords[1]

geo_dict.append(geo_info)

df_geo = pd.DataFrame(geo_dict)
df_weight = SXXP_constituents[['Country','Weight']].copy().groupby(by = 'Country', as_index = False).sum()
df_country_weight = pd.merge(df_geo, df_weight, how='inner',on = 'Country')
df_country_weight['% Weight'] = round(df_country_weight['Weight']*100,2)fig = px.scatter_geo(df_country_weight, lat="Latitude", lon = 'Longitude', size="% Weight", hover_name = 'Country')
fig.show()

Now that we are done with the countries, the next step is to explore the sectors. From Figure 1, it seems like Healthcare dominates a good part of the top 10. Let’s explore further to verify if this is true!

%matplotlib inlineconstituents_ss = SXXP_constituents[['Supersector', 'Weight']].groupby(by = ['Supersector']).sum()constituents_ss.plot.pie(y='Weight', figsize=(7.5, 7.5), cmap = 'tab20b',\
title = 'Constituents breakdown by Supersectors', autopct='%1.0f%%')
plt.legend(loc='center left', bbox_to_anchor=(1.25, 0.5))plt.show()
Figure 3. SXXP Weighting by Supersectors

As expected, the SXXP constitutes 16% Healthcare, which is the largest make up of the index. Industrial Goods & Services and Personal & Household Goods took up first- and second runner-ups, with a weighting of 13% and 9% respectively.

As seen from our visualizations, the SXXP is well-diversified, in both supersectors and countries, which makes it a suitable passive investment choice. So how did SXXP perform over the year?

Trading Activity on STOXX Europe 600 Index

Using python library yfinance, I managed to extract the past year closing prices and trading volume of SXXP (yahoo ticker ‘^STOXX’). For comparison, I also extracted the S&P500 Index (yahoo ticker ‘^GSPC’).

def get_trade_data(ticker, start, end, essential_data):

df = yf.download(ticker, start, end)
df['Log return'] = np.log(df['Close']/df['Close'].shift(periods = 1))
df['Normalized price'] = df['Close']/df['Close'].iloc[0]
return df[essential_data]trade_data = ['Volume','Close','Log return', 'Normalized price']
# Retrieve trade data for STOXX Europe 600 Index
SXXP = get_trade_data('^STOXX', start='2020-01-01', end='2020-12-02', essential_data = trade_data)
# For comparison later, extract S&P 500 Index data
SPX = get_trade_data('^GSPC', start='2020-01-01', end='2020-12-02', essential_data = trade_data)
# Create a dataframe containing the normalized prices of both STOXX Europe 600 and S&P 500 (for visualization)
normalized_prices = pd.concat([SXXP['Normalized price'], SPX['Normalized price']], axis = 1)
normalized_prices.columns = ['SXXP', 'SPX']
fig, axes = plt.subplots(nrows = 2, ncols = 2, figsize=(15,15), sharex = True)# ax 1 - close price of STOXX Europe 600
SXXP.plot.line(y = 'Close', legend = None, title = 'Close Price of SXXP', ax = axes[0][0])
# ax 2 - normalized prices of STOXX Europe 600 and S&P 500
normalized_prices.plot.line(title = 'Normalized Prices', ax = axes[1][0])
# ax 3 - Traded volume of STOXX Europe 600
SXXP.plot.line(y = 'Volume', legend = None, title = 'Traded Volume of SXXP', ax = axes[0][1])
# ax 4 - Log Return of STOXX Europe 600
SXXP.plot.line(y = 'Log return', legend = None, title = 'Log Return of SXXP', ax = axes[1][1])
plt.show()
Figure 4. Trading of SXXP

Figure 4 summarizes the trading activity of the SXXP, and we can see that there was a slump due to the COVID-19 crisis, and the market recovered, with a boost in November 2020 when Pfizer announced the vaccine.

The STOXX Europe 600 index is well-correlated (71%) with the S&P 500 Index. However, they are not well cointegrated, and this is largely due to the different building blocks. The two indices diverged drastically from May 2020 to September 2020, with S&P 500 Index outperformed SXXP. One possible reason is that the S&P 500 is tech-heavy (a quick google search showed that tech makes up 27% of the S&P 500), and the tech-rally gave the index a tailwind to climb much further.

So how did SXXP perform over the past 10 years?

Figure 5. 10 Year Historical Performance of SXXP

Based on the Adjusted Closing Price data (Adj. Price is used here to take into account corporate actions), the 10-year annualized returns of the SXXP is a decent 4.1%. The European market shows good potential over the years, although many times its momentum is being hindered by uncertainties (such as BREXIT, US-China Trade Tensions, and the COVID-19). Despite these hurdles, the diversification in the index and its focus on Healthcare and Technology could help bolster its recovery and growth in the coming years.

Monte Carlo Method in Option Pricing

In computation finance, Monte Carlo Method is extremely popular in derivatives pricing and portfolio optimization and according to Wikipedia, it is “are a broad class of computational algorithms that rely on repeated random sampling to obtain numerical results”. In the context of option pricing, this is a numerical solution that requires the analyst to simulate the underlying asset price movement, based on a Geometric Brownian Motion (GBM) mechanics with drift and volatility, under a risk-neutral assumption.

Equation 1. Underlying Asset Price Mechanics

Without delving too much into the theory, the following shows the steps taken to derive a numerical solution for the at-the-money call option price. The contract that we are trying to calculate for is December 2020, which expires on18 December 2020.

  1. Calculate, based on historical data, the daily volatility parameter to be used
  2. Define assumptions on other parameters
  3. Simulate, based on assumed parameters, the SXXP paths on a daily interval, and calculate the mean and standard deviations of the paths on a daily interval
  4. Based on the defined strike price, get the call payout at the end of each simulated path, find the mean of the payouts, and discount it by the assumed interest rate to derive the solution.

Assumptions

  • Taking the last available price on 2/12/2020, EUR 391.90, we intend to price the option at a strike price of EUR 392.50
  • Assume that the volatility is constant, and the volatility over the 3 months (September 1st to December 2nd) is representative of the upcoming volatility
  • Given the negative interest rate environment, we take the daily interest rate based on the annualized yield of a Euro-zone 3-months money market instrument on the Euro yield curve. (As of 2nd December, the annualized yield of a 3-month maturity is -0.615711%)
  • Days to expiry — 12days
  • Number of simulation — 10,000
Figure 6. Left: Monte Carlo Simulation of the SXXP path, with 50 simulations. Right: Expected stock path and +/- 3 s.d. of the SXXP path based on 10,000 simulations.

Figure 6 (left) shows a good picture of the Monte Carlo Simulation in action. Based on our assumption, the expected price and the upper, lower limits are as shown in Figure 6 (right). We are seeing a downward movement in the expected price mainly because our drift is assumed to be negative due to the interest rate assumption.

Figure 7. SXXP Option (OXXP) settlement price on Eurex

In our model, The calculated Option Price is EUR 5.61. So how realistic is this? Fortunately for us, Options on STOXX Europe 600 Index is available for trading on Eurex, the home exchange of MSCI Index, major European Index and Interest rate derivatives. Based on its website, the settlement price of the Dec20 Call 392.50 contract is EUR 4.20.

Why the discrepancy? — you may ask. My personal take is the following:

  1. The oversimplicity of the assumption on the asset price mechanics. Here we make a bold assumption of a risk-neutral reality. However, this is rarely true.
  2. The constant volatility assumption is flawed. One key downside of the traditional options pricing model is the constant volatility assumption. As with the Black-Scholes Model, we assume that volatility will remain constant. However, in the log return chart in Figure 4, there is an obvious sign of volatility clustering. The volatility is nowhere constant in the past 3 months as well, with the ups-and-downs driven by the development of COVID-19 situations and the US election. however, this can be improved with a non-constant volatility model, such as local volatility models and stochastic volatility models.
  3. The negative interest rate assumption. In our solution, we assume the interest rates based on the 3-months maturity on the Euro-yield curve. Is this the best assumption? As my knowledge of fixed income is limited, I hope to receive some feedback from you. It is certain that the interest rate assumption plays a huge part in this option pricing model, as shown in Figure 7 below.
  4. Source data. Price makers on huge exchanges tend to be career market makers from established firms. Hence, the quality of data and resources available for market makers are of the level unmatched by any casual enthusiasts like myself. Here, I’m using only the settlement price data, whereas the professional models may take into account real-time, intraday data of the underlying, the market microstructure, and the data of a related instrument (e.g. futures). All these contribute to the discrepancy as well.
Figure 7. Influence of interest rate assumption on Option Pricing

Conclusion

I hope this little exercise gives you a better idea of STOXX Europe 600 and also some insights into pricing options using Monte Carlo Method. The reasons why numerical solutions may be better than an analytical solution (such as the Black Scholes model) is that

  • It allows us to incorporate non-constant volatility models into the pricing
  • It allows us to integrate calibrated interest rate models into the pricing
  • It provides a ‘good-enough’ valuation of the options
  • It makes pricing of structured products (e.g. Barrier options) much easier
  • It looks cool :P

Please provide me any feedback you have on this and how I can explore building my expertise in financial engineering. Thanks so much for your time reading this project. The source code of this project will be made available on GitHub on the next edit, so stay tuned!

!!!Update 1!!!

As promised, here’s the link to my github repository for this mini-project:

You may find here the jupyter notebook view. Enjoy!

Disclaimer: The author is a business analyst working in Eurex, a financial derivatives exchange owned by the Deutsche Boerse Group. As a Group company, Deutsche Boerse also owns Qontigo. This article is written entirely on a personal capacity for the sole purpose of education.

--

--

Finsinyur
The Startup

Insinyur (n): refers to ‘Engineer’ in Bahasa. ‘Finsinyur’ is my take on being an aspiring Financial Engineer rooted in South East Asia.