{ "cells": [ { "cell_type": "markdown", "id": "eeadca8b", "metadata": {}, "source": [ "\n", "\n", "
\n",
"```\n"
]
},
{
"cell_type": "markdown",
"id": "9079a670",
"metadata": {},
"source": [
"The Python interpreter performs the following:\n",
"\n",
"- For each element of the `sequence`, it “binds” the name `variable_name` to that element and then executes the code block. "
]
},
{
"cell_type": "markdown",
"id": "d745def8",
"metadata": {},
"source": [
"### A Comment on Indentation\n",
"\n",
"\n",
"\n",
"In discussing the `for` loop, we explained that the code blocks being looped over are delimited by indentation.\n",
"\n",
"In fact, in Python, *all* code blocks (i.e., those occurring inside loops, if clauses, function definitions, etc.) are delimited by indentation.\n",
"\n",
"Thus, unlike most other languages, whitespace in Python code affects the output of the program.\n",
"\n",
"Once you get used to it, this is a good thing: It\n",
"\n",
"- forces clean, consistent indentation, improving readability \n",
"- removes clutter, such as the brackets or end statements used in other languages \n",
"\n",
"\n",
"On the other hand, it takes a bit of care to get right, so please remember:\n",
"\n",
"- The line before the start of a code block always ends in a colon \n",
" - `for i in range(10):` \n",
" - `if x > y:` \n",
" - `while x < 100:` \n",
" - etc. \n",
"- All lines in a code block must have the same amount of indentation. \n",
"- The Python standard is 4 spaces, and that’s what you should use. "
]
},
{
"cell_type": "markdown",
"id": "8e5fe849",
"metadata": {},
"source": [
"### While Loops\n",
"\n",
"\n",
"\n",
"The `for` loop is the most common technique for iteration in Python.\n",
"\n",
"But, for the purpose of illustration, let’s modify [the program above](#firstloopprog) to use a `while` loop instead.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "53364869",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"ts_length = 100\n",
"ϵ_values = []\n",
"i = 0\n",
"while i < ts_length:\n",
" e = np.random.randn()\n",
" ϵ_values.append(e)\n",
" i = i + 1\n",
"plt.plot(ϵ_values)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "af90e433",
"metadata": {},
"source": [
"A while loop will keep executing the code block delimited by indentation until the condition (`i < ts_length`) is satisfied.\n",
"\n",
"In this case, the program will keep adding values to the list `ϵ_values` until `i` equals `ts_length`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b16868e2",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"i == ts_length #the ending condition for the while loop"
]
},
{
"cell_type": "markdown",
"id": "0c20c1c7",
"metadata": {},
"source": [
"Note that\n",
"\n",
"- the code block for the `while` loop is again delimited only by indentation. \n",
"- the statement `i = i + 1` can be replaced by `i += 1`. "
]
},
{
"cell_type": "markdown",
"id": "2f928260",
"metadata": {},
"source": [
"## Another Application\n",
"\n",
"Let’s do one more application before we turn to exercises.\n",
"\n",
"In this application, we plot the balance of a bank account over time.\n",
"\n",
"There are no withdraws over the time period, the last date of which is denoted\n",
"by $ T $.\n",
"\n",
"The initial balance is $ b_0 $ and the interest rate is $ r $.\n",
"\n",
"The balance updates from period $ t $ to $ t+1 $ according to $ b_{t+1} = (1 + r) b_t $.\n",
"\n",
"In the code below, we generate and plot the sequence $ b_0, b_1, \\ldots, b_T $.\n",
"\n",
"Instead of using a Python list to store this sequence, we will use a NumPy\n",
"array."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "be451dd8",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"r = 0.025 # interest rate\n",
"T = 50 # end date\n",
"b = np.empty(T+1) # an empty NumPy array, to store all b_t\n",
"b[0] = 10 # initial balance\n",
"\n",
"for t in range(T):\n",
" b[t+1] = (1 + r) * b[t]\n",
"\n",
"plt.plot(b, label='bank balance')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "3590ad5e",
"metadata": {},
"source": [
"The statement `b = np.empty(T+1)` allocates storage in memory for `T+1`\n",
"(floating point) numbers.\n",
"\n",
"These numbers are filled in by the `for` loop.\n",
"\n",
"Allocating memory at the start is more efficient than using a Python list and\n",
"`append`, since the latter must repeatedly ask for storage space from the\n",
"operating system.\n",
"\n",
"Notice that we added a legend to the plot — a feature you will be asked to\n",
"use in the exercises."
]
},
{
"cell_type": "markdown",
"id": "aea44267",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"Now we turn to exercises. It is important that you complete them before\n",
"continuing, since they present new concepts we will need."
]
},
{
"cell_type": "markdown",
"id": "52fa32ea",
"metadata": {},
"source": [
"## Exercise 3.1\n",
"\n",
"Your first task is to simulate and plot the correlated time series\n",
"\n",
"$$\n",
"x_{t+1} = \\alpha \\, x_t + \\epsilon_{t+1}\n",
"\\quad \\text{where} \\quad\n",
"x_0 = 0\n",
"\\quad \\text{and} \\quad t = 0,\\ldots,T\n",
"$$\n",
"\n",
"The sequence of shocks $ \\{\\epsilon_t\\} $ is assumed to be IID and standard normal.\n",
"\n",
"In your solution, restrict your import statements to"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "768e4a1e",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"id": "ec3a0ac9",
"metadata": {},
"source": [
"Set $ T=200 $ and $ \\alpha = 0.9 $."
]
},
{
"cell_type": "markdown",
"id": "035d8031",
"metadata": {},
"source": [
"## Solution to[ Exercise 3.1](https://python-programming.quantecon.org/#pbe_ex1)\n",
"\n",
"Here’s one solution."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ea43321",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"α = 0.9\n",
"T = 200\n",
"x = np.empty(T+1)\n",
"x[0] = 0\n",
"\n",
"for t in range(T):\n",
" x[t+1] = α * x[t] + np.random.randn()\n",
"\n",
"plt.plot(x)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "cb557ccd",
"metadata": {},
"source": [
"## Exercise 3.2\n",
"\n",
"Starting with your solution to exercise 1, plot three simulated time series,\n",
"one for each of the cases $ \\alpha=0 $, $ \\alpha=0.8 $ and $ \\alpha=0.98 $.\n",
"\n",
"Use a `for` loop to step through the $ \\alpha $ values.\n",
"\n",
"If you can, add a legend, to help distinguish between the three time series.\n",
"\n",
"- If you call the `plot()` function multiple times before calling `show()`, all of the lines you produce will end up on the same figure. \n",
"- For the legend, noted that suppose `var = 42`, the expression `f'foo{var}'` evaluates to `'foo42'`. "
]
},
{
"cell_type": "markdown",
"id": "53bec080",
"metadata": {},
"source": [
"## Solution to[ Exercise 3.2](https://python-programming.quantecon.org/#pbe_ex2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2ef87632",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"α_values = [0.0, 0.8, 0.98]\n",
"T = 200\n",
"x = np.empty(T+1)\n",
"\n",
"for α in α_values:\n",
" x[0] = 0\n",
" for t in range(T):\n",
" x[t+1] = α * x[t] + np.random.randn()\n",
" plt.plot(x, label=f'$\\\\alpha = {α}$')\n",
"\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "36af60c5",
"metadata": {},
"source": [
">**Note**\n",
">\n",
">`f'\\$\\\\alpha = {α}\\$'` in the solution is an application of [f-String](https://docs.python.org/3/tutorial/inputoutput.html#tut-f-strings), which allows you to use `{}` to contain an expression.\n",
"\n",
"The contained expression will be evaluated, and the result will be placed into the string."
]
},
{
"cell_type": "markdown",
"id": "19ccd67b",
"metadata": {},
"source": [
"## Exercise 3.3\n",
"\n",
"Similar to the previous exercises, plot the time series\n",
"\n",
"$$\n",
"x_{t+1} = \\alpha \\, |x_t| + \\epsilon_{t+1}\n",
"\\quad \\text{where} \\quad\n",
"x_0 = 0\n",
"\\quad \\text{and} \\quad t = 0,\\ldots,T\n",
"$$\n",
"\n",
"Use $ T=200 $, $ \\alpha = 0.9 $ and $ \\{\\epsilon_t\\} $ as before.\n",
"\n",
"Search online for a function that can be used to compute the absolute value $ |x_t| $."
]
},
{
"cell_type": "markdown",
"id": "a8495314",
"metadata": {},
"source": [
"## Solution to[ Exercise 3.3](https://python-programming.quantecon.org/#pbe_ex3)\n",
"\n",
"Here’s one solution:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6a643143",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"α = 0.9\n",
"T = 200\n",
"x = np.empty(T+1)\n",
"x[0] = 0\n",
"\n",
"for t in range(T):\n",
" x[t+1] = α * np.abs(x[t]) + np.random.randn()\n",
"\n",
"plt.plot(x)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "f9c1e7cc",
"metadata": {},
"source": [
"## Exercise 3.4\n",
"\n",
"One important aspect of essentially all programming languages is branching and\n",
"conditions.\n",
"\n",
"In Python, conditions are usually implemented with if–else syntax.\n",
"\n",
"Here’s an example, that prints -1 for each negative number in an array and 1\n",
"for each nonnegative number"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6222525f",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"numbers = [-9, 2.3, -11, 0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9f5cfe42",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"for x in numbers:\n",
" if x < 0:\n",
" print(-1)\n",
" else:\n",
" print(1)"
]
},
{
"cell_type": "markdown",
"id": "838417ec",
"metadata": {},
"source": [
"Now, write a new solution to Exercise 3 that does not use an existing function\n",
"to compute the absolute value.\n",
"\n",
"Replace this existing function with an if–else condition."
]
},
{
"cell_type": "markdown",
"id": "17aa9797",
"metadata": {},
"source": [
"## Solution to[ Exercise 3.4](https://python-programming.quantecon.org/#pbe_ex4)\n",
"\n",
"Here’s one way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7bec033c",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"α = 0.9\n",
"T = 200\n",
"x = np.empty(T+1)\n",
"x[0] = 0\n",
"\n",
"for t in range(T):\n",
" if x[t] < 0:\n",
" abs_x = - x[t]\n",
" else:\n",
" abs_x = x[t]\n",
" x[t+1] = α * abs_x + np.random.randn()\n",
"\n",
"plt.plot(x)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "49fbaabb",
"metadata": {},
"source": [
"Here’s a shorter way to write the same thing:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "298e51a6",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"α = 0.9\n",
"T = 200\n",
"x = np.empty(T+1)\n",
"x[0] = 0\n",
"\n",
"for t in range(T):\n",
" abs_x = - x[t] if x[t] < 0 else x[t]\n",
" x[t+1] = α * abs_x + np.random.randn()\n",
"\n",
"plt.plot(x)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "a9aaadfb",
"metadata": {},
"source": [
"## Exercise 3.5\n",
"\n",
"Here’s a harder exercise, that takes some thought and planning.\n",
"\n",
"The task is to compute an approximation to $ \\pi $ using [Monte Carlo](https://en.wikipedia.org/wiki/Monte_Carlo_method).\n",
"\n",
"Use no imports besides"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a720a02",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "d80711b7",
"metadata": {},
"source": [
"Your hints are as follows:\n",
"\n",
"- If $ U $ is a bivariate uniform random variable on the unit square $ (0, 1)^2 $, then the probability that $ U $ lies in a subset $ B $ of $ (0,1)^2 $ is equal to the area of $ B $. \n",
"- If $ U_1,\\ldots,U_n $ are IID copies of $ U $, then, as $ n $ gets large, the fraction that falls in $ B $, converges to the probability of landing in $ B $. \n",
"- For a circle, $ area = \\pi * radius^2 $. "
]
},
{
"cell_type": "markdown",
"id": "0e587ade",
"metadata": {},
"source": [
"## Solution to[ Exercise 3.5](https://python-programming.quantecon.org/#pbe_ex5)\n",
"\n",
"Consider the circle of diameter 1 embedded in the unit square.\n",
"\n",
"Let $ A $ be its area and let $ r=1/2 $ be its radius.\n",
"\n",
"If we know $ \\pi $ then we can compute $ A $ via\n",
"$ A = \\pi r^2 $.\n",
"\n",
"But here the point is to compute $ \\pi $, which we can do by\n",
"$ \\pi = A / r^2 $.\n",
"\n",
"Summary: If we can estimate the area of a circle with diameter 1, then dividing\n",
"by $ r^2 = (1/2)^2 = 1/4 $ gives an estimate of $ \\pi $.\n",
"\n",
"We estimate the area by sampling bivariate uniforms and looking at the\n",
"fraction that falls into the circle."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "030b015e",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"n = 1000000 # sample size for Monte Carlo simulation\n",
"\n",
"count = 0\n",
"for i in range(n):\n",
"\n",
" # drawing random positions on the square\n",
" u, v = np.random.uniform(), np.random.uniform()\n",
"\n",
" # check whether the point falls within the boundary\n",
" # of the unit circle centred at (0.5,0.5)\n",
" d = np.sqrt((u - 0.5)**2 + (v - 0.5)**2)\n",
"\n",
" # if it falls within the inscribed circle, \n",
" # add it to the count\n",
" if d < 0.5:\n",
" count += 1\n",
"\n",
"area_estimate = count / n\n",
"\n",
"print(area_estimate * 4) # dividing by radius**2"
]
}
],
"metadata": {
"date": 1710455932.7169774,
"filename": "python_by_example.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "An Introductory Example"
},
"nbformat": 4,
"nbformat_minor": 5
}