Skip to content

Commit 6d31b96

Browse files
committed
Plot the result of comparison of runtime
1 parent 79cf288 commit 6d31b96

4 files changed

Lines changed: 2613 additions & 0 deletions

File tree

lectures/markov_asset_numpy.ipynb

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 6,
6+
"id": "143dede4",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import matplotlib.pyplot as plt\n",
11+
"import numpy as np\n",
12+
"import quantecon as qe\n",
13+
"from numpy.linalg import eigvals, solve"
14+
]
15+
},
16+
{
17+
"cell_type": "code",
18+
"execution_count": 7,
19+
"id": "0c89899c",
20+
"metadata": {},
21+
"outputs": [],
22+
"source": [
23+
"class AssetPriceModel:\n",
24+
" \"\"\"\n",
25+
" A class that stores the primitives of the asset pricing model.\n",
26+
"\n",
27+
" Parameters\n",
28+
" ----------\n",
29+
" β : scalar, float\n",
30+
" Discount factor\n",
31+
" mc : MarkovChain\n",
32+
" Contains the transition matrix and set of state values for the state\n",
33+
" process\n",
34+
" γ : scalar(float)\n",
35+
" Coefficient of risk aversion\n",
36+
" g : callable\n",
37+
" The function mapping states to growth rates\n",
38+
"\n",
39+
" \"\"\"\n",
40+
" def __init__(self, β=0.96, mc=None, γ=2.0, g=np.exp):\n",
41+
" self.β, self.γ = β, γ\n",
42+
" self.g = g\n",
43+
"\n",
44+
" # A default process for the Markov chain\n",
45+
" if mc is None:\n",
46+
" self.ρ = 0.9\n",
47+
" self.σ = 0.02\n",
48+
" self.mc = qe.tauchen(n, self.ρ, self.σ)\n",
49+
" else:\n",
50+
" self.mc = mc\n",
51+
"\n",
52+
" self.n = self.mc.P.shape[0]\n",
53+
"\n",
54+
" def test_stability(self, Q):\n",
55+
" \"\"\"\n",
56+
" Stability test for a given matrix Q.\n",
57+
" \"\"\"\n",
58+
" sr = np.max(np.abs(eigvals(Q)))\n",
59+
" if not sr < 1 / self.β:\n",
60+
" msg = f\"Spectral radius condition failed with radius = {sr}\"\n",
61+
" raise ValueError(msg)\n",
62+
"\n",
63+
"\n",
64+
"def tree_price(ap):\n",
65+
" \"\"\"\n",
66+
" Computes the price-dividend ratio of the Lucas tree.\n",
67+
"\n",
68+
" Parameters\n",
69+
" ----------\n",
70+
" ap: AssetPriceModel\n",
71+
" An instance of AssetPriceModel containing primitives\n",
72+
"\n",
73+
" Returns\n",
74+
" -------\n",
75+
" v : array_like(float)\n",
76+
" Lucas tree price-dividend ratio\n",
77+
"\n",
78+
" \"\"\"\n",
79+
" # Simplify names, set up matrices\n",
80+
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
81+
" J = P * ap.g(y)**(1 - γ)\n",
82+
"\n",
83+
" # Make sure that a unique solution exists\n",
84+
" ap.test_stability(J)\n",
85+
"\n",
86+
" # Compute v\n",
87+
" I = np.identity(ap.n)\n",
88+
" Ones = np.ones(ap.n)\n",
89+
" v = solve(I - β * J, β * J @ Ones)\n",
90+
"\n",
91+
" return v"
92+
]
93+
},
94+
{
95+
"cell_type": "code",
96+
"execution_count": 8,
97+
"id": "00ec6099",
98+
"metadata": {},
99+
"outputs": [],
100+
"source": [
101+
"def consol_price(ap, ζ):\n",
102+
" \"\"\"\n",
103+
" Computes price of a consol bond with payoff ζ\n",
104+
"\n",
105+
" Parameters\n",
106+
" ----------\n",
107+
" ap: AssetPriceModel\n",
108+
" An instance of AssetPriceModel containing primitives\n",
109+
"\n",
110+
" ζ : scalar(float)\n",
111+
" Coupon of the console\n",
112+
"\n",
113+
" Returns\n",
114+
" -------\n",
115+
" p : array_like(float)\n",
116+
" Console bond prices\n",
117+
"\n",
118+
" \"\"\"\n",
119+
" # Simplify names, set up matrices\n",
120+
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
121+
" M = P * ap.g(y)**(- γ)\n",
122+
"\n",
123+
" # Make sure that a unique solution exists\n",
124+
" ap.test_stability(M)\n",
125+
"\n",
126+
" # Compute price\n",
127+
" I = np.identity(ap.n)\n",
128+
" Ones = np.ones(ap.n)\n",
129+
" p = solve(I - β * M, β * ζ * M @ Ones)\n",
130+
"\n",
131+
" return p"
132+
]
133+
},
134+
{
135+
"cell_type": "code",
136+
"execution_count": 9,
137+
"id": "57f42de4",
138+
"metadata": {},
139+
"outputs": [],
140+
"source": [
141+
"def call_option(ap, ζ, p_s, ϵ=1e-7):\n",
142+
" \"\"\"\n",
143+
" Computes price of a call option on a consol bond.\n",
144+
"\n",
145+
" Parameters\n",
146+
" ----------\n",
147+
" ap: AssetPriceModel\n",
148+
" An instance of AssetPriceModel containing primitives\n",
149+
"\n",
150+
" ζ : scalar(float)\n",
151+
" Coupon of the console\n",
152+
"\n",
153+
" p_s : scalar(float)\n",
154+
" Strike price\n",
155+
"\n",
156+
" ϵ : scalar(float), optional(default=1e-8)\n",
157+
" Tolerance for infinite horizon problem\n",
158+
"\n",
159+
" Returns\n",
160+
" -------\n",
161+
" w : array_like(float)\n",
162+
" Infinite horizon call option prices\n",
163+
"\n",
164+
" \"\"\"\n",
165+
" # Simplify names, set up matrices\n",
166+
" β, γ, P, y = ap.β, ap.γ, ap.mc.P, ap.mc.state_values\n",
167+
" M = P * ap.g(y)**(- γ)\n",
168+
"\n",
169+
" # Make sure that a unique consol price exists\n",
170+
" ap.test_stability(M)\n",
171+
"\n",
172+
" # Compute option price\n",
173+
" p = consol_price(ap, ζ)\n",
174+
" w = np.zeros(ap.n)\n",
175+
" error = ϵ + 1\n",
176+
" while error > ϵ:\n",
177+
" # Maximize across columns\n",
178+
" w_new = np.maximum(β * M @ w, p - p_s)\n",
179+
" # Find maximal difference of each component and update\n",
180+
" error = np.amax(np.abs(w - w_new))\n",
181+
" w = w_new\n",
182+
"\n",
183+
" return w"
184+
]
185+
},
186+
{
187+
"cell_type": "code",
188+
"execution_count": 10,
189+
"id": "6bc6db6f",
190+
"metadata": {},
191+
"outputs": [],
192+
"source": [
193+
"n = 25\n",
194+
"ap = AssetPriceModel(β=0.9)\n",
195+
"ζ = 1.0\n",
196+
"strike_price = 40\n",
197+
"\n",
198+
"x = ap.mc.state_values\n",
199+
"\n",
200+
"def timer_function():\n",
201+
" p = consol_price(ap, ζ)\n",
202+
" w = call_option(ap, ζ, strike_price)\n",
203+
"\n",
204+
"result = qe.timeit(\n",
205+
" timer_function, runs=1000, verbose=False, \n",
206+
" results=True, unit=\"milliseconds\"\n",
207+
" )"
208+
]
209+
},
210+
{
211+
"cell_type": "code",
212+
"execution_count": 11,
213+
"id": "d4b6a2e3",
214+
"metadata": {},
215+
"outputs": [
216+
{
217+
"name": "stdout",
218+
"output_type": "stream",
219+
"text": [
220+
"Results saved to timer_results_numpy.json\n"
221+
]
222+
}
223+
],
224+
"source": [
225+
"import json\n",
226+
"\n",
227+
"# result is already a dictionary, no need to call _asdict()\n",
228+
"result_dict = result\n",
229+
"\n",
230+
"# Define the filename\n",
231+
"filename = 'timer_results_numpy.json'\n",
232+
"\n",
233+
"# Save the dictionary to a JSON file\n",
234+
"with open(filename, 'w') as f:\n",
235+
" json.dump(result_dict, f, indent=4)\n",
236+
"\n",
237+
"print(f\"Results saved to {filename}\")"
238+
]
239+
}
240+
],
241+
"metadata": {
242+
"jupytext": {
243+
"default_lexer": "ipython"
244+
},
245+
"kernelspec": {
246+
"display_name": "quantecon",
247+
"language": "python",
248+
"name": "python3"
249+
},
250+
"language_info": {
251+
"codemirror_mode": {
252+
"name": "ipython",
253+
"version": 3
254+
},
255+
"file_extension": ".py",
256+
"mimetype": "text/x-python",
257+
"name": "python",
258+
"nbconvert_exporter": "python",
259+
"pygments_lexer": "ipython3",
260+
"version": "3.13.5"
261+
}
262+
},
263+
"nbformat": 4,
264+
"nbformat_minor": 5
265+
}

0 commit comments

Comments
 (0)