diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1c5b4277..a7648a73 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -83,7 +83,7 @@ jobs: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - name: Deploy website to gh-pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: _build/html/ diff --git a/lectures/_config.yml b/lectures/_config.yml index 1d5a36e6..59ada928 100644 --- a/lectures/_config.yml +++ b/lectures/_config.yml @@ -75,6 +75,9 @@ sphinx: colab_url : https://colab.research.google.com thebe : false # Add a thebe button to pages (requires the repository to run on Binder) intersphinx_mapping: + intermediate: + - https://python.quantecon.org/ + - null pyprog: - https://python-programming.quantecon.org/ - null diff --git a/lectures/_static/lecture_specific/inequality/data.ipynb b/lectures/_static/lecture_specific/inequality/data.ipynb new file mode 100644 index 00000000..97aea652 --- /dev/null +++ b/lectures/_static/lecture_specific/inequality/data.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "258b4bc9-2964-470a-8010-05c2162f5e05", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: wbgapi in /Users/longye/anaconda3/lib/python3.10/site-packages (1.0.12)\n", + "Requirement already satisfied: plotly in /Users/longye/anaconda3/lib/python3.10/site-packages (5.22.0)\n", + "Requirement already satisfied: requests in /Users/longye/anaconda3/lib/python3.10/site-packages (from wbgapi) (2.31.0)\n", + "Requirement already satisfied: tabulate in /Users/longye/anaconda3/lib/python3.10/site-packages (from wbgapi) (0.9.0)\n", + "Requirement already satisfied: PyYAML in /Users/longye/anaconda3/lib/python3.10/site-packages (from wbgapi) (6.0)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /Users/longye/anaconda3/lib/python3.10/site-packages (from plotly) (8.4.1)\n", + "Requirement already satisfied: packaging in /Users/longye/anaconda3/lib/python3.10/site-packages (from plotly) (23.1)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->wbgapi) (1.26.16)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->wbgapi) (2.0.4)\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->wbgapi) (3.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->wbgapi) (2024.6.2)\n" + ] + } + ], + "source": [ + "!pip install wbgapi plotly\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import random as rd\n", + "import wbgapi as wb\n", + "import plotly.express as px\n", + "\n", + "url = 'https://media.githubusercontent.com/media/QuantEcon/high_dim_data/main/SCF_plus/SCF_plus_mini.csv'\n", + "df = pd.read_csv(url)\n", + "df_income_wealth = df.dropna()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9630a07a-fce5-474e-92af-104e67e82be5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: quantecon in /Users/longye/anaconda3/lib/python3.10/site-packages (0.7.1)\n", + "Requirement already satisfied: requests in /Users/longye/anaconda3/lib/python3.10/site-packages (from quantecon) (2.31.0)\n", + "Requirement already satisfied: numpy>=1.17.0 in /Users/longye/anaconda3/lib/python3.10/site-packages (from quantecon) (1.26.3)\n", + "Requirement already satisfied: numba>=0.49.0 in /Users/longye/anaconda3/lib/python3.10/site-packages (from quantecon) (0.59.1)\n", + "Requirement already satisfied: sympy in /Users/longye/anaconda3/lib/python3.10/site-packages (from quantecon) (1.12)\n", + "Requirement already satisfied: scipy>=1.5.0 in /Users/longye/anaconda3/lib/python3.10/site-packages (from quantecon) (1.12.0)\n", + "Requirement already satisfied: llvmlite<0.43,>=0.42.0dev0 in /Users/longye/anaconda3/lib/python3.10/site-packages (from numba>=0.49.0->quantecon) (0.42.0)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->quantecon) (2024.6.2)\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->quantecon) (3.4)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->quantecon) (2.0.4)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/longye/anaconda3/lib/python3.10/site-packages (from requests->quantecon) (1.26.16)\n", + "Requirement already satisfied: mpmath>=0.19 in /Users/longye/anaconda3/lib/python3.10/site-packages (from sympy->quantecon) (1.3.0)\n" + ] + } + ], + "source": [ + "!pip install quantecon\n", + "import quantecon as qe\n", + "\n", + "varlist = ['n_wealth', # net wealth \n", + " 't_income', # total income\n", + " 'l_income'] # labor income\n", + "\n", + "df = df_income_wealth\n", + "years = df.year.unique()\n", + "\n", + "# create lists to store Gini for each inequality measure\n", + "results = {}\n", + "\n", + "for var in varlist:\n", + " # create lists to store Gini\n", + " gini_yr = []\n", + " for year in years:\n", + " # repeat the observations according to their weights\n", + " counts = list(round(df[df['year'] == year]['weights'] ))\n", + " y = df[df['year'] == year][var].repeat(counts)\n", + " y = np.asarray(y)\n", + " \n", + " rd.shuffle(y) # shuffle the sequence\n", + " \n", + " # calculate and store Gini\n", + " gini = qe.gini_coefficient(y)\n", + " gini_yr.append(gini)\n", + " \n", + " results[var] = gini_yr\n", + "\n", + "# Convert to DataFrame\n", + "results = pd.DataFrame(results, index=years)\n", + "results.to_csv(\"usa-gini-nwealth-tincome-lincome.csv\", index_label='year')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d59e876b-2f77-4fa7-b79a-8e455ad82d43", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lectures/_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv b/lectures/_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv index bf820364..3ec95a66 100644 --- a/lectures/_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv +++ b/lectures/_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv @@ -1,21 +1,21 @@ year,n_wealth,t_income,l_income -1950,0.8257332034366338,0.44248654139458626,0.5342948198773412 -1953,0.8059487586599329,0.4264544060935945,0.5158978980963702 -1956,0.8121790488050616,0.44426942873399283,0.5349293526208142 -1959,0.795206874163792,0.43749348077061573,0.5213985948309416 -1962,0.8086945076579359,0.4435843103853645,0.5345127915054341 -1965,0.7904149225687935,0.43763715466663444,0.7487860020887753 -1968,0.7982885066993497,0.4208620794438902,0.5242396427381545 -1971,0.7911574835420259,0.4233344246090255,0.5576454812313466 -1977,0.7571418922185215,0.46187678800902543,0.5704448110072049 -1983,0.7494335400643013,0.439345618464469,0.5662220844385915 -1989,0.7715705301674302,0.5115249581654197,0.601399568747142 -1992,0.7508126614055308,0.4740650672076798,0.5983592657979563 -1995,0.7569492388110265,0.48965523558400603,0.5969779516716903 -1998,0.7603291991801185,0.49117441585168614,0.5774462841723305 -2001,0.7816118750507056,0.5239092994681135,0.6042739644967272 -2004,0.7700355469522361,0.4884350383903255,0.5981432201792727 -2007,0.7821413776486978,0.5197156312086187,0.626345219575322 -2010,0.8250825295193438,0.5195972120145615,0.6453653328291903 -2013,0.8227698931835303,0.531400174984336,0.6498682917772644 -2016,0.8342975903562234,0.5541400068900825,0.6706846793375284 +1950,0.8257332034366366,0.44248654139458743,0.534294819877344 +1953,0.805948758659935,0.4264544060935942,0.5158978980963682 +1956,0.8121790488050612,0.44426942873399367,0.5349293526208106 +1959,0.7952068741637912,0.43749348077061534,0.5213985948309414 +1962,0.8086945076579386,0.44358431038536356,0.5345127915054446 +1965,0.7904149225687949,0.4376371546666344,0.7487860020887701 +1968,0.7982885066993503,0.4208620794438885,0.5242396427381534 +1971,0.7911574835420282,0.4233344246090255,0.5576454812313462 +1977,0.7571418922185215,0.46187678800902554,0.57044481100722 +1983,0.749433540064301,0.4393456184644682,0.5662220844385925 +1989,0.7715705301674285,0.5115249581654115,0.6013995687471289 +1992,0.7508126614055305,0.4740650672076754,0.5983592657979544 +1995,0.7569492388110274,0.4896552355840001,0.5969779516717039 +1998,0.7603291991801172,0.49117441585168525,0.5774462841723346 +2001,0.781611875050703,0.523909299468113,0.6042739644967232 +2004,0.7700355469522372,0.48843503839032354,0.5981432201792916 +2007,0.782141377648698,0.5197156312086207,0.6263452195753227 +2010,0.825082529519342,0.5195972120145641,0.6453653328291843 +2013,0.8227698931835299,0.5314001749843426,0.6498682917772886 +2016,0.8342975903562537,0.55414000689009,0.6706846793375292 diff --git a/lectures/_static/quant-econ.bib b/lectures/_static/quant-econ.bib index ce5c6e1c..34cad8c4 100644 --- a/lectures/_static/quant-econ.bib +++ b/lectures/_static/quant-econ.bib @@ -2,6 +2,28 @@ QuantEcon Bibliography File used in conjuction with sphinxcontrib-bibtex package Note: Extended Information (like abstracts, doi, url's etc.) can be found in quant-econ-extendedinfo.bib file in _static/ ### + +@incollection{keynes1940pay, + title={How to Pay for the War}, + author={Keynes, John Maynard}, + booktitle={Essays in persuasion}, + pages={367--439}, + year={1940}, + publisher={Springer} +} + +@article{bryant1984price, + title={A price discrimination analysis of monetary policy}, + author={Bryant, John and Wallace, Neil}, + journal={The Review of Economic Studies}, + volume={51}, + number={2}, + pages={279--288}, + year={1984}, + publisher={Wiley-Blackwell} +} + + @article{levitt2019did, title={Why did ancient states collapse?: the dysfunctional state}, author={Levitt, Malcolm}, diff --git a/lectures/_toc.yml b/lectures/_toc.yml index 1c33f277..220ba830 100644 --- a/lectures/_toc.yml +++ b/lectures/_toc.yml @@ -11,6 +11,7 @@ parts: - file: long_run_growth - file: business_cycle - file: inflation_history + - file: french_rev - file: inequality - caption: Foundations numbered: true @@ -55,7 +56,6 @@ parts: - file: unpleasant - file: money_inflation_nonlinear - file: laffer_adaptive - # - file: french_rev - file: ak2 - caption: Stochastic Dynamics numbered: true diff --git a/lectures/ar1_processes.md b/lectures/ar1_processes.md index c12d5f18..90cc0514 100644 --- a/lectures/ar1_processes.md +++ b/lectures/ar1_processes.md @@ -19,7 +19,7 @@ kernelspec: ``` (ar1_processes)= -# AR1 Processes +# AR(1) Processes ```{index} single: Autoregressive processes ``` @@ -35,10 +35,8 @@ These simple models are used again and again in economic research to represent t * dividends * productivity, etc. -AR(1) processes can take negative values but are easily converted into positive processes when necessary by a transformation such as exponentiation. - We are going to study AR(1) processes partly because they are useful and -partly because they help us understand important concepts. +partly because they help us understand important concepts. Let's start with some imports: @@ -48,7 +46,7 @@ import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = (11, 5) #set default figure size ``` -## The AR(1) Model +## The AR(1) model The **AR(1) model** (autoregressive model of order 1) takes the form @@ -58,26 +56,41 @@ The **AR(1) model** (autoregressive model of order 1) takes the form X_{t+1} = a X_t + b + c W_{t+1} ``` -where $a, b, c$ are scalar-valued parameters. +where $a, b, c$ are scalar-valued parameters -This law of motion generates a time series $\{ X_t\}$ as soon as we -specify an initial condition $X_0$. +(Equation {eq}`can_ar1` is sometimes called a **stochastic difference equation**.) + +For example, $X_t$ might be + +* the log of labor income for a given household, or +* the log of money demand in a given economy. -This is called the **state process** and the state space is $\mathbb R$. +In either case, {eq}`can_ar1` shows that the current value evolves as a linear function +of the previous value and an IID shock $W_{t+1}$. + +(We use $t+1$ for the subscript of $W_{t+1}$ because this random variable is not +observed at time $t$.) + +The specification {eq}`can_ar1` generates a time series $\{ X_t\}$ as soon as we +specify an initial condition $X_0$. To make things even simpler, we will assume that -* the process $\{ W_t \}$ is IID and standard normal, +* the process $\{ W_t \}$ is {ref}`IID ` and standard normal, * the initial condition $X_0$ is drawn from the normal distribution $N(\mu_0, v_0)$ and * the initial condition $X_0$ is independent of $\{ W_t \}$. -### Moving Average Representation + + + +### Moving average representation Iterating backwards from time $t$, we obtain $$ X_t = a X_{t-1} + b + c W_t = a^2 X_{t-2} + a b + a c W_{t-1} + b + c W_t + = a^3 X_{t-3} + a^2 b + a^2 c W_{t-2} + b + c W_t = \cdots $$ @@ -99,7 +112,7 @@ Equation {eq}`ar1_ma` shows that $X_t$ is a well defined random variable, the va Throughout, the symbol $\psi_t$ will be used to refer to the density of this random variable $X_t$. -### Distribution Dynamics +### Distribution dynamics One of the nice things about this model is that it's so easy to trace out the sequence of distributions $\{ \psi_t \}$ corresponding to the time series $\{ X_t\}$. @@ -110,10 +123,9 @@ This is immediate from {eq}`ar1_ma`, since linear combinations of independent normal random variables are normal. Given that $X_t$ is normally distributed, we will know the full distribution -$\psi_t$ if we can pin down its first two moments. +$\psi_t$ if we can pin down its first two [moments](https://en.wikipedia.org/wiki/Moment_(mathematics)). -Let $\mu_t$ and $v_t$ denote the mean and variance -of $X_t$ respectively. +Let $\mu_t$ and $v_t$ denote the mean and variance of $X_t$ respectively. We can pin down these values from {eq}`ar1_ma` or we can use the following recursive expressions: @@ -140,8 +152,7 @@ $$ \psi_t = N(\mu_t, v_t) $$ -The following code uses these facts to track the sequence of marginal -distributions $\{ \psi_t \}$. +The following code uses these facts to track the sequence of marginal distributions $\{ \psi_t \}$. The parameters are @@ -173,14 +184,26 @@ ax.legend(bbox_to_anchor=[1.05,1],loc=2,borderaxespad=1) plt.show() ``` -## Stationarity and Asymptotic Stability -Notice that, in the figure above, the sequence $\{ \psi_t \}$ seems to be converging to a limiting distribution. + +## Stationarity and asymptotic stability + +When we use models to study the real world, it is generally preferable that our +models have clear, sharp predictions. + +For dynamic problems, sharp predictions are related to stability. + +For example, if a dynamic model predicts that inflation always converges to some +kind of steady state, then the model gives a sharp prediction. + +(The prediction might be wrong, but even this is helpful, because we can judge the quality of the model.) + +Notice that, in the figure above, the sequence $\{ \psi_t \}$ seems to be converging to a limiting distribution, suggesting some kind of stability. This is even clearer if we project forward further into the future: ```{code-cell} python3 -def plot_density_seq(ax, mu_0=-3.0, v_0=0.6, sim_length=60): +def plot_density_seq(ax, mu_0=-3.0, v_0=0.6, sim_length=40): mu, v = mu_0, v_0 for t in range(sim_length): mu = a * mu + b @@ -200,7 +223,7 @@ For example, this alternative density sequence also converges to the same limit. ```{code-cell} python3 fig, ax = plt.subplots() -plot_density_seq(ax, mu_0=3.0) +plot_density_seq(ax, mu_0=4.0) plt.show() ``` @@ -235,7 +258,7 @@ We can confirm this is valid for the sequence above using the following code. ```{code-cell} python3 fig, ax = plt.subplots() -plot_density_seq(ax, mu_0=3.0) +plot_density_seq(ax, mu_0=4.0) mu_star = b / (1 - a) std_star = np.sqrt(c**2 / (1 - a**2)) # square root of v_star @@ -248,16 +271,21 @@ plt.show() As claimed, the sequence $\{ \psi_t \}$ converges to $\psi^*$. -### Stationary Distributions +We see that, at least for these parameters, the AR(1) model has strong stability +properties. + + + + +### Stationary distributions + +Let's try to better understand the limiting distribution $\psi^*$. -A stationary distribution is a distribution that is a fixed -point of the update rule for distributions. +A stationary distribution is a distribution that is a "fixed point" of the update rule for the AR(1) process. -In other words, if $\psi_t$ is stationary, then $\psi_{t+j} = -\psi_t$ for all $j$ in $\mathbb N$. +In other words, if $\psi_t$ is stationary, then $\psi_{t+j} = \psi_t$ for all $j$ in $\mathbb N$. -A different way to put this, specialized to the current setting, is as follows: a -density $\psi$ on $\mathbb R$ is **stationary** for the AR(1) process if +A different way to put this, specialized to the current setting, is as follows: a density $\psi$ on $\mathbb R$ is **stationary** for the AR(1) process if $$ X_t \sim \psi @@ -279,8 +307,8 @@ Thus, when $|a| < 1$, the AR(1) model has exactly one stationary density and tha The concept of ergodicity is used in different ways by different authors. -One way to understand it in the present setting is that a version of the Law -of Large Numbers is valid for $\{X_t\}$, even though it is not IID. +One way to understand it in the present setting is that a version of the law +of large numbers is valid for $\{X_t\}$, even though it is not IID. In particular, averages over time series converge to expectations under the stationary distribution. @@ -310,11 +338,21 @@ $$ \quad \text{as } m \to \infty $$ -In other words, the time series sample mean converges to the mean of the -stationary distribution. +In other words, the time series sample mean converges to the mean of the stationary distribution. + + +Ergodicity is important for a range of reasons. + +For example, {eq}`ar1_ergo` can be used to test theory. + +In this equation, we can use observed data to evaluate the left hand side of {eq}`ar1_ergo`. + +And we can use a theoretical AR(1) model to calculate the right hand side. + +If $\frac{1}{m} \sum_{t = 1}^m X_t$ is not close to $\psi^(x)$, even for many +observations, then our theory seems to be incorrect and we will need to revise +it. -As will become clear over the next few lectures, ergodicity is a very -important concept for statistics and simulation. ## Exercises @@ -339,7 +377,7 @@ M_k = \end{cases} $$ -Here $n!!$ is the double factorial. +Here $n!!$ is the [double factorial](https://en.wikipedia.org/wiki/Double_factorial). According to {eq}`ar1_ergo`, we should have, for any $k \in \mathbb N$, diff --git a/lectures/cagan_adaptive.md b/lectures/cagan_adaptive.md index 14fe60cc..f3d48c34 100644 --- a/lectures/cagan_adaptive.md +++ b/lectures/cagan_adaptive.md @@ -62,7 +62,7 @@ $$ (eq:caganmd_ad) This equation asserts that the demand for real balances -is inversely related to the public's expected rate of inflation. +is inversely related to the public's expected rate of inflation with sensitivity $\alpha$. Equating the logarithm $m_t^d$ of the demand for money to the logarithm $m_t$ of the supply of money in equation {eq}`eq:caganmd_ad` and solving for the logarithm $p_t$ of the price level gives @@ -79,7 +79,7 @@ $$ $$ (eq:eqpipi) We assume that the expected rate of inflation $\pi_t^*$ is governed -by the following adaptive expectations scheme proposed by {cite}`Friedman1956` and {cite}`Cagan`: +by the following adaptive expectations scheme proposed by {cite}`Friedman1956` and {cite}`Cagan`, where $\lambda\in [0,1]$ denotes the weight on expected inflation. $$ \pi_{t+1}^* = \lambda \pi_t^* + (1 -\lambda) \pi_t diff --git a/lectures/cagan_ree.md b/lectures/cagan_ree.md index d694c57d..fab16d01 100644 --- a/lectures/cagan_ree.md +++ b/lectures/cagan_ree.md @@ -94,7 +94,7 @@ m_t^d - p_t = -\alpha \pi_t^* \: , \: \alpha > 0 ; \quad t = 0, 1, \ldots, T . $$ (eq:caganmd) This equation asserts that the demand for real balances -is inversely related to the public's expected rate of inflation. +is inversely related to the public's expected rate of inflation with sensitivity $\alpha$. People somehow acquire **perfect foresight** by their having solved a forecasting problem. @@ -296,7 +296,7 @@ $$ \mu_t = \mu^* , \quad t \geq T_1 $$ -so that, in terms of our notation and formula for $\pi_{T+1}^*$ above, $\tilde \gamma = 1$. +so that, in terms of our notation and formula for $\pi_{T+1}^*$ above, $\gamma^* = 1$. #### Experiment 1: Foreseen sudden stabilization diff --git a/lectures/cobweb.md b/lectures/cobweb.md index 41f95ec5..31d71812 100644 --- a/lectures/cobweb.md +++ b/lectures/cobweb.md @@ -298,6 +298,8 @@ def plot45(model, pmin, pmax, p0, num_arrows=5): xticks.append(pmax) xtick_labels.append(pmax) + ax.set_ylabel(r'$p_{t+1}$') + ax.set_xlabel(r'$p_t$') ax.set_xticks(xticks) ax.set_yticks(xticks) ax.set_xticklabels(xtick_labels) diff --git a/lectures/commod_price.md b/lectures/commod_price.md index be5d5f33..efab8144 100644 --- a/lectures/commod_price.md +++ b/lectures/commod_price.md @@ -32,8 +32,7 @@ We will solve an equation where the price function is the unknown. This is harder than solving an equation for an unknown number, or vector. -The lecture will discuss one way to solve a "functional equation" for an unknown -function +The lecture will discuss one way to solve a [functional equation](https://en.wikipedia.org/wiki/Functional_equation) (an equation where the unknown object is a function). For this lecture we need the `yfinance` library. @@ -70,7 +69,7 @@ s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Adj Close'] fig, ax = plt.subplots() ax.plot(s, marker='o', alpha=0.5, ms=1) -ax.set_ylabel('price', fontsize=12) +ax.set_ylabel('cotton price in USD', fontsize=12) ax.set_xlabel('date', fontsize=12) plt.show() @@ -134,13 +133,12 @@ $p_t$. The harvest of the commodity at time $t$ is $Z_t$. -We assume that the sequence $\{ Z_t \}_{t \geq 1}$ is IID with common -density function $\phi$. +We assume that the sequence $\{ Z_t \}_{t \geq 1}$ is IID with common density function $\phi$, where $\phi$ is nonnegative. Speculators can store the commodity between periods, with $I_t$ units purchased in the current period yielding $\alpha I_t$ units in the next. -Here $\alpha \in (0,1)$ is a depreciation rate for the commodity. +Here the parameter $\alpha \in (0,1)$ is a depreciation rate for the commodity. For simplicity, the risk free interest rate is taken to be zero, so expected profit on purchasing $I_t$ units is @@ -175,6 +173,7 @@ $$ \alpha \mathbb{E}_t \, p_{t+1} - p_t \leq 0 $$ (eq:arbi) +This means that if the expected price is lower than the current price, there is no room for arbitrage. Profit maximization gives the additional condition @@ -183,7 +182,7 @@ $$ $$ (eq:pmco) -We also require that the market clears in each period. +We also require that the market clears, with supply equaling demand in each period. We assume that consumers generate demand quantity $D(p)$ corresponding to price $p$. @@ -193,12 +192,12 @@ Let $P := D^{-1}$ be the inverse demand function. Regarding quantities, -* supply is the sum of carryover by speculators and the current harvest +* supply is the sum of carryover by speculators and the current harvest, and * demand is the sum of purchases by consumers and purchases by speculators. Mathematically, -* supply $ = X_t = \alpha I_{t-1} + Z_t$, which takes values in $S := \mathbb R_+$, while +* supply is given by $X_t = \alpha I_{t-1} + Z_t$, which takes values in $S := \mathbb R_+$, while * demand $ = D(p_t) + I_t$ Thus, the market equilibrium condition is @@ -220,6 +219,8 @@ How can we find an equilibrium? Our path of attack will be to seek a system of prices that depend only on the current state. +(Our solution method involves using an [ansatz](https://en.wikipedia.org/wiki/Ansatz), which is an educated guess --- in this case for the price function.) + In other words, we take a function $p$ on $S$ and set $p_t = p(X_t)$ for every $t$. Prices and quantities then follow @@ -235,8 +236,6 @@ conditions above. More precisely, we seek a $p$ such that [](eq:arbi) and [](eq:pmco) hold for the corresponding system [](eq:eosy). -To this end, suppose that there exists a function $p^*$ on $S$ -satisfying $$ p^*(x) = \max @@ -285,7 +284,7 @@ But then $D(p^*(X_t)) = X_t$ and $I_t = I(X_t) = 0$. As a consequence, both [](eq:arbi) and [](eq:pmco) hold. -We have found an equilibrium. +We have found an equilibrium, which verifies the ansatz. ### Computing the equilibrium @@ -347,7 +346,7 @@ The code below implements this iterative process, starting from $p_0 = P$. The distribution $\phi$ is set to a shifted Beta distribution (although many other choices are possible). -The integral in [](eq:dopf3) is computed via Monte Carlo. +The integral in [](eq:dopf3) is computed via {ref}`Monte Carlo `. ```{code-cell} ipython3 @@ -395,7 +394,8 @@ while error > tol: ax.plot(grid, price, 'k-', alpha=0.5, lw=2, label=r'$p^*$') ax.legend() -ax.set_xlabel('$x$', fontsize=12) +ax.set_xlabel('$x$') +ax.set_ylabel("prices") plt.show() ``` diff --git a/lectures/french_rev copy.md b/lectures/french_rev copy.md deleted file mode 100644 index e6c19e22..00000000 --- a/lectures/french_rev copy.md +++ /dev/null @@ -1,1078 +0,0 @@ ---- -jupytext: - text_representation: - extension: .md - format_name: myst - format_version: 0.13 - jupytext_version: 1.16.1 -kernelspec: - display_name: Python 3 (ipykernel) - language: python - name: python3 ---- - - -# Inflation During French Revolution - - -## Overview - -This lecture describes some monetary and fiscal features of the French Revolution -described by {cite}`sargent_velde1995`. - -In order to finance public expenditures and service debts issued by earlier French governments, -successive French governments performed several policy experiments. - -Authors of these experiments were guided by their having decided to put in place monetary-fiscal policies recommended by particular theories. - -As a consequence, data on money growth and inflation from the period 1789 to 1787 at least temorarily illustrated outcomes predicted by these arrangements: - -* some *unpleasant monetarist arithmetic* like that described in this quanteon lecture XXX -that governed French government debt dynamics in the decades preceding 1789 - -* a *real bills* theory of the effects of government open market operations in which the government *backs* its issues of paper money with valuable real property or financial assets - -* a classical ``gold or silver'' standard - -* a classical inflation-tax theory of inflation in which Philip Cagan's demand for money studied -in this lecture is a key component - -* a *legal restrictions* or *financial repression* theory of the demand for real balances - -We use matplotlib to replicate several of the graphs that they used to present salient patterns. - - - -## Data Sources - -This notebook uses data from three spreadsheets: - - * datasets/fig_3.ods - * datasets/dette.xlsx - * datasets/assignat.xlsx - -```{code-cell} ipython3 -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt -plt.rcParams.update({'font.size': 12}) -``` - - -## Figure 1 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Ratio of debt service to taxes, Britain and France" - name: fig1 ---- - -# Read the data from the Excel file -data1 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='R:S', skiprows=5, nrows=99, header=None) -data1a = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='P', skiprows=89, nrows=15, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8) - -date = np.arange(1690, 1789) -index = (date < 1774) & (data1.iloc[:, 0] > 0) -plt.plot(date[index], 100 * data1[index].iloc[:, 0], '*:', color='r', linewidth=0.8) - -# Plot the additional data -plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange') - -# Note about the data -# The French data before 1720 don't match up with the published version -# Set the plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().set_xlim([1688, 1788]) -plt.ylabel('% of Taxes') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig1.pdf', dpi=600) -#plt.savefig('frfinfig1.jpg', dpi=600) -``` - - - {numref}`fig1` plots ratios of debt service to total taxes collected for Great Britain and France. - The figure shows - - * ratios of debt service to taxes rise for both countries at the beginning of the century and at the end of the century - * ratios that are similar for both countries in most years - - - - - -## Figure 2 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Expenditures and Tax Revenues in Britain" - name: fig2 ---- - -# Read the data from Excel file -data2 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='M:X', skiprows=7, nrows=102, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8) -plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red') -plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange') -plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', markerfacecolor='none', linewidth=0.8, color='purple') - -# Customize the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.ylabel('millions of pounds', fontsize=12) - -# Add text annotations -plt.text(1765, 1.5, 'civil', fontsize=10) -plt.text(1760, 4.2, 'civil plus debt service', fontsize=10) -plt.text(1708, 15.5, 'total govt spending', fontsize=10) -plt.text(1759, 7.3, 'revenues', fontsize=10) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig2.pdf', dpi=600) -``` - - - -{numref}`fig2` plots total taxes, total government expenditures, and the composition of government expenditures in Great Britain during much of the 18th century. - -## Figure 3 - - - - -```{code-cell} ipython3 -# Read the data from the Excel file -data1 = pd.read_excel('datasets/fig_3.xlsx', sheet_name='Sheet1', usecols='C:F', skiprows=5, nrows=30, header=None) - -data1.replace(0, np.nan, inplace=True) -``` - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Spending and Tax Revenues in France" - name: fr_fig3 ---- -# Plot the data -plt.figure() - -plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3.jpg', dpi=600) -``` - - -TO TEACH TOM: By staring at {numref}`fr_fig3` carefully - -{numref}`fr_fig3` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - -```{code-cell} ipython3 - ---- -mystnb: - figure: - caption: "Government Spending and Tax Revenues in France" - name: fr_fig3b ---- -# Plot the data -plt.figure() - -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 0])], data1.iloc[:, 0][~np.isnan(data1.iloc[:, 0])], '-x', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 1])], data1.iloc[:, 1][~np.isnan(data1.iloc[:, 1])], '--*', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 2])], data1.iloc[:, 2][~np.isnan(data1.iloc[:, 2])], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 3])], data1.iloc[:, 3][~np.isnan(data1.iloc[:, 3])], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3_ignore_nan.jpg', dpi=600) -``` - -{numref}`fr_fig3b` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - - - - -## Figure 4 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Military Spending in Britain and France" - name: fig4 ---- -# French military spending, 1685-1789, in 1726 livres -data4 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='D', skiprows=3, nrows=105, header=None).squeeze() -years = range(1685, 1790) - -plt.figure() -plt.plot(years, data4, '*-', linewidth=0.8) - -plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.xlabel('*: France') -plt.ylabel('Millions of livres') -plt.ylim([0, 475]) - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig4.pdf', dpi=600) -``` - - -{numref}`fig4` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - -TO TEACH TOM: By staring at {numref}`fig4` carefully - - -## Figure 5 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Index of real per capital revenues, France" - name: fig5 ---- -# Read data from Excel file -data5 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='K', skiprows=41, nrows=120, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim([1726, 1845]) -plt.ylabel('1726 = 1', fontsize=12) - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig5.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig5` carefully - -## Rise and Fall of the *Assignat* - - - - We have partitioned Figures~\ref{fig:fig7}, \ref{fig:fig8}, and \ref{fig:fig9} - into three periods, corresponding -to different monetary regimes or episodes. The three clouds of points in -Figure~\ref{fig:fig7} - depict different real balance-inflation relationships. Only the cloud for the -third period has the inverse relationship familiar to us now from twentieth-century -hyperinflations. The first period ends in the late summer of 1793, and is characterized -by growing real balances and moderate inflation. The second period begins and ends -with the Terror. It is marked by high real balances, around 2,500 millions, and -roughly stable prices. The fall of Robespierre in late July 1794 begins the third -of our episodes, in which real balances decline and prices rise rapidly. We interpret -these three episodes in terms of three separate theories about money: a ``backing'' -or ''real bills'' theory (the text is Adam Smith (1776)), -a legal restrictions theory (TOM: HERE PLEASE CITE -Keynes,1940, AS WELL AS Bryant/Wallace:1984 and Villamil:1988) -and a classical hyperinflation theory.% -```{note} -According to the empirical definition of hyperinflation adopted by {cite}`Cagan`, -beginning in the month that inflation exceeds 50 percent -per month and ending in the month before inflation drops below 50 percent per month -for at least a year, the *assignat* experienced a hyperinflation from May to December -1795. -``` -We view these -theories not as competitors but as alternative collections of ``if-then'' -statements about government note issues, each of which finds its conditions more -nearly met in one of these episodes than in the other two. - - - - - -## Figure 7 - - -## To Do for Zejin - -I want to tweak and consolidate the extra lines that Zejin drew on the beautiful **Figure 7**. - -I'd like to experiment in plotting the **six** extra lines all on one graph -- a pair of lines for each of our subsamples - - * one for the $y$ on $x$ regression line - * another for the $x$ on $y$ regression line - -I'd like the $y$ on $x$ and $x$ on $y$ lines to be in separate colors. - -Once we are satisfied with this new graph with its six additional lines, we can dispense with the other graphs that add one line at a time. - -Zejin, I can explain on zoom the lessons I want to convey with this. - - - -Just to recall, to compute the regression lines, Zejin wrote a function that use standard formulas -for a and b in a least squares regression y = a + b x + residual -- i.e., b is ratio of sample covariance of y,x to sample variance of x; while a is then computed from a = sample mean of y - \hat b *sample mean of x - -We could presumably tell students how to do this with a couple of numpy lines -I'd like to create three additional versions of the following figure. - -To remind you, we focused on three subperiods: - - -* subperiod 1: ("real bills period): January 1791 to July 1793 - -* subperiod 2: ("terror:): August 1793 - July 1794 - -* subperiod 3: ("classic Cagan hyperinflation): August 1794 - March 1796 - - -I can explain what this is designed to show. - - - -```{code-cell} ipython3 -def fit(x, y): - - b = np.cov(x, y)[0, 1] / np.var(x) - a = y.mean() - b * x.mean() - - return a, b -``` - -```{code-cell} ipython3 -# load data -caron = np.load('datasets/caron.npy') -nom_balances = np.load('datasets/nom_balances.npy') - -infl = np.concatenate(([np.nan], -np.log(caron[1:63, 1] / caron[0:62, 1]))) -bal = nom_balances[14:77, 1] * caron[:, 1] / 1000 -``` - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror') - -# third subsample # Tom tinkered with subsample period -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - -

The above graph is Tom's experimental lab. We'll delete it eventually.

- -

Zejin: below is the grapth with six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -

The graph below is Tom's version of the six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[34:44], a2 + bal[34:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[34:44], infl[34:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3_rev.pdf', dpi=600) -``` - - -## Figure 8 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Real balances of assignats (in gold and goods)" - name: fig8 ---- -# Read the data from Excel file -data7 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='P:Q', skiprows=4, nrows=80, header=None) -data7a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='L', skiprows=4, nrows=80, header=None) - -# Create the figure and plot -plt.figure() -h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), (data7a.values * [1, 1]) * data7.values, linewidth=1.) -plt.setp(h[1], linestyle='--', color='red') - -plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], 0, 3000, linewidth=0.8, color='orange') -plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], 0, 3000, linewidth=0.8, color='purple') - -plt.ylim([0, 3000]) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01')) -plt.ylabel('millions of livres', fontsize=12) - -# Add text annotations -plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12) -plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12) -plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig8.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig8` carefully - - -## Figure 9 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Price Level and Price of Gold (log scale)" - name: fig9 ---- -# Create the figure and plot -plt.figure() -x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12) -h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--') -h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r') - -# Set properties of the plot -plt.gca().tick_params(labelsize=12) -plt.yscale('log') -plt.xlim([1789 + 10/12, 1796 + 5/12]) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# Add vertical lines -plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange') -plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple') - -# Add text -plt.text(1793.75, 120, 'Terror', fontsize=12) -plt.text(1795, 2.8, 'price level', fontsize=12) -plt.text(1794.9, 40, 'gold', fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig9.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig9` carefully - - -## Figure 11 - - - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Spending (blue) and Revenues (orange), (real values)" - name: fig11 ---- -# Read data from Excel file -data11 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Budgets', usecols='J:K', skiprows=22, nrows=52, header=None) - -# Prepare the x-axis data -x_data = np.concatenate([ - np.arange(1791, 1794 + 8/12, 1/12), - np.arange(1794 + 9/12, 1795 + 3/12, 1/12) -]) - -# Remove NaN values from the data -data11_clean = data11.dropna() - -# Plot the data -plt.figure() -h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8) -h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8) - - - -# Set plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(axis='both', which='major', labelsize=12) -plt.xlim([1791, 1795 + 3/12]) -plt.xticks(np.arange(1791, 1796)) -plt.yticks(np.arange(0, 201, 20)) - -# Set the y-axis label -plt.ylabel('millions of livres', fontsize=12) - - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig11.pdf', dpi=600) -``` -TO TEACH TOM: By staring at {numref}`fig11` carefully - - -## Figure 12 - - -```{code-cell} ipython3 -# Read data from Excel file -data12 = pd.read_excel('datasets/assignat.xlsx', sheet_name='seignor', usecols='F', skiprows=6, nrows=75, header=None).squeeze() - - -# Create a figure and plot the data -plt.figure() -plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'), data12, linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -plt.axhline(y=472.42/12, color='r', linestyle=':') -plt.xticks(ticks=pd.date_range(start='1790', end='1796', freq='AS'), labels=range(1790, 1797)) -plt.xlim(pd.Timestamp('1791'), pd.Timestamp('1796-02') + pd.DateOffset(months=2)) -plt.ylabel('millions of livres', fontsize=12) -plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', verticalalignment='top', fontsize=12) - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig12.pdf', dpi=600) -``` - - -## Figure 13 - - -```{code-cell} ipython3 -# Read data from Excel file -data13 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Exchge', usecols='P:T', skiprows=3, nrows=502, header=None) - -# Plot the last column of the data -plt.figure() -plt.plot(data13.iloc[:, -1], linewidth=0.8) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xlim([1, len(data13)]) - -# Set x-ticks and x-tick labels -ttt = np.arange(1, len(data13) + 1) -plt.xticks(ttt[~np.isnan(data13.iloc[:, 0])], - ['Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', - 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']) - -# Add text to the plot -plt.text(1, 120, '1795', fontsize=12, ha='center') -plt.text(262, 120, '1796', fontsize=12, ha='center') - -# Draw a horizontal line and add text -plt.axhline(y=186.7, color='red', linestyle='-', linewidth=0.8) -plt.text(150, 190, 'silver parity', fontsize=12) - -# Add an annotation with an arrow -plt.annotate('end of the assignat', xy=(340, 172), xytext=(380, 160), - arrowprops=dict(facecolor='black', arrowstyle='->'), fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig13.pdf', dpi=600) -``` - - -## Figure 14 - - -```{code-cell} ipython3 -# figure 14 -data14 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='I', skiprows=9, nrows=91, header=None).squeeze() -data14a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='F', skiprows=100, nrows=151, header=None).squeeze() - -plt.figure() -h = plt.plot(data14, '*-', markersize=2, linewidth=0.8) -plt.plot(np.concatenate([np.full(data14.shape, np.nan), data14a]), linewidth=0.8) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xticks(range(20, 237, 36)) -plt.gca().set_xticklabels(range(1796, 1803)) -plt.xlabel('*: Before the 2/3 bankruptcy') -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig14.pdf', dpi=600) -``` - - -## Figure 15 - - -```{code-cell} ipython3 -# figure 15 -data15 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='N', skiprows=4, nrows=88, header=None).squeeze() - -plt.figure() -h = plt.plot(range(2, 90), data15, '*-', linewidth=0.8) -plt.setp(h, markersize=2) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.text(47.5, 11.4, '17 brumaire', horizontalalignment='left', fontsize=12) -plt.text(49.5, 14.75, '19 brumaire', horizontalalignment='left', fontsize=12) -plt.text(15, -1, 'Vendémiaire 8', fontsize=12, horizontalalignment='center') -plt.text(45, -1, 'Brumaire', fontsize=12, horizontalalignment='center') -plt.text(75, -1, 'Frimaire', fontsize=12, horizontalalignment='center') -plt.ylim([0, 25]) -plt.xticks([], []) -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig15.pdf', dpi=600) -``` - -```{code-cell} ipython3 - -``` - - -## Fiscal Situation and Response of National Assembly - - -In response to a motion by Catholic Bishop Talleyrand, -the National Assembly confiscated and nationalized Church lands. - -But the National Assembly was dominated by free market advocates, not socialists. - -The National Assembly intended to use earnings from Church lands to service its national debt. - -To do this, it began to implement a ''privatization plan'' that would let it service its debt while -not raising taxes. - -Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. - -These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. - -Finance Minister Necker and the Constituants planned -to solve the privatization problem **and** the debt problem simultaneously -by creating a new currency. - -They devised a scheme to raise revenues by auctioning -the confiscated lands, thereby withdrawing paper notes issued on the security of -the lands sold by the government. - - This ''tax-backed money'' scheme propelled the National Assembly into the domain of monetary experimentation. - -Records of their debates show -how members of the Assembly marshaled theory and evidence to assess the likely -effects of their innovation. - -They quoted David Hume and Adam Smith and cited John -Law's System of 1720 and the American experiences with paper money fifteen years -earlier as examples of how paper money schemes can go awry. - - -### Necker's plan and how it was tweaked - -Necker's original plan embodied two components: a national bank and a new -financial instrument, the ''assignat''. - - -Necker's national -bank was patterned after the Bank of England. He proposed to transform the *Caisse d'Escompte* into a national bank by granting it a monopoly on issuing -notes and marketing government debt. The *Caisse* was a -discount bank founded in 1776 whose main function was to discount commercial bills -and issue convertible notes. Although independent of the government in principle, -it had occasionally been used as a source of loans. Its notes had been declared -inconvertible in August 1788, and by the time of Necker's proposal, its reserves -were exhausted. Necker's plan placed the National Estates (as the Church lands -became known after the addition of the royal demesne) at the center of the financial -picture: a ''Bank of France'' would issue a $5\%$ security mortgaged on the prospective -receipts from the modest sale of some 400 millions' worth of National Estates in -the years 1791 to 1793. -```{note} - Only 170 million was to be used initially -to cover the deficits of 1789 and 1790. -``` - - -By mid-1790, members of the National Assembly had agreed to sell the National -Estates and to use the proceeds to service the debt in a ``tax-backed money'' scheme -```{note} -Debt service costs absorbed - over 60\% of French government expenditures. -``` - -The government would issue securities with which it would reimburse debt. - -The securities -were acceptable as payment for National Estates purchased at auctions; once received -in payment, they were to be burned. - -```{note} -The appendix to {cite}`sargent_velde1995` describes the -auction rules in detail. -``` -The Estates available for sale were thought to be worth about 2,400 -million, while the exactable debt (essentially fixed-term loans, unpaid arrears, -and liquidated offices) stood at about 2,000 million. The value of the land was -sufficient to let the Assembly retire all of the exactable debt and thereby eliminate -the interest payments on it. After lengthy debates, in August 1790, the Assembly set the denomination -and interest rate structure of the debt. - - -```{note} Two distinct -aspects of monetary theory help in thinking about the assignat plan. First, a system -beginning with a commodity standard typically has room for a once-and-for-all emission -of (an unbacked) paper currency that can replace the commodity money without generating -inflation. \citet{Sargent/Wallace:1983} describe models with this property. That -commodity money systems are wasteful underlies Milton Friedman's (1960) TOM:ADD REFERENCE preference -for a fiat money regime over a commodity money. Second, in a small country on a -commodity money system that starts with restrictions on intermediation, those restrictions -can be relaxed by letting the government issue bank notes on the security of safe -private indebtedness, while leaving bank notes convertible into gold at par. See -Adam Smith and Sargent and Wallace (1982) for expressions of this idea. TOM: ADD REFERENCES HEREAND IN BIBTEX FILE. -``` - - -```{note} -The -National Assembly debated many now classic questions in monetary economics. Under -what conditions would money creation generate inflation, with what consequences -for business conditions? Distinctions were made between issue of money to pay off -debt, on one hand, and monetization of deficits, on the other. Would *assignats* be akin -to notes emitted under a real bills regime, and cause loss of specie, or would -they circulate alongside specie, thus increasing the money stock? Would inflation -affect real wages? How would it impact foreign trade, competitiveness of French -industry and agriculture, balance of trade, foreign exchange? -``` diff --git a/lectures/french_rev.md b/lectures/french_rev.md index 780f4317..8a9c6a21 100644 --- a/lectures/french_rev.md +++ b/lectures/french_rev.md @@ -1,1031 +1,961 @@ ---- -jupytext: - text_representation: - extension: .md - format_name: myst - format_version: 0.13 - jupytext_version: 1.16.1 -kernelspec: - display_name: Python 3 (ipykernel) - language: python - name: python3 ---- - - -# Inflation During French Revolution - - -## Overview - -This lecture describes some monetary and fiscal features of the French Revolution -described by {cite}`sargent_velde1995`. - -We use matplotlib to replicate several of the graphs that they used to present salient patterns. - - - -## Fiscal Situation and Response of National Assembly - - -In response to a motion by Catholic Bishop Talleyrand, -the National Assembly confiscated and nationalized Church lands. - -But the National Assembly was dominated by free market advocates, not socialists. - -The National Assembly intended to use earnings from Church lands to service its national debt. - -To do this, it began to implement a ''privatization plan'' that would let it service its debt while -not raising taxes. - -Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. - -These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. - -Finance Minister Necker and the Constituants planned -to solve the privatization problem **and** the debt problem simultaneously -by creating a new currency. - -They devised a scheme to raise revenues by auctioning -the confiscated lands, thereby withdrawing paper notes issued on the security of -the lands sold by the government. - - This ''tax-backed money'' scheme propelled the National Assembly into the domain of monetary experimentation. - -Records of their debates show -how members of the Assembly marshaled theory and evidence to assess the likely -effects of their innovation. - -They quoted David Hume and Adam Smith and cited John -Law's System of 1720 and the American experiences with paper money fifteen years -earlier as examples of how paper money schemes can go awry. - - -### Necker's plan and how it was tweaked - -Necker's original plan embodied two components: a national bank and a new -financial instrument, the ''assignat''. - - -Necker's national -bank was patterned after the Bank of England. He proposed to transform the *Caisse d'Escompte* into a national bank by granting it a monopoly on issuing -notes and marketing government debt. The *Caisse* was a -discount bank founded in 1776 whose main function was to discount commercial bills -and issue convertible notes. Although independent of the government in principle, -it had occasionally been used as a source of loans. Its notes had been declared -inconvertible in August 1788, and by the time of Necker's proposal, its reserves -were exhausted. Necker's plan placed the National Estates (as the Church lands -became known after the addition of the royal demesne) at the center of the financial -picture: a ''Bank of France'' would issue a $5\%$ security mortgaged on the prospective -receipts from the modest sale of some 400 millions' worth of National Estates in -the years 1791 to 1793. -```{note} - Only 170 million was to be used initially -to cover the deficits of 1789 and 1790. -``` - - -By mid-1790, members of the National Assembly had agreed to sell the National -Estates and to use the proceeds to service the debt in a ``tax-backed money'' scheme -```{note} -Debt service costs absorbed - over 60\% of French government expenditures. -``` - -The government would issue securities with which it would reimburse debt. - -The securities -were acceptable as payment for National Estates purchased at auctions; once received -in payment, they were to be burned. - -```{note} -The appendix to {cite}`sargent_velde1995` describes the -auction rules in detail. -``` -The Estates available for sale were thought to be worth about 2,400 -million, while the exactable debt (essentially fixed-term loans, unpaid arrears, -and liquidated offices) stood at about 2,000 million. The value of the land was -sufficient to let the Assembly retire all of the exactable debt and thereby eliminate -the interest payments on it. After lengthy debates, in August 1790, the Assembly set the denomination -and interest rate structure of the debt. - - -```{note} Two distinct -aspects of monetary theory help in thinking about the assignat plan. First, a system -beginning with a commodity standard typically has room for a once-and-for-all emission -of (an unbacked) paper currency that can replace the commodity money without generating -inflation. \citet{Sargent/Wallace:1983} describe models with this property. That -commodity money systems are wasteful underlies Milton Friedman's (1960) TOM:ADD REFERENCE preference -for a fiat money regime over a commodity money. Second, in a small country on a -commodity money system that starts with restrictions on intermediation, those restrictions -can be relaxed by letting the government issue bank notes on the security of safe -private indebtedness, while leaving bank notes convertible into gold at par. See -Adam Smith and Sargent and Wallace (1982) for expressions of this idea. TOM: ADD REFERENCES HEREAND IN BIBTEX FILE. -``` - - -```{note} -The -National Assembly debated many now classic questions in monetary economics. Under -what conditions would money creation generate inflation, with what consequences -for business conditions? Distinctions were made between issue of money to pay off -debt, on one hand, and monetization of deficits, on the other. Would *assignats* be akin -to notes emitted under a real bills regime, and cause loss of specie, or would -they circulate alongside specie, thus increasing the money stock? Would inflation -affect real wages? How would it impact foreign trade, competitiveness of French -industry and agriculture, balance of trade, foreign exchange? -``` - -## Data Sources - -This notebook uses data from three spreadsheets: - - * datasets/fig_3.ods - * datasets/dette.xlsx - * datasets/assignat.xlsx - -```{code-cell} ipython3 -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt -plt.rcParams.update({'font.size': 12}) -``` - - -## Figure 1 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Ratio of debt service to taxes, Britain and France" - name: fig1 ---- - -# Read the data from the Excel file -data1 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='R:S', skiprows=5, nrows=99, header=None) -data1a = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='P', skiprows=89, nrows=15, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8) - -date = np.arange(1690, 1789) -index = (date < 1774) & (data1.iloc[:, 0] > 0) -plt.plot(date[index], 100 * data1[index].iloc[:, 0], '*:', color='r', linewidth=0.8) - -# Plot the additional data -plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange') - -# Note about the data -# The French data before 1720 don't match up with the published version -# Set the plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().set_xlim([1688, 1788]) -plt.ylabel('% of Taxes') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig1.pdf', dpi=600) -#plt.savefig('frfinfig1.jpg', dpi=600) -``` - - -TO TEACH TOM: By staring at {numref}`fig1` carefully - - -## Figure 2 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Expenditures and Tax Revenues in Britain" - name: fig2 ---- - -# Read the data from Excel file -data2 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='M:X', skiprows=7, nrows=102, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8) -plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red') -plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange') -plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', markerfacecolor='none', linewidth=0.8, color='purple') - -# Customize the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.ylabel('millions of pounds', fontsize=12) - -# Add text annotations -plt.text(1765, 1.5, 'civil', fontsize=10) -plt.text(1760, 4.2, 'civil plus debt service', fontsize=10) -plt.text(1708, 15.5, 'total govt spending', fontsize=10) -plt.text(1759, 7.3, 'revenues', fontsize=10) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig2.pdf', dpi=600) -``` - - -## Figure 3 - - - - -```{code-cell} ipython3 -# Read the data from the Excel file -data1 = pd.read_excel('datasets/fig_3.xlsx', sheet_name='Sheet1', usecols='C:F', skiprows=5, nrows=30, header=None) - -data1.replace(0, np.nan, inplace=True) -``` - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Spending and Tax Revenues in France" - name: fr_fig3 ---- -# Plot the data -plt.figure() - -plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3.jpg', dpi=600) -``` - - -TO TEACH TOM: By staring at {numref}`fr_fig3` carefully - -```{code-cell} ipython3 -# Plot the data -plt.figure() - -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 0])], data1.iloc[:, 0][~np.isnan(data1.iloc[:, 0])], '-x', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 1])], data1.iloc[:, 1][~np.isnan(data1.iloc[:, 1])], '--*', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 2])], data1.iloc[:, 2][~np.isnan(data1.iloc[:, 2])], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 3])], data1.iloc[:, 3][~np.isnan(data1.iloc[:, 3])], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3_ignore_nan.jpg', dpi=600) -``` - - -## Figure 4 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Military Spending in Britain and France" - name: fig4 ---- -# French military spending, 1685-1789, in 1726 livres -data4 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='D', skiprows=3, nrows=105, header=None).squeeze() -years = range(1685, 1790) - -plt.figure() -plt.plot(years, data4, '*-', linewidth=0.8) - -plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.xlabel('*: France') -plt.ylabel('Millions of livres') -plt.ylim([0, 475]) - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig4.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig4` carefully - -## Figure 5 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Index of real per capital revenues, France" - name: fig5 ---- -# Read data from Excel file -data5 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='K', skiprows=41, nrows=120, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim([1726, 1845]) -plt.ylabel('1726 = 1', fontsize=12) - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig5.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig5` carefully - -## Rise and Fall of the *Assignat* - - - - We have partitioned Figures~\ref{fig:fig7}, \ref{fig:fig8}, and \ref{fig:fig9} - into three periods, corresponding -to different monetary regimes or episodes. The three clouds of points in -Figure~\ref{fig:fig7} - depict different real balance-inflation relationships. Only the cloud for the -third period has the inverse relationship familiar to us now from twentieth-century -hyperinflations. The first period ends in the late summer of 1793, and is characterized -by growing real balances and moderate inflation. The second period begins and ends -with the Terror. It is marked by high real balances, around 2,500 millions, and -roughly stable prices. The fall of Robespierre in late July 1794 begins the third -of our episodes, in which real balances decline and prices rise rapidly. We interpret -these three episodes in terms of three separate theories about money: a ``backing'' -or ''real bills'' theory (the text is Adam Smith (1776)), -a legal restrictions theory (TOM: HERE PLEASE CITE -Keynes,1940, AS WELL AS Bryant/Wallace:1984 and Villamil:1988) -and a classical hyperinflation theory.% -```{note} -According to the empirical definition of hyperinflation adopted by {cite}`Cagan`, -beginning in the month that inflation exceeds 50 percent -per month and ending in the month before inflation drops below 50 percent per month -for at least a year, the *assignat* experienced a hyperinflation from May to December -1795. -``` -We view these -theories not as competitors but as alternative collections of ``if-then'' -statements about government note issues, each of which finds its conditions more -nearly met in one of these episodes than in the other two. - - - - - -## Figure 7 - - -## To Do for Zejin - -I want to tweak and consolidate the extra lines that Zejin drew on the beautiful **Figure 7**. - -I'd like to experiment in plotting the **six** extra lines all on one graph -- a pair of lines for each of our subsamples - - * one for the $y$ on $x$ regression line - * another for the $x$ on $y$ regression line - -I'd like the $y$ on $x$ and $x$ on $y$ lines to be in separate colors. - -Once we are satisfied with this new graph with its six additional lines, we can dispense with the other graphs that add one line at a time. - -Zejin, I can explain on zoom the lessons I want to convey with this. - - - -Just to recall, to compute the regression lines, Zejin wrote a function that use standard formulas -for a and b in a least squares regression y = a + b x + residual -- i.e., b is ratio of sample covariance of y,x to sample variance of x; while a is then computed from a = sample mean of y - \hat b *sample mean of x - -We could presumably tell students how to do this with a couple of numpy lines -I'd like to create three additional versions of the following figure. - -To remind you, we focused on three subperiods: - - -* subperiod 1: ("real bills period): January 1791 to July 1793 - -* subperiod 2: ("terror:): August 1793 - July 1794 - -* subperiod 3: ("classic Cagan hyperinflation): August 1794 - March 1796 - - -I can explain what this is designed to show. - - - -```{code-cell} ipython3 -def fit(x, y): - - b = np.cov(x, y)[0, 1] / np.var(x) - a = y.mean() - b * x.mean() - - return a, b -``` - -```{code-cell} ipython3 -# load data -caron = np.load('datasets/caron.npy') -nom_balances = np.load('datasets/nom_balances.npy') - -infl = np.concatenate(([np.nan], -np.log(caron[1:63, 1] / caron[0:62, 1]))) -bal = nom_balances[14:77, 1] * caron[:, 1] / 1000 -``` - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror') - -# third subsample # Tom tinkered with subsample period -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - -

The above graph is Tom's experimental lab. We'll delete it eventually.

- -

Zejin: below is the grapth with six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -

The graph below is Tom's version of the six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[34:44], a2 + bal[34:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[34:44], infl[34:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3_rev.pdf', dpi=600) -``` - - -## Figure 8 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Real balances of assignats (in gold and goods)" - name: fig8 ---- -# Read the data from Excel file -data7 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='P:Q', skiprows=4, nrows=80, header=None) -data7a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='L', skiprows=4, nrows=80, header=None) - -# Create the figure and plot -plt.figure() -h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), (data7a.values * [1, 1]) * data7.values, linewidth=1.) -plt.setp(h[1], linestyle='--', color='red') - -plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], 0, 3000, linewidth=0.8, color='orange') -plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], 0, 3000, linewidth=0.8, color='purple') - -plt.ylim([0, 3000]) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01')) -plt.ylabel('millions of livres', fontsize=12) - -# Add text annotations -plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12) -plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12) -plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig8.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig8` carefully - - -## Figure 9 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Price Level and Price of Gold (log scale)" - name: fig9 ---- -# Create the figure and plot -plt.figure() -x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12) -h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--') -h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r') - -# Set properties of the plot -plt.gca().tick_params(labelsize=12) -plt.yscale('log') -plt.xlim([1789 + 10/12, 1796 + 5/12]) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# Add vertical lines -plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange') -plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple') - -# Add text -plt.text(1793.75, 120, 'Terror', fontsize=12) -plt.text(1795, 2.8, 'price level', fontsize=12) -plt.text(1794.9, 40, 'gold', fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig9.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig9` carefully - - -## Figure 11 - - - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Spending (blue) and Revenues (orange), (real values)" - name: fig11 ---- -# Read data from Excel file -data11 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Budgets', usecols='J:K', skiprows=22, nrows=52, header=None) - -# Prepare the x-axis data -x_data = np.concatenate([ - np.arange(1791, 1794 + 8/12, 1/12), - np.arange(1794 + 9/12, 1795 + 3/12, 1/12) -]) - -# Remove NaN values from the data -data11_clean = data11.dropna() - -# Plot the data -plt.figure() -h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8) -h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8) - - - -# Set plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(axis='both', which='major', labelsize=12) -plt.xlim([1791, 1795 + 3/12]) -plt.xticks(np.arange(1791, 1796)) -plt.yticks(np.arange(0, 201, 20)) - -# Set the y-axis label -plt.ylabel('millions of livres', fontsize=12) - - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig11.pdf', dpi=600) -``` -TO TEACH TOM: By staring at {numref}`fig11` carefully - - -## Figure 12 - - -```{code-cell} ipython3 -# Read data from Excel file -data12 = pd.read_excel('datasets/assignat.xlsx', sheet_name='seignor', usecols='F', skiprows=6, nrows=75, header=None).squeeze() - - -# Create a figure and plot the data -plt.figure() -plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'), data12, linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -plt.axhline(y=472.42/12, color='r', linestyle=':') -plt.xticks(ticks=pd.date_range(start='1790', end='1796', freq='AS'), labels=range(1790, 1797)) -plt.xlim(pd.Timestamp('1791'), pd.Timestamp('1796-02') + pd.DateOffset(months=2)) -plt.ylabel('millions of livres', fontsize=12) -plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', verticalalignment='top', fontsize=12) - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig12.pdf', dpi=600) -``` - - -## Figure 13 - - -```{code-cell} ipython3 -# Read data from Excel file -data13 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Exchge', usecols='P:T', skiprows=3, nrows=502, header=None) - -# Plot the last column of the data -plt.figure() -plt.plot(data13.iloc[:, -1], linewidth=0.8) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xlim([1, len(data13)]) - -# Set x-ticks and x-tick labels -ttt = np.arange(1, len(data13) + 1) -plt.xticks(ttt[~np.isnan(data13.iloc[:, 0])], - ['Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', - 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']) - -# Add text to the plot -plt.text(1, 120, '1795', fontsize=12, ha='center') -plt.text(262, 120, '1796', fontsize=12, ha='center') - -# Draw a horizontal line and add text -plt.axhline(y=186.7, color='red', linestyle='-', linewidth=0.8) -plt.text(150, 190, 'silver parity', fontsize=12) - -# Add an annotation with an arrow -plt.annotate('end of the assignat', xy=(340, 172), xytext=(380, 160), - arrowprops=dict(facecolor='black', arrowstyle='->'), fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig13.pdf', dpi=600) -``` - - -## Figure 14 - - -```{code-cell} ipython3 -# figure 14 -data14 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='I', skiprows=9, nrows=91, header=None).squeeze() -data14a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='F', skiprows=100, nrows=151, header=None).squeeze() - -plt.figure() -h = plt.plot(data14, '*-', markersize=2, linewidth=0.8) -plt.plot(np.concatenate([np.full(data14.shape, np.nan), data14a]), linewidth=0.8) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xticks(range(20, 237, 36)) -plt.gca().set_xticklabels(range(1796, 1803)) -plt.xlabel('*: Before the 2/3 bankruptcy') -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig14.pdf', dpi=600) -``` - - -## Figure 15 - - -```{code-cell} ipython3 -# figure 15 -data15 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='N', skiprows=4, nrows=88, header=None).squeeze() - -plt.figure() -h = plt.plot(range(2, 90), data15, '*-', linewidth=0.8) -plt.setp(h, markersize=2) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.text(47.5, 11.4, '17 brumaire', horizontalalignment='left', fontsize=12) -plt.text(49.5, 14.75, '19 brumaire', horizontalalignment='left', fontsize=12) -plt.text(15, -1, 'Vendémiaire 8', fontsize=12, horizontalalignment='center') -plt.text(45, -1, 'Brumaire', fontsize=12, horizontalalignment='center') -plt.text(75, -1, 'Frimaire', fontsize=12, horizontalalignment='center') -plt.ylim([0, 25]) -plt.xticks([], []) -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig15.pdf', dpi=600) -``` - -```{code-cell} ipython3 - -``` +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.2 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Inflation During French Revolution + + +## Overview + +This lecture describes some monetary and fiscal features of the French Revolution (1789-1799) +described by {cite}`sargent_velde1995`. + +To finance public expenditures and service its debts, +the French Revolutionaries performed several policy experiments. + +The Revolutionary legislators who authored these experiments were guided by their having decided to put in place monetary-fiscal policies recommended to them by theories that they believed. + +Some of those theories make contact with modern theories about monetary and fiscal policies that interest us today. + +* a *tax-smoothing* model like Robert Barro's {cite}`Barro1979` + + * this normative (i.e., prescriptive mode) advises a government to finance temporary war-time surges in government expenditures mostly by issuing government debt; after the war to roll over whatever debt accumulated during the war, and to increase taxes permanently by enough to finance interest payments on that post-war debt + +* *unpleasant monetarist arithmetic* like that described in {doc}`unpleasant` + + * this arithmetic governed French government debt dynamics in the decades preceding 1789 and according to leading historians set the stage for the French Revolution + +* a **real bills** theory of the effects of government open market operations in which the government *backs* its issues of paper money with valuable real property or financial assets + + * the Revolutionaries learned about this theory from Adam Smith's 1776 book The Wealth of Nations + and other contemporary sources + + * It shaped how the Revolutionaries issued paper money called assignats from 1789 to 1791 + +* a classical **gold** or **silver standard** + + * Napoleon, who became head of government in 1799 used this theory to guide his monetary and fiscal policies + +* a classical inflation-tax theory of inflation in which Philip Cagan's demand for money studied +in this lecture {doc}`cagan_ree` is a key component + + * This theory helps us explain French price level and money supply data from 1794 to 1797 s + +* a *legal restrictions* or *financial repression* theory of the demand for real balances + + * the Twelve Members comprising the Committee of Public Safety who adminstered the Terror from June 1793 to July 1794 used this theory to guide their monetary policy + +We use matplotlib to replicate several of the graphs that {cite}`sargent_velde1995` used to portray outcomes of these experiments + +--- + + + +## Data Sources + +This lecture uses data from three spreadsheets: + * [datasets/fig_3.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/fig_3.xlsx) + * [datasets/dette.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/dette.xlsx) + * [datasets/assignat.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/assignat.xlsx) + +```{code-cell} ipython3 +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +plt.rcParams.update({'font.size': 12}) + +base_url = 'https://github.com/QuantEcon/lecture-python-intro/raw/'\ + + 'main/lectures/datasets/' + +fig_3_url = f'{base_url}fig_3.xlsx' +dette_url = f'{base_url}dette.xlsx' +assignat_url = f'{base_url}assignat.xlsx' +``` + +## Government Expenditures and Taxes Collected + +We'll start by using `matplotlib` to construct two graphs that will provide important historical context. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Military Spending in Britain and France + name: fr_fig4 +--- +# Read the data from Excel file +data2 = pd.read_excel(dette_url, + sheet_name='Militspe', usecols='M:X', + skiprows=7, nrows=102, header=None) + +# French military spending, 1685-1789, in 1726 livres +data4 = pd.read_excel(dette_url, + sheet_name='Militspe', usecols='D', + skiprows=3, nrows=105, header=None).squeeze() + +years = range(1685, 1790) + +plt.figure() +plt.plot(years, data4, '*-', linewidth=0.8) + +plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().tick_params(labelsize=12) +plt.xlim([1689, 1790]) +plt.xlabel('*: France') +plt.ylabel('Millions of livres') +plt.ylim([0, 475]) + +plt.tight_layout() +plt.show() +``` + +During the 18th century, Britain and France fought four large wars. + +Britain won the first three wars and lost the fourth. + +Each of those wars produced surges in both countries government expenditures that each country somehow had to finance. + +{numref}`fr_fig4` shows surges in military expenditures in France (in blue) and Great Britain. +during those four wars. + +A remarkable aspect of {numref}`fr_fig4` is that despite having a population less than half of France's, Britain was able to finance military expenses of about the same amount as France's. + +This testifies to Britain's success in having created state institutions that could tax, spend, and borrow. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Government Expenditures and Tax Revenues in Britain + name: fr_fig2 +--- +# Read the data from Excel file +data2 = pd.read_excel(dette_url, sheet_name='Militspe', usecols='M:X', + skiprows=7, nrows=102, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8) +plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red') +plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange') +plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', + markerfacecolor='none', linewidth=0.8, color='purple') + +# Customize the plot +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().tick_params(labelsize=12) +plt.xlim([1689, 1790]) +plt.ylabel('millions of pounds', fontsize=12) + +# Add text annotations +plt.text(1765, 1.5, 'civil', fontsize=10) +plt.text(1760, 4.2, 'civil plus debt service', fontsize=10) +plt.text(1708, 15.5, 'total govt spending', fontsize=10) +plt.text(1759, 7.3, 'revenues', fontsize=10) + +plt.tight_layout() +plt.show() +``` + +Figures {numref}`fr_fig2` and {numref}`fr_fig3` summarize British and French government fiscal policies during the century before the start the French Revolution in 1789. + + +Progressive forces in France before 1789 thought admired how Britain had financed its government expenditures and advocated reforms in French institutions designed to make them more like Britain's. + +Figure {numref}`fr_fig2` shows government expenditures and how it was distributed among expenditures for + + * civil (non military) activities + * debt service, i.e., interest payments + * military expenditures (the yellow line minus the red line) + +Figure {numref}`fr_fig2` also plots total government revenues from tax collections (the purple circled line) + +Notice the surges in total government expenditures associated with surges in military expenditures +in these four wars + + * Wars against France's King Louis XIV early in the 18th century + * The War of the Spanish Succession in the 1740s + * The French and Indian War in the 1750's and 1760s + * The American War for Independence from 1775 to 1783 + +{numref}`fr_fig2` indicates that + + * during times of peace, the expenditures approximately equal taxes and debt service payments neither grow nor decline over time + * during times of wars, government expenditures exceed tax revenues + * the government finances the deficit of revenues relative to expenditures by issuing debt + * after a war is over, the government's tax revenues exceed its non-interest expenditures by just enough to service the debt that the government issued to finance earlier deficits + * thus, after a war, the government does *not* raise taxes by enough to pay off its debt + * instead, it just rolls over whatever debt it inherits, raising taxes by just enough to service the interest payments on that debt + +Eighteenth century British fiscal policy portrayed {numref}`fr_fig2` thus looks very much like a text-book example of a *tax-smoothing* model like Robert Barro's {cite}`Barro1979`. + +A striking feature of the graph is what we'll nick name a **law of gravity** for taxes and expenditures. + + * levels of government expenditures at taxes attract each other + * while they can temporarily differ -- as they do during wars -- they come back together when peace returns + +Next we'll plot data on debt service costs as fractions of government revenues in Great Britain and France during the 18th century. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Ratio of debt service to taxes, Britain and France + name: fr_fig1 +--- +# Read the data from the Excel file +data1 = pd.read_excel(dette_url, sheet_name='Debt', + usecols='R:S', skiprows=5, nrows=99, header=None) +data1a = pd.read_excel(dette_url, sheet_name='Debt', + usecols='P', skiprows=89, nrows=15, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8) + +date = np.arange(1690, 1789) +index = (date < 1774) & (data1.iloc[:, 0] > 0) +plt.plot(date[index], 100 * data1[index].iloc[:, 0], + '*:', color='r', linewidth=0.8) + +# Plot the additional data +plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange') + +# Set the plot properties +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().set_xlim([1688, 1788]) +plt.ylabel('% of Taxes') + +plt.tight_layout() +plt.show() +``` + +Figure {numref}`fr_fig1` shows that interest payments on government debt (i.e., so-called ''debt service'') were high fractions of government tax revenues in both Great Britain and France. + +{numref}`fr_fig2` showed us that Britain managed to balance its budget despite those large +interest costs. + +But as we'll see in our next graph, on the eve of the French Revolution in 1788, that fiscal policy *law of gravity* that worked so well in Britain, did not seem to be working in France. + +```{code-cell} ipython3 +# Read the data from the Excel file +data1 = pd.read_excel(fig_3_url, sheet_name='Sheet1', + usecols='C:F', skiprows=5, nrows=30, header=None) + +data1.replace(0, np.nan, inplace=True) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Government Spending and Tax Revenues in France + name: fr_fig3 +--- +# Plot the data +plt.figure() + +plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8) +plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8) +plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], + '-o', linewidth=0.8, markerfacecolor='none') +plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8) + +plt.text(1775, 610, 'total spending', fontsize=10) +plt.text(1773, 325, 'military', fontsize=10) +plt.text(1773, 220, 'civil plus debt service', fontsize=10) +plt.text(1773, 80, 'debt service', fontsize=10) +plt.text(1785, 500, 'revenues', fontsize=10) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.ylim([0, 700]) +plt.ylabel('millions of livres') + +plt.tight_layout() +plt.show() +``` + +{numref}`fr_fig3` shows that in 1788 on the eve of the French Revolution government expenditures exceeded tax revenues. + +Especially during and after France's expenditures to help the Americans in their War of Independence from Great Britain, growing government debt service (i.e., interest payments) +contributed to this situation. + +This was partly a consequence of the unfolding of the debt dynamics that underlies the Unpleasant Arithmetic discussed in this quantecon lecture {doc}`unpleasant`. + +{cite}`sargent_velde1995` describe how the Ancient Regime that until 1788 had governed France had stable institutional features that made it difficult for the government to balance its budget. + +Powerful contending interests had prevented from the government from closing the gap between its +total expenditures and its tax revenues by + + * raising taxes + * lowering government's non debt service (i.e., non-interest) expenditures + * lowering its debt service (i.e., interest) costs by rescheduling its debt, i.e., defaulting on on part of its debt + +The French constitution and prevailing arrangements had empowered three constituencies to block adjustments to components of the government budget constraint that they cared especially about + +* tax payers +* beneficiaries of government expenditures +* government creditors (i.e., owners of government bonds) + +When the French government had confronted a similar situation around 1720 after King Louis XIV's +Wars had left it with a debt crisis, it had sacrificed the interests of +government creditors, i.e., by defaulting enough of its debt to bring reduce interest payments down enough to balance the budget. + +Somehow, in 1789, creditors of the French government were more powerful than they had been in 1720. + +Therefore, King Louis XVI convened the Estates General together to ask them to redesign the French constitution in a way that would lower government expenditures or increase taxes, thereby +allowing him to balance the budget while also honoring his promises to creditors of the French government. + +The King called the Estates General together in an effort to promote the reforms that would +would bring sustained budget balance. + +{cite}`sargent_velde1995` describe how the French Revolutionaries set out to accomplish that. + +## Nationalization, Privatization, Debt Reduction + +In 1789, the Revolutionaries quickly reorganized the Estates General into a National Assembly. + +A first piece of business was to address the fiscal crisis, the situation that had motivated the King to convence the Estates General. + +The Revolutionaries were not socialists or communists. + +To the contrary, they respected private property and knew state-of-the-art economics. + +They knew that to honor government debts, they would have to raise new revenues or reduce expenditures. + +A coincidence was that the Catholic Church owned vast income-producing properties. + +Indeed, the capitalized value of those income streams put estimates of the value of church lands at +about the same amount as the entire French government debt. + +This coincidence fostered a three step plan for servicing the French government debt + + * nationalize the church lands -- i.e., sequester or confiscate it without paying for it + * sell the church lands + * use the proceeds from those sales to service or even retire French government debt + +The monetary theory underlying this plan had been set out by Adam Smith in his analysis of what he called **real bills** in his 1776 book +**The Wealth of Nations** {cite}`smith2010wealth`, which many of the revolutionaries had read. + +Adam Smith defined a **real bill** as a paper money note that is backed by a claims on a real asset like productive capital or inventories. + +The National Assembly put togethere an ingenious institutional arrangement to implement this plan. + +In response to a motion by Catholic Bishop Talleyrand (an atheist), +the National Assembly confiscated and nationalized Church lands. + +The National Assembly intended to use earnings from Church lands to service its national debt. + +To do this, it began to implement a ''privatization plan'' that would let it service its debt while +not raising taxes. + +Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. + +These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. + +Finance Minister Necker and the Constituants of the National Assembly thus planned +to solve the privatization problem *and* the debt problem simultaneously +by creating a new currency. + +They devised a scheme to raise revenues by auctioning +the confiscated lands, thereby withdrawing paper notes issued on the security of +the lands sold by the government. + + This ''tax-backed money'' scheme propelled the National Assembly into the domains of then modern monetary theories. + +Records of debates show +how members of the Assembly marshaled theory and evidence to assess the likely +effects of their innovation. + + * Members of the Natioanl Assembly quoted David Hume and Adam Smith + * They cited John Law's System of 1720 and the American experiences with paper money fifteen years +earlier as examples of how paper money schemes can go awry + * Knowing pitfalls, they set out to avoid them + +They succeeded for two or three years. + +But after that, France entered a big War that disrupted the plan in ways that completely altered the character of France's paper money. {cite}`sargent_velde1995` describe what happened. + +## Remaking the tax code and tax administration + +In 1789 the French Revolutionaries formed a National Assembly and set out to remake French +fiscal policy. + +They wanted to honor government debts -- interests of French government creditors were well represented in the National Assembly. + +But they set out to remake the French tax code and the administrative machinery for collecting taxes. + + * they abolished all sorts of taxes + * they abolished the Ancient Regimes scheme for ''tax farming'' + * tax farming meant that the government had privatized tax collection by hiring private citizes -- so called tax farmers to collect taxes, while retaining a fraction of them as payment for their services + * the great chemist Lavoisier was also a tax farmer, one of the reasons that the Committee for Public Safety sent him to the guillotine in 1794 + +As a consequence of these tax reforms, government tax revenues declined + +The next figure shows this + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Index of real per capital revenues, France + name: fr_fig5 +--- +# Read data from Excel file +data5 = pd.read_excel(dette_url, sheet_name='Debt', usecols='K', + skiprows=41, nrows=120, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(labelsize=12) +plt.xlim([1726, 1845]) +plt.ylabel('1726 = 1', fontsize=12) + +plt.tight_layout() +plt.show() +``` + +According to {numref}`fr_fig5`, tax revenues per capita did not rise to their pre 1789 levels +until after 1815, when Napoleon Bonaparte was exiled to St Helena and King Louis XVIII was restored to the French Crown. + + * from 1799 to 1814, Napoleon Bonaparte had other sources of revenues -- booty and reparations from provinces and nations that he defeated in war + + * from 1789 to 1799, the French Revolutionaries turned to another source to raise resources to pay for government purchases of goods and services and to service French government debt. + +And as the next figure shows, government expenditures exceeded tax revenues by substantial +amounts during the period form 1789 to 1799. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Spending (blue) and Revenues (orange), (real values) + name: fr_fig11 +--- +# Read data from Excel file +data11 = pd.read_excel(assignat_url, sheet_name='Budgets', + usecols='J:K', skiprows=22, nrows=52, header=None) + +# Prepare the x-axis data +x_data = np.concatenate([ + np.arange(1791, 1794 + 8/12, 1/12), + np.arange(1794 + 9/12, 1795 + 3/12, 1/12) +]) + +# Remove NaN values from the data +data11_clean = data11.dropna() + +# Plot the data +plt.figure() +h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8) +h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8) + +# Set plot properties +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(axis='both', which='major', labelsize=12) +plt.xlim([1791, 1795 + 3/12]) +plt.xticks(np.arange(1791, 1796)) +plt.yticks(np.arange(0, 201, 20)) + +# Set the y-axis label +plt.ylabel('millions of livres', fontsize=12) + +plt.tight_layout() +plt.show() +``` + +To cover the disrepancies between government expenditures and tax revenues revealed in {numref}`fr_fig11`, the French revolutionaries printed paper money and spent it. + +The next figure shows that by printing money, they were able to finance substantial purchases +of goods and services, including military goods and soldiers' pay. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Revenues raised by printing paper money notes + name: fr_fig24 +--- +# Read data from Excel file +data12 = pd.read_excel(assignat_url, sheet_name='seignor', + usecols='F', skiprows=6, nrows=75, header=None).squeeze() + +# Create a figure and plot the data +plt.figure() +plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'), + data12, linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +plt.axhline(y=472.42/12, color='r', linestyle=':') +plt.xticks(ticks=pd.date_range(start='1790', + end='1796', freq='AS'), labels=range(1790, 1797)) +plt.xlim(pd.Timestamp('1791'), + pd.Timestamp('1796-02') + pd.DateOffset(months=2)) +plt.ylabel('millions of livres', fontsize=12) +plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', + verticalalignment='top', fontsize=12) + +plt.tight_layout() +plt.show() +``` + +{numref}`fr_fig24` compares the revenues raised by printing money from 1789 to 1796 with tax revenues that the Ancient Regime had raised in 1788. + +Measured in goods, revenues raised at time $t$ by printing new money equal + +$$ +\frac{M_{t+1} - M_t}{p_t} +$$ + +where + +* $M_t$ is the stock of paper money at time $t$ measured in livres +* $p_t$ is the price level at time $t$ measured in units of goods per livre at time $t$ +* $M_{t+1} - M_t$ is the amount of new money printed at time $t$ + +Notice the 1793-1794 surge in revenues raised by printing money. + +* this reflects extraordinary measures that the Committee for Public Safety adopted to force citizens to accept paper money, or else. + +Also note the abrupt fall off in revenues raised by 1797 and the absence of further observations after 1797. + +* this reflects the end using the printing press to raise revenues. + +What French paper money entitled its holders to changed over time in interesting ways. + +These led to outcomes that vary over time and that illustrate the playing out in practice of theories that guided the Revolutionaries' monetary policy decisions. + + +The next figure shows the price level in France during the time that the Revolutionaries used paper money to finance parts of their expenditures. + +Note that we use a log scale because the price level rose so much. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Price Level and Price of Gold (log scale) + name: fr_fig9 +--- +# Read the data from Excel file +data7 = pd.read_excel(assignat_url, sheet_name='Data', + usecols='P:Q', skiprows=4, nrows=80, header=None) +data7a = pd.read_excel(assignat_url, sheet_name='Data', + usecols='L', skiprows=4, nrows=80, header=None) +# Create the figure and plot +plt.figure() +x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12) +h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--') +h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r') + +# Set properties of the plot +plt.gca().tick_params(labelsize=12) +plt.yscale('log') +plt.xlim([1789 + 10/12, 1796 + 5/12]) +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# Add vertical lines +plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange') +plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple') + +# Add text +plt.text(1793.75, 120, 'Terror', fontsize=12) +plt.text(1795, 2.8, 'price level', fontsize=12) +plt.text(1794.9, 40, 'gold', fontsize=12) + + +plt.tight_layout() +plt.show() +``` + +We have partioned {numref}`fr_fig9` that shows the log of the price level and {numref}`fr_fig8` +below that plots real balances $\frac{M_t}{p_t}$ into three periods that correspond to +to different monetary experiments. + +The first period ends in the late summer of 1793, and is characterized +by growing real balances and moderate inflation. + +The second period begins and ends +with the Terror. It is marked by high real balances, around 2,500 millions, and +roughly stable prices. The fall of Robespierre in late July 1794 begins the third +of our episodes, in which real balances decline and prices rise rapidly. + +We interpret +these three episodes in terms of three separate theories about money: a ''backing'' +or ''**real bills**'' theory (the text is Adam Smith {cite}`smith2010wealth`), +a legal restrictions theory ( {cite}`keynes1940pay`, {cite}`bryant1984price` ) +and a classical hyperinflation theory ({cite}`Cagan`).% +```{note} +According to the empirical definition of hyperinflation adopted by {cite}`Cagan`, +beginning in the month that inflation exceeds 50 percent +per month and ending in the month before inflation drops below 50 percent per month +for at least a year, the *assignat* experienced a hyperinflation from May to December +1795. +``` +We view these +theories not as competitors but as alternative collections of ''if-then'' +statements about government note issues, each of which finds its conditions more +nearly met in one of these episodes than in the other two. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Real balances of assignats (in gold and goods) + name: fr_fig8 +--- +# Read the data from Excel file +data7 = pd.read_excel(assignat_url, sheet_name='Data', + usecols='P:Q', skiprows=4, nrows=80, header=None) +data7a = pd.read_excel(assignat_url, sheet_name='Data', + usecols='L', skiprows=4, nrows=80, header=None) + +# Create the figure and plot +plt.figure() +h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), + (data7a.values * [1, 1]) * data7.values, linewidth=1.) +plt.setp(h[1], linestyle='--', color='red') + +plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], + 0, 3000, linewidth=0.8, color='orange') +plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], + 0, 3000, linewidth=0.8, color='purple') + +plt.ylim([0, 3000]) + +# Set properties of the plot +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(labelsize=12) +plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01')) +plt.ylabel('millions of livres', fontsize=12) + +# Add text annotations +plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12) +plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12) +plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12) + + +plt.tight_layout() +plt.show() +``` + +The three clouds of points in Figure +{numref}`fr_fig104` + depict different real balance-inflation relationships. + +Only the cloud for the +third period has the inverse relationship familiar to us now from twentieth-century +hyperinflations. + + + + +* subperiod 1: ("**real bills** period): January 1791 to July 1793 + +* subperiod 2: ("terror:): August 1793 - July 1794 + +* subperiod 3: ("classic Cagan hyperinflation): August 1794 - March 1796 + +```{code-cell} ipython3 +def fit(x, y): + + b = np.cov(x, y)[0, 1] / np.var(x) + a = y.mean() - b * x.mean() + + return a, b +``` + +```{code-cell} ipython3 +# Load data +caron = np.load('datasets/caron.npy') +nom_balances = np.load('datasets/nom_balances.npy') + +infl = np.concatenate(([np.nan], + -np.log(caron[1:63, 1] / caron[0:62, 1]))) +bal = nom_balances[14:77, 1] * caron[:, 1] / 1000 +``` + +```{code-cell} ipython3 +# Regress y on x for three periods +a1, b1 = fit(bal[1:31], infl[1:31]) +a2, b2 = fit(bal[31:44], infl[31:44]) +a3, b3 = fit(bal[44:63], infl[44:63]) + +# Regress x on y for three periods +a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) +a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) +a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104 +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', + color='blue', label='real bills period') + +# Second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', + color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +The three clouds of points in Figure +{numref}`fr_fig104` evidently + depict different real balance-inflation relationships. + +Only the cloud for the +third period has the inverse relationship familiar to us now from twentieth-century +hyperinflations. + + To bring this out, we'll use linear regressions to draw straight lines that compress the + inflation-real balance relationship for our three sub periods. + + Before we do that, we'll drop some of the early observations during the terror period + to obtain the following graph. + +```{code-cell} ipython3 +# Regress y on x for three periods +a1, b1 = fit(bal[1:31], infl[1:31]) +a2, b2 = fit(bal[31:44], infl[31:44]) +a3, b3 = fit(bal[44:63], infl[44:63]) + +# Regress x on y for three periods +a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) +a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) +a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104b +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# Second subsample +plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +Now let's regress inflation on real balances during the **real bills** period and plot the regression +line. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104c +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', + color='blue', label='real bills period') +plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue') + +# Second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', + color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +The regression line in {numref}`fr_fig104c` shows that large increases in real balances of +assignats (paper money) were accompanied by only modest rises in the price level, an outcome in line +with the **real bills** theory. + +During this period, assignats were claims on church lands. + +But towards the end of this period, the price level started to rise and real balances to fall +as the government continued to print money but stopped selling church land. + +To get people to hold that paper money, the government forced people to hold it by using legal restrictions. + +Now let's regress real balances on inflation during the terror and plot the regression +line. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104d +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', + color='blue', label='real bills period') + +# Second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') +plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', + color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +The regression line in {numref}`fr_fig104d` shows that large increases in real balances of +assignats (paper money) were accompanied by little upward price level pressure, even some declines in prices. + +This reflects how well legal restrictions -- financial repression -- was working during the period of the Terror. + +But the Terror ended in July 1794. That unleashed a big inflation as people tried to find other ways to transact and store values. + +The following two graphs are for the classical hyperinflation period. + +One regresses inflation on real balances, the other regresses real balances on inflation. + +Both show a prounced inverse relationship that is the hallmark of the hyperinflations studied by +Cagan {cite}`Cagan`. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104e +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', + color='blue', label='real bills period') + +# Second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', + color='orange', label='classic Cagan hyperinflation') +plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +{numref}`fr_fig104e` shows the results of regressing inflation on real balances during the +period of the hyperinflation. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation and Real Balances + name: fr_fig104f +--- +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# First subsample +plt.plot(bal[1:31], infl[1:31], 'o', + markerfacecolor='none', color='blue', label='real bills period') + +# Second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# Third subsample +plt.plot(bal[44:63], infl[44:63], '*', + color='orange', label='classic Cagan hyperinflation') +plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +``` + +{numref}`fr_fig104e` shows the results of regressing real balances on inflation during the +period of the hyperinflation. diff --git a/lectures/french_rev_tom.md b/lectures/french_rev_tom.md deleted file mode 100644 index e6c19e22..00000000 --- a/lectures/french_rev_tom.md +++ /dev/null @@ -1,1078 +0,0 @@ ---- -jupytext: - text_representation: - extension: .md - format_name: myst - format_version: 0.13 - jupytext_version: 1.16.1 -kernelspec: - display_name: Python 3 (ipykernel) - language: python - name: python3 ---- - - -# Inflation During French Revolution - - -## Overview - -This lecture describes some monetary and fiscal features of the French Revolution -described by {cite}`sargent_velde1995`. - -In order to finance public expenditures and service debts issued by earlier French governments, -successive French governments performed several policy experiments. - -Authors of these experiments were guided by their having decided to put in place monetary-fiscal policies recommended by particular theories. - -As a consequence, data on money growth and inflation from the period 1789 to 1787 at least temorarily illustrated outcomes predicted by these arrangements: - -* some *unpleasant monetarist arithmetic* like that described in this quanteon lecture XXX -that governed French government debt dynamics in the decades preceding 1789 - -* a *real bills* theory of the effects of government open market operations in which the government *backs* its issues of paper money with valuable real property or financial assets - -* a classical ``gold or silver'' standard - -* a classical inflation-tax theory of inflation in which Philip Cagan's demand for money studied -in this lecture is a key component - -* a *legal restrictions* or *financial repression* theory of the demand for real balances - -We use matplotlib to replicate several of the graphs that they used to present salient patterns. - - - -## Data Sources - -This notebook uses data from three spreadsheets: - - * datasets/fig_3.ods - * datasets/dette.xlsx - * datasets/assignat.xlsx - -```{code-cell} ipython3 -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt -plt.rcParams.update({'font.size': 12}) -``` - - -## Figure 1 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Ratio of debt service to taxes, Britain and France" - name: fig1 ---- - -# Read the data from the Excel file -data1 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='R:S', skiprows=5, nrows=99, header=None) -data1a = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='P', skiprows=89, nrows=15, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8) - -date = np.arange(1690, 1789) -index = (date < 1774) & (data1.iloc[:, 0] > 0) -plt.plot(date[index], 100 * data1[index].iloc[:, 0], '*:', color='r', linewidth=0.8) - -# Plot the additional data -plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange') - -# Note about the data -# The French data before 1720 don't match up with the published version -# Set the plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().set_xlim([1688, 1788]) -plt.ylabel('% of Taxes') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig1.pdf', dpi=600) -#plt.savefig('frfinfig1.jpg', dpi=600) -``` - - - {numref}`fig1` plots ratios of debt service to total taxes collected for Great Britain and France. - The figure shows - - * ratios of debt service to taxes rise for both countries at the beginning of the century and at the end of the century - * ratios that are similar for both countries in most years - - - - - -## Figure 2 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Expenditures and Tax Revenues in Britain" - name: fig2 ---- - -# Read the data from Excel file -data2 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='M:X', skiprows=7, nrows=102, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8) -plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red') -plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange') -plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', markerfacecolor='none', linewidth=0.8, color='purple') - -# Customize the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.ylabel('millions of pounds', fontsize=12) - -# Add text annotations -plt.text(1765, 1.5, 'civil', fontsize=10) -plt.text(1760, 4.2, 'civil plus debt service', fontsize=10) -plt.text(1708, 15.5, 'total govt spending', fontsize=10) -plt.text(1759, 7.3, 'revenues', fontsize=10) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig2.pdf', dpi=600) -``` - - - -{numref}`fig2` plots total taxes, total government expenditures, and the composition of government expenditures in Great Britain during much of the 18th century. - -## Figure 3 - - - - -```{code-cell} ipython3 -# Read the data from the Excel file -data1 = pd.read_excel('datasets/fig_3.xlsx', sheet_name='Sheet1', usecols='C:F', skiprows=5, nrows=30, header=None) - -data1.replace(0, np.nan, inplace=True) -``` - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Government Spending and Tax Revenues in France" - name: fr_fig3 ---- -# Plot the data -plt.figure() - -plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8) -plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3.jpg', dpi=600) -``` - - -TO TEACH TOM: By staring at {numref}`fr_fig3` carefully - -{numref}`fr_fig3` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - -```{code-cell} ipython3 - ---- -mystnb: - figure: - caption: "Government Spending and Tax Revenues in France" - name: fr_fig3b ---- -# Plot the data -plt.figure() - -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 0])], data1.iloc[:, 0][~np.isnan(data1.iloc[:, 0])], '-x', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 1])], data1.iloc[:, 1][~np.isnan(data1.iloc[:, 1])], '--*', linewidth=0.8) -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 2])], data1.iloc[:, 2][~np.isnan(data1.iloc[:, 2])], '-o', linewidth=0.8, markerfacecolor='none') -plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 3])], data1.iloc[:, 3][~np.isnan(data1.iloc[:, 3])], '-*', linewidth=0.8) - -plt.text(1775, 610, 'total spending', fontsize=10) -plt.text(1773, 325, 'military', fontsize=10) -plt.text(1773, 220, 'civil plus debt service', fontsize=10) -plt.text(1773, 80, 'debt service', fontsize=10) -plt.text(1785, 500, 'revenues', fontsize=10) - - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.ylim([0, 700]) -plt.ylabel('millions of livres') - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig3_ignore_nan.jpg', dpi=600) -``` - -{numref}`fr_fig3b` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - - - - -## Figure 4 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Military Spending in Britain and France" - name: fig4 ---- -# French military spending, 1685-1789, in 1726 livres -data4 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='D', skiprows=3, nrows=105, header=None).squeeze() -years = range(1685, 1790) - -plt.figure() -plt.plot(years, data4, '*-', linewidth=0.8) - -plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().tick_params(labelsize=12) -plt.xlim([1689, 1790]) -plt.xlabel('*: France') -plt.ylabel('Millions of livres') -plt.ylim([0, 475]) - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig4.pdf', dpi=600) -``` - - -{numref}`fig4` plots total taxes, total government expenditures, and the composition of government expenditures in France during much of the 18th century. - -TO TEACH TOM: By staring at {numref}`fig4` carefully - - -## Figure 5 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Index of real per capital revenues, France" - name: fig5 ---- -# Read data from Excel file -data5 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='K', skiprows=41, nrows=120, header=None) - -# Plot the data -plt.figure() -plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim([1726, 1845]) -plt.ylabel('1726 = 1', fontsize=12) - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig5.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig5` carefully - -## Rise and Fall of the *Assignat* - - - - We have partitioned Figures~\ref{fig:fig7}, \ref{fig:fig8}, and \ref{fig:fig9} - into three periods, corresponding -to different monetary regimes or episodes. The three clouds of points in -Figure~\ref{fig:fig7} - depict different real balance-inflation relationships. Only the cloud for the -third period has the inverse relationship familiar to us now from twentieth-century -hyperinflations. The first period ends in the late summer of 1793, and is characterized -by growing real balances and moderate inflation. The second period begins and ends -with the Terror. It is marked by high real balances, around 2,500 millions, and -roughly stable prices. The fall of Robespierre in late July 1794 begins the third -of our episodes, in which real balances decline and prices rise rapidly. We interpret -these three episodes in terms of three separate theories about money: a ``backing'' -or ''real bills'' theory (the text is Adam Smith (1776)), -a legal restrictions theory (TOM: HERE PLEASE CITE -Keynes,1940, AS WELL AS Bryant/Wallace:1984 and Villamil:1988) -and a classical hyperinflation theory.% -```{note} -According to the empirical definition of hyperinflation adopted by {cite}`Cagan`, -beginning in the month that inflation exceeds 50 percent -per month and ending in the month before inflation drops below 50 percent per month -for at least a year, the *assignat* experienced a hyperinflation from May to December -1795. -``` -We view these -theories not as competitors but as alternative collections of ``if-then'' -statements about government note issues, each of which finds its conditions more -nearly met in one of these episodes than in the other two. - - - - - -## Figure 7 - - -## To Do for Zejin - -I want to tweak and consolidate the extra lines that Zejin drew on the beautiful **Figure 7**. - -I'd like to experiment in plotting the **six** extra lines all on one graph -- a pair of lines for each of our subsamples - - * one for the $y$ on $x$ regression line - * another for the $x$ on $y$ regression line - -I'd like the $y$ on $x$ and $x$ on $y$ lines to be in separate colors. - -Once we are satisfied with this new graph with its six additional lines, we can dispense with the other graphs that add one line at a time. - -Zejin, I can explain on zoom the lessons I want to convey with this. - - - -Just to recall, to compute the regression lines, Zejin wrote a function that use standard formulas -for a and b in a least squares regression y = a + b x + residual -- i.e., b is ratio of sample covariance of y,x to sample variance of x; while a is then computed from a = sample mean of y - \hat b *sample mean of x - -We could presumably tell students how to do this with a couple of numpy lines -I'd like to create three additional versions of the following figure. - -To remind you, we focused on three subperiods: - - -* subperiod 1: ("real bills period): January 1791 to July 1793 - -* subperiod 2: ("terror:): August 1793 - July 1794 - -* subperiod 3: ("classic Cagan hyperinflation): August 1794 - March 1796 - - -I can explain what this is designed to show. - - - -```{code-cell} ipython3 -def fit(x, y): - - b = np.cov(x, y)[0, 1] / np.var(x) - a = y.mean() - b * x.mean() - - return a, b -``` - -```{code-cell} ipython3 -# load data -caron = np.load('datasets/caron.npy') -nom_balances = np.load('datasets/nom_balances.npy') - -infl = np.concatenate(([np.nan], -np.log(caron[1:63, 1] / caron[0:62, 1]))) -bal = nom_balances[14:77, 1] * caron[:, 1] / 1000 -``` - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -```{code-cell} ipython3 -# fit data - -# reg y on x for three periods -a1, b1 = fit(bal[1:31], infl[1:31]) -a2, b2 = fit(bal[31:44], infl[31:44]) -a3, b3 = fit(bal[44:63], infl[44:63]) - -# reg x on y for three periods -a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) -a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) -a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror') - -# third subsample # Tom tinkered with subsample period -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - -

The above graph is Tom's experimental lab. We'll delete it eventually.

- -

Zejin: below is the grapth with six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - - - -

The graph below is Tom's version of the six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.

- -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[34:44], a2 + bal[34:44] * b2, color='red', linewidth=0.8) -plt.plot(a2_rev + b2_rev * infl[34:44], infl[34:44], color='green', linewidth=0.8) - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') -plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='blue') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line1_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') -plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line2_rev.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3.pdf', dpi=600) -``` - -```{code-cell} ipython3 -plt.figure() -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# first subsample -plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') - -# second subsample -plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') - -# third subsample -plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') -plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange') - -plt.xlabel('real balances') -plt.ylabel('inflation') -plt.legend() - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig7_line3_rev.pdf', dpi=600) -``` - - -## Figure 8 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Real balances of assignats (in gold and goods)" - name: fig8 ---- -# Read the data from Excel file -data7 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='P:Q', skiprows=4, nrows=80, header=None) -data7a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='L', skiprows=4, nrows=80, header=None) - -# Create the figure and plot -plt.figure() -h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), (data7a.values * [1, 1]) * data7.values, linewidth=1.) -plt.setp(h[1], linestyle='--', color='red') - -plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], 0, 3000, linewidth=0.8, color='orange') -plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], 0, 3000, linewidth=0.8, color='purple') - -plt.ylim([0, 3000]) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(labelsize=12) -plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01')) -plt.ylabel('millions of livres', fontsize=12) - -# Add text annotations -plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12) -plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12) -plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12) - - -plt.tight_layout() -plt.show() - -# Save the figure as a PDF -#plt.savefig('frfinfig8.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig8` carefully - - -## Figure 9 - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Price Level and Price of Gold (log scale)" - name: fig9 ---- -# Create the figure and plot -plt.figure() -x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12) -h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--') -h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r') - -# Set properties of the plot -plt.gca().tick_params(labelsize=12) -plt.yscale('log') -plt.xlim([1789 + 10/12, 1796 + 5/12]) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -# Add vertical lines -plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange') -plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple') - -# Add text -plt.text(1793.75, 120, 'Terror', fontsize=12) -plt.text(1795, 2.8, 'price level', fontsize=12) -plt.text(1794.9, 40, 'gold', fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig9.pdf', dpi=600) -``` - -TO TEACH TOM: By staring at {numref}`fig9` carefully - - -## Figure 11 - - - - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: "Spending (blue) and Revenues (orange), (real values)" - name: fig11 ---- -# Read data from Excel file -data11 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Budgets', usecols='J:K', skiprows=22, nrows=52, header=None) - -# Prepare the x-axis data -x_data = np.concatenate([ - np.arange(1791, 1794 + 8/12, 1/12), - np.arange(1794 + 9/12, 1795 + 3/12, 1/12) -]) - -# Remove NaN values from the data -data11_clean = data11.dropna() - -# Plot the data -plt.figure() -h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8) -h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8) - - - -# Set plot properties -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_facecolor('white') -plt.gca().tick_params(axis='both', which='major', labelsize=12) -plt.xlim([1791, 1795 + 3/12]) -plt.xticks(np.arange(1791, 1796)) -plt.yticks(np.arange(0, 201, 20)) - -# Set the y-axis label -plt.ylabel('millions of livres', fontsize=12) - - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig11.pdf', dpi=600) -``` -TO TEACH TOM: By staring at {numref}`fig11` carefully - - -## Figure 12 - - -```{code-cell} ipython3 -# Read data from Excel file -data12 = pd.read_excel('datasets/assignat.xlsx', sheet_name='seignor', usecols='F', skiprows=6, nrows=75, header=None).squeeze() - - -# Create a figure and plot the data -plt.figure() -plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'), data12, linewidth=0.8) - -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) - -plt.axhline(y=472.42/12, color='r', linestyle=':') -plt.xticks(ticks=pd.date_range(start='1790', end='1796', freq='AS'), labels=range(1790, 1797)) -plt.xlim(pd.Timestamp('1791'), pd.Timestamp('1796-02') + pd.DateOffset(months=2)) -plt.ylabel('millions of livres', fontsize=12) -plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', verticalalignment='top', fontsize=12) - - -plt.tight_layout() -plt.show() - -#plt.savefig('frfinfig12.pdf', dpi=600) -``` - - -## Figure 13 - - -```{code-cell} ipython3 -# Read data from Excel file -data13 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Exchge', usecols='P:T', skiprows=3, nrows=502, header=None) - -# Plot the last column of the data -plt.figure() -plt.plot(data13.iloc[:, -1], linewidth=0.8) - -# Set properties of the plot -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xlim([1, len(data13)]) - -# Set x-ticks and x-tick labels -ttt = np.arange(1, len(data13) + 1) -plt.xticks(ttt[~np.isnan(data13.iloc[:, 0])], - ['Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', - 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']) - -# Add text to the plot -plt.text(1, 120, '1795', fontsize=12, ha='center') -plt.text(262, 120, '1796', fontsize=12, ha='center') - -# Draw a horizontal line and add text -plt.axhline(y=186.7, color='red', linestyle='-', linewidth=0.8) -plt.text(150, 190, 'silver parity', fontsize=12) - -# Add an annotation with an arrow -plt.annotate('end of the assignat', xy=(340, 172), xytext=(380, 160), - arrowprops=dict(facecolor='black', arrowstyle='->'), fontsize=12) - - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig13.pdf', dpi=600) -``` - - -## Figure 14 - - -```{code-cell} ipython3 -# figure 14 -data14 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='I', skiprows=9, nrows=91, header=None).squeeze() -data14a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='F', skiprows=100, nrows=151, header=None).squeeze() - -plt.figure() -h = plt.plot(data14, '*-', markersize=2, linewidth=0.8) -plt.plot(np.concatenate([np.full(data14.shape, np.nan), data14a]), linewidth=0.8) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.gca().set_xticks(range(20, 237, 36)) -plt.gca().set_xticklabels(range(1796, 1803)) -plt.xlabel('*: Before the 2/3 bankruptcy') -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig14.pdf', dpi=600) -``` - - -## Figure 15 - - -```{code-cell} ipython3 -# figure 15 -data15 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='N', skiprows=4, nrows=88, header=None).squeeze() - -plt.figure() -h = plt.plot(range(2, 90), data15, '*-', linewidth=0.8) -plt.setp(h, markersize=2) -plt.gca().spines['top'].set_visible(False) -plt.gca().spines['right'].set_visible(False) -plt.text(47.5, 11.4, '17 brumaire', horizontalalignment='left', fontsize=12) -plt.text(49.5, 14.75, '19 brumaire', horizontalalignment='left', fontsize=12) -plt.text(15, -1, 'Vendémiaire 8', fontsize=12, horizontalalignment='center') -plt.text(45, -1, 'Brumaire', fontsize=12, horizontalalignment='center') -plt.text(75, -1, 'Frimaire', fontsize=12, horizontalalignment='center') -plt.ylim([0, 25]) -plt.xticks([], []) -plt.ylabel('Francs') - -plt.tight_layout() -plt.show() -#plt.savefig('frfinfig15.pdf', dpi=600) -``` - -```{code-cell} ipython3 - -``` - - -## Fiscal Situation and Response of National Assembly - - -In response to a motion by Catholic Bishop Talleyrand, -the National Assembly confiscated and nationalized Church lands. - -But the National Assembly was dominated by free market advocates, not socialists. - -The National Assembly intended to use earnings from Church lands to service its national debt. - -To do this, it began to implement a ''privatization plan'' that would let it service its debt while -not raising taxes. - -Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. - -These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. - -Finance Minister Necker and the Constituants planned -to solve the privatization problem **and** the debt problem simultaneously -by creating a new currency. - -They devised a scheme to raise revenues by auctioning -the confiscated lands, thereby withdrawing paper notes issued on the security of -the lands sold by the government. - - This ''tax-backed money'' scheme propelled the National Assembly into the domain of monetary experimentation. - -Records of their debates show -how members of the Assembly marshaled theory and evidence to assess the likely -effects of their innovation. - -They quoted David Hume and Adam Smith and cited John -Law's System of 1720 and the American experiences with paper money fifteen years -earlier as examples of how paper money schemes can go awry. - - -### Necker's plan and how it was tweaked - -Necker's original plan embodied two components: a national bank and a new -financial instrument, the ''assignat''. - - -Necker's national -bank was patterned after the Bank of England. He proposed to transform the *Caisse d'Escompte* into a national bank by granting it a monopoly on issuing -notes and marketing government debt. The *Caisse* was a -discount bank founded in 1776 whose main function was to discount commercial bills -and issue convertible notes. Although independent of the government in principle, -it had occasionally been used as a source of loans. Its notes had been declared -inconvertible in August 1788, and by the time of Necker's proposal, its reserves -were exhausted. Necker's plan placed the National Estates (as the Church lands -became known after the addition of the royal demesne) at the center of the financial -picture: a ''Bank of France'' would issue a $5\%$ security mortgaged on the prospective -receipts from the modest sale of some 400 millions' worth of National Estates in -the years 1791 to 1793. -```{note} - Only 170 million was to be used initially -to cover the deficits of 1789 and 1790. -``` - - -By mid-1790, members of the National Assembly had agreed to sell the National -Estates and to use the proceeds to service the debt in a ``tax-backed money'' scheme -```{note} -Debt service costs absorbed - over 60\% of French government expenditures. -``` - -The government would issue securities with which it would reimburse debt. - -The securities -were acceptable as payment for National Estates purchased at auctions; once received -in payment, they were to be burned. - -```{note} -The appendix to {cite}`sargent_velde1995` describes the -auction rules in detail. -``` -The Estates available for sale were thought to be worth about 2,400 -million, while the exactable debt (essentially fixed-term loans, unpaid arrears, -and liquidated offices) stood at about 2,000 million. The value of the land was -sufficient to let the Assembly retire all of the exactable debt and thereby eliminate -the interest payments on it. After lengthy debates, in August 1790, the Assembly set the denomination -and interest rate structure of the debt. - - -```{note} Two distinct -aspects of monetary theory help in thinking about the assignat plan. First, a system -beginning with a commodity standard typically has room for a once-and-for-all emission -of (an unbacked) paper currency that can replace the commodity money without generating -inflation. \citet{Sargent/Wallace:1983} describe models with this property. That -commodity money systems are wasteful underlies Milton Friedman's (1960) TOM:ADD REFERENCE preference -for a fiat money regime over a commodity money. Second, in a small country on a -commodity money system that starts with restrictions on intermediation, those restrictions -can be relaxed by letting the government issue bank notes on the security of safe -private indebtedness, while leaving bank notes convertible into gold at par. See -Adam Smith and Sargent and Wallace (1982) for expressions of this idea. TOM: ADD REFERENCES HEREAND IN BIBTEX FILE. -``` - - -```{note} -The -National Assembly debated many now classic questions in monetary economics. Under -what conditions would money creation generate inflation, with what consequences -for business conditions? Distinctions were made between issue of money to pay off -debt, on one hand, and monetization of deficits, on the other. Would *assignats* be akin -to notes emitted under a real bills regime, and cause loss of specie, or would -they circulate alongside specie, thus increasing the money stock? Would inflation -affect real wages? How would it impact foreign trade, competitiveness of French -industry and agriculture, balance of trade, foreign exchange? -``` diff --git a/lectures/greek_square.md b/lectures/greek_square.md index d7c13887..3ae37d38 100644 --- a/lectures/greek_square.md +++ b/lectures/greek_square.md @@ -4,25 +4,31 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.14.4 + jupytext_version: 1.16.2 kernelspec: display_name: Python 3 (ipykernel) language: python name: python3 --- -+++ {"user_expressions": []} - # Computing Square Roots ## Introduction -This lectures provides an example of **invariant subspace** methods for analyzing linear difference equations. -These methods are applied throughout applied economic dynamics, for example, in this QuantEcon lecture {doc}`money financed government deficits and inflation ` +This lecture can be viewed as a sequel to {doc}`eigen_I`. + +It provides an example of how eigenvectors isolate *invariant subspaces* that help construct and analyze solutions of linear difference equations. + +When vector $x_t$ starts in an invariant subspace, iterating the different equation keeps $x_{t+j}$ +in that subspace for all $j \geq 1$. + +Invariant subspace methods are used throughout applied economic dynamics, for example, in the lecture {doc}`money_inflation`. -Our approach in this lecture is to illustrate the method with an ancient example, one that ancient Greek mathematicians used to compute square roots of positive integers. +Our approach here is to illustrate the method with an ancient example, one that ancient Greek mathematicians used to compute square roots of positive integers. + +## Perfect squares and irrational numbers An integer is called a **perfect square** if its square root is also an integer. @@ -38,19 +44,22 @@ The ancient Greeks invented an algorithm to compute square roots of integers, in Their method involved - * computing a particular sequence of integers $\{y_t\}_{t=0}^\infty$ + * computing a particular sequence of integers $\{y_t\}_{t=0}^\infty$; - * computing $\lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) = \bar r$ + * computing $\lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) = \bar r$; - * deducing the desired square root from $\bar r$ + * deducing the desired square root from $\bar r$. In this lecture, we'll describe this method. We'll also use invariant subspaces to describe variations on this method that are faster. -## Primer on second order linear difference equation +## Second-order linear difference equations + +Before telling how the ancient Greeks computed square roots, we'll provide a quick introduction +to second-order linear difference equations. -Consider the following second-order linear difference equation +We'll study the following second-order linear difference equation $$ y_t = a_1 y_{t-1} + a_2 y_{t-2}, \quad t \geq 0 @@ -58,13 +67,31 @@ $$ (eq:2diff1) where $(y_{-1}, y_{-2})$ is a pair of given initial conditions. -We want to find expressions for $y_t, t \geq 0$ as functions of the initial conditions $(y_{-1}, y_{-2})$: +Equation {eq}`eq:2diff1` is actually an infinite number of linear equations in the sequence +$\{y_t\}_{t=0}^\infty$. + +There is one equation each for $t = 0, 1, 2, \ldots$. + +We could follow an approach taken in the lecture on {doc}`present values` and stack all of these equations into a single matrix equation that we would then solve by using matrix inversion. + +```{note} +In the present instance, the matrix equation would multiply a countably infinite dimensional square matrix by a countably infinite dimensional vector. With some qualifications, matrix multiplication and inversion tools apply to such an equation. +``` + +But we won't pursue that approach here. + + +Instead, we'll seek to find a time-invariant function that *solves* our difference equation, meaning +that it provides a formula for a $\{y_t\}_{t=0}^\infty$ sequence that satisfies +equation {eq}`eq:2diff1` for each $t \geq 0$. + +We seek an expression for $y_t, t \geq 0$ as functions of the initial conditions $(y_{-1}, y_{-2})$: $$ -y_t = g((y_{-1}, y_{-2});t), \quad t \geq 0 +y_t = g((y_{-1}, y_{-2});t), \quad t \geq 0. $$ (eq:2diff2) -We call such a function $g$ a **solution** of the difference equation {eq}`eq:2diff1`. +We call such a function $g$ a *solution* of the difference equation {eq}`eq:2diff1`. One way to discover a solution is to use a guess and verify method. @@ -81,7 +108,7 @@ For initial condition that satisfy {eq}`eq:2diff3` equation {eq}`eq:2diff1` impllies that $$ -y_0 = \left(a_1 + \frac{a_2}{\delta}\right) y_{-1} +y_0 = \left(a_1 + \frac{a_2}{\delta}\right) y_{-1}. $$ (eq:2diff4) We want @@ -90,16 +117,16 @@ $$ \left(a_1 + \frac{a_2}{\delta}\right) = \delta $$ (eq:2diff5) -which we can rewrite as the **characteristic equation** +which we can rewrite as the *characteristic equation* $$ -\delta^2 - a_1 \delta - a_2 = 0 +\delta^2 - a_1 \delta - a_2 = 0. $$ (eq:2diff6) Applying the quadratic formula to solve for the roots of {eq}`eq:2diff6` we find that $$ -\delta = \frac{ a_1 \pm \sqrt{a_1^2 + 4 a_2}}{2} +\delta = \frac{ a_1 \pm \sqrt{a_1^2 + 4 a_2}}{2}. $$ (eq:2diff7) For either of the two $\delta$'s that satisfy equation {eq}`eq:2diff7`, @@ -109,9 +136,13 @@ $$ y_t = \delta^t y_0 , \forall t \geq 0 $$ (eq:2diff8) -and $y_0 = a_1 y_{-1} + a_2 y_{-2}$ +provided that we set -The **general** solution of difference equation {eq}`eq:2diff1` takes the form +$$ +y_0 = \delta y_{-1} . +$$ + +The *general* solution of difference equation {eq}`eq:2diff1` takes the form $$ y_t = \eta_1 \delta_1^t + \eta_2 \delta_2^t @@ -137,33 +168,34 @@ If we choose $(y_{-1}, y_{-2})$ to set $(\eta_1, \eta_2) = (1, 0)$, then $y_t = If we choose $(y_{-1}, y_{-2})$ to set $(\eta_1, \eta_2) = (0, 1)$, then $y_t = \delta_2^t$ for all $t \geq 0$. +Soon we'll relate the preceding calculations to components an eigen decomposition of a transition matrix that represents difference equation {eq}`eq:2diff1` in a very convenient way. + +We'll turn to that after we describe how Ancient Greeks figured out how to compute square roots of positive integers that are not perfect squares. -## Setup -Let $\sigma$ be a positive integer greater than $1$ +## Algorithm of the Ancient Greeks -So $\sigma \in {\mathcal I} \equiv \{2, 3, \ldots \}$ +Let $\sigma$ be a positive integer greater than $1$. + +So $\sigma \in {\mathcal I} \equiv \{2, 3, \ldots \}$. We want an algorithm to compute the square root of $\sigma \in {\mathcal I}$. -If $\sqrt{\sigma} \in {\mathcal I}$, $\sigma $ is said to be a **perfect square**. +If $\sqrt{\sigma} \in {\mathcal I}$, $\sigma $ is said to be a *perfect square*. If $\sqrt{\sigma} \not\in {\mathcal I}$, it turns out that it is irrational. Ancient Greeks used a recursive algorithm to compute square roots of integers that are not perfect squares. -The algorithm iterates on a second order linear difference equation in the sequence $\{y_t\}_{t=0}^\infty$: +The algorithm iterates on a second-order linear difference equation in the sequence $\{y_t\}_{t=0}^\infty$: $$ y_{t} = 2 y_{t-1} - (1 - \sigma) y_{t-2}, \quad t \geq 0 $$ (eq:second_order) -together with a pair of integers that are initial conditions for $y_{-1}, y_{-2}$. - -First, we'll deploy some techniques for solving difference equations that are also deployed in this QuantEcon lecture about the multiplier-accelerator model: - - +together with a pair of integers that are initial conditions for $y_{-1}, y_{-2}$. +First, we'll deploy some techniques for solving the difference equations that are also deployed in {doc}`dynam:samuelson`. The characteristic equation associated with difference equation {eq}`eq:second_order` is @@ -171,11 +203,9 @@ $$ c(x) \equiv x^2 - 2 x + (1 - \sigma) = 0 $$ (eq:cha_eq0) -+++ +(Notice how this is an instance of equation {eq}`eq:2diff6` above.) -(This is an instance of equation {eq}`eq:2diff6` above.) - -If we factor the right side of the equation {eq}`eq:cha_eq0`, we obtain +Factoring the right side of equation {eq}`eq:cha_eq0`, we obtain $$ c(x)= (x - \lambda_1) (x-\lambda_2) = 0 @@ -197,11 +227,11 @@ By applying the quadratic formula to solve for the roots the characteristic equ {eq}`eq:cha_eq0`, we find that $$ -\lambda_1 = 1 + \sqrt{\sigma}, \quad \lambda_2 = 1 - \sqrt{\sigma} +\lambda_1 = 1 + \sqrt{\sigma}, \quad \lambda_2 = 1 - \sqrt{\sigma}. $$ (eq:secretweapon) -Formulas {eq}`eq:secretweapon` indicate that $\lambda_1$ and $\lambda_2$ are both simple functions -of a single variable, namely, $\sqrt{\sigma}$, the object that some Ancient Greeks wanted to compute. +Formulas {eq}`eq:secretweapon` indicate that $\lambda_1$ and $\lambda_2$ are each functions +of a single variable, namely, $\sqrt{\sigma}$, the object that we along with some Ancient Greeks want to compute. Ancient Greeks had an indirect way of exploiting this fact to compute square roots of a positive integer. @@ -214,7 +244,7 @@ $$ y_t = \lambda_1^t \eta_1 + \lambda_2^t \eta_2 $$ -where $\eta_1$ and $\eta_2$ are chosen to satisfy the prescribed initial conditions $y_{-1}, y_{-2}$: +where $\eta_1$ and $\eta_2$ are chosen to satisfy prescribed initial conditions $y_{-1}, y_{-2}$: $$ \begin{aligned} @@ -225,17 +255,17 @@ $$(eq:leq_sq) System {eq}`eq:leq_sq` of simultaneous linear equations will play a big role in the remainder of this lecture. -Since $\lambda_1 = 1 + \sqrt{\sigma} > 1 > \lambda_2 = 1 - \sqrt{\sigma} $ -it follows that for **almost all** (but not all) initial conditions +Since $\lambda_1 = 1 + \sqrt{\sigma} > 1 > \lambda_2 = 1 - \sqrt{\sigma} $, +it follows that for *almost all* (but not all) initial conditions $$ -\lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) = 1 + \sqrt{\sigma} +\lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) = 1 + \sqrt{\sigma}. $$ Thus, $$ -\sqrt{\sigma} = \lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) - 1 +\sqrt{\sigma} = \lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) - 1. $$ However, notice that if $\eta_1 = 0$, then @@ -247,7 +277,7 @@ $$ so that $$ -\sqrt{\sigma} = 1 - \lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right) +\sqrt{\sigma} = 1 - \lim_{t \rightarrow \infty} \left(\frac{y_{t+1}}{y_t}\right). $$ Actually, if $\eta_1 =0$, it follows that @@ -270,40 +300,38 @@ so again, convergence is immediate, and we have no need to compute a limit. System {eq}`eq:leq_sq` of simultaneous linear equations can be used in various ways. - * we can take $y_{-1}, y_{-2}$ as given initial conditions and solve for $\eta_1, \eta_2$ + * we can take $y_{-1}, y_{-2}$ as given initial conditions and solve for $\eta_1, \eta_2$; - * we can instead take $\eta_1, \eta_2$ as given and solve for initial conditions $y_{-1}, y_{-2}$ + * we can instead take $\eta_1, \eta_2$ as given and solve for initial conditions $y_{-1}, y_{-2}$. Notice how we used the second approach above when we set $\eta_1, \eta_2$ either to $(0, 1)$, for example, or $(1, 0)$, for example. -In taking this second approach, we were in effect finding an **invariant subspace** of ${\bf R}^2$. +In taking this second approach, we constructed an *invariant subspace* of ${\bf R}^2$. Here is what is going on. -For $ t \geq 0$ and for most pairs of initial conditions $(y_{-1}, y_{-2}) \in {\bf R}^2$ for equation {eq}`eq:second_order', $y_t$ can be expressed as a linear combination of $y_{t-1}$ and $y_{t-2}$. +For $ t \geq 0$ and for most pairs of initial conditions $(y_{-1}, y_{-2}) \in {\bf R}^2$ for equation {eq}`eq:second_order`, $y_t$ can be expressed as a linear combination of $y_{t-1}$ and $y_{t-2}$. But for some special initial conditions $(y_{-1}, y_{-2}) \in {\bf R}^2$, $y_t$ can be expressed as a linear function of $y_{t-1}$ only. These special initial conditions require that $y_{-1}$ be a linear function of $y_{-2}$. -We'll study these special initial conditions soon. But first let's write some Python code to iterate on equation {eq}`eq:second_order` starting from an arbitrary $(y_{-1}, y_{-2}) \in {\bf R}^2$. +We'll study these special initial conditions soon. + +But first let's write some Python code to iterate on equation {eq}`eq:second_order` starting from an arbitrary $(y_{-1}, y_{-2}) \in {\bf R}^2$. ## Implementation We now implement the above algorithm to compute the square root of $\sigma$. - In this lecture, we use the following import: ```{code-cell} ipython3 -:tags: [] - import numpy as np +import matplotlib.pyplot as plt ``` ```{code-cell} ipython3 -:tags: [] - def solve_λs(coefs): # Calculate the roots using numpy.roots λs = np.roots(coefs) @@ -359,16 +387,12 @@ print(f"sqrt({σ}) is approximately {sqrt_σ:.5f} (error: {dev:.5f})") Now we consider cases where $(\eta_1, \eta_2) = (0, 1)$ and $(\eta_1, \eta_2) = (1, 0)$ ```{code-cell} ipython3 -:tags: [] - # Compute λ_1, λ_2 λ_1, λ_2 = solve_λs(coefs) print(f'Roots for the characteristic equation are ({λ_1:.5f}, {λ_2:.5f}))') ``` ```{code-cell} ipython3 -:tags: [] - # Case 1: η_1, η_2 = (0, 1) ηs = (0, 1) @@ -380,9 +404,7 @@ print(f"For η_1, η_2 = (0, 1), sqrt_σ = {sqrt_σ:.5f}") ``` ```{code-cell} ipython3 -:tags: [] - -# Case 2: η_1, η_2 = (0, 1) +# Case 2: η_1, η_2 = (1, 0) ηs = (1, 0) sqrt_σ = y(1, ηs) / y(0, ηs) - 1 @@ -391,9 +413,7 @@ print(f"For η_1, η_2 = (1, 0), sqrt_σ = {sqrt_σ:.5f}") We find that convergence is immediate. -+++ - -Let's represent the preceding analysis by vectorizing our second order difference equation {eq}`eq:second_order` and then using eigendecompositions of a state transition matrix. +Next, we'll represent the preceding analysis by first vectorizing our second-order difference equation {eq}`eq:second_order` and then using eigendecompositions of an associated state transition matrix. ## Vectorizing the difference equation @@ -433,13 +453,112 @@ $$ x_{t+1} = V \Lambda V^{-1} x_t $$ -Define +Now we implement the algorithm above. + +First we write a function that iterates $M$ + +```{code-cell} ipython3 +def iterate_M(x_0, M, num_steps, dtype=np.float64): + + # Eigendecomposition of M + Λ, V = np.linalg.eig(M) + V_inv = np.linalg.inv(V) + + # Initialize the array to store results + xs = np.zeros((x_0.shape[0], + num_steps + 1)) + + # Perform the iterations + xs[:, 0] = x_0 + for t in range(num_steps): + xs[:, t + 1] = M @ xs[:, t] + + return xs, Λ, V, V_inv + +# Define the state transition matrix M +M = np.array([ + [2, -(1 - σ)], + [1, 0]]) + +# Initial condition vector x_0 +x_0 = np.array([2, 2]) + +# Perform the iteration +xs, Λ, V, V_inv = iterate_M(x_0, M, num_steps=100) + +print(f"eigenvalues:\n{Λ}") +print(f"eigenvectors:\n{V}") +print(f"inverse eigenvectors:\n{V_inv}") +``` + +Let's compare the eigenvalues to the roots {eq}`eq:secretweapon` of equation +{eq}`eq:cha_eq0` that we computed above. + +```{code-cell} ipython3 +roots = solve_λs((1, -2, (1 - σ))) +print(f"roots: {np.round(roots, 8)}") +``` + +Hence we confirmed {eq}`eq:eigen_sqrt`. + +Information about the square root we are after is also contained +in the two eigenvectors. + +Indeed, each eigenvector is just a two-dimensional subspace of ${\mathbb R}^3$ pinned down by dynamics of the form + +$$ +y_{t} = \lambda_i y_{t-1}, \quad i = 1, 2 +$$ (eq:invariantsub101) + +that we encountered above in equation {eq}`eq:2diff8` above. + +In equation {eq}`eq:invariantsub101`, the $i$th $\lambda_i$ equals the $V_{i, 1}/V_{i,2}$. + +The following graph verifies this for our example. + +```{code-cell} ipython3 +:tags: [hide-input] + +# Plotting the eigenvectors +plt.figure(figsize=(8, 8)) + +plt.quiver(0, 0, V[0, 0], V[1, 0], angles='xy', scale_units='xy', + scale=1, color='C0', label=fr'$\lambda_1={np.round(Λ[0], 4)}$') +plt.quiver(0, 0, V[0, 1], V[1, 1], angles='xy', scale_units='xy', + scale=1, color='C1', label=fr'$\lambda_2={np.round(Λ[1], 4)}$') + +# Annotating the slopes +plt.text(V[0, 0]-0.5, V[1, 0]*1.2, + r'slope=$\frac{V_{1,1}}{V_{1,2}}=$'+f'{np.round(V[0, 0] / V[1, 0], 4)}', + fontsize=12, color='C0') +plt.text(V[0, 1]-0.5, V[1, 1]*1.2, + r'slope=$\frac{V_{2,1}}{V_{2,2}}=$'+f'{np.round(V[0, 1] / V[1, 1], 4)}', + fontsize=12, color='C1') + +# Adding labels +plt.axhline(0, color='grey', linewidth=0.5, alpha=0.4) +plt.axvline(0, color='grey', linewidth=0.5, alpha=0.4) +plt.legend() + +plt.xlim(-1.5, 1.5) +plt.ylim(-1.5, 1.5) +plt.show() +``` + +## Invariant subspace approach + +The preceding calculation indicates that we can use the eigenvectors $V$ to construct 2-dimensional *invariant subspaces*. + +We'll pursue that possibility now. + +Define the transformed variables + $$ x_t^* = V^{-1} x_t $$ -We can recover $x_t$ from $x_t^*$: +Evidently, we can recover $x_t$ from $x_t^*$: $$ x_t = V x_t^* @@ -453,23 +572,21 @@ Let $$ V = \begin{bmatrix} V_{1,1} & V_{1,2} \cr - V_{2,2} & V_{2,2} \end{bmatrix}, \quad + V_{2,1} & V_{2,2} \end{bmatrix}, \quad V^{-1} = \begin{bmatrix} V^{1,1} & V^{1,2} \cr - V^{2,2} & V^{2,2} \end{bmatrix} + V^{2,1} & V^{2,2} \end{bmatrix} $$ Notice that it follows from $$ \begin{bmatrix} V^{1,1} & V^{1,2} \cr - V^{2,2} & V^{2,2} \end{bmatrix} \begin{bmatrix} V_{1,1} & V_{1,2} \cr - V_{2,2} & V_{2,2} \end{bmatrix} = \begin{bmatrix} 1 & 0 \cr 0 & 1 \end{bmatrix} + V^{2,1} & V^{2,2} \end{bmatrix} \begin{bmatrix} V_{1,1} & V_{1,2} \cr + V_{2,1} & V_{2,2} \end{bmatrix} = \begin{bmatrix} 1 & 0 \cr 0 & 1 \end{bmatrix} $$ that - - $$ V^{2,1} V_{1,1} + V^{2,2} V_{2,1} = 0 $$ @@ -477,7 +594,7 @@ $$ and $$ -V^{1,1}V_{1,2} + V^{1,2} V_{2,2} = 0 +V^{1,1}V_{1,2} + V^{1,2} V_{2,2} = 0. $$ These equations will be very useful soon. @@ -493,14 +610,14 @@ $$ To deactivate $\lambda_1$ we want to set $$ -x_{1,0}^* = 0 +x_{1,0}^* = 0. $$ This can be achieved by setting $$ -x_{2,0} = -( V^{1,2})^{-1} V^{1,1} = V_{2,1} V_{1,1}^{-1} x_{1,0}. +x_{2,0} = -( V^{1,2})^{-1} V^{1,1} x_{1,0} = V_{2,2} V_{1,2}^{-1} x_{1,0}. $$ (eq:deactivate1) To deactivate $\lambda_2$, we want to set @@ -512,58 +629,89 @@ $$ This can be achieved by setting $$ -x_{2,0} = -(V^{2,2})^{-1} V^{2,1} = V_{2,1} V_{1,1}^{-1} x_{1,0} +x_{2,0} = -(V^{2,2})^{-1} V^{2,1} x_{1,0} = V_{2,1} V_{1,1}^{-1} x_{1,0}. $$ (eq:deactivate2) +Let's verify {eq}`eq:deactivate1` and {eq}`eq:deactivate2` below -We shall encounter equations very similar to {eq}`eq:deactivate1` and {eq}`eq:deactivate2` -in this QuantEcon lecture {doc}`money financed government deficits and inflation ` -and in many other places in dynamic economic theory. +To deactivate $\lambda_1$ we use {eq}`eq:deactivate1` -### Implementation +```{code-cell} ipython3 +xd_1 = np.array((x_0[0], + V[1,1]/V[0,1] * x_0[0]), + dtype=np.float64) -Now we implement the algorithm above. +# Compute x_{1,0}^* +np.round(V_inv @ xd_1, 8) +``` -First we write a function that iterates $M$ +We find $x_{1,0}^* = 0$. -```{code-cell} ipython3 -:tags: [] +Now we deactivate $\lambda_2$ using {eq}`eq:deactivate2` -def iterate_M(x_0, M, num_steps): - # Eigendecomposition of M - Λ, V = np.linalg.eig(M) - V_inv = np.linalg.inv(V) - - print(f"eigenvalue:\n{Λ}") - print(f"eigenvector:\n{V}") - - # Initialize the array to store results - x = np.zeros((x_0.shape[0], num_steps)) - - # Perform the iterations - for t in range(num_steps): - x[:, t] = V @ np.diag(Λ**t) @ V_inv @ x_0 - - return x +```{code-cell} ipython3 +xd_2 = np.array((x_0[0], + V[1,0]/V[0,0] * x_0[0]), + dtype=np.float64) -# Define the state transition matrix M -M = np.array([[2, -(1 - σ)], - [1, 0]]) +# Compute x_{2,0}^* +np.round(V_inv @ xd_2, 8) +``` -# Initial condition vector x_0 -x_0 = np.array([1, 0]) +We find $x_{2,0}^* = 0$. -# Perform the iteration -xs = iterate_M(x_0, M, num_steps=100) +```{code-cell} ipython3 +# Simulate with muted λ1 λ2. +num_steps = 10 +xs_λ1 = iterate_M(xd_1, M, num_steps)[0] +xs_λ2 = iterate_M(xd_2, M, num_steps)[0] + +# Compute ratios y_t / y_{t-1} +ratios_λ1 = xs_λ1[1, 1:] / xs_λ1[1, :-1] +ratios_λ2 = xs_λ2[1, 1:] / xs_λ2[1, :-1] ``` -Compare the eigenvector to the roots we obtained above +The following graph shows the ratios $y_t / y_{t-1}$ for the two cases. -```{code-cell} ipython3 -:tags: [] +We find that the ratios converge to $\lambda_2$ in the first case and $\lambda_1$ in the second case. -roots = solve_λs((1, -2, (1 - σ))) -print(f"roots: {np.round(roots, 8)}") +```{code-cell} ipython3 +:tags: [hide-input] + +# Plot the ratios for y_t / y_{t-1} +fig, axs = plt.subplots(1, 2, figsize=(14, 6)) + +# First subplot +axs[0].plot(np.round(ratios_λ1, 6), + label=r'$\frac{y_t}{y_{t-1}}$', linewidth=3) +axs[0].axhline(y=Λ[1], color='red', linestyle='--', + label='$\lambda_2$', alpha=0.5) +axs[0].set_xlabel('t', size=18) +axs[0].set_ylabel(r'$\frac{y_t}{y_{t-1}}$', size=18) +axs[0].set_title(r'$\frac{y_t}{y_{t-1}}$ after Muting $\lambda_1$', + size=13) +axs[0].legend() + +# Second subplot +axs[1].plot(ratios_λ2, label=r'$\frac{y_t}{y_{t-1}}$', + linewidth=3) +axs[1].axhline(y=Λ[0], color='green', linestyle='--', + label='$\lambda_1$', alpha=0.5) +axs[1].set_xlabel('t', size=18) +axs[1].set_ylabel(r'$\frac{y_t}{y_{t-1}}$', size=18) +axs[1].set_title(r'$\frac{y_t}{y_{t-1}}$ after Muting $\lambda_2$', + size=13) +axs[1].legend() + +plt.tight_layout() +plt.show() ``` -Hence we confirmed {eq}`eq:eigen_sqrt`. +## Concluding remarks + +This lecture sets the stage for many other applications of the *invariant subspace* methods. + +All of these exploit very similar equations based on eigen decompositions. + +We shall encounter equations very similar to {eq}`eq:deactivate1` and {eq}`eq:deactivate2` +in {doc}`money_inflation` and in many other places in dynamic economic theory. diff --git a/lectures/inequality.md b/lectures/inequality.md index f6c0ff67..cd6dfcf0 100644 --- a/lectures/inequality.md +++ b/lectures/inequality.md @@ -247,7 +247,7 @@ The following code block imports a subset of the dataset `SCF_plus` for 2016, which is derived from the [Survey of Consumer Finances](https://en.wikipedia.org/wiki/Survey_of_Consumer_Finances) (SCF). ```{code-cell} ipython3 -url = 'https://media.githubusercontent.com/media/QuantEcon/high_dim_data/main/SCF_plus/SCF_plus_mini.csv' +url = 'https://github.com/QuantEcon/high_dim_data/raw/main/SCF_plus/SCF_plus_mini.csv' df = pd.read_csv(url) df_income_wealth = df.dropna() ``` @@ -435,6 +435,8 @@ Let's examine the Gini coefficient in some simulations. The code below computes the Gini coefficient from a sample. +(code:gini-coefficient)= + ```{code-cell} ipython3 def gini_coefficient(y): @@ -481,6 +483,7 @@ You can check this by looking up the expression for the mean of a lognormal distribution. ```{code-cell} ipython3 +%%time k = 5 σ_vals = np.linspace(0.2, 4, k) n = 2_000 @@ -616,51 +619,11 @@ We will use US data from the {ref}`Survey of Consumer Finances - -```{code-cell} ipython3 -ginis = pd.read_csv("_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv", index_col='year') +data_url = 'https://github.com/QuantEcon/lecture-python-intro/raw/main/lectures/_static/lecture_specific/inequality/usa-gini-nwealth-tincome-lincome.csv' +ginis = pd.read_csv(data_url, index_col='year') ginis.head(n=5) ``` @@ -687,10 +650,6 @@ One possibility is that this change is mainly driven by technology. However, we will see below that not all advanced economies experienced similar growth of inequality. - - - - ### Cross-country comparisons of income inequality Earlier in this lecture we used `wbgapi` to get Gini data across many countries @@ -1093,3 +1052,90 @@ plt.show() ```{solution-end} ``` + +```{exercise} +:label: inequality_ex3 + +The {ref}`code to compute the Gini coefficient is listed in the lecture above `. + +This code uses loops to calculate the coefficient based on income or wealth data. + +This function can be re-written using vectorization which will greatly improve the computational efficiency when using `python`. + +Re-write the function `gini_coefficient` using `numpy` and vectorized code. + +You can compare the output of this new function with the one above, and note the speed differences. +``` + +```{solution-start} inequality_ex3 +:class: dropdown +``` + +Let's take a look at some raw data for the US that is stored in `df_income_wealth` + +```{code-cell} ipython3 +df_income_wealth.describe() +``` + +```{code-cell} ipython3 +df_income_wealth.head(n=4) +``` + +We will focus on wealth variable `n_wealth` to compute a Gini coefficient for the year 2016. + +```{code-cell} ipython3 +data = df_income_wealth[df_income_wealth.year == 2016].sample(3000, random_state=1) +``` + +```{code-cell} ipython3 +data.head(n=2) +``` + +We can first compute the Gini coefficient using the function defined in the lecture above. + +```{code-cell} ipython3 +gini_coefficient(data.n_wealth.values) +``` + +Now we can write a vectorized version using `numpy` + +```{code-cell} ipython3 +def gini(y): + n = len(y) + y_1 = np.reshape(y, (n, 1)) + y_2 = np.reshape(y, (1, n)) + g_sum = np.sum(np.abs(y_1 - y_2)) + return g_sum / (2 * n * np.sum(y)) +``` +```{code-cell} ipython3 +gini(data.n_wealth.values) +``` +Let's simulate five populations by drawing from a lognormal distribution as before + +```{code-cell} ipython3 +k = 5 +σ_vals = np.linspace(0.2, 4, k) +n = 2_000 +σ_vals = σ_vals.reshape((k,1)) +μ_vals = -σ_vals**2/2 +y_vals = np.exp(μ_vals + σ_vals*np.random.randn(n)) +``` +We can compute the Gini coefficient for these five populations using the vectorized function, the computation time is shown below: + +```{code-cell} ipython3 +%%time +gini_coefficients =[] +for i in range(k): + gini_coefficients.append(gini(y_vals[i])) +``` +This shows the vectorized function is much faster. +This gives us the Gini coefficients for these five households. + +```{code-cell} ipython3 +gini_coefficients +``` +```{solution-end} +``` + + + diff --git a/lectures/lln_clt.md b/lectures/lln_clt.md index 7e7676ce..291690e0 100644 --- a/lectures/lln_clt.md +++ b/lectures/lln_clt.md @@ -167,6 +167,7 @@ $$ The next theorem is called Kolmogorov's strong law of large numbers. +(iid-theorem)= ````{prf:theorem} If $X_1, \ldots, X_n$ are IID and $\mathbb E |X|$ is finite, then diff --git a/lectures/lp_intro.md b/lectures/lp_intro.md index 4e43965f..27c8093f 100644 --- a/lectures/lp_intro.md +++ b/lectures/lp_intro.md @@ -32,16 +32,14 @@ Linear programs come in pairs: * an associated **dual** problem. -If a primal problem involves **maximization**, the dual problem involves **minimization**. +If a primal problem involves *maximization*, the dual problem involves *minimization*. -If a primal problem involves **minimization**, the dual problem involves **maximization**. +If a primal problem involves *minimization**, the dual problem involves **maximization*. We provide a standard form of a linear program and methods to transform other forms of linear programming problems into a standard form. We tell how to solve a linear programming problem using [SciPy](https://scipy.org/) and [Google OR-Tools](https://developers.google.com/optimization). -We describe the important concept of complementary slackness and how it relates to the dual problem. - Let's start with some standard imports. ```{code-cell} ipython3 @@ -56,7 +54,7 @@ Let's start with some examples of linear programming problem. -## Example 1: Production Problem +## Example 1: production problem This example was created by {cite}`bertsimas_tsitsiklis1997` @@ -78,7 +76,7 @@ Required per unit material and labor inputs and revenues are shown in table b A firm's problem is to construct a production plan that uses its 30 units of materials and 20 units of labor to maximize its revenue. -Let $x_i$ denote the quantity of Product $i$ that the firm produces. +Let $x_i$ denote the quantity of Product $i$ that the firm produces and $z$ denote the total revenue. This problem can be formulated as: @@ -126,19 +124,19 @@ plt.show() The blue region is the feasible set within which all constraints are satisfied. -Parallel orange lines are iso-revenue lines. +Parallel black lines are iso-revenue lines. -The firm's objective is to find the parallel orange lines to the upper boundary of the feasible set. +The firm's objective is to find the parallel black lines to the upper boundary of the feasible set. -The intersection of the feasible set and the highest orange line delineates the optimal set. +The intersection of the feasible set and the highest black line delineates the optimal set. In this example, the optimal set is the point $(2.5, 5)$. -### Computation: Using OR-Tools +### Computation: using OR-Tools -Let's try to solve the same problem using the package *ortools.linear_solver* +Let's try to solve the same problem using the package `ortools.linear_solver`. @@ -149,7 +147,7 @@ The following cell instantiates a solver and creates two variables specifying th solver = pywraplp.Solver.CreateSolver('GLOP') ``` -Let's us create two variables $x_1$ and $x_2$ such that they can only have nonnegative values. +Let's create two variables $x_1$ and $x_2$ such that they can only have nonnegative values. ```{code-cell} ipython3 # Create the two variables and let them take on any non-negative value. @@ -174,7 +172,7 @@ Let's specify the objective function. We use `solver.Maximize` method in the cas solver.Maximize(3 * x1 + 4 * x2) ``` -Once we solve the problem, we can check whether the solver was successful in solving the problem using it's status. If it's successful, then the status will be equal to `pywraplp.Solver.OPTIMAL`. +Once we solve the problem, we can check whether the solver was successful in solving the problem using its status. If it's successful, then the status will be equal to `pywraplp.Solver.OPTIMAL`. ```{code-cell} ipython3 # Solve the system. @@ -182,26 +180,24 @@ status = solver.Solve() if status == pywraplp.Solver.OPTIMAL: print('Objective value =', solver.Objective().Value()) - x1_sol = round(x1.solution_value(), 2) - x2_sol = round(x2.solution_value(), 2) - print(f'(x1, x2): ({x1_sol}, {x2_sol})') + print(f'(x1, x2): ({x1.solution_value():.2}, {x2.solution_value():.2})') else: print('The problem does not have an optimal solution.') ``` -## Example 2: Investment Problem +## Example 2: investment problem We now consider a problem posed and solved by {cite}`hu_guo2018`. -A mutual fund has $ \$ 100,000$ to be invested over a three year horizon. +A mutual fund has $ \$ 100,000$ to be invested over a three-year horizon. Three investment options are available: -1. **Annuity:** the fund can pay a same amount of new capital at the beginning of each of three years and receive a payoff of 130\% of **total capital** invested at the end of the third year. Once the mutual fund decides to invest in this annuity, it has to keep investing in all subsequent years in the three year horizon. +1. Annuity: the fund can pay a same amount of new capital at the beginning of each of three years and receive a payoff of 130\% of total capital invested at the end of the third year. Once the mutual fund decides to invest in this annuity, it has to keep investing in all subsequent years in the three year horizon. -2. **Bank account:** the fund can deposit any amount into a bank at the beginning of each year and receive its capital plus 6\% interest at the end of that year. In addition, the mutual fund is permitted to borrow no more than $20,000 at the beginning of each year and is asked to pay back the amount borrowed plus 6\% interest at the end of the year. The mutual fund can choose whether to deposit or borrow at the beginning of each year. +2. Bank account: the fund can deposit any amount into a bank at the beginning of each year and receive its capital plus 6\% interest at the end of that year. In addition, the mutual fund is permitted to borrow no more than $20,000 at the beginning of each year and is asked to pay back the amount borrowed plus 6\% interest at the end of the year. The mutual fund can choose whether to deposit or borrow at the beginning of each year. -3. **Corporate bond:** At the beginning of the second year, a corporate bond becomes available. +3. Corporate bond: At the beginning of the second year, a corporate bond becomes available. The fund can buy an amount that is no more than $ \$ $50,000 of this bond at the beginning of the second year and at the end of the third year receive a payout of 130\% of the amount invested in the bond. @@ -271,9 +267,9 @@ $$ -### Computation: Using OR-Tools +### Computation: using OR-Tools -Let's try to solve the above problem using the package *ortools.linear_solver*. +Let's try to solve the above problem using the package `ortools.linear_solver`. The following cell instantiates a solver and creates two variables specifying the range of values that they can have. @@ -282,7 +278,7 @@ The following cell instantiates a solver and creates two variables specifying th solver = pywraplp.Solver.CreateSolver('GLOP') ``` -Let's us create five variables $x_1, x_2, x_3, x_4,$ and $x_5$ such that they can only have the values defined in the above constraints. +Let's create five variables $x_1, x_2, x_3, x_4,$ and $x_5$ such that they can only have the values defined in the above constraints. ```{code-cell} ipython3 # Create the variables using the ranges available from constraints @@ -380,7 +376,7 @@ c = \begin{bmatrix} c_1 \\ c_2 \\ \vdots \\ c_n \\ \end{bmatrix}, \quad x = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \\ \end{bmatrix}. \quad $$ -The standard form LP problem can be expressed concisely as: +The standard form linear programming problem can be expressed concisely as: $$ \begin{aligned} @@ -400,15 +396,15 @@ It is useful to know how to transform a problem that initially is not stated in By deploying the following steps, any linear programming problem can be transformed into an equivalent standard form linear programming problem. -1. **Objective Function:** If a problem is originally a constrained **maximization** problem, we can construct a new objective function that is the additive inverse of the original objective function. The transformed problem is then a **minimization** problem. +1. Objective function: If a problem is originally a constrained *maximization* problem, we can construct a new objective function that is the additive inverse of the original objective function. The transformed problem is then a *minimization* problem. -2. **Decision Variables:** Given a variable $x_j$ satisfying $x_j \le 0$, we can introduce a new variable $x_j' = - x_j$ and substitute it into original problem. Given a free variable $x_i$ with no restriction on its sign, we can introduce two new variables $x_j^+$ and $x_j^-$ satisfying $x_j^+, x_j^- \ge 0$ and replace $x_j$ by $x_j^+ - x_j^-$. +2. Decision variables: Given a variable $x_j$ satisfying $x_j \le 0$, we can introduce a new variable $x_j' = - x_j$ and substitute it into original problem. Given a free variable $x_i$ with no restriction on its sign, we can introduce two new variables $x_j^+$ and $x_j^-$ satisfying $x_j^+, x_j^- \ge 0$ and replace $x_j$ by $x_j^+ - x_j^-$. -3. **Inequality constraints:** Given an inequality constraint $\sum_{j=1}^n a_{ij}x_j \le 0$, we can introduce a new variable $s_i$, called a **slack variable** that satisfies $s_i \ge 0$ and replace the original constraint by $\sum_{j=1}^n a_{ij}x_j + s_i = 0$. +3. Inequality constraints: Given an inequality constraint $\sum_{j=1}^n a_{ij}x_j \le 0$, we can introduce a new variable $s_i$, called a **slack variable** that satisfies $s_i \ge 0$ and replace the original constraint by $\sum_{j=1}^n a_{ij}x_j + s_i = 0$. Let's apply the above steps to the two examples described above. -### Example 1: Production Problem +### Example 1: production problem The original problem is: @@ -434,9 +430,9 @@ $$ -### Computation: Using SciPy +### Computation: using SciPy -The package *scipy.optimize* provides a function ***linprog*** to solve linear programming problems with a form below: +The package `scipy.optimize` provides a function `linprog` to solve linear programming problems with a form below: $$ \begin{aligned} @@ -447,8 +443,10 @@ $$ \end{aligned} $$ +$A_{eq}, b_{eq}$ denote the equality constraint matrix and vector, and $A_{ub}, b_{ub}$ denote the inequality constraint matrix and vector. + ```{note} -By default $l = 0$ and $u = \text{None}$ unless explicitly specified with the argument 'bounds'. +By default $l = 0$ and $u = \text{None}$ unless explicitly specified with the argument `bounds`. ``` Let's now try to solve the Problem 1 using SciPy. @@ -480,7 +478,7 @@ else: The optimal plan tells the factory to produce $2.5$ units of Product 1 and $5$ units of Product 2; that generates a maximizing value of revenue of $27.5$. -We are using the *linprog* function as a **black box**. +We are using the `linprog` function as a *black box*. Inside it, Python first transforms the problem into standard form. @@ -491,12 +489,12 @@ Here the vector of slack variables is a two-dimensional NumPy array that equals See the [official documentation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linprog.html#scipy.optimize.linprog) for more details. ```{note} -This problem is to maximize the objective, so that we need to put a minus sign in front of parameter vector c. +This problem is to maximize the objective, so that we need to put a minus sign in front of parameter vector $c$. ``` -### Example 2: Investment Problem +### Example 2: investment problem The original problem is: @@ -702,7 +700,7 @@ $$ # Instantiate a GLOP(Google Linear Optimization Package) solver solver = pywraplp.Solver.CreateSolver('GLOP') ``` -Let's us create two variables $x_1$ and $x_2$ such that they can only have nonnegative values. +Let's create two variables $x_1$ and $x_2$ such that they can only have nonnegative values. ```{code-cell} ipython3 # Create the two variables and let them take on any non-negative value. diff --git a/lectures/markov_chains_I.md b/lectures/markov_chains_I.md index c50d472e..631dd70f 100644 --- a/lectures/markov_chains_I.md +++ b/lectures/markov_chains_I.md @@ -61,6 +61,8 @@ import matplotlib as mpl from mpl_toolkits.mplot3d import Axes3D from matplotlib.animation import FuncAnimation from IPython.display import HTML +from matplotlib.patches import Polygon +from mpl_toolkits.mplot3d.art3d import Poly3DCollection ``` ## Definitions and examples @@ -743,6 +745,11 @@ This is, in some sense, a steady state probability of unemployment. Not surprisingly it tends to zero as $\beta \to 0$, and to one as $\alpha \to 0$. + + + + + ### Calculating stationary distributions A stable algorithm for computing stationary distributions is implemented in [QuantEcon.py](http://quantecon.org/quantecon-py). @@ -757,6 +764,11 @@ mc = qe.MarkovChain(P) mc.stationary_distributions # Show all stationary distributions ``` + + + + + ### Asymptotic stationarity Consider an everywhere positive stochastic matrix with unique stationary distribution $\psi^*$. @@ -767,17 +779,24 @@ For example, we have the following result (strict_stationary)= ```{prf:theorem} +:label: mc_gs_thm + If there exists an integer $m$ such that all entries of $P^m$ are -strictly positive, with unique stationary distribution $\psi^*$, then +strictly positive, then $$ \psi_0 P^t \to \psi^* \quad \text{ as } t \to \infty $$ + +where $\psi^*$ is the unique stationary distribution. ``` +This situation is often referred to as **asymptotic stationarity** or **global stability**. + +A proof of the theorem can be found in Chapter 4 of {cite}`sargent2023economic`, as well as many other sources. + -See, for example, {cite}`sargent2023economic` Chapter 4. @@ -793,7 +812,7 @@ P = np.array([[0.971, 0.029, 0.000], P @ P ``` -Let's pick an initial distribution $\psi_0$ and trace out the sequence of distributions $\psi_0 P^t$ for $t = 0, 1, 2, \ldots$ +Let's pick an initial distribution $\psi_1, \psi_2, \psi_3$ and trace out the sequence of distributions $\psi_i P^t$ for $t = 0, 1, 2, \ldots$, for $i=1, 2, 3$. First, we write a function to iterate the sequence of distributions for `ts_length` period @@ -810,26 +829,46 @@ def iterate_ψ(ψ_0, P, ts_length): Now we plot the sequence ```{code-cell} ipython3 -ψ_0 = (0.0, 0.2, 0.8) # Initial condition +:tags: [hide-input] + +ψ_1 = (0.0, 0.0, 1.0) +ψ_2 = (1.0, 0.0, 0.0) +ψ_3 = (0.0, 1.0, 0.0) # Three initial conditions +colors = ['blue','red', 'green'] # Different colors for each initial point + +# Define the vertices of the unit simplex +v = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]]) + +# Define the faces of the unit simplex +faces = [ + [v[0], v[1], v[2]], + [v[0], v[1], v[3]], + [v[0], v[2], v[3]], + [v[1], v[2], v[3]] +] fig = plt.figure() ax = fig.add_subplot(projection='3d') -def update(n): - ψ_t = iterate_ψ(ψ_0, P, n+1) - +def update(n): ax.clear() ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.set_zlim([0, 1]) - ax.view_init(30, 210) + ax.view_init(45, 45) - for i, point in enumerate(ψ_t): - ax.scatter(point[0], point[1], point[2], color='r', s=60, alpha=(i+1)/len(ψ_t)) + simplex = Poly3DCollection(faces, alpha=0.03) + ax.add_collection3d(simplex) + for idx, ψ_0 in enumerate([ψ_1, ψ_2, ψ_3]): + ψ_t = iterate_ψ(ψ_0, P, n+1) + + for i, point in enumerate(ψ_t): + ax.scatter(point[0], point[1], point[2], color=colors[idx], s=60, alpha=(i+1)/len(ψ_t)) + mc = qe.MarkovChain(P) ψ_star = mc.stationary_distributions[0] - ax.scatter(ψ_star[0], ψ_star[1], ψ_star[2], c='k', s=60) + ax.scatter(ψ_star[0], ψ_star[1], ψ_star[2], c='yellow', s=60) return fig, @@ -841,110 +880,105 @@ HTML(anim.to_jshtml()) Here * $P$ is the stochastic matrix for recession and growth {ref}`considered above `. -* The highest red dot is an arbitrarily chosen initial marginal probability distribution $\psi_0$, represented as a vector in $\mathbb R^3$. -* The other red dots are the marginal distributions $\psi_0 P^t$ for $t = 1, 2, \ldots$. -* The black dot is $\psi^*$. +* The red, blue and green dots are initial marginal probability distributions $\psi_1, \psi_2, \psi_3$, each of which is represented as a vector in $\mathbb R^3$. +* The transparent dots are the marginal distributions $\psi_i P^t$ for $t = 1, 2, \ldots$, for $i=1,2,3.$. +* The yellow dot is $\psi^*$. You might like to try experimenting with different initial conditions. -#### An alternative illustration - -We can show this in a slightly different way by focusing on the probability that $\psi_t$ puts on each state. -First, we write a function to draw initial distributions $\psi_0$ of size `num_distributions` - -```{code-cell} ipython3 -def generate_initial_values(num_distributions): - n = len(P) - - draws = np.random.randint(1, 10_000_000, size=(num_distributions,n)) - ψ_0s = draws/draws.sum(axis=1)[:, None] - return ψ_0s -``` +#### Example: failure of convergence -We then write a function to plot the dynamics of $(\psi_0 P^t)(i)$ as $t$ gets large, for each state $i$ with different initial distributions -```{code-cell} ipython3 -def plot_distribution(P, ts_length, num_distributions): +Consider the periodic chain with stochastic matrix - # Get parameters of transition matrix - n = len(P) - mc = qe.MarkovChain(P) - ψ_star = mc.stationary_distributions[0] +$$ +P = +\begin{bmatrix} + 0 & 1 \\ + 1 & 0 \\ +\end{bmatrix} +$$ - ## Draw the plot - fig, axes = plt.subplots(nrows=1, ncols=n, figsize=[11, 5]) - plt.subplots_adjust(wspace=0.35) +This matrix does not satisfy the conditions of +{ref}`strict_stationary` because, as you can readily check, - ψ_0s = generate_initial_values(num_distributions) +* $P^m = P$ when $m$ is odd and +* $P^m = I$, the identity matrix, when $m$ is even. - # Get the path for each starting value - for ψ_0 in ψ_0s: - ψ_t = iterate_ψ(ψ_0, P, ts_length) +Hence there is no $m$ such that all elements of $P^m$ are strictly positive. - # Obtain and plot distributions at each state - for i in range(n): - axes[i].plot(range(0, ts_length), ψ_t[:,i], alpha=0.3) +Moreover, we can see that global stability does not hold. - # Add labels - for i in range(n): - axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*({i})$') - axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi_t({i})$') - axes[i].legend() +For instance, if we start at $\psi_0 = (1,0)$, then $\psi_m = \psi_0 P^m$ is $(1, 0)$ when $m$ is even and $(0,1)$ when $m$ is odd. - plt.show() -``` +We can see similar phenomena in higher dimensions. -The following figure shows +The next figure illustrates this for a periodic Markov chain with three states. ```{code-cell} ipython3 -# Define the number of iterations -# and initial distributions -ts_length = 50 -num_distributions = 25 - -P = np.array([[0.971, 0.029, 0.000], - [0.145, 0.778, 0.077], - [0.000, 0.508, 0.492]]) - -plot_distribution(P, ts_length, num_distributions) -``` - -The convergence to $\psi^*$ holds for different initial distributions. +:tags: [hide-input] +ψ_1 = (0.0, 0.0, 1.0) +ψ_2 = (0.5, 0.5, 0.0) +ψ_3 = (0.25, 0.25, 0.5) +ψ_4 = (1/3, 1/3, 1/3) +P = np.array([[0.0, 1.0, 0.0], + [0.0, 0.0, 1.0], + [1.0, 0.0, 0.0]]) -#### Example: failure of convergence +fig = plt.figure() +ax = fig.add_subplot(projection='3d') +colors = ['red','yellow', 'green', 'blue'] # Different colors for each initial point +# Define the vertices of the unit simplex +v = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]]) -In the case of a periodic chain, with +# Define the faces of the unit simplex +faces = [ + [v[0], v[1], v[2]], + [v[0], v[1], v[3]], + [v[0], v[2], v[3]], + [v[1], v[2], v[3]] +] -$$ -P = -\begin{bmatrix} - 0 & 1 \\ - 1 & 0 \\ -\end{bmatrix} -$$ +def update(n): + ax.clear() + ax.set_xlim([0, 1]) + ax.set_ylim([0, 1]) + ax.set_zlim([0, 1]) + ax.view_init(45, 45) + + # Plot the 3D unit simplex as planes + simplex = Poly3DCollection(faces,alpha=0.05) + ax.add_collection3d(simplex) + + for idx, ψ_0 in enumerate([ψ_1, ψ_2, ψ_3, ψ_4]): + ψ_t = iterate_ψ(ψ_0, P, n+1) + + point = ψ_t[-1] + ax.scatter(point[0], point[1], point[2], color=colors[idx], s=60) + points = np.array(ψ_t) + ax.plot(points[:, 0], points[:, 1], points[:, 2], color=colors[idx],linewidth=0.75) + + return fig, -we find the distribution oscillates +anim = FuncAnimation(fig, update, frames=range(20), blit=False, repeat=False) +plt.close() +HTML(anim.to_jshtml()) +``` +This animation demonstrates the behavior of an irreducible and periodic stochastic matrix. -```{code-cell} ipython3 -P = np.array([[0, 1], - [1, 0]]) +The red, yellow, and green dots represent different initial probability distributions. -ts_length = 20 -num_distributions = 30 +The blue dot represents the unique stationary distribution. -plot_distribution(P, ts_length, num_distributions) -``` +Unlike Hamilton’s Markov chain, these initial distributions do not converge to the unique stationary distribution. -Indeed, this $P$ fails our asymptotic stationarity condition, since, as you can -verify, $P^t$ is not everywhere positive for any $t$. +Instead, they cycle periodically around the probability simplex, illustrating that asymptotic stability fails. (finite_mc_expec)= @@ -1105,42 +1139,6 @@ mc = qe.MarkovChain(P) ψ_star ``` -Solution 3: - -We find the distribution $\psi$ converges to the stationary distribution more quickly compared to the {ref}`hamilton's chain `. - -```{code-cell} ipython3 -ts_length = 10 -num_distributions = 25 -plot_distribution(P, ts_length, num_distributions) -``` - -In fact, the rate of convergence is governed by {ref}`eigenvalues` {cite}`sargent2023economic`. - -```{code-cell} ipython3 -P_eigenvals = np.linalg.eigvals(P) -P_eigenvals -``` - -```{code-cell} ipython3 -P_hamilton = np.array([[0.971, 0.029, 0.000], - [0.145, 0.778, 0.077], - [0.000, 0.508, 0.492]]) - -hamilton_eigenvals = np.linalg.eigvals(P_hamilton) -hamilton_eigenvals -``` - -More specifically, it is governed by the spectral gap, the difference between the largest and the second largest eigenvalue. - -```{code-cell} ipython3 -sp_gap_P = P_eigenvals[0] - np.diff(P_eigenvals)[0] -sp_gap_hamilton = hamilton_eigenvals[0] - np.diff(hamilton_eigenvals)[0] - -sp_gap_P > sp_gap_hamilton -``` - -We will come back to this when we discuss {ref}`spectral theory`. ```{solution-end} ``` diff --git a/lectures/money_inflation.md b/lectures/money_inflation.md index 2b3d1721..17ec7e0f 100644 --- a/lectures/money_inflation.md +++ b/lectures/money_inflation.md @@ -170,7 +170,7 @@ We shall describe two distinct but closely related ways of computing a pair $\ But first it is instructive to describe a special type of equilibrium known as a **steady state**. -In a steady state equilibrium, a subset of key variables remain constant or **invariant** over time, while remaining variables can be expressed as functions of those constant variables. +In a steady-state equilibrium, a subset of key variables remain constant or **invariant** over time, while remaining variables can be expressed as functions of those constant variables. Finding such state variables is something of an art. @@ -180,7 +180,7 @@ This is true in the present model. ### Steady states -In a **steady state** equilibrium of the model we are studying, +In a steady-state equilibrium of the model we are studying, $$ \begin{aligned} @@ -229,7 +229,7 @@ $$ R_t \in [\underline R, \overline R], \quad t \geq 0. $$ -Maximizing steady state seigniorage {eq}`eq:SSsigng` with respect to $\bar R$, we find that the maximizing rate of return on currency is +Maximizing steady-state seigniorage {eq}`eq:SSsigng` with respect to $\bar R$, we find that the maximizing rate of return on currency is $$ \bar R_{\rm max} = \sqrt{\frac{\gamma_2}{\gamma_1}} @@ -263,7 +263,7 @@ plt.rcParams['figure.dpi'] = 300 from collections import namedtuple ``` -Let's set some parameter values and compute possible steady state rates of return on currency $\bar R$, the seigniorage maximizing rate of return on currency, and an object that we'll discuss later, namely, an initial price level $p_0$ associated with the maximum steady state rate of return on currency. +Let's set some parameter values and compute possible steady-state rates of return on currency $\bar R$, the seigniorage maximizing rate of return on currency, and an object that we'll discuss later, namely, an initial price level $p_0$ associated with the maximum steady-state rate of return on currency. First, we create a `namedtuple` to store parameters so that we can reuse this `namedtuple` in our functions throughout this lecture @@ -337,7 +337,7 @@ plt.show() Let's print the two steady-state rates of return $\bar R$ and the associated seigniorage revenues that the government collects. -(By construction, both steady state rates of return should raise the same amounts real revenue.) +(By construction, both steady-state rates of return should raise the same amounts real revenue.) We hope that the following code will confirm this. @@ -349,7 +349,7 @@ g2 = seign(msm.R_l, msm) print(f'R_l, g_l = {msm.R_l:.4f}, {g2:.4f}') ``` -Now let's compute the maximum steady state amount of seigniorage that could be gathered by printing money and the state state rate of return on money that attains it. +Now let's compute the maximum steady-state amount of seigniorage that could be gathered by printing money and the state state rate of return on money that attains it. ## Two computation strategies @@ -434,7 +434,7 @@ As we shall see soon, selecting an initial $p_0$ in method 2 is intimately tied %b_0 = \gamma_1 - \gamma_0 R_0^{-1} %$$ -Remember that there exist two steady state equilibrium values $ R_\ell < R_u$ of the rate of return on currency $R_t$. +Remember that there exist two steady-state equilibrium values $ R_\ell < R_u$ of the rate of return on currency $R_t$. We proceed as follows. @@ -460,7 +460,7 @@ condition $R_0$. The quantity $1 - R_t$ can be interpreted as an **inflation tax rate** that the government imposes on holders of its currency. -We shall soon see that the existence of two steady state rates of return on currency +We shall soon see that the existence of two steady-state rates of return on currency that serve to finance the government deficit of $g$ indicates the presence of a **Laffer curve** in the inflation tax rate. ```{note} @@ -746,7 +746,7 @@ y^*_{t+1} = \Lambda^t y^*_t . $$ (eq:stardynamics) This equation represents the dynamics of our system in a way that lets us isolate the -force that causes gross inflation to converge to the inverse of the lower steady state rate +force that causes gross inflation to converge to the inverse of the lower steady-state rate of inflation $R_\ell$ that we discovered earlier. Staring at equation {eq}`eq:stardynamics` indicates that unless diff --git a/lectures/monte_carlo.md b/lectures/monte_carlo.md index eecbd011..9f66c229 100644 --- a/lectures/monte_carlo.md +++ b/lectures/monte_carlo.md @@ -12,7 +12,7 @@ kernelspec: --- - +(monte-carlo)= # Monte Carlo and Option Pricing ## Overview @@ -49,7 +49,6 @@ from numpy.random import randn ``` - ## An introduction to Monte Carlo In this section we describe how Monte Carlo can be used to compute diff --git a/lectures/olg.md b/lectures/olg.md index 3fa56e38..6530e1be 100644 --- a/lectures/olg.md +++ b/lectures/olg.md @@ -155,7 +155,7 @@ The first-order condition for a maximum can be obtained by plugging $c_{t+1}$ into the objective function, taking the derivative with respect to $c_t$, and setting it to zero. -This leads to the **Euler equation** of the OLG model, which is +This leads to the **Euler equation** of the OLG model, which describes the optimal intertemporal consumption dynamics: ```{math} :label: euler_1_olg @@ -303,24 +303,6 @@ The next figure plots the supply of capital, as in [](saving_log_2_olg), as well (For the special case of log utility, supply does not depend on the interest rate, so we have a constant function.) -```{code-cell} ipython3 -R_vals = np.linspace(0.3, 1) -α, β = 0.5, 0.9 -w = 2.0 - -fig, ax = plt.subplots() - -ax.plot(R_vals, capital_demand(R_vals, α), - label="aggregate demand") -ax.plot(R_vals, capital_supply(R_vals, β, w), - label="aggregate supply") - -ax.set_xlabel("$R_{t+1}$") -ax.set_ylabel("$k_{t+1}$") -ax.legend() -plt.show() -``` - ## Equilibrium In this section we derive equilibrium conditions and investigate an example. @@ -409,15 +391,7 @@ ax.plot(R_vals, capital_supply(R_vals, β, w), R_e = equilibrium_R_log_utility(α, β, w) k_e = (β / (1 + β)) * w -ax.plot(R_e, k_e, 'go', ms=6, alpha=0.6) - -ax.annotate(r'equilibrium', - xy=(R_e, k_e), - xycoords='data', - xytext=(0, 60), - textcoords='offset points', - fontsize=12, - arrowprops=dict(arrowstyle="->")) +ax.plot(R_e, k_e, 'o',label='equilibrium') ax.set_xlabel("$R_{t+1}$") ax.set_ylabel("$k_{t+1}$") @@ -565,7 +539,7 @@ The interest rate reflects the marginal product of capital, which is high when c Previously, in our examples, we looked at the case of log utility. -Log utility is a rather special case. +Log utility is a rather special case of CRRA utility with $\gamma \to 1$. In this section, we are going to assume that $u(c) = \frac{ c^{1- \gamma}-1}{1-\gamma}$, where $\gamma >0, \gamma\neq 1$. diff --git a/lectures/time_series_with_matrices.md b/lectures/time_series_with_matrices.md index c809de9c..1e88336d 100644 --- a/lectures/time_series_with_matrices.md +++ b/lectures/time_series_with_matrices.md @@ -3,14 +3,16 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.2 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- (time_series_with_matrices)= -```{raw} html +```{raw} jupyter
QuantEcon @@ -26,13 +28,12 @@ This lecture uses matrices to solve some linear difference equations. As a running example, we’ll study a **second-order linear difference equation** that was the key technical tool in Paul Samuelson’s 1939 -article {cite}`Samuelson1939` that introduced the **multiplier-accelerator** model. +article {cite}`Samuelson1939` that introduced the *multiplier-accelerator model*. This model became the workhorse that powered early econometric versions of Keynesian macroeconomic models in the United States. -You can read about the details of that model in [this](https://python.quantecon.org/samuelson.html) -QuantEcon lecture. +You can read about the details of that model in {doc}`intermediate:samuelson`. (That lecture also describes some technicalities about second-order linear difference equations.) @@ -44,7 +45,7 @@ a "forward-looking" linear difference equation. We will use the following imports: -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np import matplotlib.pyplot as plt from matplotlib import cm @@ -64,20 +65,20 @@ y_{t} = \alpha_{0} + \alpha_{1} y_{t-1} + \alpha_{2} y_{t-2} ``` where we assume that $y_0$ and $y_{-1}$ are given numbers -that we take as **initial conditions**. +that we take as *initial conditions*. In Samuelson's model, $y_t$ stood for **national income** or perhaps a different measure of aggregate activity called **gross domestic product** (GDP) at time $t$. -Equation {eq}`tswm_1` is called a **second-order linear difference equation**. +Equation {eq}`tswm_1` is called a *second-order linear difference equation*. It is called second order because it depends on two lags. But actually, it is a collection of $T$ simultaneous linear equations in the $T$ variables $y_1, y_2, \ldots, y_T$. ```{note} To be able to solve a second-order linear difference -equation, we require two **boundary conditions** that can take the form -either of two **initial conditions** or two **terminal conditions** or +equation, we require two *boundary conditions* that can take the form +either of two *initial conditions*, two *terminal conditions* or possibly one of each. ``` @@ -131,42 +132,42 @@ The vector $y$ is a complete time path $\{y_t\}_{t=1}^T$. Let’s put Python to work on an example that captures the flavor of Samuelson’s multiplier-accelerator model. -We'll set parameters equal to the same values we used in [this QuantEcon lecture](https://python.quantecon.org/samuelson.html). +We'll set parameters equal to the same values we used in {doc}`intermediate:samuelson`. -```{code-cell} python3 +```{code-cell} ipython3 T = 80 # parameters -𝛼0 = 10.0 -𝛼1 = 1.53 -𝛼2 = -.9 +α_0 = 10.0 +α_1 = 1.53 +α_2 = -.9 -y_1 = 28. # y_{-1} -y0 = 24. +y_neg1 = 28. # y_{-1} +y_0 = 24. ``` Now we construct $A$ and $b$. -```{code-cell} python3 +```{code-cell} ipython3 A = np.identity(T) # The T x T identity matrix for i in range(T): if i-1 >= 0: - A[i, i-1] = -𝛼1 + A[i, i-1] = -α_1 if i-2 >= 0: - A[i, i-2] = -𝛼2 + A[i, i-2] = -α_2 -b = np.full(T, 𝛼0) -b[0] = 𝛼0 + 𝛼1 * y0 + 𝛼2 * y_1 -b[1] = 𝛼0 + 𝛼2 * y0 +b = np.full(T, α_0) +b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1 +b[1] = α_0 + α_2 * y_0 ``` Let’s look at the matrix $A$ and the vector $b$ for our example. -```{code-cell} python3 +```{code-cell} ipython3 A, b ``` @@ -175,25 +176,24 @@ Now let’s solve for the path of $y$. If $y_t$ is GNP at time $t$, then we have a version of Samuelson’s model of the dynamics for GNP. -To solve $y = A^{-1} b$ we can either invert $A$ directly, as in +To solve $y = A^{-1} b$ we can either invert $A$ directly, as in -```{code-cell} python3 +```{code-cell} ipython3 A_inv = np.linalg.inv(A) y = A_inv @ b ``` -or we can use `np.linalg.solve`: +or we can use `np.linalg.solve`: - -```{code-cell} python3 +```{code-cell} ipython3 y_second_method = np.linalg.solve(A, b) ``` Here make sure the two methods give the same result, at least up to floating point precision: -```{code-cell} python3 +```{code-cell} ipython3 np.allclose(y, y_second_method) ``` @@ -207,7 +207,7 @@ it directly. Now we can plot. -```{code-cell} python3 +```{code-cell} ipython3 plt.plot(np.arange(T)+1, y) plt.xlabel('t') plt.ylabel('y') @@ -215,7 +215,7 @@ plt.ylabel('y') plt.show() ``` -The **steady state** value $y^*$ of $y_t$ is obtained by setting $y_t = y_{t-1} = +The {ref}`*steady state*` value $y^*$ of $y_t$ is obtained by setting $y_t = y_{t-1} = y_{t-2} = y^*$ in {eq}`tswm_1`, which yields $$ @@ -225,21 +225,21 @@ $$ If we set the initial values to $y_{0} = y_{-1} = y^*$, then $y_{t}$ will be constant: -```{code-cell} python3 -y_star = 𝛼0 / (1 - 𝛼1 - 𝛼2) -y_1_steady = y_star # y_{-1} -y0_steady = y_star +```{code-cell} ipython3 +y_star = α_0 / (1 - α_1 - α_2) +y_neg1_steady = y_star # y_{-1} +y_0_steady = y_star -b_steady = np.full(T, 𝛼0) -b_steady[0] = 𝛼0 + 𝛼1 * y0_steady + 𝛼2 * y_1_steady -b_steady[1] = 𝛼0 + 𝛼2 * y0_steady +b_steady = np.full(T, α_0) +b_steady[0] = α_0 + α_1 * y_0_steady + α_2 * y_neg1_steady +b_steady[1] = α_0 + α_2 * y_0_steady ``` -```{code-cell} python3 +```{code-cell} ipython3 y_steady = A_inv @ b_steady ``` -```{code-cell} python3 +```{code-cell} ipython3 plt.plot(np.arange(T)+1, y_steady) plt.xlabel('t') plt.ylabel('y') @@ -250,7 +250,7 @@ plt.show() ## Adding a random term To generate some excitement, we'll follow in the spirit of the great economists -Eugen Slutsky and Ragnar Frisch and replace our original second-order difference +[Eugen Slutsky](https://en.wikipedia.org/wiki/Eugen_Slutsky) and [Ragnar Frisch](https://en.wikipedia.org/wiki/Ragnar_Frisch) and replace our original second-order difference equation with the following **second-order stochastic linear difference equation**: @@ -260,8 +260,8 @@ equation**: y_{t} = \alpha_{0} + \alpha_{1} y_{t-1} + \alpha_{2} y_{t-2} + u_t ``` -where $u_{t} \sim N\left(0, \sigma_{u}^{2}\right)$ and is IID, -meaning **independent** and **identically** distributed. +where $u_{t} \sim N\left(0, \sigma_{u}^{2}\right)$ and is {ref}`IID `, +meaning independent and identically distributed. We’ll stack these $T$ equations into a system cast in terms of matrix algebra. @@ -292,16 +292,13 @@ $$ (eq:eqma) Let’s try it out in Python. -```{code-cell} python3 -𝜎u = 2. -``` - -```{code-cell} python3 -u = np.random.normal(0, 𝜎u, size=T) +```{code-cell} ipython3 +σ_u = 2. +u = np.random.normal(0, σ_u, size=T) y = A_inv @ (b + u) ``` -```{code-cell} python3 +```{code-cell} ipython3 plt.plot(np.arange(T)+1, y) plt.xlabel('t') plt.ylabel('y') @@ -314,12 +311,12 @@ number of advanced countries in recent decades. We can simulate $N$ paths. -```{code-cell} python3 +```{code-cell} ipython3 N = 100 for i in range(N): col = cm.viridis(np.random.rand()) # Choose a random color from viridis - u = np.random.normal(0, 𝜎u, size=T) + u = np.random.normal(0, σ_u, size=T) y = A_inv @ (b + u) plt.plot(np.arange(T)+1, y, lw=0.5, color=col) @@ -332,12 +329,12 @@ plt.show() Also consider the case when $y_{0}$ and $y_{-1}$ are at steady state. -```{code-cell} python3 +```{code-cell} ipython3 N = 100 for i in range(N): col = cm.viridis(np.random.rand()) # Choose a random color from viridis - u = np.random.normal(0, 𝜎u, size=T) + u = np.random.normal(0, σ_u, size=T) y_steady = A_inv @ (b_steady + u) plt.plot(np.arange(T)+1, y_steady, lw=0.5, color=col) @@ -347,8 +344,6 @@ plt.ylabel('y') plt.show() ``` - - ## Computing population moments @@ -389,44 +384,42 @@ $$ Let's write a Python class that computes the mean vector $\mu_y$ and covariance matrix $\Sigma_y$. - - ```{code-cell} ipython3 class population_moments: """ - Compute population moments mu_y, Sigma_y. + Compute population moments μ_y, Σ_y. --------- Parameters: - alpha0, alpha1, alpha2, T, y_1, y0 + α_0, α_1, α_2, T, y_neg1, y_0 """ - def __init__(self, alpha0, alpha1, alpha2, T, y_1, y0, sigma_u): + def __init__(self, α_0, α_1, α_2, T, y_neg1, y_0, σ_u): # compute A A = np.identity(T) for i in range(T): if i-1 >= 0: - A[i, i-1] = -alpha1 + A[i, i-1] = -α_1 if i-2 >= 0: - A[i, i-2] = -alpha2 + A[i, i-2] = -α_2 # compute b - b = np.full(T, alpha0) - b[0] = alpha0 + alpha1 * y0 + alpha2 * y_1 - b[1] = alpha0 + alpha2 * y0 + b = np.full(T, α_0) + b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1 + b[1] = α_0 + α_2 * y_0 # compute A inverse A_inv = np.linalg.inv(A) - self.A, self.b, self.A_inv, self.sigma_u, self.T = A, b, A_inv, sigma_u, T + self.A, self.b, self.A_inv, self.σ_u, self.T = A, b, A_inv, σ_u, T def sample_y(self, n): """ Give a sample of size n of y. """ - A_inv, sigma_u, b, T = self.A_inv, self.sigma_u, self.b, self.T - us = np.random.normal(0, sigma_u, size=[n, T]) + A_inv, σ_u, b, T = self.A_inv, self.σ_u, self.b, self.T + us = np.random.normal(0, σ_u, size=[n, T]) ys = np.vstack([A_inv @ (b + u) for u in us]) return ys @@ -435,20 +428,20 @@ class population_moments: """ Compute the population moments of y. """ - A_inv, sigma_u, b = self.A_inv, self.sigma_u, self.b + A_inv, σ_u, b = self.A_inv, self.σ_u, self.b - # compute mu_y - self.mu_y = A_inv @ b - self.Sigma_y = sigma_u**2 * (A_inv @ A_inv.T) + # compute μ_y + self.μ_y = A_inv @ b + self.Σ_y = σ_u**2 * (A_inv @ A_inv.T) + + return self.μ_y, self.Σ_y - return self.mu_y, self.Sigma_y - -my_process = population_moments( - alpha0=10.0, alpha1=1.53, alpha2=-.9, T=80, y_1=28., y0=24., sigma_u=1) +series_process = population_moments( + α_0=10.0, α_1=1.53, α_2=-.9, T=80, y_neg1=28., y_0=24., σ_u=1) -mu_y, Sigma_y = my_process.get_moments() -A_inv = my_process.A_inv +μ_y, Σ_y = series_process.get_moments() +A_inv = series_process.A_inv ``` It is enlightening to study the $\mu_y, \Sigma_y$'s implied by various parameter values. @@ -458,14 +451,14 @@ Among other things, we can use the class to exhibit how **statistical stationar Let's begin by generating $N$ time realizations of $y$ plotting them together with population mean $\mu_y$ . ```{code-cell} ipython3 -# plot mean +# Plot mean N = 100 for i in range(N): col = cm.viridis(np.random.rand()) # Choose a random color from viridis - ys = my_process.sample_y(N) + ys = series_process.sample_y(N) plt.plot(ys[i,:], lw=0.5, color=col) - plt.plot(mu_y, color='red') + plt.plot(μ_y, color='red') plt.xlabel('t') plt.ylabel('y') @@ -478,41 +471,44 @@ Visually, notice how the variance across realizations of $y_t$ decreases as $t$ Let's plot the population variance of $y_t$ against $t$. ```{code-cell} ipython3 -# plot variance -plt.plot(Sigma_y.diagonal()) +# Plot variance +plt.plot(Σ_y.diagonal()) plt.show() ``` -Notice how the population variance increases and asymptotes +Notice how the population variance increases and asymptotes. +++ -Let's print out the covariance matrix $\Sigma_y$ for a time series $y$ +Let's print out the covariance matrix $\Sigma_y$ for a time series $y$. ```{code-cell} ipython3 -my_process = population_moments(alpha0=0, alpha1=.8, alpha2=0, T=6, y_1=0., y0=0., sigma_u=1) - -mu_y, Sigma_y = my_process.get_moments() -print("mu_y = ",mu_y) -print("Sigma_y = ", Sigma_y) +series_process = population_moments( + α_0=0, α_1=.8, α_2=0, T=6, y_neg1=0., y_0=0., σ_u=1) + +μ_y, Σ_y = series_process.get_moments() +print("μ_y = ", μ_y) +print("Σ_y = ", Σ_y) ``` -Notice that the covariance between $y_t$ and $y_{t-1}$ -- the elements on the superdiagonal -- are **not** identical. +Notice that the covariance between $y_t$ and $y_{t-1}$ -- the elements on the superdiagonal -- are *not* identical. -This is is an indication that the time series represented by our $y$ vector is not **stationary**. +This is an indication that the time series represented by our $y$ vector is not **stationary**. -To make it stationary, we'd have to alter our system so that our **initial conditions** $(y_1, y_0)$ are not fixed numbers but instead a jointly normally distributed random vector with a particular mean and covariance matrix. +To make it stationary, we'd have to alter our system so that our *initial conditions* $(y_0, y_{-1})$ are not fixed numbers but instead a jointly normally distributed random vector with a particular mean and covariance matrix. -We describe how to do that in another lecture in this lecture [Linear State Space Models](https://python.quantecon.org/linear_models.html). +We describe how to do that in [Linear State Space Models](https://python.quantecon.org/linear_models.html). But just to set the stage for that analysis, let's print out the bottom right corner of $\Sigma_y$. ```{code-cell} ipython3 -mu_y, Sigma_y = my_process.get_moments() -print("bottom right corner of Sigma_y = \n", Sigma_y[72:,72:]) +series_process = population_moments( + α_0=10.0, α_1=1.53, α_2=-.9, T=80, y_neg1=28., y_0=24., σ_u=1) +μ_y, Σ_y = series_process.get_moments() +print("bottom right corner of Σ_y = \n", Σ_y[72:,72:]) ``` -Please notice how the sub diagonal and super diagonal elements seem to have converged. +Please notice how the subdiagonal and superdiagonal elements seem to have converged. This is an indication that our process is asymptotically stationary. @@ -522,7 +518,6 @@ There is a lot to be learned about the process by staring at the off diagonal el +++ - ## Moving average representation Let's print out $A^{-1}$ and stare at its structure @@ -531,16 +526,13 @@ Let's print out $A^{-1}$ and stare at its structure To study the structure of $A^{-1}$, we shall print just up to $3$ decimals. -Let's begin by printing out just the upper left hand corner of $A^{-1}$ +Let's begin by printing out just the upper left hand corner of $A^{-1}$. ```{code-cell} ipython3 with np.printoptions(precision=3, suppress=True): print(A_inv[0:7,0:7]) ``` - - - Evidently, $A^{-1}$ is a lower triangular matrix. @@ -551,7 +543,6 @@ with np.printoptions(precision=3, suppress=True): print(A_inv[72:,72:]) ``` - Notice how every row ends with the previous row's pre-diagonal entries. @@ -560,7 +551,7 @@ Notice how every row ends with the previous row's pre-diagonal entries. Since $A^{-1}$ is lower triangular, each row represents $ y_t$ for a particular $t$ as the sum of - a time-dependent function $A^{-1} b$ of the initial conditions incorporated in $b$, and -- a weighted sum of current and past values of the IID shocks $\{u_t\}$ +- a weighted sum of current and past values of the IID shocks $\{u_t\}$. Thus, let $\tilde{A}=A^{-1}$. @@ -580,13 +571,13 @@ Just as system {eq}`eq:eqma` constitutes a ## A forward looking model -Samuelson’s model is **backwards looking** in the sense that we give it **initial conditions** and let it +Samuelson’s model is *backward looking* in the sense that we give it *initial conditions* and let it run. -Let’s now turn to model that is **forward looking**. +Let’s now turn to model that is *forward looking*. -We apply similar linear algebra machinery to study a **perfect -foresight** model widely used as a benchmark in macroeconomics and +We apply similar linear algebra machinery to study a *perfect +foresight* model widely used as a benchmark in macroeconomics and finance. As an example, we suppose that $p_t$ is the price of a stock and @@ -599,7 +590,7 @@ $$ y = A^{-1} \left(b + u\right) $$ -Our **perfect foresight** model of stock prices is +Our *perfect foresight* model of stock prices is $$ p_{t} = \sum_{j=0}^{T-t} \beta^{j} y_{t+j}, \quad \beta \in (0,1) @@ -634,34 +625,34 @@ y_{T} \end{array}\right] $$ -```{code-cell} python3 -𝛽 = .96 +```{code-cell} ipython3 +β = .96 ``` -```{code-cell} python3 +```{code-cell} ipython3 # construct B B = np.zeros((T, T)) for i in range(T): - B[i, i:] = 𝛽 ** np.arange(0, T-i) + B[i, i:] = β ** np.arange(0, T-i) ``` -```{code-cell} python3 +```{code-cell} ipython3 B ``` -```{code-cell} python3 -𝜎u = 0. -u = np.random.normal(0, 𝜎u, size=T) +```{code-cell} ipython3 +σ_u = 0. +u = np.random.normal(0, σ_u, size=T) y = A_inv @ (b + u) y_steady = A_inv @ (b_steady + u) ``` -```{code-cell} python3 +```{code-cell} ipython3 p = B @ y ``` -```{code-cell} python3 +```{code-cell} ipython3 plt.plot(np.arange(0, T)+1, y, label='y') plt.plot(np.arange(0, T)+1, p, label='p') plt.xlabel('t') @@ -676,7 +667,7 @@ Can you explain why the trend of the price is downward over time? Also consider the case when $y_{0}$ and $y_{-1}$ are at the steady state. -```{code-cell} python3 +```{code-cell} ipython3 p_steady = B @ y_steady plt.plot(np.arange(0, T)+1, y_steady, label='y') @@ -687,4 +678,3 @@ plt.legend() plt.show() ``` - diff --git a/lectures/unpleasant.md b/lectures/unpleasant.md index f5232b82..c3592872 100644 --- a/lectures/unpleasant.md +++ b/lectures/unpleasant.md @@ -16,7 +16,7 @@ kernelspec: ## Overview -This lecture builds on concepts and issues introduced in our lecture on **Money Supplies and Price Levels**. +This lecture builds on concepts and issues introduced in {doc}`money_inflation`. That lecture describes stationary equilibria that reveal a [*Laffer curve*](https://en.wikipedia.org/wiki/Laffer_curve) in the inflation tax rate and the associated stationary rate of return on currency. @@ -34,20 +34,18 @@ The critical **money-to-bonds** ratio stabilizes only at time $T$ and afterwards And the larger is $T$, the higher is the gross-of-interest government deficit that must be financed by printing money at times $t \geq T$. -These outcomes are the essential finding of Sargent and Wallace's **unpleasant monetarist arithmetic** {cite}`sargent1981`. - -**Reader's Guide:** Please read our lecture on Money Supplies and Price levels before diving into this lecture. +These outcomes are the essential finding of Sargent and Wallace's "unpleasant monetarist arithmetic" {cite}`sargent1981`. That lecture described supplies and demands for money that appear in lecture. It also characterized the steady state equilibrium from which we work backwards in this lecture. -In addition to learning about ''unpleasant monetarist arithmetic", in this lecture we'll learn how to implement a **fixed point** algorithm for computing an initial price level. +In addition to learning about "unpleasant monetarist arithmetic", in this lecture we'll learn how to implement a [*fixed point*](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) algorithm for computing an initial price level. ## Setup -Let's start with quick reminders of the model's components set out in our lecture on **Money Supplies and Price Levels**. +Let's start with quick reminders of the model's components set out in {doc}`money_inflation`. Please consult that lecture for more details and Python code that we'll also use in this lecture. @@ -79,7 +77,7 @@ where $\gamma_1 > \gamma_2 > 0$. ## Monetary-Fiscal Policy -To the basic model of our lecture on **Money Supplies and Price Levels**, we add inflation-indexed one-period government bonds as an additional way for the government to finance government expenditures. +To the basic model of {doc}`money_inflation`, we add inflation-indexed one-period government bonds as an additional way for the government to finance government expenditures. Let $\widetilde R > 1$ be a time-invariant gross real rate of return on government one-period inflation-indexed bonds. @@ -114,11 +112,11 @@ $$ (eq:openmarketconstraint) This equation says that the government (e.g., the central bank) can *decrease* $m_0$ relative to $\check m_0$ by *increasing* $B_{-1}$ relative to $\check B_{-1}$. -This is a version of a standard constraint on a central bank's **open market operations** in which it expands the stock of money by buying government bonds from the public. +This is a version of a standard constraint on a central bank's [**open market operations**](https://www.federalreserve.gov/monetarypolicy/openmarket.htm) in which it expands the stock of money by buying government bonds from the public. ## An open market operation at $t=0$ -Following Sargent and Wallace (1981), we analyze consequences of a central bank policy that +Following Sargent and Wallace {cite}`sargent1981`, we analyze consequences of a central bank policy that uses an open market operation to lower the price level in the face of a persistent fiscal deficit that takes the form of a positive $g$. @@ -242,18 +240,20 @@ $$ p_T = \frac{m_0}{\gamma_1 - \overline g - \gamma_2 R_u^{-1}} = \gamma_1^{-1} m_0 \left\{\frac{1}{R_u-\lambda} \right\} $$ (eq:pTformula) -**Remark:** +```{prf:remark} We can verify the equivalence of the two formulas on the right sides of {eq}`eq:pTformula` by recalling that $R_u$ is a root of the quadratic equation {eq}`eq:up_steadyquadratic` that determines steady state rates of return on currency. +``` ## Algorithm (pseudo code) Now let's describe a computational algorithm in more detail in the form of a description -that constitutes ''pseudo code'' because it approaches a set of instructions we could provide to a +that constitutes pseudo code because it approaches a set of instructions we could provide to a Python coder. To compute an equilibrium, we deploy the following algorithm. +```{prf:algorithm} Given *parameters* include $g, \check m_0, \check B_{-1}, \widetilde R >1, T $. We define a mapping from $p_0$ to $\widehat p_0$ as follows. @@ -280,8 +280,7 @@ $$ * Compute $R_u, p_T$ from formulas {eq}`eq:up_steadyquadratic` and {eq}`eq:LafferTstationary` above -* Compute a new estimate of $p_0$, call it $\widehat p_0$, from equation {eq}`eq:allts` above - +* Compute a new estimate of $p_0$, call it $\widehat p_0$, from equation {eq}`eq:allts` above * Note that the preceding steps define a mapping @@ -298,7 +297,7 @@ p_{0,j+1} = (1-\theta) {\mathcal S}(p_{0,j}) + \theta p_{0,j}, $$ where $\theta \in [0,1)$ is a relaxation parameter. - +``` ## Example Calculations @@ -318,7 +317,7 @@ That leaves the public with less currency but more government interest-bearing b Since the public has less currency (it's supply has diminished) it is plausible to anticipate that the price level at time $0$ will be driven downward. -But that is not the end of the story, because this ''open market operation'' at time $0$ has consequences for future settings of $m_{t+1}$ and the gross-of-interest government deficit $\bar g_t$. +But that is not the end of the story, because this **open market operation** at time $0$ has consequences for future settings of $m_{t+1}$ and the gross-of-interest government deficit $\bar g_t$. Let's start with some imports: @@ -329,7 +328,7 @@ import matplotlib.pyplot as plt from collections import namedtuple ``` -Now let's dive in and implement our ''pseudo code'' in Python. +Now let's dive in and implement our pseudo code in Python. ```{code-cell} ipython3 # Create a namedtuple that contains parameters @@ -395,14 +394,15 @@ def compute_fixed_point(m0, p0_guess, model, θ=0.5, tol=1e-6): return p0 ``` + Let's look at how price level $p_0$ in the stationary $R_u$ equilibrium depends on the initial money supply $m_0$. Notice that the slope of $p_0$ as a function of $m_0$ is constant. -This outcome indicates that our model verifies a ''quantity theory of money'' outcome, +This outcome indicates that our model verifies a quantity theory of money outcome, something that Sargent and Wallace {cite}`sargent1981` purposefully built into their model to justify -the adjective **monetarist** in their title. +the adjective *monetarist* in their title. ```{code-cell} ipython3 @@ -494,7 +494,7 @@ mystnb: plot_path([80, 100], msm) ``` -{numref}`fig:unpl1` summarizes outcomes of two experiments that convey messages of {cite}`sargent1981`. +{numref}`fig:unpl1` summarizes outcomes of two experiments that convey messages of Sargent and Wallace {cite}`sargent1981`. * An open market operation that reduces the supply of money at time $t=0$ reduces the price level at time $t=0$