Here are some examples of using IEtools ('Information Equilibrium tools') for python to investigate a couple of dynamic equilibrium models. There are two datasets used below, both obtainable from FRED.

One is (nominal) GDP divided by All Employees: Total Nonfarm Payrolls (PAYEMS). This can be obtained from FRED by editing the graph, editing the line, and customizing the data (adding the second series and using a custom formula "a/b")

https://fred.stlouisfed.org/series/GDP

https://fred.stlouisfed.org/series/PAYEMS

The second is more straightforward and looks at the seasonally adjusted unemployment rate (UNRATE). This model only looks at recent data since the version of IEtools used here can only handle up to two shocks.

https://fred.stlouisfed.org/series/UNRATE

Both models are assessed using two different techniques. The first is the entropy minimization approach (finding the log-linear transformation that minimizes the entropy of the log-linear slope bins). This separates the dynamic equilibrium from the shocks. The second technique is a direct curve fit of both the shocks and the dynamic equilibrium. This approach allows the dynamic equilibrium slope to potentially be affected by the details of the shock shocks. The former is more computationally intensive and requires more fiddling with the parameters to get the result right, but is theoretically more desireable for forecasts and adding data to the fit (additional shocks in new data do not affect a previously fit dynamic equilibrium slope as strongly).

These were run in Python 3 using the Anaconda distribution.

The dynamic equilibrium model is described in more detail here:

http://informationtransfereconomics.blogspot.com/2017/01/dynamic-equilibrium-presentation.html

Have fun,

Jason Smith


In [ ]:
import numpy as np
import pylab as pl
from IEtools import *
%pylab inline

Example: NGDP/PAYEMS

First we read in the GDP/PAYEMS data and plot it.


In [ ]:
filename='C:/econdata/GDP_PAYEMS.csv'

output = FREDcsvRead(filename)

In [ ]:
plotData = output['data']
plotType = pl.plot
plotType = pl.semilogy
plotScale = 10**6
plotLabel = output['name']+' [$ p.c.]'
pl.figure(figsize=(12,6))
plotType(plotData[:,0],plotData[:,1]*plotScale)
pl.ylabel(plotLabel)
pl.show()

Dynamic equilibrium models

This applies the entropy minimization method of finding the dynamic equilibrium.


In [ ]:
temp = dynamic_equilibrium_optimize(output['data'],alphaDelta=0.01,method='brute')
transform = log_linear_transform(output['data'], temp)

transform[:,1] = np.exp(transform[:,1])
guess = [1.0,-1.0,1977.0,0.1,0.1,2015.0, 0.0]
result = dynamic_eq_fit(two_shock, transform, guess)

fitData = result['fit']
popt = result['params']
pcov = result['cov']       
        
plotData = transform        
plotScale = 1
plotLabel = output['name']+' [transformed]'
plotData2 = fitData

pl.figure(figsize=(12,6))
for index in range(len(result['transitions'])):
    pl.axvline(x=result['transitions'][index],color='0.5',linewidth=0.5)   
pl.plot(plotData[:,0],np.log(plotData[:,1]),plotData[:,0],np.log(plotData2))
pl.ylabel(plotLabel)
pl.show()

print('Dynamic equilibrium growth rate (entropy min) = ',np.round(100*temp,decimals=2))
print('Shock centers = ',np.round(result['transitions'],decimals=1))
print('Shock widths = ',np.round(result['shock_widths'],decimals=2))
print('Shock magnitudes = ',np.round(result['shock_mags'],decimals=2))

This uses the global fit approach.


In [ ]:
guess = [1.0,-1.0,1980.0,0.1,0.1,2010.0,0.04,0.0]
result = dynamic_eq_fit(two_shock_eq, output['data'], guess)

fitData = result['fit']
popt = result['params']
pcov = result['cov']
        
growthRate=np.round(popt[-2]*100,decimals=2)
growthError=np.round(2*100*np.sqrt(np.diag(pcov))[-2],decimals=2)


plotData = output['data']
plotType = pl.plot
plotType = pl.semilogy
plotScale = 10**6
plotLabel = output['name']+' [$ p.c.]'
plotData2 = fitData

pl.figure(figsize=(12,6))
for index in range(len(result['transitions'])):
    pl.axvline(x=result['transitions'][index],color='0.5',linewidth=0.5)   
plotType(plotData[:,0],plotData[:,1]*plotScale,plotData[:,0],plotData2*plotScale)
pl.ylabel(plotLabel)
pl.show()

print('Dynamic equilibrium growth rate = ',growthRate,'+/-',growthError,'%')
print('Shock centers = ',np.round(result['transitions'],decimals=1))
print('Shock widths = ',np.round(result['shock_widths'],decimals=2))
print('Shock magnitudes = ',np.round(result['shock_mags'],decimals=2))

Example: UNRATE

Here we read in the unemployment rate data and plot it. We take only the most recent data because the version of python IEtools used here could only look at two shocks.


In [ ]:
filename='C:/econdata/UNRATE.csv'

output0 = FREDcsvRead(filename)
output = {
    'data': output0['data'][-170:-1],
    'name': output0['name']
}

In [ ]:
plotData = output['data']
plotType = pl.plot
plotScale = 1
plotLabel = output['name']+' [$ p.c.]'
pl.figure(figsize=(12,6))
plotType(plotData[:,0],plotData[:,1]*plotScale)
pl.ylabel(plotLabel)
pl.show()

Dynamic equilibrium models

This applies the entropy minimization method of finding the dynamic equilibrium.


In [ ]:
temp = dynamic_equilibrium_optimize(output['data'],alphaDelta=0.001,method='brute')
transform = log_linear_transform(output['data'], temp)

transform[:,1] = np.exp(transform[:,1])
guess = [1.0,-0.1,2008.0,0.1,0.1,2014.0, 0.0]
result = dynamic_eq_fit(two_shock, transform, guess)

fitData = result['fit']
popt = result['params']
pcov = result['cov']      
        
plotData = transform        
plotScale = 1
plotLabel = output['name']+' [transformed]'
plotData2 = fitData

pl.figure(figsize=(12,6))
for index in range(len(result['transitions'])):
    pl.axvline(x=result['transitions'][index],color='0.5',linewidth=0.5)   
pl.plot(plotData[:,0],np.log(plotData[:,1]),plotData[:,0],np.log(plotData2))
pl.ylabel(plotLabel)
pl.show()

print('Dynamic equilibrium growth rate (entropy min) = ',np.round(100*temp,decimals=2))
print('Shock centers = ',np.round(result['transitions'],decimals=1))
print('Shock widths = ',np.round(result['shock_widths'],decimals=2))
print('Shock magnitudes = ',np.round(result['shock_mags'],decimals=2))

This uses the global fit approach.


In [ ]:
guess = [1.0,-0.1,2008.0,0.1,0.1,2014.0,-0.09,0.0]
result = dynamic_eq_fit(two_shock_eq, output['data'], guess)

fitData = result['fit']
popt = result['params']
pcov = result['cov']  
        
growthRate=np.round(popt[-2]*100,decimals=2)
growthError=np.round(2*100*np.sqrt(np.diag(pcov))[-2],decimals=2)


plotData = output['data']
plotType = pl.plot
plotScale = 1
plotLabel = output['name']+' [%]'
plotData2 = fitData

pl.figure(figsize=(12,6))
for index in range(len(result['transitions'])):
    pl.axvline(x=result['transitions'][index],color='0.5',linewidth=0.5)   
plotType(plotData[:,0],plotData[:,1]*plotScale,plotData[:,0],plotData2*plotScale)
pl.ylabel(plotLabel)
pl.show()

print('Dynamic equilibrium growth rate = ',growthRate,'+/-',growthError,'%')
print('Shock centers = ',np.round(result['transitions'],decimals=1))
print('Shock widths = ',np.round(result['shock_widths'],decimals=2))
print('Shock magnitudes = ',np.round(result['shock_mags'],decimals=2))

In [ ]: