Unveiling the Complexity of European Options

A Journey into Pricing and Brownian Motion Modeling

Posted by Anders Harrysson on May 25, 2023

Welcome, financial enthusiasts and curious minds, to our comprehensive blog series on European options pricing! In this captivating exploration, we will delve into the intricacies of these derivatives, examining their historical significance and shedding light on the remarkable concept of Brownian motion, which serves as a foundation for modeling stock prices. Join us on this enlightening journey as we unlock the secrets behind the pricing of European options and unravel the mysteries of this fascinating financial realm.

What options do I have?

To embark on our journey, let us first establish a fundamental understanding of options. Options are financial instruments that grant their holders the right, but not the obligation, to buy (call option) or sell (put option) a specific underlying asset, such as stocks or commodities, at a predetermined price (strike price) within a predetermined timeframe. Options provide traders and investors with the ability to speculate on price movements, manage risk, and enhance their portfolio strategies.

While options have become increasingly prominent in today's financial landscape, their origins can be traced back to ancient times. The concept of options can be found in the activities of Greek philosopher Thales, who allegedly secured the rights to olive presses ahead of a promising harvest, allowing him to capitalize on a surge in olive oil prices. Since then, options have evolved through centuries of financial innovation, gaining recognition as powerful tools for risk management and speculative trading.

Brownian Motion and Modeling Stock Prices

Brownian motion, named after the Scottish botanist Robert Brown, is a mathematical concept that describes the random motion of particles suspended in a fluid. This intriguing phenomenon has found its applications in various fields, including finance, where it serves as a fundamental tool for modeling stock prices. In this article, we will explore the concept of Brownian motion and demonstrate how it can be utilized to model stock prices using Python.

At its core, Brownian motion involves the continuous and random movement of particles. In finance, it provides a framework for understanding the unpredictable nature of stock price movements. According to the theory, the changes in stock prices over time can be modeled as a stochastic process characterized by random and independent increments.

  • Independence: In a Brownian motion, the increments between different time intervals are independent of each other. This means that the future behavior of the process does not depend on its past or present values. The increments are considered to be random and unrelated.
  • Stationarity: Brownian motion is a stationary process, which means that its statistical properties remain constant over time. Specifically, the mean (expected value) of the increments is zero, and their variance is proportional to the length of the time interval. In other words, the process exhibits constant volatility.

To illustrate this concept, let's consider a simple implementation of Brownian motion using Python. Mathematically, the increment in a Brownian motion can be written as:

$$W_{t2} - W_{t1} \sim \mathcal{N}(0,\sqrt{t2-t1})$$

The increment in stock price can no we written as:

$$dX = \sigma dW$$

Where \( \sigma \) is the volatility of the stock price. The following code snippet generates a random walk, simulating the movement of a stock price over a specified time period:

import numpy as np
import matplotlib.pyplot as plt

def brownian_motion(start_price, n_steps, dt, volatility):
    t = np.linspace(0.0, n_steps * dt, num=n_steps + 1)
    dW = np.random.normal(0.0, np.sqrt(dt), size=n_steps)
    dX = volatility * dW
    X = np.cumsum(dX) + start_price
    return t, X

start_price = 100.0  # Initial stock price
n_steps = 1000       # Number of steps
dt = 10. / n_steps   # Time step
volatility = 0.5     # Volatility of the stock

t, X = brownian_motion(start_price, n_steps, dt, volatility)

plt.plot(t[1:], X,lw=2)
plt.xlabel('Time')
plt.ylabel('Stock Price')
plt.title('Simulation of Brownian Motion')
plt.grid(True)
plt.ticklabel_format(useOffset=False)
plt.show()

And the output from this code look somthing like this

This does in some way look like fluctuation of stock price! However, some “problems” exist using this model. As can be seen from the mathematical expression above, the expected termination price i.e. the price at the end of the time interval, is the same as the start price. This may actually not be the case for a stock market. In addition, we are only interested in the termination price, but still we are computing the entire stock price path up till termination. Can we do something in order to fix these shortcomings?

James Brown(ian) vs James Geometric Brown(ian)

Brownian motion and geometric Brownian motion are closely related concepts in mathematical modeling, particularly in the field of finance. Geometric Brownian motion (GBM) is an extension of Brownian motion that incorporates a drift component and is commonly used to model the dynamics of stock prices and other financial assets.

The key difference between Brownian motion and geometric Brownian motion lies in the presence of a drift term in the latter. While Brownian motion describes the random and unpredictable movement of particles or variables over time, GBM adds a deterministic component to account for the expected growth or return of the process. Mathematically (as previously stated), Brownian motion can be described as:

$$ dX(t) = \sigma dW(t) $$

On the other hand, geometric Brownian motion extends the concept by introducing a drift term to account for the average growth rate of the process:

$$ dX(t) = \mu X(t)dt + \sigma X(t)dW(t) $$

Where \( \mu \) is the drift coefficient, representing the expected rate of return or growth of the process.

By incorporating the drift component, geometric Brownian motion enables the modeling of assets that exhibit both random volatility and an expected trend or growth. This extension allows for more realistic representations of stock prices and other financial quantities0. So by introducing this term, one of the "shortcommings" previously mentioned have been adressed, but what about the second? Is there a way to "only" calculate the price at the final stage, i.e. the termination price?

By solving the stochastic differential equation (SDE) associated with the GBM model, we can obtain the solution for the terminal price of the stock, S(T), at a specified time T. The solution is given by:

$$ S(T) = S(0) e^{( (μ - σ^2/2)T + \sigma \sqrt{T}Z)} $$

where:

  • \(S(0)\) is the initial price of the stock
  • \(Z\) is a random variable following a standard normal distribution \(\mathcal{N}(0,1)\)

To estimate the distribution of the terminal price, you can simulate multiple random samples of Z from the standard normal distribution and use the formula above to calculate the corresponding terminal prices. By repeating this simulation process, you can obtain a distribution of possible terminal prices, which provides insights into the potential outcomes and risk associated with the stock. By focusing on the terminal price rather than simulating the entire path, this approach can be computationally more efficient.

Below some python code can be seen that generates the terminal price for 10 000 simulations.

# Parameters
T = 1  # time horizon
N = 1000  # number of time steps
dt = T / N  # time step size
mu = 0.1  # expected return
sigma = 0.2  # volatility

# Initial stock price
S0 = 100

# Number of simulations
n = 10000

drift = (mu - 0.5 * sigma**2)*T
volatility = sigma * np.sqrt(T)

stock_price_simulations = S0 * np.exp(np.random.normal(drift, volatility, n))

plt.hist(stock_price_simulations,color='r',bins=80,alpha=0.5)
plt.xlim(25,300)
plt.xlabel('Price at termination ($)',fontsize=14)
plt.grid()
plt.show()

And the corresponding plot looks like this:

Some things to notice. Firstly, since the expected return is 10%, the expected value or mean value should be around $110. By looking at the data, this looks to be accurate (calculated value is 110.13$). Secondly, very few values are above 200$ or below 50$. Now that we have a way to model the termination price, let’s look into how to set the price of an option.

The price is right (or is it…)

Let’s look at the example of pricing a call option. A call option is a financial contract that gives the holder the right, but not the obligation, to buy a specified asset (such as a stock) at a predetermined price (strike price) within a specific period (expiration date). What would we be willing to pay for the freedom of choice that this option provides us with?

Let's consider the different scenario that can happened:

  • Stock Price Higher than Strike Price: When the stock price is higher than the strike price, it means that the option holder can buy the underlying stock at a lower price than the current market value. In the case of a call option, which gives the holder the right to buy the stock, this is favorable. The option holder can exercise the call option, purchase the stock at the strike price, and then potentially sell it at the higher market price, generating a profit. In this situation, the call option has intrinsic value, and its payoff is positive,resulting in potential gains for the option holder.
  • Stock Price Lower than Strike Price:If the stock price is lower than the strike price, the option holder would not benefit from exercising the call option. It would be more cost-effective to purchase the stock directly from the market at the lower market price instead of exercising the option at the higher strike price. In this case, the call option has no intrinsic value, and its payoff is zero. The option holder would let the option expire worthless since there is no advantage in exercising the option and incurring a higher cost to buy the stock.
From the above scenarios, the term call payoff can be defined.

The call payoff refers to the potential profit or value obtained from holding the call option at expiration. It represents the financial outcome for the option holder based on the stock price at expiration.

The call payoff is calculated by taking the difference between the stock price at expiration and the strike price of the option. If the stock price is higher than the strike price, the call payoff will be positive. This positive value indicates that the option holder can exercise the call option, purchase the underlying asset (stock) at the strike price, and immediately sell it at the higher market price, thereby realizing a profit. Mathematically, the call payoff is given by the equation:

$$Call Payoff = Max(0, Stock Price - Strike Price)$$

We can then calculate the expected call payoff and after this expected value has been discounted back to the present value using the risk-free interest rate and the time to expiration. This would be the estimated price of the option.

A python function that calculates the estimated price of the option can be seen below. Here the expected return of the stock is similar to the risk free rate.

def call_option_price(S, K, r, sigma, T, num_simulations):
    # S: current stock price
    # K: strike price
    # r: risk-free interest rate
    # sigma: volatility of the stock price
    # T: time to expiration (in years)
    # num_simulations: number of simulations to run
    
    # Calculate drift and volatility terms
    drift = (r - 0.5 * sigma**2) * T
    volatility = sigma * np.sqrt(T)
    
    # Generate simulations of the future stock price
    stock_price_simulations = S * np.exp(np.random.normal(drift, volatility, num_simulations))
    
    # Calculate the payoffs of the call option in each simulation
    call_payoffs = np.maximum(stock_price_simulations - K, 0)
    
    # Calculate the expected payoff and discount it back to the present
    expected_payoff = np.mean(call_payoffs)
    discounted_expected_payoff = np.exp(-r * T) * expected_payoff
    
    # Return the estimated option price
    return discounted_expected_payoff

Let’s try it out using some made up values.

S = 100 # current stock price
K = 105 # strike price
r = 0.05 # risk-free interest rate
sigma = 0.2 # volatility of the stock price
T = 1 # time to expiration (in years)
num_simulations = 100000 # number of simulations to run

call_option_price(S, K, r, sigma, T, num_simulations)

Nice! The price that comes out of this function is approximately 8$. But how will the volatility and the strike price affect the price of the option? Let’s simply reuse the above function but test for some different values of strike price and volatility. After this is done, simply make a contour plot of the result. Below such a pot can be seen.

Time to conclude

This blog post has explored the use of geometric Brownian motion in predicting option prices using Python. By modeling stock prices as a geometric Brownian motion, we have been able to simulate future stock price scenarios and calculate the expected payoffs of call options. The Python code provided has demonstrated how to generate simulations, calculate option payoffs, and estimate option prices. Geometric Brownian motion, provides a useful framework for understanding and valuing options. By incorporating variables such as volatility, time to expiration, and strike price, we can make informed decisions about option trading strategies.

Well I guess that was all for this time and, as always, feel free to contact us at info@gemello.se