{
"cells": [
{
"cell_type": "markdown",
"id": "7f5edc63",
"metadata": {},
"source": [
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "f23b5b87",
"metadata": {},
"source": [
"# Asset Pricing: Finite State Models\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "60e27107",
"metadata": {},
"source": [
"## Contents\n",
"\n",
"- [Asset Pricing: Finite State Models](#Asset-Pricing:-Finite-State-Models) \n",
" - [Overview](#Overview) \n",
" - [Pricing Models](#Pricing-Models) \n",
" - [Prices in the Risk-Neutral Case](#Prices-in-the-Risk-Neutral-Case) \n",
" - [Risk Aversion and Asset Prices](#Risk-Aversion-and-Asset-Prices) \n",
" - [Exercises](#Exercises) "
]
},
{
"cell_type": "markdown",
"id": "7aecf340",
"metadata": {},
"source": [
"> “A little knowledge of geometric series goes a long way” – Robert E. Lucas, Jr.\n",
"\n",
"\n",
"> “Asset pricing is all about covariances” – Lars Peter Hansen\n",
"\n",
"\n",
"In addition to what’s in Anaconda, this lecture will need the following libraries:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a6ef8751",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"!pip install quantecon"
]
},
{
"cell_type": "markdown",
"id": "27bf01a1",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"\n",
"\n",
"An asset is a claim on one or more future payoffs.\n",
"\n",
"The spot price of an asset depends primarily on\n",
"\n",
"- the anticipated income stream \n",
"- attitudes about risk \n",
"- rates of time preference \n",
"\n",
"\n",
"In this lecture, we consider some standard pricing models and dividend stream specifications.\n",
"\n",
"We study how prices and dividend-price ratios respond in these different scenarios.\n",
"\n",
"We also look at creating and pricing *derivative* assets that repackage income streams.\n",
"\n",
"Key tools for the lecture are\n",
"\n",
"- Markov processses \n",
"- formulas for predicting future values of functions of a Markov state \n",
"- a formula for predicting the discounted sum of future values of a Markov state \n",
"\n",
"\n",
"Let’s start with some imports:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e50b981d",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"plt.rcParams[\"figure.figsize\"] = (11, 5) #set default figure size\n",
"import numpy as np\n",
"import quantecon as qe\n",
"from numpy.linalg import eigvals, solve"
]
},
{
"cell_type": "markdown",
"id": "0adbc20c",
"metadata": {},
"source": [
"## Pricing Models\n",
"\n",
"\n",
"\n",
"Let $ \\{d_t\\}_{t \\geq 0} $ be a stream of dividends\n",
"\n",
"- A time-$ t $ **cum-dividend** asset is a claim to the stream $ d_t, d_{t+1}, \\ldots $. \n",
"- A time-$ t $ **ex-dividend** asset is a claim to the stream $ d_{t+1}, d_{t+2}, \\ldots $. \n",
"\n",
"\n",
"Let’s look at some equations that we expect to hold for prices of assets under ex-dividend contracts\n",
"(we will consider cum-dividend pricing in the exercises)."
]
},
{
"cell_type": "markdown",
"id": "5eb6fa71",
"metadata": {},
"source": [
"### Risk-Neutral Pricing\n",
"\n",
"\n",
"\n",
"Our first scenario is risk-neutral pricing.\n",
"\n",
"Let $ \\beta = 1/(1+\\rho) $ be an intertemporal discount **factor**, where\n",
"$ \\rho $ is the **rate** at which agents discount the future.\n",
"\n",
"The basic risk-neutral asset pricing equation for pricing one unit of an ex-dividend asset is\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t = \\beta {\\mathbb E}_t [d_{t+1} + p_{t+1}] \\tag{71.1}\n",
"$$\n",
"\n",
"This is a simple “cost equals expected benefit” relationship.\n",
"\n",
"Here $ {\\mathbb E}_t [y] $ denotes the best forecast of $ y $, conditioned on information available at time $ t $.\n",
"\n",
"More precisely, $ {\\mathbb E}_t [y] $ is the mathematical expectation of $ y $ conditional on information available at time $ t $."
]
},
{
"cell_type": "markdown",
"id": "275a4bbd",
"metadata": {},
"source": [
"### Pricing with Random Discount Factor\n",
"\n",
"\n",
"\n",
"What happens if for some reason traders discount payouts differently depending on the state of the world?\n",
"\n",
"Michael Harrison and David Kreps [[HK79](https://python.quantecon.org/zreferences.html#id123)] and Lars Peter Hansen\n",
"and Scott Richard [[HR87](https://python.quantecon.org/zreferences.html#id124)] showed that in quite general\n",
"settings the price of an ex-dividend asset obeys\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t = {\\mathbb E}_t \\left[ m_{t+1} ( d_{t+1} + p_{t+1} ) \\right] \\tag{71.2}\n",
"$$\n",
"\n",
"for some **stochastic discount factor** $ m_{t+1} $.\n",
"\n",
"Here the fixed discount factor $ \\beta $ in [(71.1)](#equation-rnapex) has been replaced by the random variable $ m_{t+1} $.\n",
"\n",
"How anticipated future payoffs are evaluated now depends on statistical properties of $ m_{t+1} $.\n",
"\n",
"The stochastic discount factor can be specified to capture the idea that assets that tend to have good payoffs in bad states of the world are valued more highly than other assets whose payoffs don’t behave that way.\n",
"\n",
"This is because such assets pay well when funds are more urgently wanted.\n",
"\n",
"We give examples of how the stochastic discount factor has been modeled below."
]
},
{
"cell_type": "markdown",
"id": "b3325238",
"metadata": {},
"source": [
"### Asset Pricing and Covariances\n",
"\n",
"Recall that, from the definition of a conditional covariance $ {\\rm cov}_t (x_{t+1}, y_{t+1}) $, we have\n",
"\n",
"\n",
"\n",
"$$\n",
"{\\mathbb E}_t (x_{t+1} y_{t+1}) = {\\rm cov}_t (x_{t+1}, y_{t+1}) + {\\mathbb E}_t x_{t+1} {\\mathbb E}_t y_{t+1} \\tag{71.3}\n",
"$$\n",
"\n",
"If we apply this definition to the asset pricing equation [(71.2)](#equation-lteeqs0) we obtain\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t = {\\mathbb E}_t m_{t+1} {\\mathbb E}_t (d_{t+1} + p_{t+1}) + {\\rm cov}_t (m_{t+1}, d_{t+1}+ p_{t+1}) \\tag{71.4}\n",
"$$\n",
"\n",
"It is useful to regard equation [(71.4)](#equation-lteeqs102) as a generalization of equation [(71.1)](#equation-rnapex)\n",
"\n",
"- In equation [(71.1)](#equation-rnapex), the stochastic discount factor $ m_{t+1} = \\beta $, a constant. \n",
"- In equation [(71.1)](#equation-rnapex), the covariance term $ {\\rm cov}_t (m_{t+1}, d_{t+1}+ p_{t+1}) $ is zero because $ m_{t+1} = \\beta $. \n",
"- In equation [(71.1)](#equation-rnapex), $ {\\mathbb E}_t m_{t+1} $ can be interpreted as the reciprocal of the one-period risk-free gross interest rate. \n",
"- When $ m_{t+1} $ covaries more negatively with the payout $ p_{t+1} + d_{t+1} $, the price of the asset is lower. \n",
"\n",
"\n",
"Equation [(71.4)](#equation-lteeqs102) asserts that the covariance of the stochastic discount factor with the one period payout $ d_{t+1} + p_{t+1} $ is an important determinant of the price $ p_t $.\n",
"\n",
"We give examples of some models of stochastic discount factors that have been proposed later in this lecture and also in a [later lecture](https://python-advanced.quantecon.org/lucas_model.html)."
]
},
{
"cell_type": "markdown",
"id": "4e64c358",
"metadata": {},
"source": [
"### The Price-Dividend Ratio\n",
"\n",
"Aside from prices, another quantity of interest is the **price-dividend ratio** $ v_t := p_t / d_t $.\n",
"\n",
"Let’s write down an expression that this ratio should satisfy.\n",
"\n",
"We can divide both sides of [(71.2)](#equation-lteeqs0) by $ d_t $ to get\n",
"\n",
"\n",
"\n",
"$$\n",
"v_t = {\\mathbb E}_t \\left[ m_{t+1} \\frac{d_{t+1}}{d_t} (1 + v_{t+1}) \\right] \\tag{71.5}\n",
"$$\n",
"\n",
"Below we’ll discuss the implication of this equation."
]
},
{
"cell_type": "markdown",
"id": "a3ac9c4f",
"metadata": {},
"source": [
"## Prices in the Risk-Neutral Case\n",
"\n",
"What can we say about price dynamics on the basis of the models described above?\n",
"\n",
"The answer to this question depends on\n",
"\n",
"1. the process we specify for dividends \n",
"1. the stochastic discount factor and how it correlates with dividends \n",
"\n",
"\n",
"For now we’ll study the risk-neutral case in which the stochastic discount factor is constant.\n",
"\n",
"We’ll focus on how an asset price depends on a dividend process."
]
},
{
"cell_type": "markdown",
"id": "8e6ad93c",
"metadata": {},
"source": [
"### Example 1: Constant Dividends\n",
"\n",
"The simplest case is risk-neutral price of a constant, non-random dividend stream $ d_t = d > 0 $.\n",
"\n",
"Removing the expectation from [(71.1)](#equation-rnapex) and iterating forward gives\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
" p_t & = \\beta (d + p_{t+1})\n",
" \\\\\n",
" & = \\beta (d + \\beta(d + p_{t+2}))\n",
" \\\\\n",
" & \\quad \\vdots\n",
" \\\\\n",
" & = \\beta (d + \\beta d + \\beta^2 d + \\cdots + \\beta^{k-2} d + \\beta^{k-1} p_{t+k})\n",
"\\end{aligned}\n",
"$$\n",
"\n",
"If $ \\lim_{k \\rightarrow + \\infty} \\beta^{k-1} p_{t+k} = 0 $, this sequence converges to\n",
"\n",
"\n",
"\n",
"$$\n",
"\\bar p := \\frac{\\beta d}{1-\\beta} \\tag{71.6}\n",
"$$\n",
"\n",
"This is the equilibrium price in the constant dividend case.\n",
"\n",
"Indeed, simple algebra shows that setting $ p_t = \\bar p $ for all $ t $\n",
"satisfies the difference equation $ p_t = \\beta (d + p_{t+1}) $."
]
},
{
"cell_type": "markdown",
"id": "7635ae8e",
"metadata": {},
"source": [
"### Example 2: Dividends with Deterministic Growth Paths\n",
"\n",
"Consider a growing, non-random dividend process $ d_{t+1} = g d_t $\n",
"where $ 0 < g \\beta < 1 $.\n",
"\n",
"While prices are not usually constant when dividends grow over time, a price\n",
"dividend-ratio can be.\n",
"\n",
"If we guess this, substituting $ v_t = v $ into [(71.5)](#equation-pdex) as well as our\n",
"other assumptions, we get $ v = \\beta g (1 + v) $.\n",
"\n",
"Since $ \\beta g < 1 $, we have a unique positive solution:\n",
"\n",
"$$\n",
"v = \\frac{\\beta g}{1 - \\beta g }\n",
"$$\n",
"\n",
"The price is then\n",
"\n",
"$$\n",
"p_t = \\frac{\\beta g}{1 - \\beta g } d_t\n",
"$$\n",
"\n",
"If, in this example, we take $ g = 1+\\kappa $ and let\n",
"$ \\rho := 1/\\beta - 1 $, then the price becomes\n",
"\n",
"$$\n",
"p_t = \\frac{1 + \\kappa}{ \\rho - \\kappa} d_t\n",
"$$\n",
"\n",
"This is called the *Gordon formula*.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "ceb0b65a",
"metadata": {},
"source": [
"### Example 3: Markov Growth, Risk-Neutral Pricing\n",
"\n",
"Next, we consider a dividend process\n",
"\n",
"\n",
"\n",
"$$\n",
"d_{t+1} = g_{t+1} d_t \\tag{71.7}\n",
"$$\n",
"\n",
"The stochastic growth factor $ \\{g_t\\} $ is given by\n",
"\n",
"$$\n",
"g_t = g(X_t), \\quad t = 1, 2, \\ldots\n",
"$$\n",
"\n",
"where\n",
"\n",
"1. $ \\{X_t\\} $ is a finite Markov chain with state space $ S $ and\n",
" transition probabilities \n",
" $$\n",
" P(x, y) := \\mathbb P \\{ X_{t+1} = y \\,|\\, X_t = x \\}\n",
" \\qquad (x, y \\in S)\n",
" $$\n",
"1. $ g $ is a given function on $ S $ taking nonnegative values \n",
"\n",
"\n",
"You can think of\n",
"\n",
"- $ S $ as $ n $ possible “states of the world” and $ X_t $ as the\n",
" current state. \n",
"- $ g $ as a function that maps a given state $ X_t $ into a growth of dividends\n",
" factor $ g_t = g(X_t) $. \n",
"- $ \\ln g_t = \\ln (d_{t+1} / d_t) $ is the growth rate of dividends. \n",
"\n",
"\n",
"(For a refresher on notation and theory for finite Markov chains see [this lecture](https://python.quantecon.org/finite_markov.html))\n",
"\n",
"The next figure shows a simulation, where\n",
"\n",
"- $ \\{X_t\\} $ evolves as a discretized AR1 process produced using [Tauchen’s method](https://python.quantecon.org/finite_markov.html#fm_ex3). \n",
"- $ g_t = \\exp(X_t) $, so that $ \\ln g_t = X_t $ is the growth rate. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d6ab36e4",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"mc = qe.tauchen(0.96, 0.25, n=25)\n",
"sim_length = 80\n",
"\n",
"x_series = mc.simulate(sim_length, init=np.median(mc.state_values))\n",
"g_series = np.exp(x_series)\n",
"d_series = np.cumprod(g_series) # Assumes d_0 = 1\n",
"\n",
"series = [x_series, g_series, d_series, np.log(d_series)]\n",
"labels = ['$X_t$', '$g_t$', '$d_t$', r'$\\log \\, d_t$']\n",
"\n",
"fig, axes = plt.subplots(2, 2)\n",
"for ax, s, label in zip(axes.flatten(), series, labels):\n",
" ax.plot(s, 'b-', lw=2, label=label)\n",
" ax.legend(loc='upper left', frameon=False)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "4d46d544",
"metadata": {},
"source": [
"#### Pricing Formula\n",
"\n",
"To obtain asset prices in this setting, let’s adapt our analysis from the case of deterministic growth.\n",
"\n",
"In that case, we found that $ v $ is constant.\n",
"\n",
"This encourages us to guess that, in the current case, $ v_t $ is a fixed function of the state $ X_t $.\n",
"\n",
"We seek a function $ v $ such that the price-dividend ratio satisfies $ v_t = v(X_t) $.\n",
"\n",
"We can substitute this guess into [(71.5)](#equation-pdex) to get\n",
"\n",
"$$\n",
"v(X_t) = \\beta {\\mathbb E}_t [ g(X_{t+1}) (1 + v(X_{t+1})) ]\n",
"$$\n",
"\n",
"If we condition on $ X_t = x $, this becomes\n",
"\n",
"$$\n",
"v(x) = \\beta \\sum_{y \\in S} g(y) (1 + v(y)) P(x, y)\n",
"$$\n",
"\n",
"or\n",
"\n",
"\n",
"\n",
"$$\n",
"v(x) = \\beta \\sum_{y \\in S} K(x, y) (1 + v(y))\n",
"\\quad \\text{where} \\quad\n",
"K(x, y) := g(y) P(x, y) \\tag{71.8}\n",
"$$\n",
"\n",
"Suppose that there are $ n $ possible states $ x_1, \\ldots, x_n $.\n",
"\n",
"We can then think of [(71.8)](#equation-pstack) as $ n $ stacked equations, one for each state, and write it in matrix form as\n",
"\n",
"\n",
"\n",
"$$\n",
"v = \\beta K (\\mathbb 1 + v) \\tag{71.9}\n",
"$$\n",
"\n",
"Here\n",
"\n",
"- $ v $ is understood to be the column vector $ (v(x_1), \\ldots, v(x_n))' $. \n",
"- $ K $ is the matrix $ (K(x_i, x_j))_{1 \\leq i, j \\leq n} $. \n",
"- $ {\\mathbb 1} $ is a column vector of ones. \n",
"\n",
"\n",
"When does equation [(71.9)](#equation-vcumrn) have a unique solution?\n",
"\n",
"From the [Neumann series lemma](https://python.quantecon.org/linear_algebra.html#la-neumann) and Gelfand’s formula, equation [(71.9)](#equation-vcumrn) has a unique solution when $ \\beta K $ has spectral radius strictly less than one.\n",
"\n",
"Thus, we require that the eigenvalues of $ K $ be strictly less than $ \\beta^{-1} $ in modulus.\n",
"\n",
"The solution is then\n",
"\n",
"\n",
"\n",
"$$\n",
"v = (I - \\beta K)^{-1} \\beta K{\\mathbb 1} \\tag{71.10}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "6c957988",
"metadata": {},
"source": [
"### Code\n",
"\n",
"Let’s calculate and plot the price-dividend ratio at some parameters.\n",
"\n",
"As before, we’ll generate $ \\{X_t\\} $ as a [discretized AR1 process](https://python.quantecon.org/finite_markov.html#fm_ex3) and set $ g_t = \\exp(X_t) $.\n",
"\n",
"Here’s the code, including a test of the spectral radius condition"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "79d5695c",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"n = 25 # Size of state space\n",
"β = 0.9\n",
"mc = qe.tauchen(0.96, 0.02, n=n)\n",
"\n",
"K = mc.P * np.exp(mc.state_values)\n",
"\n",
"warning_message = \"Spectral radius condition fails\"\n",
"assert np.max(np.abs(eigvals(K))) < 1 / β, warning_message\n",
"\n",
"I = np.identity(n)\n",
"v = solve(I - β * K, β * K @ np.ones(n))\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.plot(mc.state_values, v, 'g-o', lw=2, alpha=0.7, label='$v$')\n",
"ax.set_ylabel(\"price-dividend ratio\")\n",
"ax.set_xlabel(\"state\")\n",
"ax.legend(loc='upper left')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "fa0fadd0",
"metadata": {},
"source": [
"Why does the price-dividend ratio increase with the state?\n",
"\n",
"The reason is that this Markov process is positively correlated, so high\n",
"current states suggest high future states.\n",
"\n",
"Moreover, dividend growth is increasing in the state.\n",
"\n",
"The anticipation of high future dividend growth leads to a high price-dividend ratio."
]
},
{
"cell_type": "markdown",
"id": "8fa4eb67",
"metadata": {},
"source": [
"## Risk Aversion and Asset Prices\n",
"\n",
"Now let’s turn to the case where agents are risk averse.\n",
"\n",
"We’ll price several distinct assets, including\n",
"\n",
"- An endowment stream \n",
"- A consol (a type of bond issued by the UK government in the 19th century) \n",
"- Call options on a consol "
]
},
{
"cell_type": "markdown",
"id": "1b2c606b",
"metadata": {},
"source": [
"### Pricing a Lucas Tree\n",
"\n",
"\n",
"\n",
"Let’s start with a version of the celebrated asset pricing model of Robert E. Lucas, Jr. [[Luc78](https://python.quantecon.org/zreferences.html#id183)].\n",
"\n",
"Lucas considered an abstract pure exchange economy with these features:\n",
"\n",
"- a single non-storable consumption good \n",
"- a Markov process that governs the total amount of the consumption good available each period \n",
"- a single *tree* that each period yields *fruit* that equals the total amount of consumption available to the economy \n",
"- a competitive market in *shares* in the tree that entitles their owners to corresponding shares of the *dividend* stream, i.e., the *fruit* stream, yielded by the tree \n",
"- a representative consumer who in a competitive equilibrium \n",
" - consumes the economy’s entire endowment each period \n",
" - owns 100 percent of the shares in the tree \n",
"\n",
"\n",
"As in [[Luc78](https://python.quantecon.org/zreferences.html#id183)], we suppose that the stochastic discount factor takes the form\n",
"\n",
"\n",
"\n",
"$$\n",
"m_{t+1} = \\beta \\frac{u'(c_{t+1})}{u'(c_t)} \\tag{71.11}\n",
"$$\n",
"\n",
"where $ u $ is a concave utility function and $ c_t $ is time $ t $ consumption of a representative consumer.\n",
"\n",
"(A derivation of this expression is given in a [later lecture](https://python-advanced.quantecon.org/lucas_model.html))\n",
"\n",
"Assume the existence of an endowment that follows growth process [(71.7)](#equation-mass-fmce).\n",
"\n",
"The asset being priced is a claim on the endowment process, i.e., the *Lucas tree* described above.\n",
"\n",
"Following [[Luc78](https://python.quantecon.org/zreferences.html#id183)], we suppose that in equilibrium the representative consumer’s consumption equals the aggregate endowment, so that $ d_t = c_t $ for all $ t $.\n",
"\n",
"For utility, we’ll assume the **constant relative risk aversion** (CRRA)\n",
"specification\n",
"\n",
"\n",
"\n",
"$$\n",
"u(c) = \\frac{c^{1-\\gamma}}{1 - \\gamma} \\ {\\rm with} \\ \\gamma > 0 \\tag{71.12}\n",
"$$\n",
"\n",
"When $ \\gamma =1 $ we let $ u(c) = \\ln c $.\n",
"\n",
"Inserting the CRRA specification into [(71.11)](#equation-lucsdf) and using $ c_t = d_t $ gives\n",
"\n",
"\n",
"\n",
"$$\n",
"m_{t+1}\n",
"= \\beta \\left(\\frac{c_{t+1}}{c_t}\\right)^{-\\gamma}\n",
"= \\beta g_{t+1}^{-\\gamma} \\tag{71.13}\n",
"$$\n",
"\n",
"Substituting this into [(71.5)](#equation-pdex) gives the price-dividend ratio\n",
"formula\n",
"\n",
"\n",
"\n",
"$$\n",
"v(X_t)\n",
"= \\beta {\\mathbb E}_t\n",
"\\left[\n",
" g(X_{t+1})^{1-\\gamma} (1 + v(X_{t+1}) )\n",
"\\right] \\tag{71.14}\n",
"$$\n",
"\n",
"Conditioning on $ X_t = x $, we can write this as\n",
"\n",
"$$\n",
"v(x)\n",
"= \\beta \\sum_{y \\in S} g(y)^{1-\\gamma} (1 + v(y) ) P(x, y)\n",
"$$\n",
"\n",
"If we let\n",
"\n",
"$$\n",
"J(x, y) := g(y)^{1-\\gamma} P(x, y)\n",
"$$\n",
"\n",
"then we can rewrite equation [(71.14)](#equation-eq-neweqn101) in vector form as\n",
"\n",
"$$\n",
"v = \\beta J ({\\mathbb 1} + v )\n",
"$$\n",
"\n",
"Assuming that the spectral radius of $ J $ is strictly less than $ \\beta^{-1} $, this equation has the unique solution\n",
"\n",
"\n",
"\n",
"$$\n",
"v = (I - \\beta J)^{-1} \\beta J {\\mathbb 1} \\tag{71.15}\n",
"$$\n",
"\n",
"We will define a function tree_price to compute $ v $ given parameters stored in\n",
"the class AssetPriceModel"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4915fa59",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"class AssetPriceModel:\n",
" \"\"\"\n",
" A class that stores the primitives of the asset pricing model.\n",
"\n",
" Parameters\n",
" ----------\n",
" β : scalar, float\n",
" Discount factor\n",
" mc : MarkovChain\n",
" Contains the transition matrix and set of state values for the state\n",
" process\n",
" γ : scalar(float)\n",
" Coefficient of risk aversion\n",
" g : callable\n",
" The function mapping states to growth rates\n",
"\n",
" \"\"\"\n",
" def __init__(self, β=0.96, mc=None, γ=2.0, g=np.exp):\n",
" self.β, self.γ = β, γ\n",
" self.g = g\n",
"\n",
" # A default process for the Markov chain\n",
" if mc is None:\n",
" self.ρ = 0.9\n",
" self.σ = 0.02\n",
" self.mc = qe.tauchen(self.ρ, self.σ, n=25)\n",
" else:\n",
" self.mc = mc\n",
"\n",
" self.n = self.mc.P.shape[0]\n",
"\n",
" def test_stability(self, Q):\n",
" \"\"\"\n",
" Stability test for a given matrix Q.\n",
" \"\"\"\n",
" sr = np.max(np.abs(eigvals(Q)))\n",
" if not sr < 1 / self.β:\n",
" msg = f\"Spectral radius condition failed with radius = {sr}\"\n",
" raise ValueError(msg)\n",
"\n",
"\n",
"def tree_price(ap):\n",
" \"\"\"\n",
" Computes the price-dividend ratio of the Lucas tree.\n",
"\n",
" Parameters\n",
" ----------\n",
" ap: AssetPriceModel\n",
" An instance of AssetPriceModel containing primitives\n",
"\n",
" Returns\n",
" -------\n",
" v : array_like(float)\n",
" Lucas tree price-dividend ratio\n",
"\n",
" \"\"\"\n",
" # Simplify names, set up matrices\n",
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
" J = P * ap.g(y)**(1 - γ)\n",
"\n",
" # Make sure that a unique solution exists\n",
" ap.test_stability(J)\n",
"\n",
" # Compute v\n",
" I = np.identity(ap.n)\n",
" Ones = np.ones(ap.n)\n",
" v = solve(I - β * J, β * J @ Ones)\n",
"\n",
" return v"
]
},
{
"cell_type": "markdown",
"id": "2ea28516",
"metadata": {},
"source": [
"Here’s a plot of $ v $ as a function of the state for several values of $ \\gamma $,\n",
"with a positively correlated Markov process and $ g(x) = \\exp(x) $"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc173e45",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"γs = [1.2, 1.4, 1.6, 1.8, 2.0]\n",
"ap = AssetPriceModel()\n",
"states = ap.mc.state_values\n",
"\n",
"fig, ax = plt.subplots()\n",
"\n",
"for γ in γs:\n",
" ap.γ = γ\n",
" v = tree_price(ap)\n",
" ax.plot(states, v, lw=2, alpha=0.6, label=rf\"$\\gamma = {γ}$\")\n",
"\n",
"ax.set_title('Price-dividend ratio as a function of the state')\n",
"ax.set_ylabel(\"price-dividend ratio\")\n",
"ax.set_xlabel(\"state\")\n",
"ax.legend(loc='upper right')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "ba984421",
"metadata": {},
"source": [
"Notice that $ v $ is decreasing in each case.\n",
"\n",
"This is because, with a positively correlated state process, higher states indicate higher future consumption growth.\n",
"\n",
"With the stochastic discount factor [(71.13)](#equation-lucsdf2), higher growth decreases the\n",
"discount factor, lowering the weight placed on future dividends."
]
},
{
"cell_type": "markdown",
"id": "226bbea7",
"metadata": {},
"source": [
"#### Special Cases\n",
"\n",
"In the special case $ \\gamma =1 $, we have $ J = P $.\n",
"\n",
"Recalling that $ P^i {\\mathbb 1} = {\\mathbb 1} $ for all $ i $ and applying [Neumann’s geometric series lemma](https://python.quantecon.org/linear_algebra.html#la-neumann), we are led to\n",
"\n",
"$$\n",
"v = \\beta(I-\\beta P)^{-1} {\\mathbb 1}\n",
"= \\beta \\sum_{i=0}^{\\infty} \\beta^i P^i {\\mathbb 1}\n",
"= \\beta \\frac{1}{1 - \\beta} {\\mathbb 1}\n",
"$$\n",
"\n",
"Thus, with log preferences, the price-dividend ratio for a Lucas tree is constant.\n",
"\n",
"Alternatively, if $ \\gamma = 0 $, then $ J = K $ and we recover the\n",
"risk-neutral solution [(71.10)](#equation-rned).\n",
"\n",
"This is as expected, since $ \\gamma = 0 $ implies $ u(c) = c $ (and hence agents are risk-neutral)."
]
},
{
"cell_type": "markdown",
"id": "71bac50c",
"metadata": {},
"source": [
"### A Risk-Free Consol\n",
"\n",
"Consider the same pure exchange representative agent economy.\n",
"\n",
"A risk-free consol promises to pay a constant amount $ \\zeta> 0 $ each period.\n",
"\n",
"Recycling notation, let $ p_t $ now be the price of an ex-coupon claim to the consol.\n",
"\n",
"An ex-coupon claim to the consol entitles an owner at the end of period $ t $ to\n",
"\n",
"- $ \\zeta $ in period $ t+1 $, plus \n",
"- the right to sell the claim for $ p_{t+1} $ next period \n",
"\n",
"\n",
"The price satisfies [(71.2)](#equation-lteeqs0) with $ d_t = \\zeta $, or\n",
"\n",
"$$\n",
"p_t = {\\mathbb E}_t \\left[ m_{t+1} ( \\zeta + p_{t+1} ) \\right]\n",
"$$\n",
"\n",
"With the stochastic discount factor [(71.13)](#equation-lucsdf2), this becomes\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t\n",
"= {\\mathbb E}_t \\left[ \\beta g_{t+1}^{-\\gamma} ( \\zeta + p_{t+1} ) \\right] \\tag{71.16}\n",
"$$\n",
"\n",
"Guessing a solution of the form $ p_t = p(X_t) $ and conditioning on\n",
"$ X_t = x $, we get\n",
"\n",
"$$\n",
"p(x)\n",
"= \\beta \\sum_{y \\in S} g(y)^{-\\gamma} (\\zeta + p(y)) P(x, y)\n",
"$$\n",
"\n",
"Letting $ M(x, y) = P(x, y) g(y)^{-\\gamma} $ and rewriting in vector notation\n",
"yields the solution\n",
"\n",
"\n",
"\n",
"$$\n",
"p = (I - \\beta M)^{-1} \\beta M \\zeta {\\mathbb 1} \\tag{71.17}\n",
"$$\n",
"\n",
"The above is implemented in the function consol_price."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed8441e4",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def consol_price(ap, ζ):\n",
" \"\"\"\n",
" Computes price of a consol bond with payoff ζ\n",
"\n",
" Parameters\n",
" ----------\n",
" ap: AssetPriceModel\n",
" An instance of AssetPriceModel containing primitives\n",
"\n",
" ζ : scalar(float)\n",
" Coupon of the console\n",
"\n",
" Returns\n",
" -------\n",
" p : array_like(float)\n",
" Console bond prices\n",
"\n",
" \"\"\"\n",
" # Simplify names, set up matrices\n",
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
" M = P * ap.g(y)**(- γ)\n",
"\n",
" # Make sure that a unique solution exists\n",
" ap.test_stability(M)\n",
"\n",
" # Compute price\n",
" I = np.identity(ap.n)\n",
" Ones = np.ones(ap.n)\n",
" p = solve(I - β * M, β * ζ * M @ Ones)\n",
"\n",
" return p"
]
},
{
"cell_type": "markdown",
"id": "85205850",
"metadata": {},
"source": [
"### Pricing an Option to Purchase the Consol\n",
"\n",
"Let’s now price options of various maturities.\n",
"\n",
"We’ll study an option that gives the owner the right to purchase a consol at a price $ p_S $."
]
},
{
"cell_type": "markdown",
"id": "d5b379ef",
"metadata": {},
"source": [
"#### An Infinite Horizon Call Option\n",
"\n",
"We want to price an *infinite horizon* option to purchase a consol at a price $ p_S $.\n",
"\n",
"The option entitles the owner at the beginning of a period either\n",
"\n",
"1. to purchase the bond at price $ p_S $ now, or \n",
"1. not to exercise the option to purchase the asset now but to retain the right to exercise it later \n",
"\n",
"\n",
"Thus, the owner either *exercises* the option now or chooses *not to exercise* and wait until next period.\n",
"\n",
"This is termed an infinite-horizon *call option* with *strike price* $ p_S $.\n",
"\n",
"The owner of the option is entitled to purchase the consol at price $ p_S $ at the beginning of any period, after the coupon has been paid to the previous owner of the bond.\n",
"\n",
"The fundamentals of the economy are identical with the one above, including the stochastic discount factor and the process for consumption.\n",
"\n",
"Let $ w(X_t, p_S) $ be the value of the option when the time $ t $ growth state is known to be $ X_t $ but *before* the owner has decided whether to exercise the option\n",
"at time $ t $ (i.e., today).\n",
"\n",
"Recalling that $ p(X_t) $ is the value of the consol when the initial growth state is $ X_t $, the value of the option satisfies\n",
"\n",
"$$\n",
"w(X_t, p_S)\n",
"= \\max \\left\\{\n",
" \\beta \\, {\\mathbb E}_t \\frac{u'(c_{t+1})}{u'(c_t)} w(X_{t+1}, p_S), \\;\n",
" p(X_t) - p_S\n",
"\\right\\}\n",
"$$\n",
"\n",
"The first term on the right is the value of waiting, while the second is the value of exercising now.\n",
"\n",
"We can also write this as\n",
"\n",
"\n",
"\n",
"$$\n",
"w(x, p_S)\n",
"= \\max \\left\\{\n",
" \\beta \\sum_{y \\in S} P(x, y) g(y)^{-\\gamma}\n",
" w (y, p_S), \\;\n",
" p(x) - p_S\n",
"\\right\\} \\tag{71.18}\n",
"$$\n",
"\n",
"With $ M(x, y) = P(x, y) g(y)^{-\\gamma} $ and $ w $ as the vector of\n",
"values $ (w(x_i), p_S)_{i = 1}^n $, we can express [(71.18)](#equation-feoption0) as the nonlinear vector equation\n",
"\n",
"\n",
"\n",
"$$\n",
"w = \\max \\{ \\beta M w, \\; p - p_S {\\mathbb 1} \\} \\tag{71.19}\n",
"$$\n",
"\n",
"To solve [(71.19)](#equation-feoption), form an operator $ T $ that maps vector $ w $\n",
"into vector $ Tw $ via\n",
"\n",
"$$\n",
"T w\n",
"= \\max \\{ \\beta M w,\\; p - p_S {\\mathbb 1} \\}\n",
"$$\n",
"\n",
"Start at some initial $ w $ and iterate with $ T $ to convergence .\n",
"\n",
"We can find the solution with the following function call_option"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "806b40a8",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def call_option(ap, ζ, p_s, ϵ=1e-7):\n",
" \"\"\"\n",
" Computes price of a call option on a consol bond.\n",
"\n",
" Parameters\n",
" ----------\n",
" ap: AssetPriceModel\n",
" An instance of AssetPriceModel containing primitives\n",
"\n",
" ζ : scalar(float)\n",
" Coupon of the console\n",
"\n",
" p_s : scalar(float)\n",
" Strike price\n",
"\n",
" ϵ : scalar(float), optional(default=1e-8)\n",
" Tolerance for infinite horizon problem\n",
"\n",
" Returns\n",
" -------\n",
" w : array_like(float)\n",
" Infinite horizon call option prices\n",
"\n",
" \"\"\"\n",
" # Simplify names, set up matrices\n",
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
" M = P * ap.g(y)**(- γ)\n",
"\n",
" # Make sure that a unique consol price exists\n",
" ap.test_stability(M)\n",
"\n",
" # Compute option price\n",
" p = consol_price(ap, ζ)\n",
" w = np.zeros(ap.n)\n",
" error = ϵ + 1\n",
" while error > ϵ:\n",
" # Maximize across columns\n",
" w_new = np.maximum(β * M @ w, p - p_s)\n",
" # Find maximal difference of each component and update\n",
" error = np.amax(np.abs(w - w_new))\n",
" w = w_new\n",
"\n",
" return w"
]
},
{
"cell_type": "markdown",
"id": "242cb8c7",
"metadata": {},
"source": [
"Here’s a plot of $ w $ compared to the consol price when $ P_S = 40 $"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a9c2ff3a",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"ap = AssetPriceModel(β=0.9)\n",
"ζ = 1.0\n",
"strike_price = 40\n",
"\n",
"x = ap.mc.state_values\n",
"p = consol_price(ap, ζ)\n",
"w = call_option(ap, ζ, strike_price)\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.plot(x, p, 'b-', lw=2, label='consol price')\n",
"ax.plot(x, w, 'g-', lw=2, label='value of call option')\n",
"ax.set_xlabel(\"state\")\n",
"ax.legend(loc='upper right')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "a0e1aba5",
"metadata": {},
"source": [
"In high values of the Markov growth state, the value of the option is close to zero.\n",
"\n",
"This is despite the facts that the Markov chain is irreducible and that low states —\n",
"where the consol prices are high — will be visited recurrently.\n",
"\n",
"The reason for low valuations in high Markov growth states is that $ \\beta=0.9 $, so future payoffs are discounted substantially."
]
},
{
"cell_type": "markdown",
"id": "445e680f",
"metadata": {},
"source": [
"### Risk-Free Rates\n",
"\n",
"Let’s look at risk-free interest rates over different periods."
]
},
{
"cell_type": "markdown",
"id": "cc90fee9",
"metadata": {},
"source": [
"#### The One-period Risk-free Interest Rate\n",
"\n",
"As before, the stochastic discount factor is $ m_{t+1} = \\beta g_{t+1}^{-\\gamma} $.\n",
"\n",
"It follows that the reciprocal $ R_t^{-1} $ of the gross risk-free interest rate $ R_t $ in state $ x $ is\n",
"\n",
"$$\n",
"{\\mathbb E}_t m_{t+1} = \\beta \\sum_{y \\in S} P(x, y) g(y)^{-\\gamma}\n",
"$$\n",
"\n",
"We can write this as\n",
"\n",
"$$\n",
"m_1 = \\beta M {\\mathbb 1}\n",
"$$\n",
"\n",
"where the $ i $-th element of $ m_1 $ is the reciprocal of the one-period gross risk-free interest rate in state $ x_i $."
]
},
{
"cell_type": "markdown",
"id": "00acec92",
"metadata": {},
"source": [
"#### Other Terms\n",
"\n",
"Let $ m_j $ be an $ n \\times 1 $ vector whose $ i $ th component is the reciprocal of the $ j $ -period gross risk-free interest rate in state $ x_i $.\n",
"\n",
"Then $ m_1 = \\beta M $, and $ m_{j+1} = M m_j $ for $ j \\geq 1 $."
]
},
{
"cell_type": "markdown",
"id": "17bd8135",
"metadata": {},
"source": [
"## Exercises"
]
},
{
"cell_type": "markdown",
"id": "f8d94d42",
"metadata": {},
"source": [
"## Exercise 71.1\n",
"\n",
"In the lecture, we considered **ex-dividend assets**.\n",
"\n",
"A **cum-dividend** asset is a claim to the stream $ d_t, d_{t+1}, \\ldots $.\n",
"\n",
"Following [(71.1)](#equation-rnapex), find the risk-neutral asset pricing equation for\n",
"one unit of a cum-dividend asset.\n",
"\n",
"With a constant, non-random dividend stream $ d_t = d > 0 $, what is the equilibrium\n",
"price of a cum-dividend asset?\n",
"\n",
"With a growing, non-random dividend process $ d_t = g d_t $ where $ 0 < g \\beta < 1 $,\n",
"what is the equilibrium price of a cum-dividend asset?"
]
},
{
"cell_type": "markdown",
"id": "45cd5b98",
"metadata": {},
"source": [
"## Solution to[ Exercise 71.1](https://python.quantecon.org/#ma_ex1)\n",
"\n",
"For a cum-dividend asset, the basic risk-neutral asset pricing equation is\n",
"\n",
"$$\n",
"p_t = d_t + \\beta {\\mathbb E}_t [ p_{t+1} ]\n",
"$$\n",
"\n",
"\n",
"\n",
"With constant dividends, the equilibrium price is\n",
"\n",
"$$\n",
"p_t = \\frac{1}{1-\\beta} d_t\n",
"$$\n",
"\n",
"With a growing, non-random dividend process, the equilibrium price is\n",
"\n",
"$$\n",
"p_t = \\frac{1}{1 - \\beta g} d_t\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "62106ba0",
"metadata": {},
"source": [
"## Exercise 71.2\n",
"\n",
"Consider the following primitives"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "de88977c",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"n = 5\n",
"P = np.full((n, n), 0.0125)\n",
"P[range(n), range(n)] += 1 - P.sum(1)\n",
"# State values of the Markov chain\n",
"s = np.array([0.95, 0.975, 1.0, 1.025, 1.05])\n",
"γ = 2.0\n",
"β = 0.94"
]
},
{
"cell_type": "markdown",
"id": "18e72c37",
"metadata": {},
"source": [
"Let $ g $ be defined by $ g(x) = x $ (that is, $ g $ is the identity map).\n",
"\n",
"Compute the price of the Lucas tree.\n",
"\n",
"Do the same for\n",
"\n",
"- the price of the risk-free consol when $ \\zeta = 1 $ \n",
"- the call option on the consol when $ \\zeta = 1 $ and $ p_S = 150.0 $ "
]
},
{
"cell_type": "markdown",
"id": "09d465c9",
"metadata": {},
"source": [
"## Solution to[ Exercise 71.2](https://python.quantecon.org/#ma_ex2)\n",
"\n",
"First, let’s enter the parameters:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "899dcb82",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"n = 5\n",
"P = np.full((n, n), 0.0125)\n",
"P[range(n), range(n)] += 1 - P.sum(1)\n",
"s = np.array([0.95, 0.975, 1.0, 1.025, 1.05]) # State values\n",
"mc = qe.MarkovChain(P, state_values=s)\n",
"\n",
"γ = 2.0\n",
"β = 0.94\n",
"ζ = 1.0\n",
"p_s = 150.0"
]
},
{
"cell_type": "markdown",
"id": "6e2656c2",
"metadata": {},
"source": [
"Next, we’ll create an instance of `AssetPriceModel` to feed into the\n",
"functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0bc3a5a6",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"apm = AssetPriceModel(β=β, mc=mc, γ=γ, g=lambda x: x)"
]
},
{
"cell_type": "markdown",
"id": "255c9ae3",
"metadata": {},
"source": [
"Now we just need to call the relevant functions on the data:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a386eef9",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"tree_price(apm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "540584f2",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"consol_price(apm, ζ)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c1775c1f",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"call_option(apm, ζ, p_s)"
]
},
{
"cell_type": "markdown",
"id": "cc7dd847",
"metadata": {},
"source": [
"Let’s show the last two functions as a plot"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "054f2d17",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
"ax.plot(s, consol_price(apm, ζ), label='consol')\n",
"ax.plot(s, call_option(apm, ζ, p_s), label='call option')\n",
"ax.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "287b8a36",
"metadata": {},
"source": [
"## Exercise 71.3\n",
"\n",
"Let’s consider finite horizon call options, which are more common than\n",
"infinite horizon ones.\n",
"\n",
"Finite horizon options obey functional equations closely related to [(71.18)](#equation-feoption0).\n",
"\n",
"A $ k $ period option expires after $ k $ periods.\n",
"\n",
"If we view today as date zero, a $ k $ period option gives the owner the right to exercise the option to purchase the risk-free consol at the strike price $ p_S $ at dates $ 0, 1, \\ldots , k-1 $.\n",
"\n",
"The option expires at time $ k $.\n",
"\n",
"Thus, for $ k=1, 2, \\ldots $, let $ w(x, k) $ be the value of a $ k $-period option.\n",
"\n",
"It obeys\n",
"\n",
"$$\n",
"w(x, k)\n",
"= \\max \\left\\{\n",
" \\beta \\sum_{y \\in S} P(x, y) g(y)^{-\\gamma}\n",
" w (y, k-1), \\;\n",
" p(x) - p_S\n",
"\\right\\}\n",
"$$\n",
"\n",
"where $ w(x, 0) = 0 $ for all $ x $.\n",
"\n",
"We can express this as a sequence of nonlinear vector equations\n",
"\n",
"$$\n",
"w_k = \\max \\{ \\beta M w_{k-1}, \\; p - p_S {\\mathbb 1} \\}\n",
" \\quad k =1, 2, \\ldots\n",
" \\quad \\text{with } w_0 = 0\n",
"$$\n",
"\n",
"Write a function that computes $ w_k $ for any given $ k $.\n",
"\n",
"Compute the value of the option with `k = 5` and `k = 25` using parameter values as in Exercise 71.1.\n",
"\n",
"Is one higher than the other? Can you give intuition?"
]
},
{
"cell_type": "markdown",
"id": "516a4a83",
"metadata": {},
"source": [
"## Solution to[ Exercise 71.3](https://python.quantecon.org/#ma_ex3)\n",
"\n",
"Here’s a suitable function:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "166b0b53",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def finite_horizon_call_option(ap, ζ, p_s, k):\n",
" \"\"\"\n",
" Computes k period option value.\n",
" \"\"\"\n",
" # Simplify names, set up matrices\n",
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
" M = P * ap.g(y)**(- γ)\n",
"\n",
" # Make sure that a unique solution exists\n",
" ap.test_stability(M)\n",
"\n",
"\n",
" # Compute option price\n",
" p = consol_price(ap, ζ)\n",
" w = np.zeros(ap.n)\n",
" for i in range(k):\n",
" # Maximize across columns\n",
" w = np.maximum(β * M @ w, p - p_s)\n",
"\n",
" return w"
]
},
{
"cell_type": "markdown",
"id": "46120e4a",
"metadata": {},
"source": [
"Now let’s compute the option values at `k=5` and `k=25`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d04d69f4",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
"for k in [5, 25]:\n",
" w = finite_horizon_call_option(apm, ζ, p_s, k)\n",
" ax.plot(s, w, label=rf'$k = {k}$')\n",
"ax.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "e7cd30f3",
"metadata": {},
"source": [
"Not surprisingly, options with larger $ k $ are worth more.\n",
"\n",
"This is because an owner has a longer horizon over which\n",
"the option can be exercised."
]
}
],
"metadata": {
"date": 1667552488.297278,
"filename": "markov_asset.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "Asset Pricing: Finite State Models"
},
"nbformat": 4,
"nbformat_minor": 5
}