# Illustrating the new LPIRF Stata 18’s command

Good news! In the new version of Stata 18, we have a new command that produces local-projection impulse–response functions. You can find the complete description of the command here. Local projections were introduced in 2005 by Òscar Jordà in the following AER article: Estimation and Inference of Impulse Responses by Local Projections.

To illustrate the new Stata command, we will use the database found in a previous article of mine, written with Valérie Mignon and Yifei Cai. We will start the Stata code by estimating a SVAR from January 2000 to December 2019. The variables involved are: political tension between US and China, a proxy for the oil demand, the oil production and the real price of oil. We use short-run restrictions based on a Cholesky decomposition. Once the model is estimated, we will retrieve the structural shocks. As explained to me by Miguel Dorta (Stata Corp), I can use the matrix command to recover the structural shock from a VAR model with the A and B matrixes:

/*

In the "Short-run SVAR models" section of the "[TS] var intro" manual
(PDF documentation) you can see that

A*epsilon_t = B*e_t

Where e_t is the matrix of structural shocks and epsilon_t is the matrix of
the residuals for the reduced form VAR model. Therefore,

e_t = inv(B)*A*epsilon_t

Below is an example that computes the structural shocks (e_t).

*/

Now, I will reproduce the code to draw a time-series plot for the structural residuals (e1) and the reduced-form residuals (Residuals).

**# Analysing US-CHN tensions on oil price
**********************************************************

version 18.0
set more off
cd "C:\Users\jamel\Dropbox\stata\lpirf"
capture log close
log using blog-lpirf.smcl, replace

import excel .\data_svar.xlsx,/*
*/ sheet("data") firstrow clear

generate mth = tm(1960m1) + _n-1
format %tm mth

label variable pri "Political Relationship Index"
label variable pri_s "PRI Standardized"
label variable gop "Global Oil Production"
label variable rspri "Real Spot Price"
label variable wip "World Industrial Production"
label variable dinv "Variation of Inventories"
label variable gprcn ///
"Percent of Articles on China in the Bil. GPR"

rename gop pro
rename wip dem
rename rspri rpo

capture generate lpro = log(pro)
la var lpro "Natural log of PRO"
capture generate lrpo = log(rpo)
la var lpro "Natural log of RPO"
capture generate ldem = log(dem)
la var ldem "Natural log of DEM"

drop t
order mth, first

**#  Declare time series

tsset mth, monthly

matrix A = (1,0,0,0\.,1,0,0\.,.,1,0\.,.,.,1)
matlist A

matrix B = (.,0,0,0\0,.,0,0\0,0,.,0\0,0,0,.)
matlist B

svar lpri lpro ldem lrpo if mth>tm(2000m1), aeq(A) beq(B) ///
lags(1/24)

/* compute the inv(B)*A matrix */
matrix A=e(A)
matrix B=e(B)
matrix BA = inv(B)*A
/* compute reduced form epsilon_t residuals */
var lpri lpro ldem lrpo if mth>tm(2000m1)
capture drop epsilon*
predict double epsilon1 if mth>tm(2000m1),residual eq(#1)
predict double epsilon2 if mth>tm(2000m1),residual eq(#2)
predict double epsilon3 if mth>tm(2000m1),residual eq(#3)
predict double epsilon4 if mth>tm(2000m1),residual eq(#4)
/* store the epsilon* variables in the epsilon matrix */
mkmat epsilon*, matrix(epsilon)
/* compute e_t matrix of structural shocks */
matrix e = (BA*epsilon')'
/* store columns of e as variables e1, e2, and e3 */
svmat double e

twoway (tsline e1 if mth>tm(2000m1)) (tsline epsilon1 ///
if mth>tm(2000m1), yaxis(2)), ///
name(G1, replace)

graph export "G1.svg", as(svg) replace

You need to be careful on the matrixes size and each epsilon corresponds to the structural shock in the ordering, namely, US–China political relations at first, oil supply, oil demand, and, at last, oil prices.

Once I have the structural shocks, I will follow now the approach presented on the Stata website with identified shocks obtained at the previous step to estimate the impact of an unanticipated improvement of political relationship will produce on the real price of oil:

irf set comparemodels.irf, replace
quietly lpirf lpro ldem lrpo, step(48) lags(1/24) ///
exog(L(0/24).e1)
irf create lpmodel

quietly var lpro ldem lrpo, lags(1/24)            ///
exog(L(0/24).e1)
irf create varmodel, step(48)

irf graph dm, impulse(e1) response(lrpo)   ///
irf(lpmodel varmodel) level(95) name(G2, replace) ///
xline(0 10 20 30 40 50, lcolor(blue)) yline(-.05 0 .05 .1, lcolor(blue))

graph export "G2.svg", replace

Here, we assess the impact of political relations shocks on the real price of oil. The dynamic is similar between the dynamic multipliers, but the oil price increase is more significant in the LP than in the VAR.

We can redo the same exercise for the well-established bilateral Geopolitical Risk index for China. The bilateral GPR index measures the share of press articles related to a specific country, here, China in the leading US journal. So, the interpretation of impulse-response functions could be quite different from the case of the political relation index between China and the US from the Chinese perspective.

The results are very interesting. In the LP, an increase of the bilateral GPR (share of press articles on China) produces an increase that persists for several months. Maybe, before Trump’s trade war, an unanticipated increase in the share of articles on China were associated with good news that positively impacted the real price of oil. The results are quite different in the SVAR. I reproduce the code below.

/* GPR */

svar gprcn lpro ldem lrpo if mth>tm(2000m1), aeq(A) beq(B) ///
lags(1/24)

/* compute the inv(B)*A matrix */
matrix A=e(A)
matrix B=e(B)
matrix BA = inv(B)*A
/* compute reduced form epsilon_t residuals */
var gprcn lpro ldem lrpo if mth>tm(2000m1)
capture drop epsilon*
predict double epsilon1 if mth>tm(2000m1),residual eq(#1)
predict double epsilon2 if mth>tm(2000m1),residual eq(#2)
predict double epsilon3 if mth>tm(2000m1),residual eq(#3)
predict double epsilon4 if mth>tm(2000m1),residual eq(#4)
/* store the epsilon* variables in the epsilon matrix */
mkmat epsilon*, matrix(epsilon)
/* compute e_t matrix of structural shocks */
matrix e_ = (BA*epsilon')'
/* store columns of e as variables e1, e2, and e3 */
svmat double e_

twoway (tsline e_1 if mth>tm(2000m1)) (tsline epsilon1 ///
if mth>tm(2000m1), yaxis(2)), ///
name(G3, replace)

graph export "G3.svg", as(svg) replace

irf set comparemodels1.irf, replace
quietly lpirf lpro ldem lrpo, step(48) lags(1/24) ///
exog(L(0/24).e_1)
irf create lpmodel1

quietly var lpro ldem lrpo, lags(1/24)            ///
exog(L(0/24).e_1)
irf create varmodel1, step(48)

irf graph dm, impulse(e_1) response(lrpo)   ///
irf(lpmodel1 varmodel1) level(95) name(G4, replace) ///
xline(0 10 20 30 40 50, lcolor(blue)) yline(-.05 0 .05 .1, lcolor(blue))

graph export "G4.svg", replace

twoway (tsline e_1 if mth>tm(2000m1)) (tsline e1 ///
if mth>tm(2000m1), yaxis(1)), ///
name(G5, replace)

graph export "G5.svg", replace

save lpirf_EEter, replace

Conclusion: we illustrate the new LPIRF command in Stata 18. An improvement of political relation between the US and China and an increase in the share of articles related to China can cause an increase in the real price of oil in the short-run during 10 months. While LP and VAR impulse-response functions have similar patterns in the medium run, the LP impulse-response functions seem to capture short-run dynamics.

Please note that the files for replicating this blog are (or will be) available here: https://github.com/

[…] decompositions (HD), and variance decompositions (VD). Let me remind that I already covered Local Projection with Stata and Moving Block Bootstrap with GAUSS using a similar […]

Eduardo Montesinos says:

What if I want to capture the shocks but from a long-term SVAR?
In Stata the form is yt=C*e_t where C is the long-term impact matrix of the shocks. When solving, e_t=yt*inv(C).

How do I calculate e_t in Stata just like you did with the short run? How do I compute yt?

Thank you very much, greetings from Ecuador.

Hi Eduardo, thanks for your question. By following this blog:
https://blog.stata.com/2016/10/27/, and adapting my code, you should be able to recover the structural shocks.

Eduardo Montesinos says:

Hi Jamel,

I’ve seen that post before and it confirms my estimate in the long term but it doesn’t tell me anything about how to recover the shocks in Stata. My only question is how to replace the SVAR variables from short to long term. For example, y=A*epsilon? e=C^-1*y?
I want to make a simple plot comparing the short and long shocks of my model such as Beaudry & Portier (2006). If you can help me with this last part of my work to communicate and talk in detail.

Thank you.

Use the predict command after the SVAR, in my case:

predict double epsilon1 if mth>tm(2000m1),residual eq(#1)
predict double epsilon2 if mth>tm(2000m1),residual eq(#2)
predict double epsilon3 if mth>tm(2000m1),residual eq(#3)
predict double epsilon4 if mth>tm(2000m1),residual eq(#4)

Kind regards,
Jamel

Eduardo Montesinos says:

Those lines help me calculate epsilon but not to compute e_t in the long term, because I did 2 different regressions.

Thank you Jamel for answering me, your code to recover from the short-term shock is precise, on that side I must keep trying.

Kind regards.
Eduardo

By choosing the appropriate writing for the structural model, you should be able to recover structural shocks from the reduced form model.

Kind regards,
Jamel

Ishmael says:

Hi Jamel,
I am an undergraduate student at the University of Warwick. I am currently doing my dissertations and wish to decompose oil price shocks using the svar function in stata. I then wish to produce an IRF graph to analyse the effect of structural oil price shocks on financial market data I have collected on a set of countries. Following the code in this blog, I am unable to run an IRF graph on my svar as the shock is treated as an exogenous variable. How should I go about this?

Your guidance on the above would be deeply appreciated.