Lattice Models of Equity Pricing#
Introduction#
A lattice model discretizes the potential future states of the world into a finite number of options. For instance, a binomial lattice model has two future states: up
and down
, while a ternary lattice model has three: up
, down
, and flat
. To make predictions, we must assign values and probabilities to each of these future states and then calculate the expected value and variance of future values. Thus, we do not know quantities such as share price exactly because we are projecting into the future. Instead, we have only a probabilistic model of the possible future values.
Let’s look at the simplest possible lattice model, a binomial lattice. This is our first example of a stochastic model of equity pricing.
Single-period binomial model#
Consider a single-period binomial model which goes from an initial time 0
to a final time 1
(Fig. 17). The initial share price at time 0
is \(S_{\circ}\) and the share price at time 1
is \(S_{1}\). During the transition from time 0
\(\rightarrow\)1
the world moves from a current state to the up
state with probability \(p\) or the down
state with probability \((1-p)\).
Fig. 17 Schematic of a single-period binomial lattice model. In the future, the world can probabilistically move to the up
with probability \(p\) or the down
state with probability \((1-p)\). The share price at time 1
is \(S_{1}\) and can take on one of two possible values: \(S^{u}\) if the world moves to the up
state, or \(S^{d}\) if the world moves to the down
state.#
At the time 1
, the share price \(S_{1}\) can take on one of two possible values: \(S^{u} = u\cdot{S_{\circ}}\) if the world moves to the up
state, or \(S^{d} = d\cdot{S_{\circ}}\) if the world moves to the down
state. The up
and down
factors \(u\) and \(d\), and the probability \(p\) can be defined in various ways.
Let’s consider two approaches for computing the tuple \((u,d,p)\): real-world probabilities, which can be estimated from historical data, and risk-neutral probabilities, which are hypothetical probabilities that allow us to price assets as if investors are risk-neutral.
Real-world probability#
We can estimate real-world values for the up
and down
factors \(u\) and \(d\), and the probability \(p\) by analyzing realized prices (the real world realization of the hidden pricing process for an asset). For example, consider the following strategy:
Real-world \((u,d,p)\) strategy
We can estimate the real world probability \(p\) by counting the number of times the share price went up and dividing by the total number of observations. Similarly, we can estimate the up
and down
factors \(u\) and \(d\) by computing the average change in the share price when the share price went up and down, respectively.
Implementation: Real-world \((u,d,p)\) strategy#
To create a binomial lattice model for share price projections using real-world probabilities, we estimate the three critical parameters: \(p\), \(u\), and \(d\) from historical data:
The \(p\) parameter represents the probability of a share price increase or an
up
move between two periods \(j\rightarrow{j+1}\). As a binary lattice model only allowsup
anddown
moves, the probability of adown
move is \(1-p\).The \(u\) parameter represents the amount of an
up
move. If \(S_{j}\) stands for the share price in period \(j\), and \(S_{j+1}\) is the share price in the next period, then anup
move will give \(S_{j+1} = u\cdot{S}_{j}\).The \(d\) parameter represents the amount of a
down
move. If \(S_{j}\) stands for the share price in period \(j\), and \(S_{j+1}\) is the share price in the next period, then adown
move will give \(S_{j+1} = d\cdot{S}_{j}\).
We can calculate the number of up
and down
moves, and the magnitude of these moves by analyzing a training dataset. To do this, we assume a share price model of the form:
where \(\mu_{j,j-1}\) denotes the growth rate (units: 1/time) and \(\Delta{t}\) (units: time) denotes the step size during the time period \((j-1)\rightarrow{j}\). Solving for the growth rate parameter \(\mu_{j,j-1}\) gives the expression:
Assuming we use daily data the natural time frame between \(S_{j-1}\) and \(S_{j}\) is a single trading day. However, subsequently, it will be easier to use an annualized value for the \(\mu\) parameter; thus, we let \(\Delta{t} = 1/252\), i.e., the fraction of a year that occurs in a single trading day. If we use a different ferquency of data, e.g., weekly, then we would need to adjust the \(\Delta{t}\) parameter accordingly.
1# initialize -
2max_number_of_records = nrow(firm_data) # how many records do we have?
3Δt = (1.0/252.0); # daily data: assume time step is 1 x trading data
4μ = Array{Float64,1}(undef, max_number_of_records - 1) # initialize growth rate array
5
6# main loop: compute the growth rate, store in the μ array
7for j ∈ 2:max_number_of_records
8
9 S₁ = firm_data[j-1,:volume_weighted_average_price];
10 S₂ = firm_data[j,:volume_weighted_average_price];
11 μ[j-1] = (1/Δt)*log(S₂/S₁);
12end
Finally to estimate \(p\), after calculating \(\mu_{j,j-1}\) for each trading day in the training dataset, we count the number of times the share price went up, i.e., \(\mu_{j,j-1}>0\), and divide by the total number of observations. The magnitude of the up
and down
moves can be estimated by computing the average change in the share price factors when the share price went up and down, respectively, transforming these values, i.e., \(u(j)= \exp\left(\mu_{j,j-1}\cdot\Delta{t}\right)\) when \(\mu_{j,j-1}>0\) and \(d(j)= \exp\left(\mu_{j,j-1}\cdot\Delta{t}\right)\) when \(\mu_{j,j-1}<0\), and then taking the average of these values.
Assuming we have already calculated the \(\mu_{j,j-1}\) values for each trading period in the training dataset, the following code snippet defines the analyze
function which estimates the \(p\), \(u\), and \(d\) parameters from the \(\mu_{j,j-1}\) values:
1"""
2 analyze(R::Array{Float64,1};
3 Δt::Float64 = (1.0/252.0)) -> Tuple{Float64,Float64,Float64}
4
5Computes the probability of an up move and the up and down factors for a binomial lattice model.
6The `R` argument is an array of growth rate values, and the `Δt` argument is the fraction of a
7year that occurs in a single lattice step (default: 1 trading day). The function returns a
8tuple of the form $(p,u,d)$
9"""
10function analyze(R::Array{Float64,1};
11 Δt::Float64 = (1.0/252.0))::Tuple{Float64,Float64,Float64}
12
13 # initialize -
14 u,d,p = 0.0, 0.0, 0.0;
15 darray = Array{Float64,1}();
16 uarray = Array{Float64,1}();
17 N₊ = 0;
18
19 # up - compute the up moves, and estimate the average u value -
20 index_up_moves = findall(x->x>0, R);
21 for index ∈ index_up_moves
22 R[index] |> (μ -> push!(uarray, exp(μ*Δt)))
23 end
24 u = mean(uarray);
25
26 # down - compute the down moves, and estimate the average d value -
27 index_down_moves = findall(x->x<0, R);
28 for index ∈ index_down_moves
29 R[index] |> (μ -> push!(darray, exp(μ*Δt)))
30 end
31 d = mean(darray);
32
33 # probability -
34 N₊ = length(index_up_moves);
35 p = N₊/length(R);
36
37 # return -
38 return (u,d,p);
39end
We implemented the analyze
function on the μ
array we computed above for some common stocks (Observation 3):
Observation 3 (Real-world Binomial parameters for common stocks)
Real-world values for the \(p\), \(u\), and \(d\) parameters for some common stocks. The data is based on the daily volume weighted average price for the period 2018-01-03
to 2022-12-31
. The id
column is the unique identifier for the stock in the firm_data
table.
id |
ticker |
name |
sector |
probability |
up |
down |
---|---|---|---|---|---|---|
11 |
AMD |
Advanced Micro Devices |
Information Technology |
0.5331 |
1.022 |
0.9785 |
241 |
IBM |
IBM |
Information Technology |
0.5227 |
1.01 |
0.9892 |
487 |
WFC |
Wells Fargo |
Financials |
0.5227 |
1.013 |
0.9854 |
221 |
GS |
Goldman Sachs |
Financials |
0.502 |
1.013 |
0.9875 |
437 |
TSLA |
Tesla |
Consumer Discretionary |
0.5283 |
1.027 |
0.9744 |
For the five tickers in the table, the probability of an up
move is between 50% and 53%, and the average up
and down
factors are between 0.97 and 1.03.
Risk neutral probability#
In finance, risk-neutral pricing is an important concept that helps investors determine the value of financial instruments. This approach assumes that market participants are not affected by risk and are only motivated by their expected returns. By using risk-neutral pricing, investors can estimate the fair value of securities by discounting their expected future cash flows at a risk-free rate. This is particularly useful in derivatives valuation, and other financial models as it allows investors to account for uncertainty in their investment decisions and make informed choices in the marketplace.
In the one-period binomial model described above, the expected value of the future risk neutral price is governed by:
where \(\mathcal{D}_{1,0}(\bar{r},\Delta{t})\) denotes the discount factor between period 0
and 1
, \(\Delta{t}\) is the length of the time between periods 0
and 1
(in years) , and \(\bar{r}\) denotes the annualized risk-free rate. The expectation operator \(\mathbb{E}_{\mathbb{Q}}(\dots)\) is taken with respect to a risk neutral probability measure \(\mathbb{Q}\). The risk neutral probability measure \(\mathbb{Q}\) is a hypothetical probability measure that allows us to price assets as if investors are risk neutral. For a binomial model, we can expand the expectation operator \(\mathbb{E}_{\mathbb{Q}}(\dots)\) on the right-hand side of Eqn. (11) as:
where \(q\) is the risk neutral probability of the share price in the up
state. We can solve for \(q\) to given an expression for the risk neutral probability of the share price being in the up
state at time 1
:
Finally, we can model the up
and down
share price as the product of an up
factor \(u\) (or a down
factor \(d\)) and the initial share price, i.e., \(S^{u} = u\cdot{S_{\circ}}\) and \(S^{d} = d\cdot{S_{\circ}}\). Substituting \(S^{u}\) (and \(S^{d}\)) into Eqn. (13) to arrive at:
Putting these ideas gives us a defintion of the risk-neutral probability (Definition 11):
Definition 11 (Risk neutral probability)
Let 0
denote the index of the current state, and 1
denote a one-step ahead future state. The future state exists in one of two possible configurations, an up
or down
configuration. The risk neutral probability that the world transitions to the up
configuration between 0
\(\rightarrow\)1
is given by:
where \(\mathcal{D}_{1,0}(\bar{r},\Delta{t})\) denotes the discount factor evaluated using the effective annualized risk free rate \(\bar{r}\), \(\Delta{t}\) denotes the length of time (in years) between states 0
and 1
, and the factors \(u\) and \(d\) denote the up
and down
factors, respectively.
Implementation: Risk-neutral \((u,q)\) strategy#
To determine the risk-neutral probability, we can refactor the analyze
function mentioned earlier, where we assume (for now) the realized average up
factors are the same as the real-world case, but the moves are symmetric, namely \(d = 1/u\). This assumption will be relaxed when dealing with derivatives pricing; specific models for u
are typically applied to calculate q
in the case of derivatives.
The modified function, called riskneutralanalyze
, is defined below:
1"""
2 riskneutralanalyze(R::Array{Float64,1}; Δt::Float64 = (1.0/252.0),
3 r̄::Float64 = 0.040) -> Tuple{Float64,Float64,Float64}
4"""
5function riskneutralanalyze(R::Array{Float64,1}; Δt::Float64 = (1.0/252.0),
6 r̄::Float64 = 0.040)::Tuple{Float64,Float64,Float64}
7
8 # initialize -
9 u,d,q = 0.0, 0.0, 0.0;
10 darray = Array{Float64,1}();
11 uarray = Array{Float64,1}();
12
13 # up - compute the up moves, and estimate the average u value -
14 index_up_moves = findall(x->x>0, R);
15 for index ∈ index_up_moves
16 R[index] |> (μ -> push!(uarray, exp(μ*Δt)))
17 end
18 u = mean(uarray);
19 d = 1/u;
20
21 # risk neutral probability -
22 q = (exp(r̄*Δt) - d)/(u - d);
23
24 # return -
25 return (u,d,q);
26end
We implemented the riskneutralanalyze
function and processed the μ
array for some common stocks (Observation 4):
Observation 4 (Risk-neutral Binomial parameters for common stocks)
Risk-neutral values for the \(q\), \(u\), and \(d\) parameters for some common stocks. The data is based on the daily volume weighted average price for the period 2018-01-03
to 2022-12-31
. The id
column is the unique identifier for the stock in the firm_data
table.
id |
ticker |
name |
sector |
probability |
up |
down |
---|---|---|---|---|---|---|
11 |
AMD |
Advanced Micro Devices |
Information Technology |
0.4982 |
1.022 |
0.9783 |
241 |
IBM |
IBM |
Information Technology |
0.5058 |
1.01 |
0.9902 |
487 |
WFC |
Wells Fargo |
Financials |
0.5029 |
1.013 |
0.987 |
221 |
GS |
Goldman Sachs |
Financials |
0.5029 |
1.013 |
0.987 |
437 |
TSLA |
Tesla |
Consumer Discretionary |
0.4965 |
1.027 |
0.974 |
For the five tickers in the table, the risk-neutral probability of an up
move is approximately 50%, i.e., a coin-flip.
The risk-neutral probability of all the stocks in the table is around 50%. This is expected because the risk-neutral probability depends upon the risk-free rate \(\bar{r}\), which is consistent across all the stocks. Thus, the difference between the real-world and risk-neutral probabilities is influenced by the stock’s volatility, specifically the size of its up
and down
movements. The greater the volatility, the higher the probability of an up
move in the risk-neutral scenario.
Testing the lattice model#
Now that we can calculate both the real-world and risk-neutral probabilities, we can test the lattice model. However, before we do that let’s extend the single-period lattice model to simulate multiple trading time periods, i.e., multiple days, weeks, months, or years into the future.
Extension to multiple periods#
The single-period lattice model can be extended to multiple periods by simply adding more nodes to the lattice (Fig. 18).
Fig. 18 Schematic of a multiple-period binomial lattice model. In the future, the world can probabilistically move to the up
with probability \(p\) or the down
state with probability \((1-p)\). The share price at each future node (\(j-1\rightarrow{j})\) can take on one of two possible values: \(S_{j}=u\cdot{S}_{j-1}\) if the world moves to the up
state, or \(S_{j}=d\cdot{S}_{j-1}\) if the world moves to the down
state.#
At each node, we treat the future state of the world as the outcome of a Bernoulli trial with probability \(p\) of success (or the risk-neutral probability \(q\) if we are dealing with a risk-netural pricing scheme). Thus, at any node in the tree, the share price is governed by the following equation:
where \(S_{\circ}\) is the initial share price, \(u\) is the up factor, \(d\) is the down factor, and \(t\) is the number of periods into the future that we are simulating. The probability of reaching a particular node in the lattice is given by the binomial distribution:
where \(k\) is the number of up
moves and \(t-k\) is the number of down
moves. The binomial coefficient \(\binom{t}{k}\) is the number of ways to choose \(k\) up
moves from \(t\) total moves:
where \(t!\) is the factorial of \(t\).
Testing strategy#
Let’s determine the likelihood of making accurate predictions using the binomial lattice model. To do this, we’ll randomly divide the future time into continuous segments of T
days, denoted as \(\mathcal{I}_{k}\in\mathcal{I}\). At the beginning of each segment \(\mathcal{I}_{k}\), we’ll create a binomial lattice model and compare the actual price of a company (\(S_{j}\)) at time \(j\) with the simulated price during each time segment.
If the simulated price falls between the lower bound (\(L_{j}\)) and upper bound (\(U_{j}\)) for all \(j\in\mathcal{I}_{k}\), we consider the simulation to be a
success
. The lower and upper bounds can be specified, but we’ll set them to \(\mu\pm{2.576}\cdot\sigma\) by default, where \(\mu\) is the expected value, and \(\sigma\) is the standard deviation of the binomial lattice simulation.However, if the actual price violates the upper or lower bound at any point, the simulation is deemed a
failure
.
We’ll repeat this process \(\forall{\mathcal{I}_{k}}\in\mathcal{I}\) and calculate the percentage of simulations that are a success
. This percentage is the likelihood of making accurate predictions using the binomial lattice model (Observation 6):
Observation 6 (Likelihood of success for real-world lattice model)
We compute the success probability of the binomial lattice model for each stock in the table below using the real-world parameters for random T = 21
day periods (N = 1200). The lower and upper bounds are set to \(\mu\pm{2.576}\cdot\sigma\).
id |
ticker |
name |
sector |
probability |
---|---|---|---|---|
11 |
AMD |
Advanced Micro Devices |
Information Technology |
0.6467 |
241 |
IBM |
IBM |
Information Technology |
0.6833 |
487 |
WFC |
Wells Fargo |
Financials |
0.7317 |
221 |
GS |
Goldman Sachs |
Financials |
0.735 |
437 |
TSLA |
Tesla |
Consumer Discretionary |
0.6383 |
Real-world lattice models forcast the share price within the lower and upper bounds with a probability of success between 64% and 74% of the random date ranges sampled (which is surprisingly high). The success probability is lower for stocks with higher volatility, e.g., Tesla or AMD, and higher for stocks with lower volatility, e.g., IBM or GS.
We could also do a similar analysis using the risk-neutral parameters (Observation 7):
Observation 7 (Likelihood of success for risk-neutral lattice model)
We compute the success probability of the binomial lattice model for each stock in the table below using the risk-neutral parameters for random T = 21
day periods (N = 1200). The lower and upper bounds are set to \(\mu\pm{2.576}\cdot\sigma\).
id |
ticker |
name |
sector |
probability |
---|---|---|---|---|
11 |
AMD |
Advanced Micro Devices |
Information Technology |
0.6308 |
241 |
IBM |
IBM |
Information Technology |
0.6592 |
487 |
WFC |
Wells Fargo |
Financials |
0.6967 |
221 |
GS |
Goldman Sachs |
Financials |
0.7458 |
437 |
TSLA |
Tesla |
Consumer Discretionary |
0.6425 |
The risk-neutral analysis gives qualitatively similar results to the real-world analysis. The success probability is lower for stocks with higher volatility, e.g., Tesla, and higher for stocks with lower volatility, e.g., IBM or GS.
Summary#
In this lecture, we discussed the first type of model of equity pricing, namely lattice models. In particular, we discussed the following topics:
Introduction to lattice models. Lattice models discretize the possible furture states of the world, e.g., the share price of a stock, into a finite number of states. For example, a Binomial lattice model has two future states, up and down. We’ll discuss how to build a lattice model and how to use it to price assets.
Real-world and risk-neutral pricing. Real-world pricing refers to the observed price, while risk-neutral pricing is a hypothetical pricing framework that assumes investors are risk-neutral. In this section, we will explore how to use both methods to price assets within a lattice model.
Testing the lattice model is an important step in the model building process. We’ll discuss how to test the lattice model using real-world versus risk-neutral probabilities. We’ll also discuss how to test the lattice model using the implied volatility of options.