%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;}
# ABOVE CELL IS "NO SCROLLING SUBWINDOWS" SETUP
#
# keep output cells from shifting to autoscroll: little scrolling
# subwindows within the notebook are an annoyance...
# THIS CELL LOADS THE LIBRARIES
#
# set up the environment by reading in every library we might need:
# os... graphics... data manipulation... time... math... statistics...
import sys
import os
from urllib.request import urlretrieve
import matplotlib as mpl
import matplotlib.pyplot as plt
from IPython.display import Image
import pandas as pd
from pandas import DataFrame, Series
from datetime import datetime
import scipy as sp
import numpy as np
import math
import random
import seaborn as sns
import statsmodels
import statsmodels.api as sm
import statsmodels.formula.api as smf
# PRETTIER GRAPHICS SETUP
#
# graphics setup: seaborn-whitegrid and figure size;
# graphs in the notebook itself...
%matplotlib inline
plt.style.use('seaborn-whitegrid')
figure_size = plt.rcParams["figure.figsize"]
figure_size[0] = 12
figure_size[1] = 10
plt.rcParams["figure.figsize"] = figure_size
# THIS CELL IS THE KEY TO THE OKPY.ORG AUTOGRADER SYSTEM
#
# Don't change this cell; just run it.
# The result will give you directions about how to log in to the submission system, called OK.
# Once you're logged in, you can run this cell again, but it won't ask you who you are because
# it remembers you. However, you will need to log in once per assignment.
!pip install -U okpy
from client.api.notebook import Notebook
ok = Notebook('ps6.ok')
_ = ok.auth(force=True, inline=True)
Requirement already up-to-date: okpy in /anaconda3/lib/python3.6/site-packages (1.13.11) Requirement not upgraded as not directly required: coverage==3.7.1 in /anaconda3/lib/python3.6/site-packages (from okpy) (3.7.1) Requirement not upgraded as not directly required: requests==2.12.4 in /anaconda3/lib/python3.6/site-packages (from okpy) (2.12.4) distributed 1.21.8 requires msgpack, which is not installed. You are using pip version 10.0.1, however version 18.0 is available. You should consider upgrading via the 'pip install --upgrade pip' command. ===================================================================== Assignment: PS6 Notebook OK, version v1.13.11 ===================================================================== Open the following URL: https://okpy.org/client/login/ After logging in, copy the code from the web page and paste it into the box. Then press the "Enter" key on your keyboard. Paste your code here:
ERROR | auth.py:91 | {'error': 'invalid_grant'}
--------------------------------------------------------------------- Authentication error: invalid grant ---------------------------------------------------------------------
The autograder, both in the tests you run along the way as you work on the problem set and in calculating the final score, looks in the same directory as the problem set notebook for an "ok.tests" directory, and then runs the tests in the "q**.py" files in that directory (where "**" denotes a two-digit number, possibly with a leading zero). Those tests take the form of comparing a variable that should be in your namespace and seeing if it is close to some desired value that we get when we do the problem set.
Thus while the problem set instructions ask you to run simulations and plot graphs, what you are tested on is whether the appropriate variables in your namespace have (close to the) right values. We do not care what code you use in order to get those variables to the right values.
You can run simulations and then pick appropriate values out by slicing a series in order to get the right number. You can use your knowledge of the algebraic solution to the model to have Python calculate the answer, having first set the parameters to the right values. You can even do all of the calculations on pen and paper, and simply code up the variables.
Perhaps we should ask you to do all three—start with simulations, or with algebraic equations with set parameter values, or with full pen-and-paper calculations with only the final results entered into the notebook—and then ask you to check your results from one mode by doing the other two. But: ars longa, vita brevis. Focus on what works for you: the key is to get a sense of how economists' center-of-gravity analyses of long-run growth work, so that when you encounter such an analysis later, outside the university, you have the right intellectual panoply to evaluate it.
(Task E) Savings and Investment
Suppose somebody who hasn’t taken any economics courses asks you why some countries are so very, very much poorer than others in the world today. What an swer would you give? Double-click on this markdown cell and write your answer below:
ANSWER:
(Task F) Long Run Human Populations: Levels and Growth
Run the code cell below, unchanged, to enter Michael Kremer's data—his estimates of human population and its growth, updated to 2015, into the pandas dataframe "Pop_df". Then proceed to do the tasks in the markdown cells further down:
# HUMAN POPULATION OVER THE LAST 10000 YEARS
#
# make sure the standard libraries are active
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from IPython.display import Image
Population = (
[-8000,5],
[-4000, 7],
[-2000, 27],
[-1000, 50],
[-500, 100],
[-200, 150],
[0, 170],
[200, 190],
[400, 190],
[600, 200],
[800, 230],
[1000, 265],
[1200, 360],
[1400, 350],
[1500, 425],
[1600, 545],
[1700, 610],
[1750, 720],
[1800, 900],
[1850, 1200],
[1875, 1325],
[1900, 1625],
[1925, 1875],
[1950, 2516],
[1975, 4000],
[2000, 6100],
[2015, 7250])
Population = np.array(Population)
Pop_df = pd.DataFrame(Population)
Pop_df.columns = ['Date', 'Population']
Pop_df['Year'] = 0.0
for i in range(26):
Pop_df.Year[i] = Pop_df.Date[i]
Pop_df = Pop_df.set_index('Date')
Now let us compare growth rates of human populations across different time periods. Set the variables in the code cell below to their appropriate values:
Growth_Rate_1000BC_to_1000AD =
Growth_Rate_1400_to_1600 =
Growth_Rate_1900_to_1950 =
ok.grade('q03')
Now suppose that we are in a Malthusian population régime, in which the rate of population growth is linearly proportional to the relative deviation of typical standards of living from 750 dollars a year, with population growth at zero when output per capita is 750 dollars per year and 1 percent per year when output per worker is 1500. What would you think typical standards of living were in the 1400 to 1600 period and the in the 1900 to 1950 period? Enter the appropriate values for the variables in the code cell below:
SoLtypical1400to1600 =
SoLtypical1900to1950 =
ok.grade('q04')
(Task G) American and British Economic Growth
Run the code cell below, unchanged, to enter Measuring Worth data for the United Kingdom and the United States into the pandas dataframes "uklongrun_df" and "uslongrun_df" and the pandas dictionaries "uklongrun_dict" and "uslongrun_dict". Then proceed to do the tasks in the markdown cell further down:
# CODE
# British long run real GDP per capita growth
# From Sam Williamson and Louis Johnston, Measuring Worth
# Data
sourceURL = "http://delong.typepad.com/2018-02-18_ukgdp_1700-2017.csv"
uklongrun_df = pd.read_csv(sourceURL, index_col = 0)
uklongrun_dict = {}
uklongrun_dict["df"] = uklongrun_df
uklongrun_dict["sourceURL"] = sourceURL
uklongrun_dict["sourceDescription"] = "Ryland Thomas and Samuel H. Williamson, 'What Was the Consistent U.K. GDP Then?' MeasuringWorth 2018"
uklongrun_dict["sourceNotes"] = "http://www.measuringworth.com/ukgdp/"
# ----
# U.S. long run economic growth of real GDP per capita: data cell
# From Sam Williamson and Louis Johnston, Measuring Worth
sourceURL = "http://delong.typepad.com/2018-02-18_usgdp_1790-2016.csv"
uslongrun_df = pd.read_csv(sourceURL, index_col = 0)
uslongrun_dict = {}
uslongrun_dict["df"] = uslongrun_df
uslongrun_dict["sourceURL"] = sourceURL
uslongrun_dict["sourceDescription"] = "Louis Johnston and Samuel H. Williamson, 'What Was the U.S. GDP Then?' MeasuringWorth, 2018"
uslongrun_dict["sourceNotes"] = "https://www.measuringworth.com/usgdp/"
Now, using the code cell below, plot United Kingdom economic growth in estimated GDP per capita since 1700. And, using the code below that, plot United States economic growth in estimated GDP per capita since 1790 What would you say the key dividing points in the past several centuries economic growth have been for both countries? What key breakpoints do they share? What key breakpoints are confined to one or the other alone? After running your code and looking at your graphs, double-click on this markdown cell and write your answer below:
ANSWER:
# CODE
# CODE
(Task H) Malthusian Economies
Below we have a function code cell that performs a simulation for the Malthusian economy discussed in lecture and in §5.1 of the DRAFT 3rd edition of DeLong and Olney: Macroeconomics, with an interact link to the texbook file at: http://datahub.berkeley.edu/user-redirect/interact?account=braddelong&repo=LSS18E101b&branch=master&path=m%26O3ed/ch5/2018-02-06_DeLong_and_Olney_Macro_3rd_Ch_5.1%20The%20Reality%20of%20Economic%20Growth-Before%20Modern%20Economic%20Growth.ipynb
This version of the Malthusian model has:
Run the function code cell below
The code cell after the function code cell presents a baseline run of this simulation, with parameters calibrated to more-or-less reproduce human economic history from the invention of agriculture up to the year 1, running for 800 decades—8000 years from 8000 BC to the year 1 (set in the function call by setting T=801).
Run this second code cell to check that it does indeed track human history, with income per worker in year 1 at about 1700 dollars per year and the labor force in year 1 at about 80 million.
Copy and paste the function call code cell, and edit it by altering the "T=" declaration that determines how long the simulation runs for to add more decades in order to track the simulated economy up to the year 2500. When, for these baselien parameter values, does the Industrial Revolution take place?
Copy and paste the function call code cell, and edit it by altering the "h=" declaration that determines how ingenious humans are in their economy to make us and our predecessors more ingenious—choose h=0.00012 instead of the baseline h=0.0000805. When, for these parameter values, does the Industrial Revolution take place?
Copy and paste the function call code cell, and edit it by altering the "h=" declaration that determines how ingenious humans are in their economy to make us and our predecessors less ingenious—choose h=0.00005 instead of the baseline h=0.0000805. When, for these parameter values, does the Industrial Revolution take place?
Write your answers to (2), (3), and (4) below in this markdown cell:
ANSWER:
# FUNCTION FOR CALCULATING AND GRAPHING THE LEVELS OF
# SOLOW GROWTH MODEL VARIABLES IN MALTHUSIAN SIMULATIONS
#
# ADDING IN TWO HEADS ARE BETTER THAN ONE: TECHNOLOGICAL PROGRESS
# PROPORTIONAL TO POPULATION RAISED TO THE POWER LAMBDA...
#
# IDEAS GROWTH NEVER GREATER THAN 2% PER YEAR
#
# ADDING IN DEMOGRAPHIC TRANSITION: POPULATION GROWTH SLOWS
# AFTER REAL INCOMES REACH 2000 DOLLARS PER YEAR
#
# might as well put "check that common libraries are active" as a default header
# in every long python code cell...
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import scipy as sp
import numpy as np
%matplotlib inline
# we are going to want to see what happens for lots of
# different model parameter values and ini conditions,
# so stuff our small simulation program inside a function, so
# we can then invoke it with a single line...
#
# we are going to assume the economy starts on its ini
# balanced growth path...
#
# we are going to want to keep track not just of what the
# economy's variables are at each point in time, but also
# what the ini and alternative balanced-growth path
# values of variables are. Given the parameters, the new BGP
# is attracting the economy to it at the speed (1-α)(n+g+δ),
# closing that fraction of the gap between its current state
# and the balanced growth path attractor every period...
#
def sgm_malthus_run(H0=900, N0=2250, gamma=2, L0=2.5, n=0.000442, h=0.0000805, s=0.10,
alpha=1/3, delta=0.04, Delta_s=0, Delta_g=0, Delta_n=0, phi=0.01, ybar = 1500,
lambda_i = 0.5, T = 1001, figure_title = "Ideas: Two Heads Are (Somewhat) Better than One"):
sg_df = pd.DataFrame(index=range(T),columns=[
'Year',
'Labor',
'Efficiency',
'Capital',
'Output',
'Output_per_Worker',
'Capital_Output_Ratio',
'Ideas',
'Resources',
'BGP_ini_Labor',
'BGP_ini_Eff',
'BGP_ini_Capital',
'BGP_ini_Output',
'BGP_ini_Output_per_Worker',
'BGP_ini_Capital_Output_Ratio',
'BGP_alt_Labor',
'BGP_alt_Eff',
'BGP_alt_Capital',
'BGP_alt_Output',
'BGP_alt_Output_per_Worker',
'BGP_alt_Capital_Output_Ratio'],
dtype='float')
g = (gamma/(1+gamma))*h - (1/(1+gamma))*n
sg_df.Ideas[0] = H0
sg_df.Resources[0] = N0
E0 = sg_df.Ideas[0]**(gamma/(1+gamma))*(sg_df.Resources[0]/L0)**(1/(1+gamma))
sg_df.Labor[0] = L0
sg_df.BGP_ini_Labor[0] = L0
sg_df.BGP_alt_Labor[0] = L0
sg_df.Efficiency[0] = E0
sg_df.BGP_ini_Eff[0] = E0
sg_df.BGP_alt_Eff[0] = E0
KoverY_ini_steady_state = s/(n+g+delta)
YoverL_ini_steady_state = ((s/(n+g+delta))**(alpha/(1-alpha))
* E0)
KoverL_ini_steady_state = (YoverL_ini_steady_state *
KoverY_ini_steady_state)
sg_df.Capital[0] = KoverL_ini_steady_state * L0
sg_df.Output[0] = (sg_df.Capital[0]**alpha * (sg_df.Labor[0] *
sg_df.Efficiency[0])**(1-alpha))
sg_df.Output_per_Worker[0] = sg_df.Output[0]/sg_df.Labor[0]
sg_df.Capital_Output_Ratio[0] = sg_df.Capital[0]/sg_df.Output[0]
sg_df.BGP_ini_Capital_Output_Ratio[0] = (s / (n + g + delta))
sg_df.BGP_ini_Output_per_Worker[0] = sg_df.Efficiency[0] * (
sg_df.BGP_ini_Capital_Output_Ratio[0]*(alpha/(1 - alpha)))
sg_df.BGP_ini_Output[0] = sg_df.BGP_ini_Output_per_Worker[0] * sg_df.Labor[0]
sg_df.BGP_ini_Capital[0] = sg_df.Labor[0] * sg_df.Efficiency[0] * (
sg_df.BGP_ini_Capital_Output_Ratio[0]*(1/(1 - alpha)))
sg_df.BGP_alt_Capital_Output_Ratio[0] = ((s + Delta_s) /
(n + Delta_n + g + Delta_g + delta))
sg_df.BGP_alt_Output_per_Worker[0] = sg_df.Efficiency[0] * (
sg_df.BGP_alt_Capital_Output_Ratio[0]*(alpha/(1 - alpha)))
sg_df.BGP_alt_Output[0] = sg_df.BGP_alt_Output_per_Worker[0] * sg_df.Labor[0]
sg_df.BGP_alt_Capital[0] = sg_df.Labor[0] * sg_df.Efficiency[0] * (
sg_df.BGP_alt_Capital_Output_Ratio[0]*(1/(1 - alpha)))
for i in range(T):
if (sg_df.Output_per_Worker[i] < 2*ybar):
n = phi * np.log(sg_df.Output_per_Worker[i]/ybar)
else:
n = phi * np.log(2)*np.exp(-sg_df.Output_per_Worker[i]/(2*ybar) + 1)
sg_df.Labor[i+1] = (sg_df.Labor[i] * np.exp(10*(n + Delta_n)))
sg_df.Ideas[i+1] = sg_df.Ideas[i]*np.exp(10*min((h*sg_df.Labor[i]**lambda_i), 0.02))
sg_df.Resources[i+1] = sg_df.Resources[i]
KoverY_current = sg_df.Capital[i]/sg_df.Output[i]
sg_df.Capital[i+1] = (sg_df.Capital[i] * np.exp(10*(s+Delta_s)/
KoverY_current - 10*delta))
sg_df.Efficiency[i+1] = (sg_df.Ideas[i+1]**(gamma/(1+gamma)) *
(sg_df.Resources[i+1]/sg_df.Labor[i+1])**(1/(1+gamma)))
sg_df.Output[i+1] = (sg_df.Capital[i+1]**alpha *
(sg_df.Labor[i+1] * sg_df.Efficiency[i+1])**(1-alpha))
sg_df.Output_per_Worker[i+1] = sg_df.Output[i+1]/sg_df.Labor[i+1]
sg_df.Capital_Output_Ratio[i+1] = (sg_df.Capital[i+1]/
sg_df.Output[i+1])
sg_df.BGP_ini_Labor[i+1] = (sg_df.BGP_ini_Labor[i] * np.exp(n))
sg_df.BGP_ini_Eff[i+1] = (sg_df.BGP_ini_Eff[i] * np.exp(g))
sg_df.BGP_ini_Capital_Output_Ratio[i+1] = (s / (n + g + delta))
sg_df.BGP_ini_Output_per_Worker[i+1] = sg_df.BGP_ini_Eff[i+1] * (
sg_df.BGP_ini_Capital_Output_Ratio[i+1]**(alpha/(1 - alpha)))
sg_df.BGP_ini_Output[i+1] = (sg_df.BGP_ini_Output_per_Worker[i+1] *
sg_df.BGP_ini_Labor[i+1])
sg_df.BGP_ini_Capital[i+1] = (s / (n + g + delta))**(1/(1-alpha)) * (
sg_df.BGP_ini_Eff[i+1] * sg_df.BGP_ini_Labor[i+1])
sg_df.BGP_alt_Labor[i+1] = (sg_df.BGP_alt_Labor[i] * np.exp(n+ Delta_n))
sg_df.BGP_alt_Eff[i+1] = (sg_df.BGP_alt_Eff[i] * np.exp(g+ Delta_g))
sg_df.BGP_alt_Capital_Output_Ratio[i+1] = ((s+ Delta_s) /
(n + Delta_n + g + Delta_g + delta))
sg_df.BGP_alt_Output_per_Worker[i+1] = sg_df.BGP_alt_Eff[i+1] * (
sg_df.BGP_alt_Capital_Output_Ratio[i+1]**(alpha/(1 - alpha)))
sg_df.BGP_alt_Output[i+1] = (sg_df.BGP_alt_Output_per_Worker[i+1] *
sg_df.BGP_alt_Labor[i+1])
sg_df.BGP_alt_Capital[i+1] = ((s + Delta_s) / (n + Delta_n +
g + Delta_g + delta))**(1/(1-alpha)) * (
sg_df.BGP_alt_Eff[i+1] * sg_df.BGP_alt_Labor[i+1])
sg_df.Year = range(-8000, -8000 + 10*T, 10)
sg_df = sg_df.set_index('Year')
fig = plt.figure(figsize=(12, 9))
ax1 = plt.subplot(2,3,1)
sg_df.Labor.plot(ax = ax1, title = "Labor Force")
plt.ylabel("Values")
plt.ylim(0, )
ax2 = plt.subplot(2,3,2)
sg_df.Efficiency.plot(ax = ax2, title = "Efficiency of Labor")
plt.ylim(0, )
ax3 = plt.subplot(2,3,3)
sg_df.Capital.plot(ax = ax3, title = "Capital Stock")
plt.ylim(0, )
ax4 = plt.subplot(2,3,4)
sg_df.Output.plot(ax = ax4, title = "Output")
plt.ylabel("Values")
plt.xlabel("Years")
plt.ylim(0, )
ax5 = plt.subplot(2,3,5)
sg_df.Output_per_Worker.plot(ax = ax5, title = "Output per Worker")
plt.xlabel("Years")
plt.ylim(0, )
ax6 = plt.subplot(2,3,6)
sg_df.Capital_Output_Ratio.plot(ax = ax6,
title = "Capital-Output Ratio")
plt.xlabel("Years")
plt.ylim(0, 6)
plt.suptitle(figure_title, size = 20)
plt.show()
print(n + Delta_n, "is the labor force growth rate")
print(g + Delta_g, "is the efficiency of labor growth rate")
print(delta, "is the depreciation rate")
print(s + Delta_s, "is the savings rate")
print(alpha, "is the decreasing-returns-to-scale parameter")
print(" ")
print(sg_df.Labor[0], "is the labor force in year 0")
print(sg_df.Output_per_Worker[0], "is output per worker in year 0")
print(" ")
sgm_malthus_run(T=801, figure_title = "Demographic Transition",
h=0.0000805, phi=0.01, ybar = 1500)
_ = ok.submit()
(Task ∞) Programming Practices
If it strikes you that anything should be added to this list of programming dos and don'ts, please email it to me at delong@econ.berkeley.edu