In this post, we will tackle the valuation of a call option using two methods: a closed-form formula and a stochastic model. Options are a type of financial instrument that give their owner the right, but not the obligation, to buy or sell an asset at a predetermined price within a certain period. Here, we'll focus on a call option, which is a type of option allowing the holder to purchase the asset at a specific price (known as the strike price) before the option expires. Call options are commonly used in financial markets to bet on the potential increase in an asset's value.
The valuation of options can be quite complex because it involves forecasting how the price of the underlying asset might change over time. Several factors influence an option's value, including the current price of the asset, the strike price, time remaining until expiry, interest rates, and the volatility of the asset's price.
We'll use two popular methods to assess the option's value: the Black-Scholes closed-form formula and a stochastic model. After calculating the option's value using each approach, we'll compare the results to see if they align or if they produce differing valuations.
List of content:
Option attributes
For our exercise, we'll be valuing a European call option, a type of option that can only be exercised at its expiration date (as opposed to American options, which can be exercised at any point before expiration). Our focus will be on a call option, which means the holder has the right to purchase the underlying asset at a set price, known as the strike price, when the option expires.
Here are the attributes of the option we'll be working with:
- Current price (\( S_{0} \)) - The asset's current market price, which we'll set at EUR 100. This price serves as the starting point for evaluating how the option's value might change.
- Strike price (\( X \)) - The price at which the holder of the option can buy the asset when the option expires. We'll use a strike price of EUR 100, meaning the option will be "at the money" if the asset's price doesn't change over the year.
- Time to expiration (\( T \)) - This is the duration until the option expires, which we'll set to 1 year. Options with longer times to expiration generally have higher value, as there is more time for the asset price to change.
- Risk-free interest rate (\( r \)) - This is the theoretical rate of return on a completely risk-free investment, such as government bonds. For this exercise, we'll assume a 5% risk-free interest rate, reflecting a stable and low-risk environment.
- Volatility of the stock (\( \sigma \)) - This measures the asset's price fluctuations over time. In this case, we'll use a volatility of 0.2, or 20%. Higher volatility means a greater chance for the asset price to swing, which affects the option's potential value.
With these attributes defined, we'll now proceed to valuing the option. In the next section, we'll explore how to calculate the option's price using the Black-Scholes formula, a widely used model in finance for evaluating options.
Black-Scholes formula
Our first approach to valuing the call option is to use the Black-Scholes formula, a closed-form solution that gives us a theoretical price for European options. This formula, introduced by Fischer Black and Myron Scholes in the early 1970s, is widely used in finance due to its simplicity and effectiveness. It allows us to calculate the price of a call option based on five inputs: the current price of the asset, the strike price, the risk-free interest rate, the time to expiration, and the asset's volatility.
The Black-Scholes formula for the price of a European call option is given by:
$$ C = S_{0} \cdot \mathcal{N}(d1) - X \cdot e^{-r \cdot T} \cdot \mathcal{N}(d2) $$where:
\( d1 = \frac{\ln(\frac{S_{0}}{X}) + (r + \frac{\sigma^2}{2} \cdot T)}{\sigma \cdot \sqrt{T}} \)\( d2 = d1 - \sigma \cdot \sqrt{T} \)
In this formula:
\( \mathcal{N}(d1) \) and \( \mathcal{N}(d2) \) represent the cumulative distribution function values for a standard normal distribution at \( d1 \) and \( d2 \). The logic behind the formula is that it combines the expected payoff from exercising the option with adjustments for time value and risk. The factors \( \mathcal{N}(d1) \) and \( \mathcal{N}(d2) \) capture the probabilities that the option will expire "in the money" (profitable) and reflect how much the option's price should account for this uncertainty.
The Python code below calculates the call option price using the Black-Scholes formula:
import numpy as np
from scipy.stats import norm
# Parameters
S0 = 100
X = 100
r = 0.05
T = 1
sigma = 0.2
# Calculate the call option price
d1 = (np.log(S0 / X) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
call_price = S0 * norm.cdf(d1) - X * np.exp(-r * T) * norm.cdf(d2)
print(f"Call option price: EUR {call_price:.2f}")
# Call option price: EUR 10.45
This code computes the option price by applying the Black-Scholes formula. Running the code gives the call option price in euros based on the provided inputs. This method provides a clear, quick way to estimate the option's value, but it does make several assumptions, such as constant volatility and a single risk-free rate, which may not hold in all real-world cases.
In the next section, we'll explore a different approach using stochastic modelling to evaluate the option's value.
Monte Carlo simulation
Our second approach for valuing the call option is to use stochastic modelling, specifically a Monte Carlo simulation. Unlike the Black-Scholes formula, which gives a single theoretical price based on fixed inputs, Monte Carlo simulations allow us to generate a wide range of possible outcomes by simulating many scenarios for the underlying asset's price.
The basic idea is to project the asset's price over the option's life, calculate the payoff for each simulated scenario and then take the average payoff to estimate the option's value.
Economic scenarios
To project the future value of the stock price, we will use a mathematical process called Geometric Brownian Motion (GBM), which is a common model for simulating asset prices. GBM assumes that the price evolves over time in a way that accounts for both predictable growth (linked to the risk-free rate) and random fluctuations (linked to volatility). This combination makes it well-suited for capturing the uncertain, often volatile nature of stock prices.
Here's the Python function to generate simulated price paths based on GBM:
import numpy as np
def gbm(S0, r, T, sigma, n_scen=1, seed=1):
"""Geometric Brownian Motion"""
np.random.seed(seed)
Z = np.random.randn(n_scen)
return S0 * np.exp((r - 0.5 * sigma**2) * T + sigma * np.sqrt(T) * Z)
In this function:
- S0 - the current stock price,
- r - the risk-free interest rate,
- T - the time to expiration,
- sigma - the stock's volatility,
- n_scen - the number of simulated scenarios, and
- Z - the random component, drawn from a normal distribution.
For this exercise, we'll generate 100,000 scenarios to capture a wide range of possible outcomes for the stock price at expiration. Each scenario represents one potential future price path for the asset.
Setting and input
To set up the model, we'll use the cashflower package. Normally, cash flow models use monthly time steps, but since we only care about the option's value at expiration, we'll use an annual step here. In our settings file, we specify 100,000 stochastic scenarios and set the maximum calculation and output times to 1.
# settings.py
settings = {
# ...
"NUM_STOCHASTIC_SCENARIOS": 100_000,
"T_MAX_CALCULATION": 1,
"T_MAX_OUTPUT": 1,
}
The input for our model includes the option's parameters (current price, strike price, time to expiration, risk-free rate, and volatility) and the 100,000 stochastic scenarios generated by the GBM function.
# input.py
import pandas as pd
from settings import settings
from utils.gbm import gbm
n_scen = settings.get("NUM_STOCHASTIC_SCENARIOS")
# European call option parameters
option = {
"S0": 100,
"X": 100,
"T": 1.0,
"r": 0.05,
"sigma": 0.2,
}
# Stochastic scenarios for the stock price
scenarios = pd.DataFrame({
"num": range(1, n_scen+1),
"S1": gbm(option["S0"], option["r"], option["T"], option["sigma"], n_scen)
}).set_index("num")
assumption = {
"option": option,
"scenarios": scenarios,
}
Model
The model itself will have two key variables: the payoff of the option and the present value of the payoff.
- Payoff - the option's payoff depends on whether it expires "in the money". Specifically, if the stock price at expiration (S1) exceeds the strike price (X), the payoff is S1 - X; otherwise, it's zero.
- Discounted payoff - to determine the current value of this future payoff, we need to discount it back to the present using the risk-free interest rate.
Here's the code implementing these steps:
# model.py
import numpy as np
from cashflower import variable
from input import assumption
from settings import settings
@variable()
def payoff(t, stoch):
option = assumption["option"]
if t == option["T"]:
S1 = assumption["scenarios"].loc[stoch, "S1"]
X = option["X"]
return max(S1 - X, 0)
else:
return 0
@variable()
def pv_payoff(t, stoch):
option = assumption["option"]
if t == settings["T_MAX_CALCULATION"]:
return payoff(t, stoch)
else:
return np.exp(-option["r"] * option["T"]) * payoff(t+1, stoch)
In this model:
- The payoff function checks if t equals the option's expiration (T). If so, it calculates the payoff by comparing the stock price S1 to the strike price X.
- The pv_payoff function discounts the payoff to present value.
Behind the scenes stoch changes its value from 1 to 100,000. By averaging the pv_payoff across all scenarios, we'll estimate the fair value of the option. This approach captures the potential range of future prices and their associated payoffs, providing a realistic estimate based on the simulated scenarios.
# output
t payoff pv_payoff
0 0.00 10.50
1 11.04 11.04
Monte Carlo simulations like this one are versatile and can handle complex options or situations where prices follow unpredictable paths, though they tend to be computationally intensive. In the next and final section, we'll wrap up by summarising our findings and comparing the two approaches.
Comparison
Now that we've evaluated the call option using both the closed-form formula and stochastic modelling, let's compare the results and consider what they reveal.
Using the Black-Scholes formula, we arrived at a price of EUR 10.45. This method provides a quick and precise result based on the assumptions that the stock follows a log-normal distribution, volatility remains constant and there are no dividends or transaction costs. The closed-form solution is efficient and gives a solid estimate for simpler options like this European call.
The stochastic modelling approach, which used 100,000 simulated price scenarios, resulted in a price of EUR 10.50. By generating a large number of possible outcomes, we were able to capture a range of potential future prices and their associated payoffs. Monte Carlo simulation is particularly useful for complex options or in situations where market assumptions are less certain, allowing us to see how random fluctuations in price might affect the option's value. Here, we see that the Monte Carlo result is very close to the Black-Scholes price, confirming that both methods yield similar valuations under our set parameters.
Which method to choose?
In this example, both approaches produced similar results, which is often the case when assumptions like constant volatility and a known expiration time hold true. For simple options, the Black-Scholes formula is usually preferred for its speed and precision. However, stochastic modelling is highly valuable when flexibility is needed, such as when dealing with options that have complex payoffs, path dependencies, or other features that make analytical solutions challenging.
In summary, both methods have their strengths and the choice depends on the option's complexity and the level of accuracy required. For our European call option, either approach would be suitable, giving us a consistent valuation of around EUR 10.45–10.50.
Which approach do you find more intuitive for valuing options: analytical formulas or simulations?