' This code replicate Tables 1,2, 3 and 5 in Chen (2025) "Inflation Expectations and Inflation Persistence"
' Table 1: See Equation "linear", and "ms"
' Table 2: See Equation "pred1" "pred2" "pred3"
' Table 3: See Matrix "oos"
' Table 5: Chose !ie = 2
 

%path = @runpath
cd %path
mode quiet

wfcreate(wf=sticky) m 1947:1 2022:11
read(b14,s=Data) CPIdata.xls cpi corecpi MICH pcepi NY Cleveland 
read(b16,s=Data) Controls.xls UNRATE WTI M2 TB3MS GS10 FEDFUNDS

genr diffcpi12 = 1200*(cpi-cpi(-1))/cpi(-1)
genr diffpce12 = 1200*(pcepi-pcepi(-1))/pcepi(-1)
genr diffcore12 = 1200*(corecpi-corecpi(-1))/corecpi(-1)


'=========================
!price = 0
' 0 if headline cpi, 1 if PCE, 2 if corecpi

!scheme = 0
' 0 if rolling, 1 if recursive

!probset = 0
' 0 if smoothing prob, 1 if filtered prob 

!persist = 0
'0 if default, 1 if Regime Probability-weighted Inflation Persistence

!ie = 1
' 1 if Michigan University
' 2 if Cleveland Fed 

!PR = 1
' 1 if 'P/R=4  1986:12
' 2 if P/R=3 1988:12
' 3 if P/R=2 1992:12
' 4 if P/R=1 1999:12
' 5 if P/R=0.5 2007:12


!islag = 1
' lags in in-sample predictive regression model

!switch = 1


!control = 5
' # of control variables, 5 (baseline) 7 (robustness)
'=========================

if !ie = 1 then
genr pie = MICH
svector renddate = @wsplit("1986:12 1988:12 1992:12 1999:12 2007:12")  
else
genr pie = Cleveland 
svector renddate = @wsplit("1989:12 1991:12 1995:12 2002:12 2008:12")  
endif


svector rstart = @wsplit("1978:01 1982:01")

 
!rend = @dateval(renddate(!PR))
!pstart = @dateadd(!rend, 1, "mm")
!pend = @dateval("2022:11")
scalar Psample = @datediff(!pend,!pstart,"mm")
scalar Rsample = @datediff(!rend,@dateval(rstart(!ie)),"mm")
scalar PRratio = Psample/Rsample
sample spred !pstart !pend


smpl 1947:1 2022:11

if !price = 0 then
genr p = cpi
else if !price = 1 then
genr p = pcepi
else if !price = 2 then
genr p = corecpi
endif
endif 
endif




'  monthly change of the price level at an annualized rate
genr dcpi = 1200*(p-p(-1))/p(-1)


'genr dsticky = 100*corestickycpi_ex_shelter

' generate indicator of crediability losses (Neuenkirch and Tillmann, 2014 JIMF)
genr pitilde = @movav(dcpi, 12) 
genr pidev = pitilde - 2
genr credit = pidev*@abs(pidev)

genr M2G = 100*(M2-M2(-1))/M2(-1)


matrix(4,2) mscoeff1

equation linear.ls dcpi c dcpi(-1)
freeze(waldtable_linear) linear.wald C(1)/(1-C(2))=0



!seed = 123456789


equation MS.switchreg(type=markov,  heterr, seed=13992022) dcpi c dcpi(-1)
svector ind = @wsplit("1 3 6 12")


mscoeff1(1,1) = @coefs(1)
mscoeff1(1,2) = @stderrs(1)
mscoeff1(2,1) = @coefs(4)
mscoeff1(2,2) = @stderrs(4)
mscoeff1(3,1) = @coefs(2)
mscoeff1(3,2) = @stderrs(2)
mscoeff1(4,1) = @coefs(5)
mscoeff1(4,2) = @stderrs(5)
matrix mscoeff1a = @vec(@transpose(mscoeff1))


freeze(waldtable_mu0) ms.wald C(1)/(1-C(2))=0
freeze(waldtable_mu1) ms.wald C(4)/(1-C(5))=0
freeze(waldtable_sigma0) ms.wald exp(c(3))=0
freeze(waldtable_sigma1) ms.wald exp(c(6))=0
freeze(waldtable_equal_rho) ms.wald C(2)=C(5)

freeze(tptable) ms.transprobs(type=trans, view=table)


if !probset = 0 then
MS.makergmprobs(type=smooth) prob1 prob2
else
MS.makergmprobs(type=filt) prob1 prob2
endif

genr persistence = prob1*C(2) + prob2*C(5)

matrix(4,2) oos






!coeff = !control + 2

matrix(2,2) coeff1
matrix(!coeff ,2) coeff2
matrix(!coeff -1,2) coeff3
matrix(3,3) info

smpl 1978:1 2022:11
if !persist = 1 then
genr Q = persistence
else
genr Q = prob!switch
endif

if !control = 5 then
group control UNRATE(-!islag) WTI(-!islag) M2G(-!islag) FEDFUNDS(-!islag) dcpi(-!islag)
else
!islag1 = !islag + 1
group control UNRATE(-!islag) WTI(-!islag) M2G(-!islag) FEDFUNDS(-!islag) dcpi(-!islag to -!islag1) Credit(-!islag)
endif

equation pred1.ls(cov=hac, covbwint) Q c pie(-!islag)
for !j = 1 to @ncoef
coeff1(!j,1) = @coefs(!j)
coeff1(!j,2) = @stderrs(!j)
next
matrix coeff1a = @vec(@transpose(coeff1))
info(1,1)=@rbar2
info(2,1)=@aic
info(3,1)=@schwarz


equation pred2.ls(cov=hac, covbwint) Q c pie(-!islag)  control
for !j = 1 to @ncoef
coeff2(!j,1) = @coefs(!j)
coeff2(!j,2) = @stderrs(!j)
next
matrix coeff2a = @vec(@transpose(coeff2))
info(1,2)=@rbar2
info(2,2)=@aic
info(3,2)=@schwarz



equation pred3.ls(cov=hac, covbwint) Q c control
for !j = 1 to @ncoef
coeff3(!j,1) = @coefs(!j)
coeff3(!j,2) = @stderrs(!j)
next
matrix coeff3a = @vec(@transpose(coeff3))
info(1,3)=@rbar2
info(2,3)=@aic
info(3,3)=@schwarz






for !kk = 1 to 4 
!lag= @val(ind(!kk))

if !control = 5 then
group control UNRATE(-!lag) WTI(-!lag) M2G(-!lag) FEDFUNDS(-!lag) dcpi(-!lag) 
else
!lag1 = !lag + 1
group control UNRATE(-!lag) WTI(-!lag) M2G(-!lag) FEDFUNDS(-!lag) dcpi(-!lag to -!lag1) Credit(-!lag)
endif







'genr hstate = (Q>0.5)
'equation probitmodel.binary(d=n) hstate c pie(-!lag) 





smpl spred
genr rest_Qhat = 0.0
genr unrest_Qhat = 0.0

scalar window = @datediff(!pend,!pstart,"mm")


!regstart = @dateval(rstart(!ie))
!regend = @dateval(renddate(1))

'Rolling estimation with FOR Loop
for !k = 0 to window
if !scheme = 0 then
smpl !regstart+!k !rend+!k
else    
smpl !regstart !regend+!k
endif
equation rest.ls Q c control
equation unrest.ls Q c pie(-!lag) control 


smpl !pstart+!k !pstart+!k
rest.fit restf 
unrest.fit unrestf 
genr rest_Qhat =  rest_Qhat + restf
genr unrest_Qhat =  unrest_Qhat + unrestf
next

smpl spred

'MSE
genr u_rest = (Q - rest_Qhat)^2
genr u_unrest = (Q - unrest_Qhat)^2
genr uu = u_rest - (Q - rest_Qhat)*(Q - unrest_Qhat)
scalar mse_rest = @mean(u_rest)
scalar mse_unrest = @mean(u_unrest)
scalar mse_uu = @mean(uu)
scalar msperatio = mse_rest/mse_unrest


' Test Statistics
scalar CM = @obs(u_rest)*mse_uu/mse_unrest
genr d_dm = u_rest   - u_unrest
genr d_cw = u_rest - (u_unrest - (rest_Qhat - unrest_Qhat)^2)
'equation DMtest.ls(cov=hac, covbwint) d_dm c
'equation CWtest.ls(cov=hac, covbwint,nodf) d_cw c   ' To match RATS HAC results
equation CWtest.ls(cov=hac, covbwint) d_cw c
scalar CW = @tstats(1)

oos(!kk,1)=msperatio
oos(!kk,2)=CW
next

smpl @all
freeze(dcpi_plot) DCPI.line
dcpi_plot.delete text
dcpi_plot.addtext(-0.03,-0.18,font(Calibri,14,-b,-i,-u,-s)) %

if !price=0 then
dcpi_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) dcpi_plot_head.pdf
endif
if !price=1 then
dcpi_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) dcpi_plot_pce.pdf
endif
if !price=2 then
dcpi_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) dcpi_plot_core.pdf
endif

if !probset = 0 then
freeze(smooth_plot) prob!switch.line
smooth_plot.delete text
smooth_plot.draw(shade, bottom) if prob!switch>0.5
smooth_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) smooth_plot.pdf
else
freeze(filtered_plot) prob!switch.line
filtered_plot.delete text
filtered_plot.draw(shade, bottom) if prob!switch>0.5
filtered_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) filtered_plot.pdf
endif


smpl 1978:1 2022:11
freeze(mich_plot) mich.line 
mich_plot.delete text
mich_plot.addtext(-0.03,-0.18,font(Calibri,14,-b,-i,-u,-s)) %
mich_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) mich_plot.pdf

group g1 MICH Cleveland
freeze(pie2_plot) g1.line 
pie2_plot.delete text
pie2_plot.name(1) Michigan Survey
pie2_plot.name(2) Cleveland Fed
pie2_plot.legend position(3.81,0.57)
pie2_plot.addtext(-0.03,-0.18,font(Calibri,14,-b,-i,-u,-s)) %
pie2_plot.options linepat
pie2_plot.save(t=pdf, c, box, port, w=6.8, h = 4.3, u=in, d=96, trans) pie2_plot.pdf

