├── Aiyagari1994 ├── Aiyagari1994.m ├── Aiyagari1994.pdf ├── Aiyagari1994_Fn.m └── Aiyagari1994_ReturnFn.m ├── AuerbachKotlikoff1987 ├── AuerbachKotlikoff1987.m ├── AuerbachKotlikoff1987_ConsumptionFn.m ├── AuerbachKotlikoff1987_ReturnFn.m └── AuerbachKotlikoff1987_TotalTaxRevenue.m ├── CastanedaDiazGimenezRiosRull2003 ├── CDGRR2003_ConsumptionFn.m ├── CDGRR2003_ConsumptionFn_ExWealthiest1percent.m ├── CDGRR2003_IncomeTaxRevenueFn.m ├── CDGRR2003_IntergenerationalEarnings.m ├── CDGRR2003_ModelTargetsFn.m ├── CDGRR2003_RatioEarningsOldYoung.m ├── CastanedaDiazGimenezRiosRull2003.m ├── CastanedaDiazGimenezRiosRull2003.pdf ├── CastanedaDiazGimenezRiosRull2003_Create_Exog_Shock.m ├── CastanedaDiazGimenezRiosRull2003_PhiaprimeMatrix.m ├── CastanedaDiazGimenezRiosRull2003_ReturnFn.m └── CastanedaDiazGimenezRiosRull2003_Tables345.m ├── ConesaKrueger1999 ├── ConesaKrueger1999.m ├── ConesaKrueger1999.pdf ├── ConesaKrueger1999_Fn.m ├── ConesaKrueger1999_Ptype_ReturnFn.m ├── ConesaKrueger1999_ReturnFn.m └── tauchenHussey.m ├── DiazGimenezPrescottAlvarezFitzgerald1992 ├── DGPAF1992.pdf ├── DiazGimenezPrescottAlvarezFitzgerald1992.m ├── DiazGimenezPrescottAlvarezFitzgerald1992_ConsumptionFn.m ├── DiazGimenezPrescottAlvarezFitzgerald1992_ReturnFn.m ├── DiazGimenezPrescottAlvarezFitzgerald1992_StationaryDist.m ├── DiazGimenezPrescottAlvarezFitzgerald1992_Table8.m └── DiazGimenezPrescottAlvarezFitzgerald1992_Welfare.m ├── GourioMiao2010 ├── GourioMiao2010.m ├── GourioMiao2010_EarningsFn.m ├── GourioMiao2010_NewEquityFn.m ├── GourioMiao2010_ReturnFn.m └── Replication_GM2010.pdf ├── GuerrieriLorenzoni2017 ├── GuerrieriLorenzoni2017.m ├── GuerrieriLorenzoni2017.pdf ├── GuerrieriLorenzoni2017_ConsumptionFn.m ├── GuerrieriLorenzoni2017_DurableGoods.m ├── GuerrieriLorenzoni2017_DurableGoods_ConsumptionFn.m ├── GuerrieriLorenzoni2017_DurableGoods_ReturnFn.m ├── GuerrieriLorenzoni2017_Fn.m ├── GuerrieriLorenzoni2017_ReturnFn.m ├── GuerrieriLorenzoni2017_altcalibration.m ├── SimulationOfThetaFromGL2017.m └── inc_process.mat ├── Hansen1985 ├── Hansen1985.m ├── Hansen1985.pdf └── Hansen1985_ReturnFn.m ├── HopenhaynRogerson1993 ├── HopenhaynRogerson1993.m ├── HopenhaynRogerson1993.pdf ├── HopenhaynRogerson1993_Fn.m ├── HopenhaynRogerson1993_ReturnFn.m └── HopenhaynRogerson1993_ReturnFn_ChrisEdmonds.m ├── HubbardSkinnerZeldes1994 ├── HubbardSkinnerZeldes1994.m ├── HubbardSkinnerZeldes1994.pdf ├── HubbardSkinnerZeldes1994_ConsumptionFn.m ├── HubbardSkinnerZeldes1994_ReturnFn.m ├── HubbardSkinnerZeldes1994_TRFn.m └── HubbardSkinnerZeldes1994_function.m ├── Huggett1993 ├── Huggett1993.m ├── Huggett1993.pdf ├── Huggett1993_Fn.m └── Huggett1993_ReturnFn.m ├── Huggett1996 ├── Huggett1996.m ├── Huggett1996.pdf ├── Huggett1996_Fn.m └── Huggett1996_ReturnFn.m ├── Imrohoroglu1989 ├── Imrohoroglu1989.m ├── Imrohoroglu1989.pdf ├── Imrohoroglu1989_ConsFn.m ├── Imrohoroglu1989_IncomeFn.m └── Imrohoroglu1989_ReturnFn.m ├── ImrohorogluImrohorogluJoines1995 ├── IIJ1995_absOmega0minusOmega1.m ├── ImrohorogluImrohorogluJoines1995.m ├── ImrohorogluImrohorogluJoines1995.pdf ├── ImrohorogluImrohorogluJoines1995_ConsumptionFn.m ├── ImrohorogluImrohorogluJoines1995_ExogShockFn.m ├── ImrohorogluImrohorogluJoines1995_Fn.m ├── ImrohorogluImrohorogluJoines1995_IncomeFn.m └── ImrohorogluImrohorogluJoines1995_ReturnFn.m ├── KulishKentSmith2010 ├── KulishKentSmith2010.m ├── KulishKentSmith2010_ConsumptionFn.m ├── KulishKentSmith2010_ReturnFn.m └── Replication_KKS2010.pdf ├── LICENSE ├── README.md ├── RestucciaRogerson2008 ├── RestucciaRogerson2008.m ├── RestucciaRogerson2008.pdf ├── RestucciaRogerson2008_Fn.m ├── RestucciaRogerson2008_ReturnFn.m ├── RestucciaRogerson2008_ReturnFn_CapitalTax.m └── RestucciaRogerson2008_ReturnFn_LabourTax.m ├── RestucciaUrrutia2004 ├── RestucciaUrrutia2004.m ├── RestucciaUrrutia2004.pdf ├── RestucciaUrrutia2004_Consumption.m ├── RestucciaUrrutia2004_F.m ├── RestucciaUrrutia2004_FnF.m ├── RestucciaUrrutia2004_FnkappaF.m ├── RestucciaUrrutia2004_HFn.m ├── RestucciaUrrutia2004_PhiaprimeFn.m ├── RestucciaUrrutia2004_ReturnFn.m ├── RestucciaUrrutia2004_TableColumnFn.m ├── RestucciaUrrutia2004_Tables1to4.m ├── RestucciaUrrutia2004_a_gridfn.m ├── RestucciaUrrutia2004_d_gridfn.m ├── RestucciaUrrutia2004_kappaF.m ├── RestucciaUrrutia2004_logEarnings.m └── RestucciaUrrutia2004_z_gridfn.m └── Tauchen1986 └── Tauchen1986.m /Aiyagari1994/Aiyagari1994.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/Aiyagari1994/Aiyagari1994.pdf -------------------------------------------------------------------------------- /Aiyagari1994/Aiyagari1994_Fn.m: -------------------------------------------------------------------------------- 1 | function OutputVector=Aiyagari1994_Fn(n_k,n_z,n_p,Params,vfoptions,simoptions) 2 | %This code replicates the results of Aiyagari (1994) - Uninsured Idiosyncratic Risk and Aggregate Saving 3 | disp('Running Aiyagari1994_Fn') 4 | %% Set up 5 | 6 | 7 | % %Parameters 8 | % CreateIndividualParams(Params) 9 | % whos 10 | 11 | % beta=0.96; %Model period is one-sixth of a year 12 | % alpha=0.36; 13 | % delta=0.08; 14 | % 15 | % mu=1; % {1,3,5} 16 | % sigma=0.2; % {0.2,0.4} 17 | % rho=0; % {0,0.3,0.6,0.9} 18 | 19 | %Create markov process for the exogenous labour productivity, l. 20 | % q=3; %Footnote 33 of Aiyagari(1993WP, pg 25) implicitly says that he uses q=3 21 | [z_grid, pi_z]=TauchenMethod(0,(Params.sigma^2)*(1-Params.rho^2),Params.rho,n_z,Params.q); %[states, transmatrix]=TauchenMethod_Param(mew,sigmasq,rho,znum,q,Parallel,Verbose), transmatix is (z,zprime) 22 | 23 | 24 | %[s_grid, pi_z]=TauchenMethod_Param(0,(sigma^2)*(1-rho^2),rho,7,3); %This is the process for ln(l). Aiyagari uses 7 states, 25 | [z_mean,z_variance,z_corr,~]=MarkovChainMoments(z_grid,pi_z); 26 | z_grid=exp(z_grid); 27 | %Get some info on the markov process 28 | [Expectation_l,~,~,~]=MarkovChainMoments(z_grid,pi_z); %Since l is exogenous, this will be it's eqm value 29 | %Note: Aiyagari (1994) actually then normalizes l by dividing it by 30 | %Expectation_l (so that the resulting process has expectaion equal to 1 31 | %(see Aiyagari (1993WP), footnote 33 pg 25-26). 32 | %The following three lines do just this. 33 | z_grid=z_grid./Expectation_l; 34 | [Expectation_l,~,~,~]=MarkovChainMoments(z_grid,pi_z); 35 | 36 | 37 | %In the absence of idiosyncratic risk, the steady state equilibrium is given by 38 | r_ss=1/Params.beta-1; 39 | K_ss=((r_ss+Params.delta)/Params.alpha)^(1/(Params.alpha-1)); %The steady state capital in the absence of aggregate uncertainty. 40 | 41 | %% Grids 42 | % Set grid for asset holdings 43 | %Aiyagari uses 25 points, but with a piecewise-linear approx. see Aiyagari (1993WP, pg 28). 44 | %His grid is not directly on k, but implicitly his k grid runs from zero up 45 | %to k_max, where k_max is given by f(k_max,1)=delta*k_max 46 | %k_max=delta^(1/(alpha-1)); 47 | %Doing this k_max is slightly less than 10*K_ss. But if I use this as the upper limit on 48 | %the grid the results are wrong (in that increasing this to 15 or 20*K_ss 49 | %gives different results). It might be that Aiyagari gets away with this 50 | %due to his use of piecewise-linear approximation (ie. that policy fn is 51 | %almost linear in this region anyway). 52 | nk1=floor(n_k/3); nk2=floor(n_k/3); nk3=n_k-nk1-nk2; 53 | k_grid=sort([linspace(0,K_ss,nk1),linspace(K_ss+0.0001,3*K_ss,nk2),linspace(3*K_ss+0.0001,15*K_ss,nk3)]'); 54 | 55 | %Set grid for interest rates (Aiyagari proves that with idiosyncratic 56 | %uncertainty, the eqm interest rate is limited above by it's steady state value 57 | %without idiosyncratic uncertainty, that is that r0 12 | if mu==1 13 | F=log(c); 14 | else 15 | F=(c^(1-mu) -1)/(1-mu); 16 | end 17 | end 18 | 19 | end -------------------------------------------------------------------------------- /AuerbachKotlikoff1987/AuerbachKotlikoff1987_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function c=AuerbachKotlikoff1987_ConsumptionFn(l,aprime,a,z,wt,rt,ej,tau_phi,tau_pi,tau_c,tau_w) 2 | % z is unused as model is deterministic 3 | % F=-Inf; 4 | 5 | %c=(1+rt)*a+wt*ej*(1-l)-aprime; % in absence of taxes 6 | TaxableIncome=rt*a+(1-tau_w)*wt*ej*(1-l); 7 | c=(1/(1+tau_c))*((1-(tau_phi+tau_pi*TaxableIncome/2))*TaxableIncome+a-aprime); 8 | % ((tau_phi+tau_pi*TaxableIncome/2) is average tax rate on taxable income 9 | % 10 | % if c>0 11 | % Finner=(c^(1-1/rho)+alpha*l^(1-1/rho))^(1/(1-1/rho)); 12 | % F=(Finner^(1-1/gamma))/(1-1/gamma); 13 | % end 14 | % 15 | % if jj==55 && aprime<0 16 | % F=-Inf; % Impose a_J>=0 17 | % end 18 | 19 | end -------------------------------------------------------------------------------- /AuerbachKotlikoff1987/AuerbachKotlikoff1987_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=AuerbachKotlikoff1987_ReturnFn(l,aprime,a,z,jj,wt,rt,rho,gamma,alpha,ej,tau_phi,tau_pi,tau_c,tau_w) 2 | % z is unused as model is deterministic 3 | F=-Inf; 4 | 5 | %c=(1+rt)*a+wt*ej*(1-l)-aprime; % in absence of taxes 6 | TaxableIncome=rt*a+(1-tau_w)*wt*ej*(1-l); 7 | c=(1/(1+tau_c))*((1-(tau_phi+tau_pi*TaxableIncome/2))*TaxableIncome+a-aprime); 8 | % ((tau_phi+tau_pi*TaxableIncome/2) is average tax rate on taxable income 9 | 10 | if c>0 11 | Finner=(c^(1-1/rho)+alpha*l^(1-1/rho))^(1/(1-1/rho)); 12 | F=(Finner^(1-1/gamma))/(1-1/gamma); 13 | end 14 | 15 | if jj==55 && aprime<0 16 | F=-Inf; % Impose a_J>=0 17 | end 18 | 19 | end -------------------------------------------------------------------------------- /AuerbachKotlikoff1987/AuerbachKotlikoff1987_TotalTaxRevenue.m: -------------------------------------------------------------------------------- 1 | function TotalRevenue=AuerbachKotlikoff1987_TotalTaxRevenue(l,aprime,a,z,wt,rt,ej,tau_phi,tau_pi,tau_c,tau_w,tau_k) 2 | % z is unused as model is deterministic 3 | 4 | %c=(1+rt)*a+wt*ej*(1-l)-aprime; % in absence of taxes 5 | 6 | % Revenue from earnings tax: 7 | Revenue_w=tau_w*wt*ej*(1-l); 8 | 9 | % Revenue from capital income tax 10 | Revenue_capital=tau_k*(1/(1-tau_k)*rt)*a; %rt is after-capital-tax (but before income tax). So 1/(1-tau_k)*rt give the before-capital-tax rate of return on capital 11 | 12 | TaxableIncome=rt*a+(1-tau_w)*wt*ej*(1-l); 13 | % Revenue from income tax: 14 | Revenue_income=(tau_phi+tau_pi*TaxableIncome/2)*TaxableIncome; % ((tau_phi+tau_pi*TaxableIncome/2) is average tax rate on taxable income 15 | 16 | c=(1/(1+tau_c))*((1-(tau_phi+tau_pi*TaxableIncome/2))*TaxableIncome+a-aprime); 17 | % Revenue from consumption tax: 18 | Revenue_c=tau_c*c; 19 | 20 | TotalRevenue=Revenue_w+Revenue_capital+Revenue_income+Revenue_c; 21 | 22 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function c=CDGRR2003_ConsumptionFn(d1_val,d2_val,a_val,s_val,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3) 2 | 3 | %d1_values %h (hours worked) 4 | %d2_values %z 5 | %a_values %a (capital) 6 | %s_indexes %age (& determines retirement) 7 | 8 | w=(1-theta)*(((r+delta)/(theta))^(theta/(theta-1))); 9 | 10 | % Income 11 | % If retired 12 | e=0; 13 | y=a_val*r+e*d1_val*w+omega; 14 | if s_val<=J %If working 15 | e=e1*(s_val==1)+e2*(s_val==2)+e3*(s_val==3)+e4*(s_val==4); 16 | y=a_val*r+e*d1_val*w; 17 | end 18 | 19 | %Income tax revenue 20 | IncomeTax=a0*(y-(y^(-a1)+a2)^(-1/a1))+a3*y; 21 | 22 | c=(y-IncomeTax)+a_val-d2_val; 23 | 24 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_ConsumptionFn_ExWealthiest1percent.m: -------------------------------------------------------------------------------- 1 | function c=CDGRR2003_ConsumptionFn_ExWealthiest1percent(d1_val,d2_val,a_val,s_val,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3,cutoff_wealth1percent) 2 | 3 | %d1_values %h (hours worked) 4 | %d2_values %z 5 | %a_values %a (capital) 6 | %s_indexes %age (& determines retirement) 7 | 8 | w=(1-theta)*(((r+delta)/(theta))^(theta/(theta-1))); 9 | 10 | % Income 11 | % If retired 12 | e=0; 13 | y=a_val*r+e*d1_val*w+omega; 14 | if s_val<=J %If working 15 | e=e1*(s_val==1)+e2*(s_val==2)+e3*(s_val==3)+e4*(s_val==4); 16 | y=a_val*r+e*d1_val*w; 17 | end 18 | 19 | %Income tax revenue 20 | IncomeTax=a0*(y-(y^(-a1)+a2)^(-1/a1))+a3*y; 21 | 22 | c=(y-IncomeTax)+a_val-d2_val; 23 | 24 | % Throw out wealthiest 1 percent. This will be done automatically if we 25 | % return -Inf 26 | if a_val>cutoff_wealth1percent 27 | c=-Inf; 28 | end 29 | 30 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_IncomeTaxRevenueFn.m: -------------------------------------------------------------------------------- 1 | function [IncomeTaxRevenue]=CDGRR2003_IncomeTaxRevenueFn(h,kprime,k,s,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3) 2 | 3 | w=(1-theta)*(((r+delta)/(theta))^(theta/(theta-1))); 4 | 5 | % Income 6 | % If retired 7 | e=0; 8 | y=k*r+e*h*w+omega; 9 | if s<=J %If working 10 | e=e1*(s==1)+e2*(s==2)+e3*(s==3)+e4*(s==4); 11 | y=k*r+e*h*w; 12 | end 13 | 14 | %Income tax revenue 15 | IncomeTaxRevenue=a0*(y-(y^(-a1)+a2)^(-1/a1))+a3*y; 16 | 17 | %c=0; 18 | %c=y+a_val-d1_val; 19 | 20 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_IntergenerationalEarnings.m: -------------------------------------------------------------------------------- 1 | function IntergenerationalEarningsCorr=CDGRR2003_IntergenerationalEarnings(Nsim,StationaryDist, Policy, Phi_aprimeKron, n_d,n_a,n_s,d_grid, pi_s, e,w,J) 2 | % Intergenerational correlation of average lifetime earnings 3 | 4 | % This statistic is calculated by simulation 5 | % Simulate Nsim people 6 | % At birth, people in the model are 21, we need to follow them till age 60, 7 | % so follow them for T=40 periods 8 | 9 | %Some variables we will later need 10 | N_a=prod(n_a); 11 | N_s=prod(n_s); 12 | 13 | Policy=gather(Policy); 14 | pi_s=gather(pi_s); 15 | Phi_aprimeKron=gather(Phi_aprimeKron); 16 | 17 | P=zeros(N_a,N_s,N_a,N_s); %P(a,z,aprime,zprime)=proby of going to (a',z') given in (a,z) 18 | for a_c=1:N_a 19 | for s_c=1:N_s 20 | for sprime_c=1:N_s 21 | d2_c=Policy(1,a_c,s_c); 22 | optaprime=Phi_aprimeKron(d2_c,sprime_c,s_c); 23 | P(a_c,s_c,optaprime,sprime_c)=gather(pi_s(s_c,sprime_c)/sum(pi_s(s_c,:))); 24 | end 25 | end 26 | end 27 | P=reshape(P,[N_a*N_s,N_a*N_s]); 28 | %Now turn P into a cumulative distn 29 | P=cumsum(P,2); 30 | 31 | StationaryDistKron=reshape(gather(StationaryDist),[N_a,N_s]); 32 | 33 | % The actual calculations 34 | AvgIndividualEarnings_Generation1=zeros(Nsim,1); 35 | AvgIndividualEarnings_Generation2=zeros(Nsim,1); 36 | 37 | CumSumSteadyStateDistVec_Old=cumsum(reshape(StationaryDistKron(:,J+1:2*J),[N_a*J,1])); 38 | CumSumSteadyStateDistVec_Old=CumSumSteadyStateDistVec_Old./max(CumSumSteadyStateDistVec_Old); %renormalize so it is a cdf 39 | parfor i=1:Nsim 40 | %First, t=1, they are born to a random position. 41 | %Observe that all old are equally likely to die, thus we use stationary 42 | %distribution to pick a 'random old position', and we then figure out 43 | %where this would leave the newborn (note, set from the old to newborn is random). 44 | [~,DyingIndex]=max(CumSumSteadyStateDistVec_Old>rand(1,1)); 45 | temp=ind2sub_homemade([N_a,J],DyingIndex); a_c=temp(1); s_c_minus_J=temp(2); 46 | s_c=s_c_minus_J+J; %this is to compensate for the fact the DyingIndex is taken only from the old. 47 | %So our old person who is about to die is in [a_c,s_c]. 48 | %currstate=sub2ind_homemade([N_a,N_s],[a_c,s_c]); 49 | %Thus our newborn will be born in exogenous state s_newborn (we have to 'force' death to occour): 50 | pi_temp=cumsum(pi_s(s_c,1:J)); 51 | pi_temp=pi_temp./max(pi_temp); 52 | [~,s_newborn]=max(pi_temp>rand(1,1)); 53 | %And with asset holdings a_newborn: 54 | d2_c=Policy(2,a_c,s_c); 55 | a_newborn=Phi_aprimeKron(d2_c,s_newborn,s_c); 56 | %So newborn is in [a_newborn,s_newborn] 57 | AvgIndividualEarnings=e(s_newborn)*d_grid(Policy(1,a_newborn,s_newborn))*w; 58 | currstate=sub2ind_homemade([N_a,N_s],[a_newborn,s_newborn]); 59 | t=1; 60 | NumOfDeaths=0; 61 | while NumOfDeaths<2 %ie. for this generation and the next 62 | sold_c=s_c; 63 | t=t+1; 64 | [~,currstate]=max(P(currstate,:)>rand(1,1)); 65 | temp=ind2sub_homemade([N_a,N_s],currstate); a_c=temp(1); s_c=temp(2); 66 | if J+1<=sold_c<=2*J && s_c<=J %if individual dies 67 | NumOfDeaths=NumOfDeaths+1; 68 | if NumOfDeaths==1 69 | AvgIndividualEarnings_Generation1(i)=AvgIndividualEarnings; 70 | else 71 | AvgIndividualEarnings_Generation2(i)=AvgIndividualEarnings; 72 | end 73 | AvgIndividualEarnings=e(s_c)*d_grid(Policy(1,a_c,s_c))*w; 74 | t=1; 75 | elseif s_c<=J %If they are still working update their earnings 76 | AvgIndividualEarnings=((t-1)/t)*AvgIndividualEarnings+(1/t)*e(s_c)*d_grid(Policy(1,a_c,s_c))*w; 77 | end 78 | end 79 | end 80 | AvgIndividualEarnings_Generations=[AvgIndividualEarnings_Generation1, AvgIndividualEarnings_Generation2]; 81 | 82 | Cov_old_young=sum(AvgIndividualEarnings_Generations(:,1).*AvgIndividualEarnings_Generations(:,2))/Nsim-(sum(AvgIndividualEarnings_Generations(:,1))/Nsim)*(sum(AvgIndividualEarnings_Generations(:,2))/Nsim); 83 | StdDev_old=sqrt(sum(AvgIndividualEarnings_Generations(:,2).^2)/Nsim-(sum(AvgIndividualEarnings_Generations(:,2))/Nsim)^2); 84 | StdDev_young=sqrt(sum(AvgIndividualEarnings_Generations(:,1).^2)/Nsim-(sum(AvgIndividualEarnings_Generations(:,1))/Nsim)^2); 85 | IntergenerationalEarningsCorr=Cov_old_young/(StdDev_old*StdDev_young); 86 | 87 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_ModelTargetsFn.m: -------------------------------------------------------------------------------- 1 | function ModelTargets=CDGRR2003_ModelTargetsFn(Params, n_d,n_a,n_z,a_grid,ReturnFn, DiscountFactorParamNames,Case2_Type,PhiaprimeParamNames,FnsToEvaluate,GEPriceParamNames,GeneralEqmEqns, vfoptions,simoptions) 2 | 3 | Params.w=(1-Params.theta)*(((Params.r+Params.delta)/(Params.theta))^(Params.theta/(Params.theta-1))); 4 | 5 | %% The following are just directly copied from CastanedaDiazGimenezRiosRull2003 6 | % Since this is just a copy I have removed most of the comments here. 7 | 8 | [e_grid,Gamma,gammastar,gammastarfull]=CastanedaDiazGimenezRiosRull2003_Create_Exog_Shock(Params); 9 | l_grid=linspace(0,Params.elle,n_d(1))'; 10 | 11 | % Bring model into the notational conventions used by the toolkit 12 | d_grid=[l_grid; a_grid]; % Is a 'Case 2' value function problem 13 | z_grid=linspace(1,2*Params.J,2*Params.J)'; %(age (& determines retirement)) 14 | pi_z=Gamma; 15 | 16 | % For 'bad' calibrations it is possible that some elements of pi_z are 17 | % negative, if this occours then simply return that the model targets are 18 | % all equal to zero (which will hopefully be judged as a bad calibration. 19 | if min(min(pi_z))<0 20 | fprintf('Bad parameters as min(min(pi_z))<0: returning ModelTargets as all 10^5 \n') 21 | ModelTargets.GE_InterestRate=10^5; 22 | ModelTargets.GE_GovBudgetBalance=10^5; 23 | ModelTargets.CapitalOutputRatio=10^5; 24 | ModelTargets.GovExpenditureToOutputRatio=10^5; 25 | ModelTargets.TransfersToOutputRatio=10^5; 26 | ModelTargets.ShareOfDisposableTimeAllocatedToMarket=10^5; 27 | ModelTargets.zlowerbarMinus10timesAverageIncome=10^5; 28 | ModelTargets.EstateTaxRevenueAsFractionOfGDP=10^5; 29 | ModelTargets.EffectiveTaxRateOnAverageHHIncome=10^5; 30 | ModelTargets.RatioOfCoeffOfVarForConsumptionToCoeffOfVarForHoursWorked=10^5; 31 | ModelTargets.EarningsGini=10^5; 32 | ModelTargets.EarningsQuintileSharesAsFraction=[0,0,0,0,0]; 33 | ModelTargets.EarningsTopSharesAsFraction=[0,0,0]; 34 | ModelTargets.WealthGini=10^5; 35 | ModelTargets.WealthQuintileSharesAsFraction=[0,0,0,0,0]; 36 | ModelTargets.WealthTopSharesAsFraction=[0,0,0]; 37 | ModelTargets.RatioOfEarningsOldtoYoung=10^5; 38 | ModelTargets.CrossSectionalCorrelationOfIncomeBetweenFathersAndSons=10^5; 39 | return 40 | end 41 | pi_z 42 | sum(pi_z,2) 43 | 44 | l_p=length(GEPriceParamNames); 45 | p=nan(l_p,1); 46 | for ii=1:l_p 47 | p(ii)=Params.(GEPriceParamNames{ii}); 48 | end 49 | 50 | Phi_aprimeMatrix=CastanedaDiazGimenezRiosRull2003_PhiaprimeMatrix(n_d,n_z,a_grid,Params.J,Params.zlowerbar,Params.tauE); 51 | 52 | fprintf('TargetsFn: Solve value fn \n') 53 | [~, Policy]=ValueFnIter_Case2(n_d, n_a, n_z, d_grid, a_grid, z_grid, pi_z, Phi_aprimeMatrix, Case2_Type, ReturnFn, Params, DiscountFactorParamNames, [], PhiaprimeParamNames, vfoptions); 54 | % fprintf('TargetsFn: Some parts of the Policy function: \n') 55 | % [Policy(2,1:10,1);... 56 | % Policy(2,end-9:end,1);... 57 | % Policy(2,1:10,4);... 58 | % Policy(2,end-9:end,4)] 59 | % fprintf('TargetsFn: Value of min(min(min(Policy(2,:,:)))) =%8.2f \n', min(min(min(Policy(2,:,:)))) ) 60 | % fprintf('TargetsFn: Value of max(max(max(Policy(2,:,:)))) =%8.2f \n', max(max(max(Policy(2,:,:)))) ) 61 | % fprintf('TargetsFn: Value of min(min(min(Policy(1,:,:)))) =%8.2f \n', min(min(min(Policy(1,:,:)))) ) 62 | % fprintf('TargetsFn: Value of max(max(max(Policy(1,:,:)))) =%8.2f \n', max(max(max(Policy(1,:,:)))) ) 63 | 64 | fprintf('TargetsFn: Solve stationary dist \n') 65 | StationaryDist=StationaryDist_Case2(Policy,Phi_aprimeMatrix,Case2_Type,n_d,n_a,n_z,pi_z,simoptions); 66 | 67 | temp=min(min(StationaryDist)); 68 | if temp<0 69 | fprintf('TargetsFn: Value of min(min(StationaryDist)) =%8.2f \n', temp ) 70 | fprintf('TargetsFn: Seems that there is some kind of rounding error that sometimes gives min(min(StationaryDist))<0, so have added line to forcibly override this \n') 71 | StationaryDist(StationaryDist<0)=0; 72 | StationaryDist=StationaryDist./sum(sum(StationaryDist)); 73 | fprintf('TargetsFn: (Corrected) Value of min(min(StationaryDist)) =%8.2f \n', min(min(StationaryDist)) ) 74 | end 75 | fprintf('TargetsFn: Total mass of stationary dist=%8.2f \n', sum(sum(StationaryDist))) 76 | 77 | AggVars=EvalFnOnAgentDist_AggVars_Case2(StationaryDist, Policy, FnsToEvaluate, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid); 78 | 79 | % use of real() is a hack that could disguise errors, but I couldn't find why matlab was treating output as complex 80 | AggVarNames=fieldnames(AggVars); % Using GeneralEqmEqns as a struct presupposes using FnsToEvaluate (and hence AggVars) as a stuct 81 | for ii=1:length(AggVarNames) 82 | Params.(AggVarNames{ii})=AggVars.(AggVarNames{ii}).Mean; 83 | end 84 | 85 | GeneralEqmConditionsVec=real(GeneralEqmConditions_Case1_v2(GeneralEqmEqns, Params)); % Note, the GeneralEqmConditions_Case1_v2 actually has nothing to do with Case1 vs Case2 86 | 87 | ModelTargets.GE_InterestRate=GeneralEqmConditionsVec(1); 88 | ModelTargets.GE_GovBudgetBalance=GeneralEqmConditionsVec(2); 89 | 90 | %% Calculate the Estimation Targets 91 | 92 | FnsToEvaluate.K = @(l,kprime,k,s) k; %K 93 | FnsToEvaluate.I = @(l,kprime,k,s,delta) kprime-k*(1-delta); %I 94 | FnsToEvaluate.L = @(l,kprime,k,s,e1,e2,e3,e4) l*(e1*(s==1)+e2*(s==2)+e3*(s==3)+e4*(s==4)); % Efficiency hours worked: L 95 | FnsToEvaluate.H = @(l,kprime,k,s) l; %H 96 | FnsToEvaluate.IncomeTaxRevenue = @(l,kprime,k,s,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3) CDGRR2003_IncomeTaxRevenueFn(l,kprime,k,s,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3); 97 | FnsToEvaluate.Pensions = @(l,kprime,k,s,J,omega) omega*(s>J); % If you are retired you earn pension omega (otherwise it is zero). 98 | FnsToEvaluate.EstateTaxRevenue = @(l,kprime,k,s,J,p_gg,zlowerbar,tauE) (s>J)*(1-p_gg)*tauE*max(kprime-zlowerbar,0); % If you are retired: the probability of dying times the estate tax you would pay 99 | FnsToEvaluate.Consumption = @(l,kprime,k,s,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3) CDGRR2003_ConsumptionFn(l,kprime,k,s,J,r,theta,delta,omega,e1,e2,e3,e4,a0,a1,a2,a3); 100 | AggVars=EvalFnOnAgentDist_AggVars_Case2(StationaryDist, Policy, FnsToEvaluate, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid); 101 | 102 | Y=(AggVars.K.Mean^Params.theta)*(AggVars.L.Mean^(1-Params.theta)); 103 | 104 | ModelTargets.CapitalOutputRatio=AggVars.K.Mean/Y; % K/Y 105 | ModelTargets.GovExpenditureToOutputRatio=(AggVars.IncomeTaxRevenue.Mean+AggVars.EstateTaxRevenue.Mean-AggVars.Pensions.Mean)/Y; 106 | ModelTargets.TransfersToOutputRatio=AggVars.Pensions.Mean/Y; 107 | 108 | ModelTargets.ShareOfDisposableTimeAllocatedToMarket=AggVars.H.Mean/Params.elle; % h % Working one-third of the time...??? 109 | 110 | ModelTargets.zlowerbarMinus10timesAverageIncome=Params.zlowerbar-10*Y; % Not 100 percent sure this is how CDGRR2003 thought of 'average income' in this calibration target. 111 | ModelTargets.EstateTaxRevenueAsFractionOfGDP=AggVars.EstateTaxRevenue.Mean/Y; 112 | ModelTargets.EffectiveTaxRateOnAverageHHIncome=AggVars.IncomeTaxRevenue.Mean/Y; % Not clear from CDGRR2003 if they focus on income tax or all taxes. I focus on income tax. 113 | 114 | AggVarNames=fieldnames(AggVars); 115 | fprintf('Target Fn: Aggregate Variables are \n') 116 | for ii=1:length(AggVarNames) 117 | fprintf(' %s: %8.4f \n',AggVarNames{ii},AggVars.(AggVarNames{ii}).Mean) 118 | end 119 | 120 | FnsToEvaluate2.H=FnsToEvaluate.H; 121 | FnsToEvaluate2.Consumption=FnsToEvaluate.Consumption; 122 | MeanMedianStdDev=EvalFnOnAgentDist_MeanMedianStdDev_Case2(StationaryDist, Policy, FnsToEvaluate2, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid); 123 | 124 | ModelTargets.RatioOfCoeffOfVarForConsumptionToCoeffOfVarForHoursWorked=gather((MeanMedianStdDev.Consumption.StdDev/MeanMedianStdDev.Consumption.Mean)/(MeanMedianStdDev.H.StdDev/MeanMedianStdDev.H.Mean)); % Coefficient of Variation=std deviation divided by mean. 125 | 126 | % Lorenz Curves 127 | FnsToEvaluate3.L=FnsToEvaluate.L; 128 | FnsToEvaluate3.K=FnsToEvaluate.K; 129 | LorenzCurves=EvalFnOnAgentDist_LorenzCurve_Case2(StationaryDist, Policy, FnsToEvaluate3, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid); 130 | % Calculate Distributions of Earnings and Wealth 131 | ModelTargets.EarningsGini=Gini_from_LorenzCurve(LorenzCurves.L); 132 | ModelTargets.EarningsQuintileSharesAsFraction=LorenzCurves.L([20,40,60,80,100])-LorenzCurves.L([1,21,41,61,81]); 133 | ModelTargets.EarningsTopSharesAsFraction=LorenzCurves.L([95,99,100])-LorenzCurves.L([90,95,99]); 134 | ModelTargets.WealthGini=Gini_from_LorenzCurve(LorenzCurves.K); 135 | ModelTargets.WealthQuintileSharesAsFraction=LorenzCurves.K([20,40,60,80,100])-LorenzCurves.K([1,21,41,61,81]); 136 | ModelTargets.WealthTopSharesAsFraction=LorenzCurves.K([95,99,100])-LorenzCurves.K([90,95,99]); 137 | 138 | % The following two model moments are somewhat unusual so required custom functions rather than using more standard VFI toolkit commands. 139 | NSimulations=10^6; 140 | e=[Params.e1,Params.e2,Params.e3,Params.e4,0,0,0,0]; 141 | % Ratio of earnings of 40 year olds to 20 year olds. This is quite complicated to calculate and so required a dedicated script. 142 | ModelTargets.RatioOfEarningsOldtoYoung=CDGRR2003_RatioEarningsOldYoung(NSimulations, StationaryDist, Policy, Phi_aprimeMatrix, n_d,n_a,n_z, d_grid, Gamma, e,Params.w,Params.J); 143 | % Intergenerational correlation coefficient. This is quite complicated to calculate and so required a dedicated script. 144 | ModelTargets.CrossSectionalCorrelationOfIncomeBetweenFathersAndSons=CDGRR2003_IntergenerationalEarnings(NSimulations,StationaryDist, Policy, Phi_aprimeMatrix, n_d,n_a,n_z,d_grid, Gamma, e,Params.w,Params.J); 145 | 146 | % Print out some info on what is going on: 147 | fprintf('Targets Fn: Summary information about what is currently being evaluated \n') 148 | Params 149 | ModelTargets 150 | 151 | 152 | 153 | 154 | 155 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CDGRR2003_RatioEarningsOldYoung.m: -------------------------------------------------------------------------------- 1 | function RatioEarningsOldYoung=CDGRR2003_RatioEarningsOldYoung(Nsim, StationaryDist, Policy, Phi_aprimeMatrix, n_d,n_a,n_s, d_grid, pi_s, e,w,J) 2 | 3 | % Life-cycle profile of earnings 4 | % (avg. earnings of HH aged 46 to 50)/(avg. earnings of HH aged 26 to 30) 5 | 6 | % This statistic is calculated by simulation 7 | % Simulate Nsim people 8 | % At birth, people in the model are 21, we follow them till age 50, 9 | % so follow them for T=30 periods 10 | % Only people who work for all 40 periods are considered in this sample. 11 | % Anyone who retires at any point is deleted from sample and replaced. 12 | 13 | K=3; %I am going to simulate 'K' times as many people as needed, and then just keep all of those who actually did retire 14 | 15 | %Some variables we will later need 16 | N_a=prod(n_a); 17 | N_s=prod(n_s); 18 | 19 | 20 | StationaryDistKron=reshape(StationaryDist,[N_a,N_s]); 21 | CumSumSteadyStateDistVec_Old=cumsum(reshape(StationaryDistKron(:,J+1:2*J),[N_a*J,1])); 22 | CumSumSteadyStateDistVec_Old=gather(CumSumSteadyStateDistVec_Old./max(CumSumSteadyStateDistVec_Old)); %renormalize so it is a cdf 23 | Policy=gather(Policy); 24 | Phi_aprimeMatrix=gather(Phi_aprimeMatrix); 25 | pi_s=gather(pi_s); 26 | 27 | 28 | % The actual calculations 29 | % Note that the sample is taken such that only people who remain workers 30 | % for 40 years are considered (if they retire they are deleted from this 31 | % sample). 32 | IndividualEarnings_Young=zeros(K*Nsim,1); %age 26-30 33 | IndividualEarnings_Old=zeros(K*Nsim,1); %age 46-50 34 | cumsumpi_s=cumsum(pi_s(1:J,:),2); %rows have to add to one anyway 35 | 36 | pi_temp=cumsum(pi_s(J+1:2*J,1:J),2); 37 | pi_temp=pi_temp./(max(pi_temp,[],2)*ones(1,J)); 38 | 39 | 40 | parfor i=1:K*Nsim 41 | TheyRetired=0; 42 | YoungEarnings=zeros(1,20); 43 | OldEarnings=zeros(1,10); 44 | %First, t=1, they are born to a random position. 45 | %Observe that all old are equally likely to die, thus we use stationary 46 | %distribution to pick a 'random old position', and we then figure out 47 | %where this would leave the newborn (note, set from the old to newborn is random). 48 | [~,DyingIndex]=max(CumSumSteadyStateDistVec_Old>rand(1,1)); 49 | temp=ind2sub_homemade([N_a,J],DyingIndex); a_c=temp(1); s_c_minus_J=temp(2); 50 | s_c=s_c_minus_J+J; %this is to compensate for the fact the DyingIndex is taken only from the old. 51 | %So our old person who is about to die is in [a_c,s_c]. 52 | %Thus our newborn will be born in exogenous state s_newborn (we have to 'force' death to occour): 53 | 54 | [~,s_newborn]=max(pi_temp(s_c_minus_J,:)>rand(1,1)); 55 | %And with asset holdings a_newborn: 56 | d2_c=Policy(2,a_c,s_c); 57 | 58 | a_newborn=Phi_aprimeMatrix(d2_c);%s_newborn,s_c); %a_newborn=Phi_aprimeKron(d1_c,s_c,s_newborn); %Actually, can just impose the estate tax directly since this is someone who dies. 59 | 60 | %So newborn is in [a_newborn,s_newborn] 61 | YoungEarnings(1)=e(s_newborn)*d_grid(Policy(1,a_newborn,s_newborn))*w; 62 | a_c=a_newborn; 63 | s_c=s_newborn; 64 | for t=2:20 65 | if s_c>J %Check that they are still working 66 | TheyRetired=1; %If not working mark them as having retired. 67 | else 68 | d2_c=Policy(2,a_c,s_c); 69 | a_c=d2_c; %a_c=Phi_aprimeKron(d1_c,s_c,new_s_c); %Actually, can ignore the estate tax, since we are only looking at people who don't retire (and so cannot die) anyway 70 | [~,s_c]=max(cumsumpi_s(s_c,:)>rand(1,1)); 71 | YoungEarnings(t)=e(s_c)*d_grid(Policy(1,a_c,s_c))*w; 72 | end 73 | 74 | end 75 | if TheyRetired==0 76 | for t=21:30 77 | 78 | if s_c>J %Check that they are still working 79 | TheyRetired=1; %If not working mark them as having retired. 80 | else 81 | d2_c=Policy(2,a_c,s_c); 82 | a_c=d2_c; %a_c=Phi_aprimeKron(d1_c,s_c,new_s_c); %Actually, can ignore the estate tax, since we are only looking at people who don't retire (and so cannot die) anyway 83 | [~,s_c]=max(cumsumpi_s(s_c,:)>rand(1,1)); 84 | OldEarnings(t-20)=e(s_c)*d_grid(Policy(1,a_c,s_c))*w; 85 | end 86 | end 87 | end 88 | if TheyRetired==0 89 | IndividualEarnings_Young(i)=mean(YoungEarnings(6:10)); % YoungEarnings(6:10) corresponds to ages 26-30 90 | IndividualEarnings_Old(i)=mean(OldEarnings(6:10)); % OldEarnings(6:10) corresponds to ages 46-50 91 | % disp('Got one!') 92 | end 93 | end 94 | IndividualEarnings_Young=IndividualEarnings_Young(IndividualEarnings_Young~=0); 95 | IndividualEarnings_Old=IndividualEarnings_Old(IndividualEarnings_Old~=0); 96 | disp('Number of sample points for RatioEarningsOldYoung') 97 | size(IndividualEarnings_Old) 98 | RatioEarningsOldYoung=mean(IndividualEarnings_Old)/mean(IndividualEarnings_Young); 99 | 100 | %One oddity here is that since aging is random, it is possible that 21 to 101 | %60 year olds may be retired. We do not wish to allow for this when 102 | %calculating this statistic. So we only consider people who make it through 103 | %the 40 periods without retiring. 104 | 105 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003.pdf -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003_Create_Exog_Shock.m: -------------------------------------------------------------------------------- 1 | function [e,pi_s,gammastar,gammastarfull]=CastanedaDiazGimenezRiosRull2003_Create_Exog_Shock(Params,vfoptions) 2 | % Creates the transition matrix on the exogenous shocks. 3 | 4 | Parallel=2; 5 | if exist('vfoptions','var') 6 | if isfield(vfoptions,'parallel') 7 | if vfoptions.parallel<2 8 | Parallel=1; 9 | end 10 | end 11 | end 12 | 13 | 14 | % Note, there are both gammastar and gammastarfull 15 | 16 | 17 | e=[1,Params.e2,Params.e3,Params.e4, zeros(1,Params.J)]; %e(s) 18 | if Parallel==2 19 | e=gpuArray(e); 20 | end 21 | 22 | Gamma_ee_11=1-Params.Gamma_ee_12-Params.Gamma_ee_13-Params.Gamma_ee_14-Params.p_eg; 23 | Gamma_ee_22=1-Params.Gamma_ee_21-Params.Gamma_ee_23-Params.Gamma_ee_24-Params.p_eg; 24 | Gamma_ee_33=1-Params.Gamma_ee_31-Params.Gamma_ee_32-Params.Gamma_ee_34-Params.p_eg; 25 | Gamma_ee_44=1-Params.Gamma_ee_41-Params.Gamma_ee_42-Params.Gamma_ee_43-Params.p_eg; 26 | 27 | if Parallel==2 28 | Gamma_ee=gpuArray([Gamma_ee_11, Params.Gamma_ee_12, Params.Gamma_ee_13, Params.Gamma_ee_14; Params.Gamma_ee_21, Gamma_ee_22, Params.Gamma_ee_23, Params.Gamma_ee_24; Params.Gamma_ee_31, Params.Gamma_ee_32, Gamma_ee_33, Params.Gamma_ee_34; Params.Gamma_ee_41, Params.Gamma_ee_42, Params.Gamma_ee_43, Gamma_ee_44]); 29 | Gamma_ee=Gamma_ee./(sum(Gamma_ee,2)*ones(1,Params.J,'gpuArray')); %This is a normalization of Gamma_ee into a probability matrix 30 | else 31 | Gamma_ee=[Gamma_ee_11, Params.Gamma_ee_12, Params.Gamma_ee_13, Params.Gamma_ee_14; Params.Gamma_ee_21, Gamma_ee_22, Params.Gamma_ee_23, Params.Gamma_ee_24; Params.Gamma_ee_31, Params.Gamma_ee_32, Gamma_ee_33, Params.Gamma_ee_34; Params.Gamma_ee_41, Params.Gamma_ee_42, Params.Gamma_ee_43, Gamma_ee_44]; 32 | Gamma_ee=Gamma_ee./(sum(Gamma_ee,2)*ones(1,Params.J)); %This is a normalization of Gamma_ee into a probability matrix 33 | end 34 | % Gamma_ee=Gamma_ee./(1-p_eg); %this would be equivalent to the normalization in the line above 35 | 36 | % Calculate the gammastar's 37 | gammastar=ones(1,Params.J)/Params.J; 38 | for ii=1:5000 39 | gammastar=gammastar*Gamma_ee; 40 | end 41 | 42 | %Now we calculate all of the points for Gamma_re 43 | %Step 1 44 | p_51_Step1=gammastar(1)+Params.phi1*gammastar(2)+Params.phi1^2*gammastar(3)+Params.phi1^3*gammastar(4); 45 | p_52_Step1=(1-Params.phi1)*(gammastar(2)+Params.phi1*gammastar(3)+Params.phi1^2*gammastar(4)); 46 | p_53_Step1=(1-Params.phi1)*(gammastar(3)+Params.phi1*gammastar(4)); 47 | p_54_Step1=(1-Params.phi1)*gammastar(4); 48 | p_61_Step1=(1-Params.phi1)*gammastar(1); 49 | p_62_Step1=Params.phi1*gammastar(1)+gammastar(2)+Params.phi1*gammastar(3)+Params.phi1^2*gammastar(4); 50 | p_63_Step1=(1-Params.phi1)*(gammastar(3)+Params.phi1*gammastar(4)); 51 | p_64_Step1=(1-Params.phi1)*gammastar(4); 52 | p_71_Step1=(1-Params.phi1)*gammastar(1); 53 | p_72_Step1=(1-Params.phi1)*(Params.phi1*gammastar(1)+gammastar(2)); 54 | p_73_Step1=Params.phi1^2*gammastar(1)+Params.phi1*gammastar(2)+gammastar(3)+Params.phi1*gammastar(4); 55 | p_74_Step1=(1-Params.phi1)*gammastar(4); 56 | p_81_Step1=(1-Params.phi1)*gammastar(1); 57 | p_82_Step1=(1-Params.phi1)*(Params.phi1*gammastar(1)+gammastar(2)); 58 | p_83_Step1=(1-Params.phi1)*(Params.phi1^2*gammastar(1)+Params.phi1*gammastar(2)+gammastar(3)); 59 | p_84_Step1=Params.phi1^3*gammastar(1)+Params.phi1^2*gammastar(2)+Params.phi1*gammastar(3)+gammastar(4); 60 | %Step 2 61 | p_51=p_51_Step1+Params.phi2*p_52_Step1+Params.phi2^2*p_53_Step1+Params.phi2^3*p_54_Step1; 62 | p_61=p_61_Step1+Params.phi2*p_62_Step1+Params.phi2^2*p_63_Step1+Params.phi2^3*p_64_Step1; 63 | p_71=p_71_Step1+Params.phi2*p_72_Step1+Params.phi2^2*p_73_Step1+Params.phi2^3*p_74_Step1; 64 | p_81=p_81_Step1+Params.phi2*p_82_Step1+Params.phi2^2*p_83_Step1+Params.phi2^3*p_84_Step1; 65 | p_52=(1-Params.phi2)*(p_52_Step1+Params.phi2*p_53_Step1+Params.phi2^2*p_54_Step1); 66 | p_62=(1-Params.phi2)*(p_62_Step1+Params.phi2*p_63_Step1+Params.phi2^2*p_64_Step1); 67 | p_72=(1-Params.phi2)*(p_72_Step1+Params.phi2*p_73_Step1+Params.phi2^2*p_74_Step1); 68 | p_82=(1-Params.phi2)*(p_82_Step1+Params.phi2*p_83_Step1+Params.phi2^2*p_84_Step1); 69 | p_53=(1-Params.phi2)*(p_53_Step1+Params.phi2*p_54_Step1); 70 | p_63=(1-Params.phi2)*(p_63_Step1+Params.phi2*p_64_Step1); 71 | p_73=(1-Params.phi2)*(p_73_Step1+Params.phi2*p_74_Step1); 72 | p_83=(1-Params.phi2)*(p_83_Step1+Params.phi2*p_84_Step1); 73 | p_54=(1-Params.phi2)*p_54_Step1; 74 | p_64=(1-Params.phi2)*p_64_Step1; 75 | p_74=(1-Params.phi2)*p_74_Step1; 76 | p_84=(1-Params.phi2)*p_84_Step1; 77 | 78 | %Now put these into the matrix 79 | if Parallel==2 80 | Gamma_re=gpuArray([p_51, p_52, p_53, p_54; p_61, p_62, p_63, p_64; p_71, p_72, p_73, p_74; p_81, p_82, p_83, p_84]); 81 | Gamma_re=Gamma_re./(sum(Gamma_re,2)*ones(1,Params.J,'gpuArray')); %This is a normalization of Gamma_re into a probability matrix 82 | 83 | pi_s=[Gamma_ee.*(1-Params.p_eg), diag(Params.p_eg*ones(Params.J,1,'gpuArray')); Gamma_re.*(1-Params.p_gg), diag(Params.p_gg*ones(Params.J,1,'gpuArray'))]; %transmatix is (z,zprime) %dim N_s-by-N_s (s by sprime) 84 | else 85 | Gamma_re=[p_51, p_52, p_53, p_54; p_61, p_62, p_63, p_64; p_71, p_72, p_73, p_74; p_81, p_82, p_83, p_84]; 86 | Gamma_re=Gamma_re./(sum(Gamma_re,2)*ones(1,Params.J)); %This is a normalization of Gamma_re into a probability matrix 87 | 88 | pi_s=[Gamma_ee.*(1-Params.p_eg), diag(Params.p_eg*ones(Params.J,1)); Gamma_re.*(1-Params.p_gg), diag(Params.p_gg*ones(Params.J,1))]; %transmatix is (z,zprime) %dim N_s-by-N_s (s by sprime) 89 | end 90 | % Make doubly sure that rows sum to exactly one (had a rounding error on 91 | % very rare occasions, which was only apparent when solving thousands of 92 | % times as part of calibration codes. 93 | if min(min(pi_s))>=0 94 | fix_pi_z_counter=0; 95 | while (min(sum(pi_s,2))~=1 || max(sum(pi_s,2))~=1) && fix_pi_z_counter<10 96 | if min(abs(sum(pi_s,2)-1)) < 10^(-12) 97 | fprintf('adjusting pi_s so rows sum to 1 (first attempt) \n') 98 | [min(sum(pi_s,2)),max(sum(pi_s,2))] 99 | [min(sum(pi_s,2))-1,max(sum(pi_s,2))-1] 100 | pi_s=pi_s./sum(pi_s,2); 101 | end 102 | % If that does not fix it then try adjusting the diagonals 103 | if min(abs(sum(pi_s,2)-1)) < 10^(-12) 104 | fprintf('adjusting pi_s so rows sum to 1 (second attempt) \n') 105 | [min(sum(pi_s,2)),max(sum(pi_s,2))] 106 | [min(sum(pi_s,2))-1,max(sum(pi_s,2))-1] 107 | pi_s=pi_s-(eye(size(pi_s)).*(sum(pi_s,2)-1)); 108 | end 109 | fix_pi_z_counter=fix_pi_z_counter+1; 110 | % if min(abs(sum(pi_s,2)-1)) < 10^(-12) 111 | % fprintf('adjusting pi_s so rows sum to 1 (third attempt) \n') 112 | % [min(sum(pi_s,2)),max(sum(pi_s,2))] 113 | % [min(sum(pi_s,2))-1,max(sum(pi_s,2))-1] 114 | % pi_s=pi_s./sum(pi_s,2); 115 | % end 116 | end 117 | end 118 | 119 | gammastarfull=ones(1,2*Params.J)/(2*Params.J); 120 | for ii=1:5000 121 | gammastarfull=gammastarfull*pi_s; 122 | end 123 | 124 | 125 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003_PhiaprimeMatrix.m: -------------------------------------------------------------------------------- 1 | function Phi_aprimeKron=CastanedaDiazGimenezRiosRull2003_PhiaprimeMatrix(n_d,n_s,k_grid,J,zlowerbar,tauE,vfoptions) 2 | % Case2_Type==2: a'(d,z,z') 3 | 4 | 5 | Parallel=2; 6 | if exist('vfoptions','var') 7 | if isfield(vfoptions,'parallel') 8 | if vfoptions.parallel<2 9 | Parallel=1; 10 | end 11 | end 12 | end 13 | 14 | N_d=prod(n_d); 15 | N_s=prod(n_s); 16 | k_grid=gather(k_grid); 17 | 18 | Phi_aprimeKron=zeros([N_d,N_s,N_s]); 19 | parfor i=1:N_d 20 | %Next periods assets is what you choose 21 | d_sub=ind2sub_homemade(n_d,i); 22 | d2_c=d_sub(2); 23 | Phi_aprimeKron_d=d2_c*ones([1,N_s,N_s]); 24 | %Unless you have to pay the inhertiance tax, in which case... 25 | if k_grid(d2_c)>=zlowerbar %if the inheritance tax is relevant 26 | tau_e=tauE*(k_grid(d2_c)-zlowerbar); 27 | aprime=k_grid(d2_c)-tau_e; 28 | aprime_c=dsearchn(k_grid,aprime); 29 | Phi_aprimeKron_d(1,J+1:2*J,1:J)=aprime_c*ones(size(Phi_aprimeKron_d(1,J+1:2*J,1:J))); 30 | end 31 | Phi_aprimeKron(i,:,:)=Phi_aprimeKron_d; 32 | end 33 | 34 | if Parallel==2 35 | Phi_aprimeKron=gpuArray(Phi_aprimeKron); 36 | end 37 | 38 | % Was using the following as a check for debugging 39 | % % Check that is seems find 40 | % if sum(sum(sum(Phi_aprimeKron>=1)))~=N_d*N_s*N_s || sum(sum(sum(Phi_aprimeKron<=n_d(2))))~=N_d*N_s*N_s % Every choice for end-of-period assets should map to a specific tomorrows assets, for any today's shock and tomorrow's shock 41 | % fprintf('CastanedaDiazGimenezRiosRull2003_PhiaprimeMatrix: Seems to be a problem with Phi_aprimeKron \n') 42 | % sum(sum(sum(Phi_aprimeKron<1))) 43 | % sum(sum(sum(Phi_aprimeKron>n_d(2)))) 44 | % min(min(min(Phi_aprimeKron))) 45 | % end 46 | 47 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=CastanedaDiazGimenezRiosRull2003_ReturnFn(d1_val, d2_val, a_val, z_val,r,sigma1,sigma2,chi,elle,theta,delta,e1,e2,e3,e4,omega,a0,a1,a2,a3) 2 | % You can include comments in the return function file, but only on 3 | % seperate lines to the commands. If you try putting a comment on the same 4 | % line as a command (and following line is not blank) then this will cause 5 | % an error with the GPU codes. 6 | 7 | w=(1-theta)*(((r+delta)/(theta))^(theta/(theta-1))); 8 | 9 | 10 | % Determine values of e and omega_e as functions of 'age' (z_val) 11 | e=0; 12 | omega_s=0; 13 | if z_val==1 14 | e=e1; 15 | elseif z_val==2 16 | e=e2; 17 | elseif z_val==3 18 | e=e3; 19 | elseif z_val==4 20 | e=e4; 21 | else 22 | omega_s=omega; 23 | end 24 | 25 | % Calculate income and then income after tax 26 | y=a_val*r+e*d1_val*w+omega_s; %eqn 5 27 | 28 | % Calculate income tax 29 | tau_y=a0*(y-a2)+a3*y; 30 | if a1>0 31 | tau_y=a0*(y-(y^(-a1)+a2)^(-1/a1))+a3*y; 32 | end 33 | 34 | % Estate tax is dealt with as part of 'phiaprime' (Case 2 value function problem). 35 | 36 | F=-Inf; 37 | c=a_val+y-tau_y-d2_val; % eqn 4 38 | if c>0 39 | if sigma1==1 40 | F=log(c)+chi*((elle-d1_val)^(1-sigma2))/(1-sigma2); 41 | else 42 | F=(c^(1-sigma1))/(1-sigma1)+chi*((elle-d1_val)^(1-sigma2))/(1-sigma2); 43 | end 44 | end 45 | 46 | end -------------------------------------------------------------------------------- /CastanedaDiazGimenezRiosRull2003/CastanedaDiazGimenezRiosRull2003_Tables345.m: -------------------------------------------------------------------------------- 1 | % Recreates Tables 3, 4, and 5 of CastanedaDiazGimenezRiosRull2003. 2 | % These Tables simply report the calibrated model parameters. 3 | 4 | 5 | FID = fopen('./SavedOutput/LatexInputs/CastanedaDiazGimenezRiosRull2003_Table3.tex', 'w'); 6 | fprintf(FID, 'Parameter Values for the Benchmark Model Economy \\\\ \n'); 7 | fprintf(FID, '\\begin{tabular*}{1.00\\textwidth}{@{\\extracolsep{\\fill}}llr} \n \\hline \\hline \n'); 8 | fprintf(FID, '\\multicolumn{3}{l}{\\sl Preferences} \\\\ \n'); 9 | fprintf(FID, '\\quad Time discount factor \\hspace*{6cm} & $\\beta$ & %8.3f\\\\ \n', Params.beta); 10 | fprintf(FID, '\\quad Curvature of consumption & $\\sigma_1$ & %8.3f\\\\ \n', Params.sigma1); 11 | fprintf(FID, '\\quad Curvature of leisure & $\\sigma_2$ & %8.3f\\\\ \n', Params.sigma2); 12 | fprintf(FID, '\\quad Relative share of consumption and leisure & $\\chi$ & %8.3f\\\\ \n', Params.chi); 13 | fprintf(FID, '\\quad Endowment of productive time & $\\ell$ & %8.3f\\\\ \n', Params.elle); 14 | fprintf(FID, '\\multicolumn{3}{l}{\\sl Age and endowment process} \\\\ \n'); 15 | fprintf(FID, '\\quad Common probability of retiring & $p_{e\\varrho}$ & %8.3f\\\\ \n', Params.p_eg); 16 | fprintf(FID, '\\quad Common probability of dying & $1-p_{\\varrho\\varrho}$ & %8.3f\\\\ \n', 1-Params.p_gg); 17 | fprintf(FID, '\\quad Life cycle earnings profile & $\\phi_1$ & %8.3f\\\\ \n', Params.phi1); 18 | fprintf(FID, '\\quad Intergenerational persistence of earnings & $\\phi_2$ & %8.3f\\\\ \n', Params.phi2); 19 | fprintf(FID, '\\multicolumn{3}{l}{\\sl Technology} \\\\ \n'); 20 | fprintf(FID, '\\quad Capital share of income & $\\theta$ & %8.3f\\\\ \n', Params.theta); 21 | fprintf(FID, '\\quad Capital depreciation rate & $\\delta$ & %8.3f\\\\ \n', Params.delta); 22 | fprintf(FID, '\\multicolumn{3}{l}{\\sl Fiscal policy} \\\\ \n'); 23 | fprintf(FID, '\\quad Government consumption & $G$ & %8.3f\\\\ \n', Params.G); 24 | fprintf(FID, '\\quad Normalized Retirement pensions & $\\omega$ & %8.3f\\\\ \n', Params.omega); 25 | fprintf(FID, '\\quad Income tax function parameters & $a_0$ & %8.3f\\\\ \n', Params.a0); 26 | fprintf(FID, '\\quad & $a_1$ & %8.3f\\\\ \n', Params.a1); 27 | fprintf(FID, '\\quad & $a_2$ & %8.3f\\\\ \n', Params.a2); 28 | fprintf(FID, '\\quad & $a_3$ & %8.3f\\\\ \n', Params.a3); 29 | fprintf(FID, '\\quad Estate tax function parameters: \\\\ \n'); 30 | fprintf(FID, '\\quad \\quad Tax-exempt level & $\\underbar{z}$ & %8.3f\\\\ \n', Params.zlowerbar); 31 | fprintf(FID, '\\quad \\quad Marginal tax rate & $\\tau_{E}$ & %8.3f\\\\ \n', Params.tauE); 32 | fprintf(FID, '\\hline \\hline \n \\end{tabular*} \n'); 33 | fprintf(FID, '\\begin{minipage}[t]{1.00\\textwidth}{\\baselineskip=.5\\baselineskip \\vspace{.3cm} \\footnotesize{ \n'); 34 | fprintf(FID, 'Some minor changes to the precise description of the parameters are made from the original.'); 35 | fprintf(FID, '}} \\end{minipage}'); 36 | fclose(FID); 37 | 38 | %Table for the transition matix 39 | Gamma_ee=Gamma(1:Params.J,1:Params.J)./(1-Params.p_eg); 40 | FID = fopen('./SavedOutput/LatexInputs/CastanedaDiazGimenezRiosRull2003_Table4and5_TransMatrix.tex', 'w'); 41 | fprintf(FID, 'Transition Probabilities of the Process on the Endowment of Efficiency Labor \\\\ \n'); 42 | fprintf(FID, 'Units for Working-Age Households That Remain at Working Age One Period \\\\ \n'); 43 | fprintf(FID, 'Later $\\Gamma_{\\mathcal{E}\\mathcal{E}}$ (\\%%) \\\\ \n'); 44 | fprintf(FID, '\\begin{tabular*}{1.00\\textwidth}{@{\\extracolsep{\\fill}}crrrrrr} \n \\hline \\hline \n'); 45 | fprintf(FID, ' & & & \\multicolumn{4}{c}{{$\\Gamma_{\\cal{E} \\cal{E}}$ {\\footnotesize(\\%%)} From $s$ To $s''$}} \\\\ \n'); 46 | fprintf(FID, ' \\cline{4-7} & $e(s)$ & $\\gamma^*_s$ {\\footnotesize(\\%%)} & $s''=1$ & $s''=2$ & $s''=3$ & $s''=4$ \\\\ \n \\hline \n'); 47 | fprintf(FID, ' $s = 1$ & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f \\\\ \n', Params.e1, 100*gammastarfull(1)/sum(gammastarfull(1:Params.J)),100*Gamma_ee(1,1),100*Gamma_ee(1,2),100*Gamma_ee(1,3),100*Gamma_ee(1,4)); 48 | fprintf(FID, ' $s = 2$ & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f \\\\ \n', Params.e2, 100*gammastarfull(2)/sum(gammastarfull(1:Params.J)),100*Gamma_ee(2,1),100*Gamma_ee(2,2),100*Gamma_ee(2,3),100*Gamma_ee(2,4)); 49 | fprintf(FID, ' $s = 3$ & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f \\\\ \n', Params.e3, 100*gammastarfull(3)/sum(gammastarfull(1:Params.J)),100*Gamma_ee(3,1),100*Gamma_ee(3,2),100*Gamma_ee(3,3),100*Gamma_ee(3,4)); 50 | fprintf(FID, ' $s = 4$ & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f & %8.2f \\\\ \n', Params.e4, 100*gammastarfull(4)/sum(gammastarfull(1:Params.J)),100*Gamma_ee(4,1),100*Gamma_ee(4,2),100*Gamma_ee(4,3),100*Gamma_ee(4,4)); 51 | fprintf(FID, '\\hline \\hline \n \\end{tabular*} \n'); 52 | fclose(FID); 53 | -------------------------------------------------------------------------------- /ConesaKrueger1999/ConesaKrueger1999.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/ConesaKrueger1999/ConesaKrueger1999.pdf -------------------------------------------------------------------------------- /ConesaKrueger1999/ConesaKrueger1999_Ptype_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=ConesaKrueger1999_Ptype_ReturnFn(l,aprime,a,u,zeta,r,tau,epsilon_j,I_j,Tr,SS,theta,alpha,delta,gamma,sigma) 2 | % We don't need w and tau as these can be imputed from the others. 3 | 4 | % Note that epsilon_j and I_j are both dependent on j 5 | 6 | % Rearranging that r=MPK-delta gives the following eqn (MPK is marginal product of capital) 7 | KdivN=((r+delta)/(theta*alpha))^(1/(alpha-1)); 8 | % We know w=MPL (MPL is marginal product of labour) 9 | w=theta*(1-alpha)*(KdivN^alpha); % wage rate (per effective labour unit) 10 | 11 | % Difference in Ptype is exp(u+zeta) instead of eta directly (note that eta=exp(u+zeta) and without Ptypes zeta would just be zero) 12 | eta=exp(u+zeta); 13 | 14 | % Budget constraint 15 | c=I_j*(1-tau)*w*epsilon_j*eta*l+(1+r)*(a+Tr)+(1-I_j)*SS-aprime; 16 | 17 | F=-Inf; 18 | 19 | % both aprime>=0 and 0<=l<=1 are built into the grids 20 | if c>0 21 | F=(((c^gamma)*((1-l)^(1-gamma))).^(1-sigma))/(1-sigma); 22 | end 23 | 24 | end -------------------------------------------------------------------------------- /ConesaKrueger1999/ConesaKrueger1999_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=ConesaKrueger1999_ReturnFn(l,aprime,a,eta,r,tau,epsilon_j,I_j,Tr,SS,theta,alpha,delta,gamma,sigma) 2 | % We don't need w as this can be imputed from the others. 3 | 4 | % Note that epsilon_j and I_j are both dependent on j 5 | 6 | % Rearranging that r=MPK-delta gives the following eqn (MPK is marginal product of capital) 7 | KdivN=((r+delta)/(theta*alpha))^(1/(alpha-1)); 8 | % We know w=MPL (MPL is marginal product of labour) 9 | w=theta*(1-alpha)*(KdivN^alpha); % wage rate (per effective labour unit) 10 | 11 | % Budget constraint 12 | c=I_j*(1-tau)*w*epsilon_j*eta*l+(1+r)*(a+Tr)+(1-I_j)*SS-aprime; 13 | 14 | F=-Inf; %(l by aprime) 15 | 16 | % both aprime>=0 and 0<=l<=1 are built into the grids 17 | if c>0 18 | F=(((c^gamma)*((1-l)^(1-gamma))).^(1-sigma))/(1-sigma); 19 | end 20 | 21 | end -------------------------------------------------------------------------------- /ConesaKrueger1999/tauchenHussey.m: -------------------------------------------------------------------------------- 1 | function [Z,Zprob] = tauchenHussey(N,mu,rho,sigma,baseSigma) 2 | % Function tauchenhussey 3 | % 4 | % Purpose: Finds a Markov chain whose sample paths 5 | % approximate those of the AR(1) process 6 | % z(t+1) = (1-rho)*mu + rho * z(t) + eps(t+1) 7 | % where eps are normal with stddev sigma 8 | % 9 | % Format: {Z, Zprob} = TauchenHussey(N,mu,rho,sigma,m) 10 | % 11 | % Input: N scalar, number of nodes for Z 12 | % mu scalar, unconditional mean of process 13 | % rho scalar 14 | % sigma scalar, std. dev. of epsilons 15 | % baseSigma scalar, std. dev. used to calculate Gaussian 16 | % quadrature weights and nodes, i.e. to build the 17 | % grid. I recommend that you use baseSigma = w*sigma + 18 | % (1-w)*sigmaZ where sigmaZ = sigma/sqrt(1-rho^2), 19 | % and w = 0.5 + rho/4. Tauchen & Hussey recommend 20 | % baseSigma = sigma, and also mention baseSigma = sigmaZ. 21 | % 22 | % Output: Z N*1 vector, nodes for Z 23 | % Zprob N*N matrix, transition probabilities 24 | % 25 | % Martin Floden, Stockholm School of Economics 26 | % January 2007 (updated August 2007) 27 | % 28 | % This procedure is an implementation of Tauchen and Hussey's 29 | % algorithm, Econometrica (1991, Vol. 59(2), pp. 371-396) 30 | 31 | Z=zeros(N,1); 32 | Zprob = zeros(N,N); 33 | 34 | [Z,w] = gaussnorm(N,mu,baseSigma^2); % See note 1 below 35 | 36 | 37 | for i = 1:N 38 | for j = 1:N 39 | EZprime = (1-rho)*mu + rho*Z(i); 40 | Zprob(i,j) = w(j) * norm_pdf(Z(j),EZprime,sigma^2) / norm_pdf(Z(j),mu,baseSigma^2); 41 | end 42 | end 43 | 44 | for i = 1:N 45 | Zprob(i,:) = Zprob(i,:) / sum(Zprob(i,:),2); 46 | end 47 | 48 | a = 1; 49 | 50 | function c = norm_pdf(x,mu,s2) 51 | c = 1/sqrt(2*pi*s2) * exp(-(x-mu)^2/2/s2); 52 | 53 | function [x,w] = gaussnorm(n,mu,s2) 54 | % Find Gaussian nodes and weights for the normal distribution 55 | % n = # nodes 56 | % mu = mean 57 | % s2 = variance 58 | [x0,w0] = gausshermite(n); 59 | x = x0*sqrt(2*s2) + mu; 60 | w = w0 / sqrt(pi); 61 | 62 | 63 | function [x,w] = gausshermite(n) 64 | % Gauss Hermite nodes and weights following "Numerical Recipes for C" 65 | 66 | MAXIT = 10; 67 | EPS = 3e-14; 68 | PIM4 = 0.7511255444649425; 69 | 70 | x = zeros(n,1); 71 | w = zeros(n,1); 72 | 73 | m = floor(n+1)/2; 74 | for i=1:m 75 | if i == 1 76 | z = sqrt((2*n+1)-1.85575*(2*n+1)^(-0.16667)); 77 | elseif i == 2 78 | z = z - 1.14*(n^0.426)/z; 79 | elseif i == 3 80 | z = 1.86*z - 0.86*x(1); 81 | elseif i == 4 82 | z = 1.91*z - 0.91*x(2); 83 | else 84 | z = 2*z - x(i-2); 85 | end 86 | 87 | for iter = 1:MAXIT 88 | p1 = PIM4; 89 | p2 = 0; 90 | for j=1:n 91 | p3 = p2; 92 | p2 = p1; 93 | p1 = z*sqrt(2/j)*p2 - sqrt((j-1)/j)*p3; 94 | end 95 | pp = sqrt(2*n)*p2; 96 | z1 = z; 97 | z = z1 - p1/pp; 98 | if abs(z-z1) <= EPS 99 | break 100 | end 101 | end 102 | if iter>MAXIT 103 | error('too many iterations') 104 | end 105 | x(i) = z; 106 | x(n+1-i) = -z; 107 | w(i) = 2/pp/pp; 108 | w(n+1-i) = w(i); 109 | end 110 | x(:) = x(end:-1:1); 111 | 112 | 113 | % Note 1: If you have Miranda and Fackler's CompEcon toolbox you can use 114 | % their qnwnorm function to obtain quadrature nodes and weights for the 115 | % normal function: [Z,w] = qnwnorm(N,mu,baseSigma^2); 116 | % Compecon is available at http://www4.ncsu.edu/~pfackler/compecon/ 117 | % Otherwise, use gaussnorm as here. -------------------------------------------------------------------------------- /DiazGimenezPrescottAlvarezFitzgerald1992/DGPAF1992.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/DiazGimenezPrescottAlvarezFitzgerald1992/DGPAF1992.pdf -------------------------------------------------------------------------------- /DiazGimenezPrescottAlvarezFitzgerald1992/DiazGimenezPrescottAlvarezFitzgerald1992_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function C=DiazGimenezPrescottAlvarezFitzgerald1992_ConsumptionFn(N_val,Aprime_val,Kprime_val, A_val,K_val, s_val,z_val,phi,e,omega,w1,w2,w3,w4,theta,i_d,i_l,mew,alpha,alpha_k,gamma,tau,psi,delta_r,Experiment) 2 | % A is called a by Diaz-Gimenez, Prescott, Alvarez & Fitzgerald (1992) [renamed so can use VFI toolkit standard notation of 'a' being endogenous state vector] 3 | 4 | C=nan; 5 | 6 | %firstly calculate the values of x_d, x_s (note that this implicitly 7 | %imposes constraint given by eqn 23) 8 | x_d=0; 9 | x_s=0; 10 | if K_val>Kprime_val 11 | % x_d=0; 12 | x_s=phi*(K_val-Kprime_val); 13 | elseif K_val0 25 | d=(1+e)*Aprime_val; 26 | % l=0; 27 | elseif Aprime_val<0 28 | % d=0; 29 | l=-Aprime_val*(1+e); %the minus is because Aprime_val itself is negative 30 | end 31 | 32 | pension=0; 33 | if A_val==0 && K_val==0 && s_val==3 %retired, no assets, no house 34 | pension=omega; 35 | end 36 | 37 | w=nan; 38 | if s_val==1 39 | w=w1; 40 | elseif s_val==2 41 | w=w2; 42 | elseif s_val==3 43 | w=w3; 44 | elseif s_val==4 45 | w=w4; 46 | end 47 | if Experiment==2 48 | if z_val==1 49 | w=w*1.02; 50 | elseif z_val 51 | w=w*0.98; 52 | end 53 | end 54 | 55 | C=A_val+(1-theta)*(w*N_val+d*i_d-l*i_l) + x_s-x_d +l-d+pension-mew*Kprime_val; % Budget constraint: Eqn 20 56 | 57 | % if C>0 %If this is not met, then just leave Fmatrix as -Inf 58 | % if s_val==1 || s_val==2 59 | % if K_val==0 60 | % % The following eqn comes from replacing C1 and C2 with C using FOCs from the problem of choosing between c1 and c2 on middle of pg.550 61 | % % Observe that you can rewrite utility fn as (C1^(1-alpha_k/alpha) * C2^(alpha_k/alpha))^alpha 62 | % % As this is just a monotone transformation of the CES utility formulation you get standard result that you spend 1-alpha_k/alpha fraction of C on C1, and alpha_k/alpha fraction of C on C2 at price of 63 | % % gamma per unit. So C1=(1-alpha_k/alpha)C, C2=(1/gamma)*(alpha_k/alpha)*C. Substitute these and rearrange to get the below expression. 64 | % F=( ( C^alpha * (1-alpha_k/alpha)^(alpha-alpha_k) * (alpha_k/(gamma*alpha))^alpha_k * (tau-N_val)^(1-alpha) )^(1-psi) )/(1-psi); 65 | % 66 | % % Impose collateral constraint (eqn 21) 67 | % if l>phi*Kprime_val*(1+e) 68 | % F=-Inf; 69 | % end 70 | % end 71 | % if K_val>0 %ie. if K=3 72 | % F=( ( C^(alpha-alpha_k) * K_val^alpha_k * (tau-N_val)^(1-alpha) )^(1-psi) )/(1-psi); 73 | % end 74 | % elseif s_val==3 75 | % F=delta_r* ((C^alpha)^(1-psi)) /(1-psi); 76 | % end 77 | % end 78 | 79 | if s_val==4 % If HH is dead, just overrule everything and give zero consumption 80 | C=0; 81 | end 82 | 83 | end -------------------------------------------------------------------------------- /DiazGimenezPrescottAlvarezFitzgerald1992/DiazGimenezPrescottAlvarezFitzgerald1992_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=DiazGimenezPrescottAlvarezFitzgerald1992_ReturnFn(N_val,Aprime_val,Kprime_val, A_val,K_val, s_val,z_val,phi,e,omega,w1,w2,w3,w4,theta,i_d,i_l,mew,alpha,alpha_k,gamma,tau,psi,delta_r,Experiment) 2 | % A is called a by Diaz-Gimenez, Prescott, Alvarez & Fitzgerald (1992) [renamed so can use VFI toolkit standard notation of 'a' being endogenous state vector] 3 | 4 | F=-Inf; 5 | C=nan; 6 | 7 | %firstly calculate the values of x_d, x_s (note that this implicitly 8 | %imposes constraint given by eqn 23) 9 | x_d=0; 10 | x_s=0; 11 | if K_val>Kprime_val 12 | % x_d=0; 13 | x_s=phi*(K_val-Kprime_val); 14 | elseif K_val0 26 | d=(1+e)*Aprime_val; 27 | % l=0; 28 | elseif Aprime_val<0 29 | % d=0; 30 | l=-Aprime_val*(1+e); %the minus is because Aprime_val itself is negative 31 | end 32 | 33 | pension=0; 34 | if A_val==0 && K_val==0 && s_val==3 %retired, no assets, no house 35 | pension=omega; 36 | end 37 | 38 | w=nan; 39 | if s_val==1 40 | w=w1; 41 | elseif s_val==2 42 | w=w2; 43 | elseif s_val==3 44 | w=w3; 45 | elseif s_val==4 46 | w=w4; 47 | end 48 | if Experiment==2 49 | if z_val==1 50 | w=w*1.02; 51 | elseif z_val 52 | w=w*0.98; 53 | end 54 | end 55 | 56 | C=A_val+(1-theta)*(w*N_val+d*i_d-l*i_l) + x_s-x_d +l-d+pension-mew*Kprime_val; % Budget constraint: Eqn 20 57 | 58 | if C>0 %If this is not met, then just leave Fmatrix as -Inf 59 | if s_val==1 || s_val==2 60 | if K_val==0 61 | % The following eqn comes from replacing C1 and C2 with C using FOCs from the problem of choosing between c1 and c2 on middle of pg.550 62 | % Observe that you can rewrite utility fn as (C1^(1-alpha_k/alpha) * C2^(alpha_k/alpha))^alpha 63 | % As this is just a monotone transformation of the CES utility formulation you get standard result that you spend 1-alpha_k/alpha fraction of C on C1, and alpha_k/alpha fraction of C on C2 at price of 64 | % gamma per unit. So C1=(1-alpha_k/alpha)C, C2=(1/gamma)*(alpha_k/alpha)*C. Substitute these and rearrange to get the below expression. 65 | F=( ( C^alpha * (1-alpha_k/alpha)^(alpha-alpha_k) * (alpha_k/(gamma*alpha))^alpha_k * (tau-N_val)^(1-alpha) )^(1-psi) )/(1-psi); 66 | 67 | % Impose collateral constraint (eqn 21) 68 | if l>phi*Kprime_val*(1+e) 69 | F=-Inf; 70 | end 71 | end 72 | if K_val>0 %ie. if K=3 73 | F=( ( C^(alpha-alpha_k) * K_val^alpha_k * (tau-N_val)^(1-alpha) )^(1-psi) )/(1-psi); 74 | end 75 | elseif s_val==3 76 | F=delta_r* ((C^alpha)^(1-psi)) /(1-psi); 77 | end 78 | end 79 | 80 | if s_val==4 % If HH is dead, just overrule everything and give zero utility 81 | F=0; 82 | end 83 | 84 | end -------------------------------------------------------------------------------- /DiazGimenezPrescottAlvarezFitzgerald1992/DiazGimenezPrescottAlvarezFitzgerald1992_StationaryDist.m: -------------------------------------------------------------------------------- 1 | function StationaryDist=DiazGimenezPrescottAlvarezFitzgerald1992_StationaryDist(Policy,Params,n_d,n_a,n_s,n_z,n_sz,n_A_zero,pi_sz) 2 | 3 | % Simulation of the model is highly non-standard due to the combination of 4 | % stochastic death in infinitely lived agents together with their not 5 | % caring about future generations. [Normally would either use 6 | % finite-lifetime, or if using infinite-lived they would be dynasties 7 | % that care about future generations.] 8 | 9 | % Note that for n_z=1 this stationary distribution is also the stationary 10 | % distribution in which all the agents actually find themselves. If n_z>1 11 | % then it does not represent where all the agents actually at any point in 12 | % time (which varies with z and must be simulated for a given path of z) 13 | % but does still represent the asymptotic distribution of agents and so can 14 | % be used to find asymptotic values of many model statistics of interest. 15 | 16 | % The following makes use of some 'internal functions' of the VFI Toolkit 17 | % to deal with the non-standard agent distribution. Most of it is simply a 18 | % minor modification of contents of StationaryDist_Case1(). 19 | simoptions.parallel=2; 20 | simoptions.tolerance=10^(-9); 21 | simoptions.maxit=5*10^4; 22 | PolicyKron=KronPolicyIndexes_Case1(Policy, n_d, n_a, n_sz); 23 | 24 | % Create a stationary dist. Am simply setting it up as if all newborns. 25 | StationaryDist=zeros([n_a,n_sz],'gpuArray'); 26 | StationaryDist(n_A_zero,1,1,:)=Params.phi_1/prod(n_z); 27 | StationaryDist(n_A_zero,1,2,:)=Params.phi_2/prod(n_z); 28 | 29 | N_a=prod(n_a); 30 | N_sz=prod(n_sz); 31 | StationaryDistKron=reshape(StationaryDist,[N_a*N_sz,1]); 32 | 33 | % simoptions.parallel==2 % Using the GPU 34 | optaprime=reshape(PolicyKron(2,:,:),[1,N_a*N_sz]); 35 | 36 | Ptemp=zeros(N_a,N_a*N_sz,'gpuArray'); 37 | Ptemp(optaprime+N_a*(gpuArray(0:1:N_a*N_sz-1)))=1; 38 | Ptran=(kron(pi_sz',ones(N_a,N_a,'gpuArray'))).*(kron(ones(N_sz,1,'gpuArray'),Ptemp)); 39 | 40 | StationaryDistKronOld=zeros(N_a*N_sz,1,'gpuArray'); 41 | SScurrdist=sum(abs(StationaryDistKron-StationaryDistKronOld)); 42 | SScounter=0; 43 | 44 | while SScurrdist>simoptions.tolerance && (100*SScounter)10^(-9) 9 | hold=h; 10 | h=sigma_sz.*w_sz+Params.beta*sigma_sz.*(pi_sz*hold); % might need to be pi_sz' 11 | 12 | hdist=sum(abs(h-hold)); 13 | end 14 | 15 | % Total Wealth of Household 16 | W=zeros(n_A,n_K,n_s,n_z); 17 | for i1=1:n_A 18 | for i2=1:n_K 19 | for i3=1:n_s 20 | for i4=1:n_z 21 | W(i1,i2,i3,i4)=A_grid(i1)+K_grid(i2)+h(i3,i4); 22 | end 23 | end 24 | end 25 | end 26 | 27 | % v1 is the value function computed earlier 28 | 29 | % v2: value of public consumption (note: this code only works for n_z=1) 30 | FnsToEvaluateParamNames=struct(); 31 | FnsToEvaluateParamNames(1).Names={'phi'}; 32 | FnsToEvaluateParamNames(2).Names={'eta_d','eta_l'}; 33 | FnsToEvaluateParamNames(3).Names={'w1','w2'}; 34 | FnsToEvaluateParamNames(4).Names={'phi','e','omega','w1','w2','w3','w4','theta','i_d','i_l','mew','alpha','alpha_k','gamma','tau','psi','delta_r','Experiment'}; 35 | FnsToEvaluateParamNames(5).Names={}; 36 | FnsToEvaluateFn_1 = @(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val,phi) a2prime_val*(a2prime_val-a2_val>0)-phi*a2_val*(a2prime_val-a2_val<0); % Investment (Housing investment) 37 | FnsToEvaluateFn_2 = @(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val,eta_d,eta_l) eta_d*a1_val*(a1_val>0)-eta_l*a1_val*(a1_val<0); % Banking Value Added 38 | FnsToEvaluateFn_3 = @(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val,w1,w2) w1*(s_val==1)*d_val+w2*(s_val==2)*d_val; % Wage income 39 | FnsToEvaluateFn_4 = @(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val,phi,e,omega,w1,w2,w3,w4,theta,i_d,i_l,mew,alpha,alpha_k,gamma,tau,psi,delta_r,Experiment) DiazGimenezPrescottAlvarezFitzgerald1992_ConsumptionFn(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val,phi,e,omega,w1,w2,w3,w4,theta,i_d,i_l,mew,alpha,alpha_k,gamma,tau,psi,delta_r,Experiment); % Goods Consumption of Homeowners 40 | FnsToEvaluateFn_5 = @(d_val,a1prime_val,a2prime_val,a1_val,a2_val,s_val,z_val) a2_val; % Capital (Housing Stock) 41 | FnsToEvaluate={FnsToEvaluateFn_1, FnsToEvaluateFn_2, FnsToEvaluateFn_3, FnsToEvaluateFn_4, FnsToEvaluateFn_5}; 42 | AggVars3=EvalFnOnAgentDist_AggVars_Case1(StationaryDist, Policy, FnsToEvaluate, Params, FnsToEvaluateParamNames, n_d, n_a, n_sz, d_grid, a_grid,sz_grid, 2); 43 | g=8*(AggVars3(3)-(AggVars3(4)+AggVars3(1)+AggVars3(2)+Params.mew*AggVars3(5))); 44 | 45 | v2dist=Inf; 46 | v2=zeros(n_s,n_z); 47 | while v2dist>10^(-9) 48 | v2old=v2; 49 | v2=sigma_sz*Params.delta_g*(g^(Params.alpha*(1-Params.psi)))/(1-Params.psi)+Params.beta*sigma_sz.*(pi_sz*v2old); 50 | 51 | v2dist=sum(abs(v2-v2old)); 52 | end 53 | v2=real(v2); % for some reason matlab is making them complex numbers even though imaginary component is 0 54 | v2=gather(v2); 55 | 56 | % V= v1+v2 57 | v1=gather(V); 58 | ValueFnofPublicandPrivateConsumption=zeros(n_A,n_K,n_s,n_z); 59 | for i1=1:n_A 60 | for i2=1:n_K 61 | for i3=1:n_s 62 | for i4=1:n_z 63 | ValueFnofPublicandPrivateConsumption(i1,i2,i3,i4)=v1(i1,i2,i3,i4)+v2(i3,i4); 64 | end 65 | end 66 | end 67 | end 68 | 69 | end -------------------------------------------------------------------------------- /GourioMiao2010/GourioMiao2010_EarningsFn.m: -------------------------------------------------------------------------------- 1 | function earnings=GourioMiao2010_EarningsFn(dividend,kprime,k,z,w,alpha_k,alpha_l) 2 | % Whether we set it up so that dividends or equity issuance is the decision 3 | % variable is unimportant, here I use dividends as the decision variable. 4 | 5 | % Note: r is not needed anywhere here, it is relevant to the firm via the discount factor. 6 | 7 | % We can solve a static problem to get the firm labor input 8 | l=(w/(alpha_l*z*(k^alpha_k)))^(1/(alpha_l-1)); % This is just w=Marg. Prod. Labor, but rearranged 9 | 10 | % Output 11 | y=z*(k^alpha_k)*(l^alpha_l); 12 | 13 | % Profit 14 | profit=y-w*l; 15 | 16 | earnings=profit; 17 | 18 | % Note: earnings is "before tax earnings" and is defined on line 67 of GM2010 code divGEstatdis.m. 19 | % earnings = exp(z)*(Anorm*k^alpha)^(1/(1-nu)) *(nu/wage)^(nu/(1-nu)) *(1-nu) 20 | % nu is their alpha_l, alpha is there alpha_k. 21 | % This is the same as what I call profit (their formula actually assumes 22 | % you are in general eqm so profit=(1-alpha_l)*y. My formulation does not assume this. 23 | 24 | end 25 | -------------------------------------------------------------------------------- /GourioMiao2010/GourioMiao2010_NewEquityFn.m: -------------------------------------------------------------------------------- 1 | function s=GourioMiao2010_NewEquityFn(dividend,kprime,k,z,w,delta,alpha_k,alpha_l,capadjconstant,tau_corp,phi) 2 | % Whether we set it up so that dividends or equity issuance is the decision 3 | % variable is unimportant, here I use dividends as the decision variable. 4 | 5 | % Note: r is not needed anywhere here, it is relevant to the firm via the discount factor. 6 | 7 | % We can solve a static problem to get the firm labor input 8 | l=(w/(alpha_l*z*(k^alpha_k)))^(1/(alpha_l-1)); % This is just w=Marg. Prod. Labor, but rearranged 9 | 10 | % Output 11 | y=z*(k^alpha_k)*(l^alpha_l); 12 | 13 | % Profit 14 | profit=y-w*l; 15 | 16 | % Investment 17 | invest=kprime-(1-delta)*k; 18 | 19 | % Capital-adjustment costs 20 | capitaladjcost=(capadjconstant/2)*(invest^2)/k; 21 | 22 | % Taxable corporate income 23 | T=profit-delta*k-phi*capitaladjcost; 24 | % -delta*k: investment expensing 25 | % phi is the fraction of capitaladjcost that can be deducted from corporate taxes (=0 in GM2010 baseline) 26 | 27 | % Firms financing constraint gives the new equity issuance 28 | s=dividend+invest+capitaladjcost-(profit-tau_corp*T); 29 | 30 | end 31 | -------------------------------------------------------------------------------- /GourioMiao2010/GourioMiao2010_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=GourioMiao2010_ReturnFn(dividend,kprime,k,z,w,delta,alpha_k,alpha_l,capadjconstant,tau_corp,phi,tau_d,tau_cg) 2 | % Whether we set it up so that dividends or equity issuance is the decision 3 | % variable is unimportant, here I use dividends as the decision variable. 4 | 5 | % Note: r is not needed anywhere here, it is relevant to the firm via the discount factor. 6 | 7 | F=-Inf; 8 | 9 | % We can solve a static problem to get the firm labor input 10 | l=(w/(alpha_l*z*(k^alpha_k)))^(1/(alpha_l-1)); % This is just w=Marg. Prod. Labor, but rearranged 11 | 12 | % Output 13 | y=z*(k^alpha_k)*(l^alpha_l); 14 | 15 | % Profit 16 | profit=y-w*l; % =(1-alpha_l)*y in the general eqm 17 | 18 | % Investment 19 | invest=kprime-(1-delta)*k; 20 | 21 | % Capital-adjustment costs 22 | capitaladjcost=(capadjconstant/2)*(invest^2)/k; 23 | 24 | % Taxable corporate income 25 | T=profit-delta*k-phi*capitaladjcost; 26 | % -delta*k: investment expensing 27 | % phi is the fraction of capitaladjcost that can be deducted from corporate taxes (=0 in GM2010 baseline) 28 | 29 | % Firms financing constraint gives the new equity issuance 30 | s=dividend+invest+capitaladjcost-(profit-tau_corp*T); 31 | 32 | % Firms per-period objective 33 | if s>=0 % enforce that 'no share repurchases allowed' 34 | F=((1-tau_d)/(1-tau_cg))*dividend-s; 35 | end 36 | 37 | % Note: dividend payments cannot be negative is enforced by the grid on dividends which has a minimum value of zero 38 | 39 | 40 | %% GM2010: 41 | % Define XXX=(z*Anorm*k^alpha)^(1/(1-nu)) *(1-nu) 42 | % Define YYY=delta*tauc*k+(1-delta)*k-kprime-capitaladjcost -fc*notchangingcap + slowerbar 43 | % where Anorm=1 44 | % slowerbar=0, is the repurchase constraint, s=slowerbar; it is also minus the s required if the dividend is zero. 49 | % 50 | % They then define 51 | 52 | % Note: XXX*(nu/wage)^(nu/(1-nu)) is y*(1-nu) which is profits (assumes general eqm wage). 53 | % Hence divifszero is essentially my line 30, impose s=0 and then you get 54 | % dividend=(1-tauc)*profit+((1-delta)*k-kprime)+capitaladjcost-tau_corp(-delta*k-phi*capitaladjcost), 55 | % which is now like their (1-tauc)*XXX*stuff+YYY 56 | 57 | % Pretty sure they mess this up as it is only true that you can do the 58 | % profits=(1-nu)*y trick if wage is the optimal wage. But it is typically 59 | % not the optimal wage. 60 | % However, in general eqm it should not matter as long as they have the correct w. 61 | 62 | % They find a general eqm wage of 1.2606 63 | 64 | end 65 | -------------------------------------------------------------------------------- /GourioMiao2010/Replication_GM2010.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/GourioMiao2010/Replication_GM2010.pdf -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/GuerrieriLorenzoni2017/GuerrieriLorenzoni2017.pdf -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function c=GuerrieriLorenzoni2017_ConsumptionFn(d, aprime, a, z, r, v, B, Bprime) 2 | 3 | % Guerrieri & Lorenzoni (2017) refer to: d as n_it, aprime as bit+1, a as b_it, and z as theta_it. 4 | 5 | % In steady-state we know that tau=u*v+r/(1+r)*B 6 | tau=0.0607*v+B-(1/(1+r))*Bprime; % From pg 1434, notice that q_t=1/(1+r) 7 | % In steady-state we know that tau=u*v+r/(1+r)*B, as Bprime=B, so the formula could be simplified. 8 | % But this more general form will allow us to later do the 'Fiscal Policy' transitions. 9 | % Tax and transfers: 10 | tau_tilde=tau-v*(z==0); % Note: by definition z cannot actually be negative 11 | 12 | c=a+z*d-tau_tilde-(1/(1+r))*aprime; % q=1/(1+r) 13 | % if c>0 14 | % % Note: this won't work if gamma=1 or eta=1 15 | % F=(c^(1-gamma) -1)/(1-gamma)+psi*(c^(1-eta) -1)/(1-eta); 16 | % end 17 | % 18 | % % Impose borrowing constraint 19 | % if aprime_val<-phi 20 | % F=-Inf; 21 | % end 22 | 23 | end -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_DurableGoods.m: -------------------------------------------------------------------------------- 1 | function Output=GuerrieriLorenzoni2017_DurableGoods(figurenumber,Params,n_d,n_a,n_k,d_grid,a_grid, T, ParamPath, heteroagentoptions, transpathoptions, vfoptions, simoptions) 2 | % Replicates the results of Guerrieri & Lorenzoni (2017) - Credit Crises, Precautionary Savings, and the Liquidity Trap 3 | % For the Durable Goods model of Section 7. 4 | 5 | %% To translate durable goods model in Section 7 of Guerrieri & Lorenzoni (2017) into the standard setup of VFI Toolkit I use following: 6 | % d variables: n_it 7 | % aprime variables: b_it+1, k_it+1 8 | % a variables: b_it, k_it 9 | % z variables: theta_it, e_it 10 | 11 | % Keep the initial value of whatever the ParamPath parameter is 12 | % There is only one, but am just going to allow for possibility of multiple anyway 13 | ParamPathNames=fieldnames(ParamPath); 14 | for ii=1:length(ParamPathNames) % Note: it is actually just length 1, but whatever 15 | initialvalforParamPathParams(ii)=Params.(ParamPathNames{ii}); 16 | end 17 | 18 | %% Set some basic variables 19 | 20 | % For durable goods model GL2017 reduce the grid size to 5 for the productivity shock on theta, and set tauchenq=1. 21 | % Following is really just copy-paste from main script, just redoing with different n_theta value and tauchenq value. 22 | n_theta=6; 23 | % Params.tauchenq=1; % Done in main script 24 | [theta1_grid,pi_theta1]=discretizeAR1_Tauchen(0,Params.rho,sqrt(Params.sigmasq_epsilon),n_theta-1,Params.tauchenq); 25 | z_grid=[0; exp(theta1_grid)]; 26 | pistar_theta1=ones(n_theta-1,1)/(n_theta-1); 27 | for ii=1:10^4 % G&L2017, pg 1438 "when first employed, workers draw theta from its unconditional distribution" 28 | pistar_theta1=pi_theta1'*pistar_theta1; % There is a more efficient form to do this directly from a formula but I am feeling lazy. %FIX THIS LATER!!! 29 | end 30 | pi_z=[(1-Params.pi_ue), Params.pi_ue*pistar_theta1'; Params.pi_eu*ones(n_theta-1,1),(1-Params.pi_eu)*pi_theta1]; 31 | pi_z=pi_z./sum(pi_z,2); 32 | pistar_z=ones(n_theta,1)/n_theta; 33 | for ii=1:10^4 % % There is a more efficient way to do this directly from a formula but I am feeling lazy. %FIX THIS LATER!!! 34 | pistar_z=pi_z'*pistar_z; % Formula could be used to find stationary dist of the employment unemployment process, then just combine with stationary dist of theta1, which is already calculated 35 | end 36 | z_grid=z_grid/sum(z_grid.*pistar_z); 37 | 38 | %% Grids 39 | % Set grid for durable good holdings 40 | Params.klowerbar=0; 41 | k_grid=(Params.kupperbar-Params.klowerbar)*(1/(exp(1)-1))*(exp(linspace(0,1,n_k)')-1)+Params.klowerbar; 42 | 43 | % Switch endogenous states into form required by VFI Toolkit 44 | n_a=[n_a,n_k]; 45 | a_grid=[a_grid;k_grid]; 46 | n_z=n_theta; 47 | 48 | FnsToEvaluate.Aprime = @(d,aprime,kprime,a,k,z) aprime; % Aggregate assets (which is this periods state) 49 | GeneralEqmEqns.BondMarketClearence = @(Aprime,Bprime) Aprime-Bprime; %The requirement that the aggregate assets (lending and borrowing) equal zero 50 | 51 | %% 52 | DiscountFactorParamNames={'beta'}; 53 | 54 | % Change the durable goods return function. 55 | ReturnFn=@(d, aprime, kprime, a, k, z,r, alpha, gamma, psi, eta, phi_k,delta, zeta, chi, v, B, Bprime,omega) ... 56 | GuerrieriLorenzoni2017_DurableGoods_ReturnFn(d, aprime, kprime, a, k, z,r, alpha, gamma, psi, eta, phi_k,delta, zeta, chi, v, B, Bprime, omega); 57 | 58 | %% Solve the initial stationary equilibrium 59 | simoptions.iterate=0; % Iterating runs out of memory, just use simulation 60 | 61 | %Use the toolkit to find the equilibrium price index 62 | GEPriceParamNames={'r'}; 63 | 64 | fprintf('Calculating initial eqm (for durable goods) \n') 65 | p_eqm_initial=HeteroAgentStationaryEqm_Case1(n_d, n_a, n_z, [], pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames,heteroagentoptions, simoptions, vfoptions); 66 | Params.r=p_eqm_initial.r; 67 | [~,Policy_initial]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions); 68 | StationaryDist_initial=StationaryDist_Case1(Policy_initial,n_d,n_a,n_z,pi_z, simoptions); 69 | AggVars_initial=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_initial, Policy_initial, FnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid,2); 70 | 71 | save ./SavedOutput/GuerrieriLorenzoni2017_durablegoods_initial.mat Params p_eqm_initial StationaryDist_initial AggVars_initial Policy_initial 72 | 73 | %% Final stationary equilibrium 74 | % Only change is 75 | % ParamPathNames=fieldnames(ParamPath); % Done above 76 | for ii=1:length(ParamPathNames) % Note: it is actually just length 1, but whatever 77 | temp=ParamPath.(ParamPathNames{ii}); 78 | Params.(ParamPathNames{ii})=temp(end); 79 | end 80 | 81 | fprintf('Calculating final eqm (for durable goods) \n') 82 | p_eqm_final=HeteroAgentStationaryEqm_Case1(n_d, n_a, n_z, [], pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames,heteroagentoptions, simoptions, vfoptions); 83 | Params.r=p_eqm_final.r; 84 | [V_final,Policy_final]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions); 85 | StationaryDist_final=StationaryDist_Case1(Policy_final,n_d,n_a,n_z,pi_z, simoptions); 86 | AggVars_final=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_final, Policy_final, FnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid,2); 87 | 88 | save ./SavedOutput/GuerrieriLorenzoni2017_durablegoods_final.mat Params p_eqm_final StationaryDist_final AggVars_final Policy_final 89 | 90 | %% 91 | % Free up space on gpu 92 | clear StationaryDist_final 93 | 94 | %% Compute the transition path 95 | 96 | fprintf('Calculating general eqm transitiona (for durable goods) \n') 97 | 98 | % We need to give an initial guess for the price path on interest rates 99 | PricePath0.r=[linspace(p_eqm_initial.r, p_eqm_final.r, floor(T/2))'; p_eqm_final.r*ones(T-floor(T/2),1)]; % PricePath0 is matrix of size T-by-'number of prices' 100 | 101 | % Rewrite the aggregate variable to be next period bonds rather than current bonds as this is the actual 102 | % timing of the decision which the interest rate (r) effects 103 | TransPathFnsToEvaluate.Aprime = @(d, aprime,kprime,a,k,z) aprime; % Aggregate assets decisions 104 | % Rewrite the General Eqm conditions as rules for updating the price 105 | TransPathGeneralEqmEqns.BondMarket = @(Aprime,Bprime) Aprime-Bprime; % New interest rate is previous minus 0.1 times excess of bonds (I just guessed 0.1 as being pretty conservative, remember that the transition path will anyway do 0.1 new + 0.9 old price when updating at each iteration) 106 | 107 | transpathoptions.GEnewprice=3; % 3 allows you to say which general eqm eqn is used to update which general eqm price/param, and how 108 | transpathoptions.GEnewprice3.howtoupdate=... % a row is: GEcondn, price, add, factor 109 | {'BondMarket','r',0,0.01};... % first GE condition will be positive if r is too big (as this will lead to too much Aprime), so subtract 110 | % Note: the update is essentially new_price=price+factor*add*GEcondn_value-factor*(1-add)*GEcondn_value 111 | % Notice that this adds factor*GEcondn_value when add=1 and subtracts it what add=0 112 | % A small 'factor' will make the convergence to solution take longer, but too large a value will make it 113 | % unstable (fail to converge). Technically this is the damping factor in a shooting algorithm. 114 | 115 | 116 | 117 | PricePath=TransitionPath_Case1(PricePath0, ParamPath, T, V_final, StationaryDist_initial, n_d, n_a, n_z, pi_z, d_grid,a_grid,z_grid, ReturnFn, TransPathFnsToEvaluate, TransPathGeneralEqmEqns, Params, DiscountFactorParamNames,transpathoptions,vfoptions,simoptions); 118 | 119 | save ./SavedOutput/GuerrieriLorenzoni2017_durablegoods_transition.mat PricePath 120 | 121 | DurableGoodsFigFnsToEvaluate.output = @(d, aprime, kprime,a,k,z) d*z; % y_it=n_it*theta_it Note that since gov budget is balanced every period it neither adds nor subtracts (unemployment benefits + interest payments on B=lump-sum tax revenue) 122 | DurableGoodsFigFnsToEvaluate.durablespurchases = @(d, aprime, kprime,a,k,z,delta) kprime-delta*k; % am not certain of this definition for "purchases" 123 | DurableGoodsFigFnsToEvaluate.nondurablespurchases = @(d, aprime, kprime,a,k,z,r, delta, zeta, chi, v, B, Bprime) GuerrieriLorenzoni2017_DurableGoods_ConsumptionFn(d, aprime, kprime,a,k,z,r, delta, zeta, chi, v, B, Bprime); 124 | 125 | AggVars_initial=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_initial, Policy_initial, DurableGoodsFigFnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid); 126 | AggVarsPath=EvalFnOnTransPath_AggVars_Case1(DurableGoodsFigFnsToEvaluate,PricePath, ParamPath, Params, T, V_final, StationaryDist_initial, n_d, n_a, n_z, pi_z, d_grid, a_grid,z_grid, DiscountFactorParamNames, ReturnFn,transpathoptions); 127 | 128 | Output_pch=([AggVars_initial.output.Mean; AggVarsPath.output.Mean]-AggVars_initial.output.Mean)/AggVars_initial.output.Mean; 129 | durablespurchases_pch=([AggVars_initial.durablespurchases.Mean; AggVarsPath.durablespurchases.Mean]-AggVars_initial.durablespurchases.Mean)/AggVars_initial.durablespurchases.Mean; 130 | nondurablespurchases_pch=([AggVars_initial.nondurablespurchases.Mean; AggVarsPath.nondurablespurchases.Mean]-AggVars_initial.nondurablespurchases.Mean)./AggVars_initial.nondurablespurchases.Mean; 131 | 132 | % figure(figurenumber) 133 | % % First parameter in ParamPath 134 | % subplot(2,2,1); plot(0:1:T,[initialvalforParamPathParams(1); ParamPath.(ParamPathNames{1})]) 135 | % % interest rate 136 | % subplot(2,2,2); plot(0:1:T,[p_eqm_initial.r; PricePath.r]) 137 | % % output 138 | % subplot(2,2,3); plot(0:1:T,4*100*Output_pch) 139 | % % durable and nondurable purchases 140 | % subplot(2,2,4); plot(0:1:T,durablespurchases_pch,0:1:T,nondurablespurchases_pch) 141 | % saveas(gcf,['./SavedOutput/Graphs/GuerrieriLorenzoni2017_Figure',num2str(figurenumber),'.pdf']) 142 | save(['./SavedOutput/GL2017_fig',num2str(figurenumber),'.mat'],'initialvalforParamPathParams','ParamPath','p_eqm_initial','PricePath','Output_pch','durablespurchases_pch','nondurablespurchases_pch','T','AggVars_initial','AggVarsPath') 143 | 144 | Output.p_eqm_initial=p_eqm_initial; 145 | Output.PricePath=PricePath; 146 | Output.initialvalforParamPathParams=initialvalforParamPathParams; 147 | Output.ParamPath=ParamPath; 148 | Output.Output_pch=Output_pch; 149 | Output.durablespurchases_pch=durablespurchases_pch; 150 | Output.nondurablespurchases_pch=nondurablespurchases_pch; 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_DurableGoods_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function F=GuerrieriLorenzoni2017_DurableGoods_ConsumptionFn(d, a1prime, a2prime, a1, a2, z, r, delta, zeta, chi, v, B, Bprime) 2 | 3 | % Guerrieri & Lorenzoni (2017) refer to: d as n_it, a1prime as bit+1, a2prime as kit+1, a1 as b_it, a2 as k_it, and z as theta_it. 4 | % omega is the 'wedge' induced by stick wages in the New Keynesian version 5 | % of model in Section 4 of GL (2017), pg 1450. Notice that when omega=0 it 6 | % plays no role and this is the case in the rest of the paper. 7 | % So a2 is durable consumption good, a1 is non-durable consumption good 8 | 9 | tau=0.0607*v+B-(1/(1+r))*Bprime; % From pg 1434, notice that q_t=1/(1+r) 10 | % In steady-state we know that tau=u*v+r/(1+r)*B, as Bprime=B, so the formula could be simplified. 11 | % But this more general form will allow us to later do the 'Fiscal Policy' transitions. 12 | 13 | % Tax and transfers: 14 | tau_tilde=tau-v*(z==0); % Note: by definition z cannot actually be negative 15 | 16 | % Adjustment costs g(k_t+1,kt) [pg 48 of online appendix to GL2017] 17 | gk=(a2prime-a2+delta*a2)*(a2prime>=a2)+((1-zeta)*(a2prime-a2)+delta*a2)*(a2prime0)*(1/(1+r))*a1prime-gk; % q=1/(1+r) 27 | % % Note: as well as adding capital adjustment cost gk, also introduce intermediation cost between borrowing and lending cost (1-zeta)*(a1prime_val<0) 28 | % if c>0 && k>0 29 | % % Note: this won't work if gamma=1 or eta=1 30 | % F=(((c^alpha)*(k^(1-alpha)))^(1-gamma))/(1-gamma)+(1/(1-omega))*psi*((1-d_val)^(1-eta))/(1-eta); 31 | % end 32 | % 33 | % % Impose borrowing constraint (now a collateral constraint) 34 | % if a1prime_val<-phi_k*a2prime_val 35 | % F=-Inf; 36 | % end 37 | 38 | end -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_DurableGoods_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=GuerrieriLorenzoni2017_DurableGoods_ReturnFn(d, bprime, kprime, b, k, z, r, alpha, gamma, psi, eta, phi_k, delta, zeta, chi, v, B, Bprime, omega) 2 | 3 | % Guerrieri & Lorenzoni (2017) refer to: d as n_it, bprime_val as b_it+1, 4 | % kprime_val as k_it+1, b_val as b_it, k_val as k_it, and z_val as theta_it. 5 | % omega is the 'wedge' induced by sticky wages in the New Keynesian version 6 | % of model in Section 4 of GL (2017), pg 1450. Notice that when omega=0 it 7 | % plays no role and this is the case in the rest of the paper. 8 | % So k is durable consumption good, b is non-durable consumption good 9 | 10 | tau=0.0607*v+B-(1/(1+r))*Bprime; % From pg 1434, notice that q_t=1/(1+r) 11 | % In steady-state we know that tau=u*v+r/(1+r)*B, as Bprime=B, so the formula could be simplified. 12 | % But this more general form will allow us to later do the 'Fiscal Policy' transitions. 13 | 14 | % Tax and transfers: 15 | tau_tilde=tau-v*(z==0); % Note: by definition z cannot actually be negative 16 | 17 | % Adjustment costs g(k_t+1,kt) [pg 48 of online appendix to GL2017] 18 | gk=(kprime-k+delta*k)*(kprime>=k)+((1-zeta)*(kprime-k)+delta*k)*(kprime0)*(1/(1+r))*bprime-gk; % q=1/(1+r) 28 | % Note: as well as adding capital adjustment cost gk, also introduce intermediation cost between borrowing and lending cost (1-zeta)*(a1prime_val<0) 29 | % Note: when a1prime_val=0 we just get zero in the above, no need to treat it seperate from the < and > 30 | if c>0 && k>0 31 | % Note: this won't work if gamma=1 or eta=1 32 | F=(((c^alpha)*(k^(1-alpha)))^(1-gamma))/(1-gamma)+(1/(1-omega))*psi*((1-d)^(1-eta))/(1-eta); 33 | end 34 | 35 | % Impose borrowing constraint (now a collateral constraint) 36 | if bprime<(-phi_k*kprime) 37 | F=-Inf; 38 | end 39 | 40 | end -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_Fn.m: -------------------------------------------------------------------------------- 1 | function Output=GuerrieriLorenzoni2017_Fn(n_d,n_a,n_theta,n_r,Params, vfoptions, simoptions) 2 | %This code replicates the results of Guerrieri & Lorenzoni (2017) - Credit Crises, Precautionary Savings, and the Liquidity Trap 3 | disp('Running GuerrieriLorenzoni2017_Fn') 4 | %% Set up 5 | 6 | %Create markov process for the exogenous income (based on idea of employment and unemployment states, following Imrohoroglu, 1989). 7 | [theta1_grid, pi_theta1]=TauchenMethod(0, Params.sigma_epsilon.^2,Params.rho, n_theta-1, Params.tauchenq); 8 | z_grid=[0; exp(theta1_grid)]; 9 | pistar_theta1=ones(n_theta-1,1)/(n_theta-1); 10 | for ii=1:10^4 % G&L2017, pg 1438 "when first employed, workers draw theta from its unconditional distribution" 11 | pistar_theta1=pi_theta1'*pistar_theta1; % There is a more efficient form to do this directly from a formula but I am feeling lazy. %FIX THIS LATER!!! 12 | end 13 | pi_z=[(1-Params.pi_ue), Params.pi_ue*pistar_theta1'; Params.pi_eu*ones(n_theta-1,1),(1-Params.pi_eu)*pi_theta1]; 14 | % Rows were did not sum to one due to rounding errors at order of 10^(-11), fix this 15 | pi_z=pi_z./sum(pi_z,2); 16 | pistar_z=ones(n_theta,1)/n_theta; 17 | for ii=1:10^4 % % There is a more efficient way to do this directly from a formula but I am feeling lazy. %FIX THIS LATER!!! 18 | pistar_z=pi_z'*pistar_z; % Formula could be used to find stationary dist of the employment unemployment process, then just combine with stationary dist of theta1, which is already calculated 19 | end 20 | % "The average level of theta is chosen so that yearly output in the initial steady state is normalized to 1" 21 | z_grid=z_grid/sum(z_grid.*pistar_z); 22 | % Double-check that this is 1 23 | % sum(z_grid.*pistar_z) 24 | 25 | % That the "normalized to 1" refers to E[theta] and not E[n*theta] is clear from setting 26 | % v=0.1 to satisfy "For the unemployment benefit, we also follow Shimer 27 | % (2005) and set it to 40% of average labor income." (pg 1438) 28 | 29 | %% Grids 30 | % Set grid for asset holdings 31 | Params.alowerbar=-2; % This seems reasonable (No-one can go below -Params.phi in any case) 32 | Params.aupperbar=12; % Not clear exactly what value is appropriate, have gone with this based on axes of Figure 1. 33 | a_grid=linspace(Params.alowerbar,Params.aupperbar,n_a)'; 34 | 35 | % Set grid for interest rate, r 36 | r_grid=linspace(-0.05,0.05,n_r)'; % This grid is substantially wider than the actual likely equilibrium values and so is somewhat overkill. 37 | % % Set grid for tax rate 38 | % tau_grid=linspace(); % Can calculate this from the gov budget constraint 39 | 40 | %Bring model into the notational conventions used by the toolkit 41 | d_grid=linspace(0,1,n_d)'; % Labor supply 42 | p_grid=r_grid; 43 | 44 | n_z=n_theta; 45 | n_p=n_r; 46 | 47 | %Create descriptions of SS values as functions of d_grid, a_grid, s_grid & 48 | %pi_s (used to calculate the integral across the SS dist fn of whatever 49 | %functions you define here) 50 | FnsToEvaluateParamNames(1).Names={}; 51 | FnsToEvaluateFn_1 = @(d_val, aprime_val,a_val,z_val) a_val; % Aggregate assets (which is this periods state) 52 | %FnsToEvaluateParamNames(2).Names={'v'}; 53 | %FnsToEvaluateFn_2 = @(d_val, aprime_val,a_val,z_val,v) v*(z_val==0); % Total unemployment benefits 54 | FnsToEvaluate={FnsToEvaluateFn_1}; %, FnsToEvaluateFn_2}; 55 | 56 | %Now define the functions for the General Equilibrium conditions 57 | %Should be written as LHS of general eqm eqn minus RHS, so that 58 | %the closer the value given by the function is to zero, the closer 59 | %the general eqm condition is to holding. 60 | GeneralEqmEqnParamNames(1).Names={'B'}; 61 | GeneralEqmEqn_1 = @(AggVars,p,B) AggVars(1)-B; %The requirement that the aggregate assets (lending and borrowing) equal zero 62 | % GeneralEqmEqnParamNames(2).Names={'B'}; 63 | % GeneralEqmEqn_2 = @(AggVars,p,B) p(2)-AggVars(2)-(p(1)/(1+p(1)))*B; % Government budget constraint 64 | GeneralEqmEqns={GeneralEqmEqn_1}; %, GeneralEqmEqn_2}; 65 | 66 | 67 | %% 68 | DiscountFactorParamNames={'beta'}; 69 | 70 | ReturnFn=@(d_val, aprime_val, a_val, z_val,r, gamma, psi, eta, phi, v) GuerrieriLorenzoni2017_ReturnFn(d_val, aprime_val, a_val, z_val,r, gamma, psi, eta, phi, v); 71 | ReturnFnParamNames={'r', 'gamma', 'psi', 'eta', 'phi', 'v'}; %It is important that these are in same order as they appear in 'Aiyagari1994_ReturnFn' 72 | 73 | %% Solve 74 | 75 | V0=ones(n_a,n_z,'gpuArray'); 76 | %Use the toolkit to find the equilibrium price index 77 | GEPriceParamNames={'r'}; %,'tau' 78 | 79 | disp('Calculating price vector corresponding to the stationary eqm') 80 | % tic; 81 | heteroagentoptions.verbose=1; 82 | heteroagentoptions.pgrid=p_grid; 83 | [p_eqm,p_eqm_index, MarketClearance]=HeteroAgentStationaryEqm_Case1(V0, n_d, n_a, n_z, n_p, pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, ReturnFnParamNames, FnsToEvaluateParamNames, GeneralEqmEqnParamNames, GEPriceParamNames,heteroagentoptions, simoptions, vfoptions); 84 | % findeqmtime=toc 85 | % Params.q=p_eqm; 86 | save ./SavedOutput/GuerrieriLorenzoni2017.mat p_eqm p_eqm_index MarketClearance 87 | 88 | %% %Now that we know what the equilibrium price is, lets calculate a bunch of 89 | load ./SavedOutput/GuerrieriLorenzoni2017.mat p_eqm p_eqm_index MarketClearance 90 | 91 | % %other things associated with the equilibrium 92 | p_eqm_index 93 | disp('Calculating various equilibrium objects') 94 | [~,Policy]=ValueFnIter_Case1(V0, n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, ReturnFnParamNames); 95 | 96 | % PolicyValues=PolicyInd2Val_Case1(Policy,n_d,n_a,n_s,d_grid,a_grid, Parallel); 97 | 98 | StationaryDist=StationaryDist_Case1(Policy,n_d,n_a,n_z,pi_z, simoptions); 99 | 100 | AggVars=EvalFnOnAgentDist_AggVars_Case1(StationaryDist, Policy, FnsToEvaluate,Params, FnsToEvaluateParamNames,n_d, n_a, n_z, d_grid, a_grid,z_grid,pi_z, Parallel); 101 | 102 | eqm_MC=real(GeneralEqmConditions_Case1(AggVars,Params.q, GeneralEqmEqns, Params, GeneralEqmEqnParamNames)); 103 | 104 | save ./SavedOutput/GuerrieriLorenzoni2017.mat p_eqm p_eqm_index MarketClearance Policy StationaryDist 105 | 106 | 107 | %% Display some output about the solution 108 | GraphString=['Huggett1993_MarketClearance_mu', num2str(Params.mu), 'alowerbar', num2str(abs(Params.alowerbar))]; 109 | GraphString=strrep(GraphString, '.', '_'); 110 | % Create a graph displaying the market clearance 111 | fig1=figure(1); 112 | plot(p_grid,MarketClearance, 'x',p_grid, zeros(n_p,1),p_eqm, 0, 'r o') 113 | title(['Market clearance: mu=', num2str(Params.mu), ' alowerbar=', num2str(Params.alowerbar)],'FontSize',18); 114 | xlabel('p','FontSize',16); ylabel('tilde(p)-p','FontSize',16); 115 | set(fig1, 'Color', 'white'); % white bckgr 116 | set(fig1, 'Unit', 'centimeters'); % set unit to cm 117 | set(fig1,'position',[0 0 20 10]); % set size 118 | export_fig(fig1, ... % figure handle 119 | ['./SavedOutput/Graphs/',GraphString,'.pdf'],... % name of output file without extension % '-painters', ... % renderer 120 | '-pdf', ... % file format 121 | '-r300' ); % resolution 122 | 123 | %plot(cumsum(sum(StationaryDist,2))) %Plot the asset cdf 124 | 125 | fprintf('For parameter values mu=%.2f, alowerbar=%.2f \n', [Params.mu,Params.alowerbar]) 126 | fprintf('The table elements are q=%.4f, r=%.4f \n',[Params.q,100*Params.r]) 127 | 128 | %% Outputs of the function 129 | % Tables: q,r 130 | 131 | Output.q=gather(Params.q); 132 | Output.r=gather(100*Params.r); 133 | Output.Policy=gather(Policy); 134 | Output.StationaryDist=gather(StationaryDist); 135 | Output.a_grid=gather(a_grid); 136 | 137 | end 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=GuerrieriLorenzoni2017_ReturnFn(d, aprime, a, z,r, gamma, psi, eta, phi, v,B,Bprime,omega)%, tau) 2 | 3 | % Guerrieri & Lorenzoni (2017) refer to: d as n_it, aprime as b_it+1, a as b_it, and z as theta_it. 4 | % omega is the 'wedge' induced by stick wages in the New Keynesian version 5 | % of model in Section 4 of GL (2017), pg 1450. Notice that when omega=0 it 6 | % plays no role and this is the case in the rest of the paper. 7 | 8 | tau=0.0607*v+B-(1/(1+r))*Bprime; % From pg 1434, notice that q_t=1/(1+r) 9 | % In stationary eqm we know that tau=u*v+r/(1+r)*B, as Bprime=B, so the formula could be simplified. 10 | % But this more general form will allow us to later do the 'Fiscal Policy' transitions. 11 | 12 | % (Net) Tax and transfers: 13 | tau_tilde=tau-v*(z==0); % Note: by definition z cannot actually be negative 14 | 15 | % Note: Agent can choose labour supply, but only gets unemployment benefits 16 | % if z==0, do not get unemployment benefits if choose zero labour supply (d==0). 17 | 18 | F=-Inf; 19 | c=a+z*d-tau_tilde-(1/(1+r))*aprime; % q=1/(1+r) 20 | if c>0 21 | % Note: this won't work if gamma=1 or eta=1 22 | F=(c^(1-gamma))/(1-gamma)+(1/(1-omega))*psi*((1-d)^(1-eta))/(1-eta); 23 | end 24 | 25 | % Impose borrowing constraint 26 | if aprime<-phi 27 | F=-Inf; 28 | end 29 | 30 | end -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/GuerrieriLorenzoni2017_altcalibration.m: -------------------------------------------------------------------------------- 1 | % This script is called by GuerrieriLorenzoni2017.m 2 | % Following is largely just a copy of a chunk of GuerrieriLorenzoni2017.m file. 3 | 4 | % Just use the grids, parameter values, etc that have already been set up by GuerrieriLorenzoni2017.m 5 | 6 | Params.phi=Params.phi_initial; 7 | 8 | %% Solve the initial stationary equilibrium 9 | % GL2007 misleadingly refer to this as the initial steady-state equilibrium, which it 10 | % is not. It is the inital stationary equilibrium. (there are plenty of shocks at the idiosyncratic level, hence not steady-state which means the absence of shocks) 11 | 12 | %Use the toolkit to find the equilibrium price index 13 | GEPriceParamNames={'r'}; %,'tau' 14 | 15 | heteroagentoptions.verbose=1; 16 | heteroagentoptions.pgrid=p_grid; 17 | 18 | disp('Calculating price vector corresponding to the stationary eqm') 19 | % tic; 20 | p_eqm_initial=HeteroAgentStationaryEqm_Case1(n_d, n_a, n_z, [], pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames,heteroagentoptions); 21 | % findeqmtime=toc 22 | Params.r=p_eqm_initial.r; 23 | 24 | % Now that we know what the equilibrium price is, lets calculate a bunch of other things associated with the equilibrium 25 | disp('Calculating various equilibrium objects') 26 | [~,Policy_initial]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions); 27 | StationaryDist_initial=StationaryDist_Case1(Policy_initial,n_d,n_a,n_z,pi_z, simoptions); 28 | % AggVars_initial=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_initial, Policy_initial, FnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid); 29 | 30 | % Final stationary equilibrium 31 | % Only change is 32 | Params.phi=Params.phi_final; 33 | p_eqm_final=HeteroAgentStationaryEqm_Case1(n_d, n_a, n_z, [], pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames,heteroagentoptions); 34 | Params.r=p_eqm_final.r; 35 | [V_final,Policy_final]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions); 36 | StationaryDist_final=StationaryDist_Case1(Policy_final,n_d,n_a,n_z,pi_z, simoptions); 37 | AggVars_final=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_final, Policy_final, FnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid); 38 | 39 | %% Compute the flexible price transition path 40 | clear PricePath0 ParamPath 41 | % We want to look at a one off unanticipated path of phi. ParamPath & PathParamNames are thus given by 42 | ParamPath.phi=Params.phi_final*ones(T,1); % ParamPath is matrix of size T-by-'number of parameters that change over path' 43 | temp=linspace(Params.phi_initial,Params.phi_final,7); ParamPath.phi(1:6)=temp(2:7); % At t=0, is inital stationary distribution, then falls over the following 6 periods to equal 0.525, remains there 44 | % (the way ParamPath is set is designed to allow for a series of changes in the parameters) 45 | 46 | % We need to give an initial guess for the price path on interest rates 47 | PricePath0.r=[linspace(-0.01, p_eqm_final.r, floor(T/3))'; p_eqm_final.r*ones(T-floor(T/3),1)]; % PricePath0 is matrix of size T-by-'number of prices' 48 | 49 | fprintf('Starting flex prices transition in alt calibration \n') 50 | PricePath_flex=TransitionPath_Case1(PricePath0, ParamPath, T, V_final, StationaryDist_initial, n_d, n_a, n_z, pi_z, d_grid,a_grid,z_grid, ReturnFn, TransPathFnsToEvaluate, TransPathGeneralEqmEqns, Params, DiscountFactorParamNames, transpathoptions); 51 | 52 | [~,PolicyPath_flex]=ValueFnOnTransPath_Case1(PricePath_flex, ParamPath, T, V_final, Policy_final, Params, n_d, n_a, n_z, pi_z, d_grid, a_grid,z_grid, DiscountFactorParamNames, ReturnFn, transpathoptions, vfoptions); 53 | AgentDistPath_flex=AgentDistOnTransPath_Case1(StationaryDist_initial,PolicyPath_flex,n_d,n_a,n_z,pi_z,T); 54 | 55 | %% Sticky Wages 56 | if altcalib_figurenumber==9 || altcalib_figurenumber==11 57 | PricePath0.r=PricePath_flex.r; 58 | PricePath0.omega=zeros(T,1); 59 | 60 | fprintf('Starting sticky wages transition in alt calibration \n') 61 | PricePath_NK=TransitionPath_Case1(PricePath0, ParamPath, T, V_final, StationaryDist_initial, n_d, n_a, n_z, pi_z, d_grid,a_grid,z_grid, ReturnFn, TransPathFnsToEvaluate, NKTransPathGeneralEqmEqns, Params, DiscountFactorParamNames, transpathoptions_NK); 62 | 63 | [~,PolicyPath_NK]=ValueFnOnTransPath_Case1(PricePath_NK, ParamPath, T, V_final, Policy_final, Params, n_d, n_a, n_z, pi_z, d_grid, a_grid,z_grid, DiscountFactorParamNames, ReturnFn, transpathoptions, vfoptions); 64 | AgentDistPath_NK=AgentDistOnTransPath_Case1(StationaryDist_initial,PolicyPath_NK,n_d,n_a,n_z,pi_z,T); 65 | end 66 | 67 | %% Figure for Alternative Calibration 68 | AltCalibFnsToEvaluate.output = @(d_val, aprime_val,a_val,z_val) d_val*z_val; % y_it=n_it*theta_it Note that since gov budget is balanced every period it neither adds nor subtracts (unemployment benefits + interest payments on B=lump-sum tax revenue) 69 | AltCalibFnsToEvaluate.employment = @(d_val, aprime_val,a_val,z_val) d_val; %n_it in notation of GL2017 70 | 71 | % For the initial dist will need 72 | Params.phi=Params.phi_initial; 73 | Params.r=p_eqm_initial.r; 74 | 75 | % Get the 76 | AggVars_initial=EvalFnOnAgentDist_AggVars_Case1(StationaryDist_initial, Policy_initial, AltCalibFnsToEvaluate,Params, [],n_d, n_a, n_z, d_grid, a_grid,z_grid,2); 77 | AggVarsPath_Flex=EvalFnOnTransPath_AggVars_Case1(AltCalibFnsToEvaluate, AgentDistPath_flex, PolicyPath_flex, PricePath_flex, ParamPath, Params, T, n_d, n_a, n_z, pi_z, d_grid, a_grid,z_grid, simoptions); 78 | 79 | Output_pch_flex=([AggVars_initial.output.Mean; AggVarsPath_Flex.output.Mean]-AggVars_initial.output.Mean)/AggVars_initial.output.Mean; 80 | Employment_pch_flex=([AggVars_initial.employment.Mean; AggVarsPath_Flex.employment.Mean]-AggVars_initial.employment.Mean)/AggVars_initial.employment.Mean; 81 | 82 | if altcalib_figurenumber==9 || altcalib_figurenumber==11 83 | AggVarsPath_NK=EvalFnOnTransPath_AggVars_Case1(AltCalibFnsToEvaluate, AgentDistPath_NK, PolicyPath_NK, PricePath_NK, ParamPath, Params, T, n_d, n_a, n_z, pi_z, d_grid, a_grid,z_grid, simoptions); 84 | Output_pch_NK=([AggVars_initial.output.Mean; AggVarsPath_NK.output.Mean]-AggVars_initial.output.Mean)/AggVars_initial.output.Mean; 85 | Employment_pch_NK=([AggVars_initial.employment.Mean; AggVarsPath_NK.employment.Mean]-AggVars_initial.employment.Mean)/AggVars_initial.employment.Mean; 86 | end 87 | 88 | 89 | if CreateFigures==1 90 | % For some of the alternative calibrations employment is plotted as well. 91 | figure(altcalib_figurenumber) 92 | if altcalib_figurenumber==9 93 | % interest rate 94 | subplot(1,2,1); plot(0:1:T,4*100*[p_eqm_initial.r; PricePath_flex.r],0:1:T,4*100*[p_eqm_initial.r; PricePath_NK.r]) 95 | title('annual interest rate') 96 | % output 97 | subplot(1,2,2); plot(0:1:T,Output_pch_flex, 0:1:T,Output_pch_NK) 98 | title('output (pct deviation)') 99 | % ylabel('percent deviation from inital output in stationary eqm') 100 | elseif altcalib_figurenumber==10 101 | % interest rate 102 | subplot(1,3,1); plot(0:1:T,4*100*[p_eqm_initial.r; PricePath_flex.r]) 103 | title('annual interest rate') 104 | % output 105 | subplot(1,3,2); plot(0:1:T,Output_pch_flex) 106 | title('output (pct deviation)') 107 | % ylabel('percent deviation from inital output in stationary eqm') 108 | % employment 109 | subplot(1,3,3); plot(0:1:T,Employment_pch_flex,0:1:T) 110 | title('employment') 111 | % ylabel('percent deviation from inital employment in stationary eqm') 112 | elseif altcalib_figurenumber==11 113 | % interest rate 114 | subplot(1,3,1); plot(0:1:T,4*100*[p_eqm_initial.r; PricePath_flex.r],0:1:T,4*100*[p_eqm_initial.r; PricePath_NK.r]) 115 | title('annual interest rate') 116 | % output 117 | subplot(1,3,2); plot(0:1:T,Output_pch_flex, 0:1:T,Output_pch_NK) 118 | title('output (pct deviation)') 119 | % ylabel('percent deviation from inital output in stationary eqm') 120 | % employment 121 | subplot(1,3,3); plot(0:1:T,Employment_pch_flex,0:1:T,Employment_pch_NK) 122 | title('employment') 123 | % ylabel('percent deviation from inital employment in stationary eqm') 124 | elseif altcalib_figurenumber==12 125 | % interest rate 126 | subplot(1,2,1); plot(0:1:T,Full_PricePath_Flex_baseline, 0:1:T,4*100*[p_eqm_initial.r; PricePath_flex.r]) 127 | title('annual interest rate') 128 | % output 129 | subplot(1,2,2); plot(0:1:T,Full_OutputPath_pch_Flex_baseline, 0:1:T,Output_pch_flex) 130 | title('output (pct deviation)') 131 | legend('baseline', 'higher risk aversion') 132 | % ylabel('percent deviation from inital output in stationary eqm') 133 | end 134 | saveas(gcf,['./SavedOutput/Graphs/GuerrieriLorenzoni2017_Figure',num2str(altcalib_figurenumber),'.pdf']) 135 | else 136 | if altcalib_figurenumber==9 137 | save(['./SavedOutput/GL2017Figs/GuerrieriLorenzoni2017_Figure',num2str(altcalib_figurenumber),'.mat'], 'T', 'p_eqm_initial', 'PricePath_flex', 'PricePath_NK', 'Output_pch_flex', 'Output_pch_NK') 138 | elseif altcalib_figurenumber==10 139 | save(['./SavedOutput/GL2017Figs/GuerrieriLorenzoni2017_Figure',num2str(altcalib_figurenumber),'.mat'], 'T', 'p_eqm_initial', 'PricePath_flex', 'Output_pch_flex', 'Employment_pch_flex') 140 | elseif altcalib_figurenumber==11 141 | save(['./SavedOutput/GL2017Figs/GuerrieriLorenzoni2017_Figure',num2str(altcalib_figurenumber),'.mat'], 'T', 'p_eqm_initial', 'PricePath_flex', 'PricePath_NK', 'Output_pch_flex', 'Output_pch_NK', 'Employment_pch_flex', 'Employment_pch_NK') 142 | elseif altcalib_figurenumber==12 143 | save(['./SavedOutput/GL2017Figs/GuerrieriLorenzoni2017_Figure',num2str(altcalib_figurenumber),'.mat'], 'T', 'p_eqm_initial', 'PricePath_flex', 'Output_pch_flex', 'Full_PricePath_Flex_baseline', 'Full_OutputPath_pch_Flex_baseline') 144 | end 145 | end 146 | 147 | %% Clean up after itself 148 | clear Policy_initial StationaryDist_initial V_final 149 | disp('What is leftover from altcalib') 150 | whos 151 | 152 | -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/SimulationOfThetaFromGL2017.m: -------------------------------------------------------------------------------- 1 | %% Takes a closer look at the inc_process.mat from the Guerrieri & Lorenzoni (2017) codes. 2 | % This is how I figured out that they use tauchenq=2.1, and that this is 3 | % based on targeting that sigmasqz takes the correct value. 4 | 5 | %% Load the log-income process (which is 12-state Tauchen method approximation of AR(1)) 6 | load ./PaperMaterials/replication-codes-for-Credit-Crises-2017-1f7cb32/inc_process.mat 7 | 8 | % Simulate a time series 9 | burnin=10^3; 10 | T=10^4 11 | currenttimeseries_index=1 12 | cumPr=cumsum(Pr,2); 13 | % Start with the indexes 14 | for ii=1:burnin 15 | [~,currenttimeseries_index]=max(cumPr(currenttimeseries_index,:)>rand(1,1)); 16 | end 17 | for ii=1:T 18 | [~,currenttimeseries_index]=max(cumPr(currenttimeseries_index,:)>rand(1,1)); 19 | timeseries_index(ii)=currenttimeseries_index; 20 | end 21 | % Now the values 22 | timeseries_values=x(timeseries_index); 23 | % Variance of these 24 | var(timeseries_values) 25 | 26 | % It should be 27 | rho=0.967; 28 | sigmasq_epsilon=0.017; 29 | sigmasq_z=sigmasq_epsilon/(1-rho^2) 30 | 31 | 32 | %% Use Tauchen Method 33 | tauchenoptions.parallel=1; 34 | Params.tauchenq=2.1 35 | n_theta=13; 36 | Params.rho=rho; 37 | Params.sigmasq_epsilon=sigmasq_epsilon; 38 | [theta1_grid, pi_theta1]=TauchenMethod(0, Params.sigmasq_epsilon, Params.rho, n_theta-1, Params.tauchenq,tauchenoptions); 39 | 40 | cumpi_theta1=cumsum(pi_theta1,2); 41 | % Start with the indexes 42 | for ii=1:burnin 43 | [~,currenttimeseries_index]=max(cumpi_theta1(currenttimeseries_index,:)>rand(1,1)); 44 | end 45 | for ii=1:T 46 | [~,currenttimeseries_index]=max(cumpi_theta1(currenttimeseries_index,:)>rand(1,1)); 47 | timeseries_index(ii)=currenttimeseries_index; 48 | end 49 | % Now the values 50 | timeseries_values=theta1_grid(timeseries_index); 51 | % Variance of these 52 | var(timeseries_values) 53 | -------------------------------------------------------------------------------- /GuerrieriLorenzoni2017/inc_process.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/GuerrieriLorenzoni2017/inc_process.mat -------------------------------------------------------------------------------- /Hansen1985/Hansen1985.m: -------------------------------------------------------------------------------- 1 | %%% Example using the model of Hansen (1985) 2 | % Note: Most of the run time is spent creating the 3 | % discretization of the shock process [AR(1) shock with log-normal 4 | % innovations means standard methods cannot be used]. 5 | n_d=751; % decide whether to work 6 | n_a=3001; % assets 7 | n_z=91; % tech shock 8 | AlternativeProductivityShocks=0 9 | 10 | % 101, 501, 31 % 151, 751, 51 11 | vfoptions.lowmemory=2 12 | 13 | % Because the model output is based on just 100 simulations (following Hansen (1985)) the random number seed matters. 14 | % rng(1) 15 | % (Nowadays you should use more like 10,000 simulations but in the 1980s 100 simulations would 16 | % already be pushing the limited computational power available.) 17 | 18 | %% Setup 19 | 20 | % The toolkit uses a 'structure' called Params to store the parameter values. 21 | % In this basic model this may appear over-complicated, but in more advanced models it is much simpler and more useful. 22 | 23 | %Discounting rate 24 | Params.beta = 0.99; 25 | 26 | %Parameter values 27 | Params.alpha = 0.36; % alpha (Hansen refers to this as theta) 28 | Params.A=2; 29 | Params.h0=0.53; 30 | Params.B=-Params.A*log(1-Params.h0)/Params.h0; 31 | Params.rho = 0.95; % rho (Hansen refers to this as gamma) 32 | Params.delta = 0.025; % delta 33 | Params.sigma_epsilon=0.00712; 34 | Params.sigmasq_epsilon=Params.sigma_epsilon^2; 35 | %Step 1: Compute the steady state 36 | K_ss=(Params.alpha/(1/Params.beta-1+Params.delta))^(1/(1-Params.alpha))*2/3; % Hansen footnote 15. 37 | 38 | 39 | %Create grids (it is very important that each grid is defined as a column vector) 40 | 41 | if AlternativeProductivityShocks==0 42 | % Creating a grid (and transition matrix) for z is slightly awkward due to epsilon being 43 | % distributed as lognormal (so cannot just use the Tauchen quadrature like 44 | % we usually might) 45 | % Instead, simulate z, then do a quadrature with states chosen by 46 | % matlab's histcounts. Transition matrix is just done by counting the 47 | % transitions and then normalizing. 48 | burnin=10^4; 49 | T=10^8; 50 | z_sim=zeros(T,1); 51 | % Calculate the mean and std dev of the normal shock the exponential of 52 | % which will be a lognormal with mean 1-rho and std dev sigma_epsilon 53 | sigma_ln=sqrt(log(1+(Params.sigma_epsilon^2)/((1-Params.rho)^2))); 54 | mu_ln=log(1-Params.rho)-(sigma_ln^2)/2; 55 | % check=exp(mu_ln+sigma_ln*randn(10^4,1)); mean(check); std(check); % Works 56 | temp=1-Params.rho; %The unconditional mean of z 57 | for tt=1:burnin 58 | temp=Params.rho*temp+exp(mu_ln+sigma_ln*randn(1,1)); 59 | end 60 | z_sim(1)=temp; 61 | for tt=2:T 62 | z_sim(tt)=Params.rho*z_sim(tt-1)+exp(mu_ln+sigma_ln*randn(1,1)); 63 | end 64 | [N,edges,bin] = histcounts(z_sim,n_z); 65 | z_grid=zeros(n_z,1); 66 | for ii=1:n_z 67 | z_grid(ii)=mean(z_sim(bin==ii)); 68 | end 69 | pi_z=zeros(n_z,n_z); 70 | for tt=2:T 71 | pi_z(bin(tt-1),bin(tt))=pi_z(bin(tt-1),bin(tt))+1; 72 | end 73 | pi_z=pi_z./(sum(pi_z,2)*ones(1,n_z)); 74 | elseif AlternativeProductivityShocks==1 75 | % Use productivity shocks modelled as log(z) is AR(1) with normal dist innovations 76 | q=3; 77 | tauchenoptions.parallel=Parallel; 78 | mcmomentsoptions.parallel=Parallel; 79 | [z_grid,pi_z]=discretizeAR1_Tauchen(0,Params.rho,Params.sigma_epsilon,n_z,q, tauchenoptions); % the AR(1) on log(z) 80 | z_grid=exp(z_grid); % so z is just exp(log(z)) 81 | %Normalize z by dividing it by Expectation_z (so that the resulting process has expectaion equal to 1. 82 | [Expectation_z,~,~,~]=MarkovChainMoments(z_grid,pi_z,mcmomentsoptions); 83 | z_grid=z_grid./Expectation_z; 84 | [Expectation_z,~,~,~]=MarkovChainMoments(z_grid,pi_z,mcmomentsoptions); 85 | end 86 | 87 | a_grid=sort([linspace(0+0.0001,K_ss-0.0001,n_a-floor(n_a/2)),linspace(0,2*K_ss,floor(n_a/2))])'; 88 | d_grid=linspace(0,1,n_d)'; 89 | 90 | pi_z=gpuArray(pi_z); 91 | 92 | 93 | DiscountFactorParamNames={'beta'}; 94 | 95 | ReturnFn=@(d, aprime, a, z, alpha, delta, A, B, Economy) Hansen1985_ReturnFn(d, aprime, a, z, alpha, delta, A, B, Economy); 96 | 97 | %% Solve Model and Generate Table 1 of Hansen (1985) 98 | 99 | % Hansen footnote (b) of Table 1 says statistics are based on 100 simulations of 115 periods each. 100 | % I instead use 10,000 simulations to ensure that results are not 'random' (not impacted by the seed of the random number generator) 101 | NSims=10000; %Number of simulations 102 | simoptions.simperiods=115; 103 | if gpuDeviceCount>0 % If there is a gpu 104 | StdBusCycleStats=zeros(2,7,2,NSims,'gpuArray'); 105 | else % If there is no gpu, will use cpu but is much slower 106 | StdBusCycleStats=zeros(2,7,2,NSims); 107 | end 108 | 109 | for Economy=1:2 % Divisible and Indivisible labour respectively 110 | Params.Economy=Economy; 111 | %% Solve 112 | disp('Solve value fn problem') 113 | [V,Policy]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames,[],vfoptions); 114 | 115 | %No need for asyptotic distribution. 116 | %simoptions.simperiods=10^4; simoptions.iterate=1; 117 | %StationaryDist=StationaryDist_Case1(Policy,n_d,n_a,n_z,pi_z,simoptions); 118 | %plot(1:1:n_z, N/sum(N), 1:1:n_z, sum(StationaryDist,1)) % Can see that the z discretization is working as two lines are identical. 119 | 120 | if AlternativeProductivityShocks==0 121 | if Economy==1 122 | save ./SavedOutput/Hansen1985_Economy1.mat V Policy 123 | elseif Economy==2 124 | save ./SavedOutput/Hansen1985_Economy2.mat V Policy 125 | end 126 | end 127 | 128 | %% Generate Table 1 of Hansen (1985) 129 | disp('Simulate time series') 130 | for ii=1:NSims 131 | %Define the functions which we wish to create time series for 132 | FnsToEvaluate.Y = @(d,aprime,a,z,alpha) z*(a^alpha)*(d^(1-alpha)); %Output (from eqn 1) 133 | FnsToEvaluate.C = @(d,aprime,a,z) z*(a^Params.alpha)*(d^(1-Params.alpha)) -(aprime-(1-Params.delta)*a); %Consumption (=output-investment, from eqn 2; this formula is valid for both divisible and indivisible labour) 134 | FnsToEvaluate.I = @(d,aprime,a,z) aprime-(1-Params.delta)*a; %Investment (from eqn 3) 135 | FnsToEvaluate.K = @(d,aprime,a,z) a; %Capital Stock 136 | FnsToEvaluate.H = @(d,aprime,a,z) d; %Hours 137 | FnsToEvaluate.TFP = @(d,aprime,a,z,alpha) (z*(a^alpha)*(d^(1-alpha)))/d; %Productivity (measured in data as output divided by hours) 138 | FnsToEvaluate.z = @(d,aprime,a,z) z; %Tech Shock (Hansen 1985 does not report this, just for interest) 139 | 140 | TimeSeries=TimeSeries_Case1(Policy, FnsToEvaluate, Params, n_d, n_a, n_z, d_grid, a_grid, z_grid,pi_z,simoptions); 141 | 142 | [OutputTrend,OutputCyc]=hpfilter(gather(log(TimeSeries.Y)),1600); % hpfilter() does not yet exist for gpu 143 | FnNames=fieldnames(FnsToEvaluate); 144 | for jj=1:7 145 | [TimeSeriesTrend,TimeSeriesCyc]=hpfilter(gather(log(TimeSeries.(FnNames{jj}))),1600); % hpfilter() does not yet exist for gpu 146 | temp=cov(100*OutputCyc,100*TimeSeriesCyc); % To match treatment of data the model output must be logged and then hpfiltered, then multiply by 100 to express as percent 147 | StdBusCycleStats(1,jj,Economy,ii)=sqrt(temp(2,2)); % Std dev (column a) 148 | StdBusCycleStats(2,jj,Economy,ii)=temp(1,2)/(sqrt(temp(1,1))*sqrt(temp(2,2))); % Correlation with output (column b) 149 | end 150 | end 151 | StdBusCycleStats_means=mean(StdBusCycleStats,4); % multiply by 100 to make them percents 152 | StdBusCycleStats_stddev=std(StdBusCycleStats,0,4); 153 | 154 | end 155 | 156 | 157 | %% Print out a file containing Table 1 158 | HansenDataResults=[1.76, 1.00; 1.29, 0.85; 8.60, 0.92; 0.63, 0.04; 1.66, 0.76; 1.18, 0.42]; 159 | VarNamesStrVec={'Output', 'Consumption','Investment','Capital Stock','Hours','Productivity'}; 160 | if AlternativeProductivityShocks==0 161 | FID = fopen('./SavedOutput/LatexInputs/Table_Hansen1985.tex', 'w'); 162 | elseif AlternativeProductivityShocks==1 163 | FID = fopen('./SavedOutput/LatexInputs/Table_Hansen1985_AltProdShocks.tex', 'w'); 164 | end 165 | fprintf(FID, 'Standard deviations in percent (a) and correlations with output (b) for US and artificial economies. \\\\ \n'); 166 | fprintf(FID, '\\begin{tabular*}{1.00\\textwidth}{@{\\extracolsep{\\fill}}lcccccc} \\hline \\hline \n'); 167 | fprintf(FID, ' & \\multicolumn{2}{c}{Quarterly U.S. Time Series\\textsuperscript{a}} & \\multicolumn{2}{c}{Economy with} & \\multicolumn{2}{c}{Economy with} \\\\ \n'); 168 | fprintf(FID, ' & \\multicolumn{2}{c}{1955:Q3-1984:Q1} & \\multicolumn{2}{c}{divisible labor\\textsuperscript{b}} & \\multicolumn{2}{c}{indivisible labor\\textsuperscript{b}} \\\\ \n'); 169 | fprintf(FID, 'Series & (a) & (b) & (a) & (b) & (a) & (b) \\\\ \\hline \n'); 170 | for jj=1:6 171 | VarNameStr=VarNamesStrVec{jj}; 172 | fprintf(FID, [VarNameStr,' & %1.2f & %1.2f & %1.2f (%1.2f) & %1.2f (%1.2f) & %1.2f (%1.2f) & %1.2f (%1.2f) \\\\ \n'], HansenDataResults(jj,1), HansenDataResults(jj,2), StdBusCycleStats_means(1,jj,1), StdBusCycleStats_stddev(1,jj,1), StdBusCycleStats_means(2,jj,1), StdBusCycleStats_stddev(2,jj,1), StdBusCycleStats_means(1,jj,2), StdBusCycleStats_stddev(1,jj,2), StdBusCycleStats_means(2,jj,2), StdBusCycleStats_stddev(2,jj,2) ); 173 | end 174 | fprintf(FID, '\\hline \\hline \n \\end{tabular*} \n'); 175 | %fprintf(FID, '\\begin{minipage}[t]{1.00\\textwidth}{\\baselineskip=.5\\baselineskip \\vspace{.3cm} \\footnotesize{ \n'); 176 | %fprintf(FID, ['\\textsuperscript{a} The US time series used are real GNP, total consumption expenditures, and gross private domestic investment (all in 1972 dollars). The capital stock series includes non-residential equipment and structures. The hours series includes total hours for persons at work in non-agricultural industries as derived from the \\textit{Current Population Survey}. Productivity is output divided by hours. All series are seasonally adjusted, logged and detrended. \\\\ \n']); 177 | %fprintf(FID, ['\\textsuperscript{b} The standard deviations and correlations with output are sample means of statistics computed for each of 100 simulations. Each simulation consists of 115 periods, which is the same number of periods as the US sample. The numbers in parentheses are sample standard deviations of these statistics. Before computing any statistics each simulated time series was logged and detrended using the same procedure used for the US time series. \\\\ \n']); 178 | %fprintf(FID, '}} \\end{minipage}'); 179 | fclose(FID); -------------------------------------------------------------------------------- /Hansen1985/Hansen1985.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/Hansen1985/Hansen1985.pdf -------------------------------------------------------------------------------- /Hansen1985/Hansen1985_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=Hansen1985_ReturnFn(d_val, aprime_val, a_val, z_val, alpha, delta, A, B, Economy) 2 | 3 | F=-Inf; 4 | C=z_val*(a_val^alpha)*(d_val^(1-alpha))-(aprime_val-(1-delta)*a_val); 5 | if C>0 6 | if Economy==1 7 | F=log(C)+A*log(1-d_val); % Divisible labour 8 | elseif Economy==2 9 | F=log(C)+B*(1-d_val); % Indivisible labour 10 | end 11 | end 12 | 13 | end -------------------------------------------------------------------------------- /HopenhaynRogerson1993/HopenhaynRogerson1993.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/HopenhaynRogerson1993/HopenhaynRogerson1993.pdf -------------------------------------------------------------------------------- /HopenhaynRogerson1993/HopenhaynRogerson1993_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=HopenhaynRogerson1993_ReturnFn(aprime_val, a_val, z_val, p, alpha, tau, cf) 2 | % a_val is what HopenhaynRogerson1993 call n_{t-1}, aprime_val is n_t. 3 | 4 | F=-Inf; 5 | 6 | gnnlag=0; % pg 918 g(n_t,n_{t-1}) in notation of Hopenhayn & Rogerson (1993), the labour adjustment-costs (firing cost) 7 | if aprime_val=0, it is 'minus a negative number' 9 | end 10 | 11 | % pg 918 12 | pi=p*z_val*(aprime_val^alpha)-aprime_val-p*cf-gnnlag; %Hardcodes normalization w=1 13 | 14 | % Following few lines are just required to deal with Footnote 5. 15 | if a_val==10^6 % Impose Footnote 5 (see first few lines of HopenhaynRogerson1993 for explanation of this) 16 | gnnlag=0; % The 'actual' number of lag employees of a new entrant is zero, so firing costs must be zero. 17 | pi=p*z_val*(aprime_val^alpha)-aprime_val-gnnlag; % same as above, but without the -p*cf term. 18 | end 19 | if aprime_val==10^6 % Impose Footnote 5 (see first few lines of HopenhaynRogerson1993 for explanation of this) 20 | pi=-Inf; % Existing firms cannot choose to become new entrants. 21 | end 22 | 23 | F=pi; 24 | 25 | end -------------------------------------------------------------------------------- /HopenhaynRogerson1993/HopenhaynRogerson1993_ReturnFn_ChrisEdmonds.m: -------------------------------------------------------------------------------- 1 | function F=HopenhaynRogerson1993_ReturnFn_ChrisEdmonds(aprime_val, a_val, z_val, p, alpha, tau, cf) 2 | % a_val is what HopenhaynRogerson1993 call n_{t-1}, aprime_val is n_t. 3 | 4 | F=-Inf; 5 | 6 | gnnlag=0; % pg 918 g(n_t,n_{t-1}) in notation of Hopenhayn & Rogerson (1993), the labour adjustment-costs (firing cost) 7 | if aprime_val=0, it is 'minus a negative number' 9 | end 10 | 11 | % pg 918 12 | pi=p*z_val*(aprime_val^alpha)-aprime_val-cf-gnnlag; % Only difference is -cf, instead of -p*cf 13 | 14 | F=pi; 15 | 16 | end -------------------------------------------------------------------------------- /HubbardSkinnerZeldes1994/HubbardSkinnerZeldes1994.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/HubbardSkinnerZeldes1994/HubbardSkinnerZeldes1994.pdf -------------------------------------------------------------------------------- /HubbardSkinnerZeldes1994/HubbardSkinnerZeldes1994_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function c=HubbardSkinnerZeldes1994_ConsumptionFn(aprime,a,W_z1,M_z2,r,Cbar,DeterministicWj,w_sigmasqu, DeterministicMj) %i 2 | 3 | %i: education type 4 | %jj: age (index 1:J; indicates ages 21 to 100) 5 | 6 | 7 | % Bottom of pg 103 (45th pg): Wit=exp(log(DeterministicWj)-0.5*sigmasqu+uit) 8 | % "This specification ensures that when we compare the certainty case with 9 | % the earnings uncertainty case, we hold the age-conditional means of earnings constant." 10 | Wj=exp(log(DeterministicWj)-0.5*w_sigmasqu+W_z1); 11 | Mj=exp(DeterministicMj+M_z2); 12 | 13 | TR=max(Cbar+Mj-(1+r)*a-Wj,0); 14 | 15 | c=(1+r)*a+Wj-Mj+TR-aprime; 16 | 17 | end -------------------------------------------------------------------------------- /HubbardSkinnerZeldes1994/HubbardSkinnerZeldes1994_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=HubbardSkinnerZeldes1994_ReturnFn(aprime,a,W_z1,M_z2,age,gamma,r,Cbar,DeterministicWj,w_sigmasqu,DeterministicMj, m_sigmasqmew) %i 2 | 3 | %i: education type 4 | %jj: age (index 1:J; indicates ages 21 to 100) 5 | 6 | 7 | % Bottom of pg 103 (45th pg): Wit=exp(log(DeterministicWj)-0.5*sigmasqu+uit) 8 | % "This specification ensures that when we compare the certainty case with 9 | % the earnings uncertainty case, we hold the age-conditional means of earnings constant." 10 | Wj=exp(log(DeterministicWj)-0.5*w_sigmasqu+W_z1); 11 | % Paper makes no mention that the equivalent is done to ensure holding 12 | % age-conditional means of medical expenses constant. I assume that it is. 13 | Mj=exp(DeterministicMj-0.5*m_sigmasqmew+M_z2); 14 | % (DeterministicMj is already in logs) 15 | 16 | % Paper does not mention earnings uncertainty being shut off in retirement 17 | % but it appears from the results that it is supposed to be. The 18 | % calibration describes it as estimated on pre-retirement, so would be 19 | % in line with that. 20 | if age>65 21 | Wj=exp(log(DeterministicWj)); 22 | end 23 | 24 | TR=max(Cbar+Mj-(1+r)*a-Wj,0); 25 | 26 | c=(1+r)*a+Wj-Mj+TR-aprime; 27 | 28 | F=-Inf; %(l by aprime) 29 | 30 | if c>0 31 | if gamma~=1 32 | F=(c.^(1-gamma)-1)/(1-gamma); 33 | else 34 | F=log(c); 35 | end 36 | end 37 | 38 | % Paper is unclear about whether people at the consumption floor Cbar 39 | % actually have to consume Cbar, or if they just receive enough transfers 40 | % to reach Cbar but then decide for themselves how much of that to consume 41 | % and how much to save. I have interpreted the floor as the later, since 42 | % this appears to be how the transfers function implies that it works. 43 | 44 | end -------------------------------------------------------------------------------- /HubbardSkinnerZeldes1994/HubbardSkinnerZeldes1994_TRFn.m: -------------------------------------------------------------------------------- 1 | function TR=HubbardSkinnerZeldes1994_TRFn(aprime,a,W_z1,M_z2,r,Cbar,DeterministicWj,w_sigmasqu, DeterministicMj) %i 2 | 3 | %i: education type 4 | %jj: age (index 1:J; indicates ages 21 to 100) 5 | 6 | 7 | % Bottom of pg 103 (45th pg): Wit=exp(log(DeterministicWj)-0.5*sigmasqu+uit) 8 | % "This specification ensures that when we compare the certainty case with 9 | % the earnings uncertainty case, we hold the age-conditional means of earnings constant." 10 | Wj=exp(log(DeterministicWj)-0.5*w_sigmasqu+W_z1); 11 | Mj=exp(DeterministicMj+M_z2); 12 | 13 | TR=max(Cbar+Mj-(1+r)*a-Wj,0); 14 | 15 | end -------------------------------------------------------------------------------- /Huggett1993/Huggett1993.m: -------------------------------------------------------------------------------- 1 | % Replicates the results (and more) of Huggett (1993) 2 | % Figures use plotly 3 | % Note: The algorithm used for calculating the general equilibrium is not what you would want to use normally for solving this model. It finds the general equilibrium using a discrete grid on interest rates, rather 4 | % than just solving the fixed-point problem on interest rates directly by using optimization. This is done for robustness reasons and because these codes were written as part of a paper on 5 | % a convergent algorithm for solving Bewley-Huggett-Aiyagari-models. 6 | 7 | 8 | %% Set some basic variables 9 | 10 | n_a=2^10;% Huggett used "between 150 and 350 evenly spaced gridpoints" (and uses linear interpolation) 11 | n_e=2; 12 | n_q=1551; 13 | 14 | %Parameters 15 | Params.beta=0.99322; %Model period is one-sixth of a year, so implied 'annual beta' is 0.96. 16 | 17 | Params.mu=1.5; % Huggett (1993) calls this sigma 18 | mu_vec=[1.5,3]; 19 | 20 | Params.alowerbar=-2; % {-2,-4,-6,-8} 21 | alowerbar_vec=[-2,-4,-6,-8]; 22 | %Params.q % The price 23 | 24 | Params.eh=1; 25 | Params.el=0.1; 26 | Params.pieheh=0.925; % Probability of eh given eh 27 | Params.piehel=0.5; % Probability of eh given el 28 | 29 | %% Some Toolkit options 30 | simoptions.ncores=feature('numcores'); % Number of CPU cores 31 | 32 | %% Solve the model a bunch of times 33 | Tables=struct(); 34 | TimeTable=zeros(4,2); 35 | for alowerbar_c=1:4 36 | Params.alowerbar=alowerbar_vec(alowerbar_c); 37 | for mu_c=1:2 38 | Params.mu=mu_vec(mu_c); 39 | fprintf('Current iteration alowerbar_c=%d, mu_c=%d \n', alowerbar_c,mu_c) 40 | tic; 41 | Output=Huggett1993_Fn(n_a,n_e,n_q,Params, simoptions); 42 | time1=toc 43 | % Output is a structure 44 | Tables(alowerbar_c,mu_c).q=Output.q; 45 | Tables(alowerbar_c,mu_c).r=Output.r; 46 | 47 | Figures(alowerbar_c,mu_c).Policy=Output.Policy; 48 | Figures(alowerbar_c,mu_c).StationaryDist=Output.StationaryDist; 49 | 50 | Figures(alowerbar_c,mu_c).a_grid=Output.a_grid; 51 | 52 | TimeTable(alowerbar_c,mu_c)=time1; 53 | end 54 | end 55 | 56 | save ./SavedOutput/Huggett1993Tables.mat Tables TimeTable Figures 57 | 58 | %% Reproduce Tables 1 & 2 of Huggett (1993) 59 | 60 | mu_c=1; 61 | FilenameString=['./SavedOutput/LatexInputs/Huggett1993_Table1.tex']; 62 | FID = fopen(FilenameString, 'w'); 63 | fprintf(FID, 'Coefficient of Relative Risk Aversion $\\mu$=%1.1f \\\\ \n', mu_vec(mu_c)); 64 | fprintf(FID, '\\begin{tabular*}{0.5\\textwidth}{@{\\extracolsep{\\fill}}lcr} \\hline \\hline \n'); 65 | fprintf(FID, ' Credit Limit & Interest Rate & Price \\\\ \n'); 66 | fprintf(FID, ' (-$\\underbar{a}$) & ($r$) & ($q$) \\\\ \\hline \n'); 67 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(1), Tables(1,mu_c).r, Tables(1,mu_c).q); 68 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(2), Tables(2,mu_c).r, Tables(2,mu_c).q); 69 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(3), Tables(3,mu_c).r, Tables(3,mu_c).q); 70 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(4), Tables(4,mu_c).r, Tables(4,mu_c).q); 71 | fprintf(FID, '\\hline \\hline \n \\end{tabular*} \n'); 72 | fprintf(FID, '\\begin{minipage}[t]{1.00\\textwidth}{\\baselineskip=.5\\baselineskip \\vspace{.3cm} \\footnotesize{ \n'); 73 | fprintf(FID, 'Replication of Table 1 of Huggett (1993) using grid sizes $ n_a=%d $, $ n_e=%d $, $ n_q=%d $ \n', n_a, n_e, n_q); 74 | fprintf(FID, '}} \\end{minipage}'); 75 | fclose(FID); 76 | 77 | mu_c=2; 78 | FilenameString=['./SavedOutput/LatexInputs/Huggett1993_Table2.tex']; 79 | FID = fopen(FilenameString, 'w'); 80 | fprintf(FID, 'Coefficient of Relative Risk Aversion $\\mu$=%1.1f \\\\ \n', mu_vec(mu_c)); 81 | fprintf(FID, '\\begin{tabular*}{0.5\\textwidth}{@{\\extracolsep{\\fill}}lcr} \\hline \\hline \n'); 82 | fprintf(FID, ' Credit Limit & Interest Rate & Price \\\\ \n'); 83 | fprintf(FID, ' (-$\\underbar{a}$) & ($r$) & ($q$) \\\\ \\hline \n'); 84 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(1), Tables(1,mu_c).r, Tables(1,mu_c).q); 85 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(2), Tables(2,mu_c).r, Tables(2,mu_c).q); 86 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(3), Tables(3,mu_c).r, Tables(3,mu_c).q); 87 | fprintf(FID, ' %d & %1.1f \\%% & %1.4f \\\\ \n', alowerbar_vec(4), Tables(4,mu_c).r, Tables(4,mu_c).q); 88 | fprintf(FID, '\\hline \\hline \n \\end{tabular*} \n'); 89 | fprintf(FID, '\\begin{minipage}[t]{1.00\\textwidth}{\\baselineskip=.5\\baselineskip \\vspace{.3cm} \\footnotesize{ \n'); 90 | fprintf(FID, 'Replication of Table 2 of Huggett (1993) using grid sizes $ n_a=%d $, $ n_e=%d $, $ n_q=%d $ \n', n_a, n_e, n_q); 91 | fprintf(FID, '}} \\end{minipage}'); 92 | fclose(FID); 93 | 94 | %% Reproduce Figures 1 & 2 of Huggett (1993) 95 | load ./SavedOutput/Huggett1993Tables.mat Tables TimeTable Figures 96 | % Note that figures depend on plotly 97 | a_grid=Figures(1,1).a_grid; 98 | 99 | % Figure 1 100 | Policy=Figures(1,1).Policy; 101 | fig2=figure(2); 102 | plot(a_grid,a_grid(Policy(1,:,1)),a_grid,a_grid(Policy(1,:,2)),a_grid,a_grid) 103 | title('Optimal Decision Rule','FontSize',18); 104 | xlabel('Assets (a)','FontSize',16); ylabel('Decision (next period assets)','FontSize',16); 105 | legend('e_l','e_h','45 deg line') 106 | set(fig2, 'Color', 'white'); % white bckgr 107 | set(fig2, 'Unit', 'centimeters'); % set unit to cm 108 | set(fig2,'position',[0 0 20 10]); % set size 109 | saveas(fig2, ['./SavedOutput/Graphs/Huggett1993_Figure1.png']) 110 | 111 | % Figure 2 112 | StationaryDist=Figures(1,1).StationaryDist; 113 | fig3=figure(3); 114 | plot(a_grid,cumsum(StationaryDist(:,1)),a_grid,cumsum(StationaryDist(:,2))) 115 | title('Stationarty Distribution','FontSize',18); 116 | xlabel('Assets (a)','FontSize',16); ylabel('Cumulative Distribution Fn','FontSize',16); 117 | legend('e_l','e_h') 118 | set(fig3, 'Color', 'white'); % white bckgr 119 | set(fig3, 'Unit', 'centimeters'); % set unit to cm 120 | set(fig3,'position',[0 0 20 10]); % set size 121 | saveas(fig3, ['./SavedOutput/Graphs/Huggett1993_Figure2.png']) 122 | -------------------------------------------------------------------------------- /Huggett1993/Huggett1993.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/Huggett1993/Huggett1993.pdf -------------------------------------------------------------------------------- /Huggett1993/Huggett1993_Fn.m: -------------------------------------------------------------------------------- 1 | function Output=Huggett1993_Fn(n_a,n_e,n_q,Params,simoptions) 2 | %This code replicates the results of Huggett (1993) - Uninsured Idiosyncratic Risk and Aggregate Saving 3 | disp('Running Huggett1993_Fn') 4 | %% Set up 5 | 6 | %Create markov process for the exogenous income (based on idea of employment and unemployment states, following Imrohoroglu, 1989). 7 | e_grid=[Params.el,Params.eh]'; 8 | pi_e=[1-Params.piehel,Params.piehel; 1-Params.pieheh, Params.pieheh]; 9 | 10 | 11 | %% Grids 12 | % Set grid for asset holdings 13 | Params.aupperbar=4; % Not clear exactly what value Huggett used, have gone with this based on axes of Figure 1. 14 | a_grid=linspace(Params.alowerbar,Params.aupperbar,n_a)'; 15 | 16 | %Set grid for asset prices, q 17 | q_grid=sort(linspace(0.9,1.1,n_q))'; % This grid is substantially wider than the actual likely equilibrium values and so is somewhat overkill. 18 | 19 | %Bring model into the notational conventions used by the toolkit 20 | d_grid=0; %There is no d variable 21 | z_grid=e_grid; 22 | pi_z=pi_e; 23 | p_grid=q_grid; 24 | 25 | n_d=0; 26 | n_z=n_e; 27 | n_p=n_q; 28 | 29 | %Create descriptions of SS values as functions of d_grid, a_grid, s_grid & 30 | %pi_s (used to calculate the integral across the SS dist fn of whatever 31 | %functions you define here) 32 | FnsToEvaluateParamNames(1).Names={}; 33 | FnsToEvaluateFn_1 = @(aprime_val,a_val,s_val) a_val; %We just want the aggregate assets (which is this periods state) 34 | FnsToEvaluate={FnsToEvaluateFn_1}; 35 | 36 | %Now define the functions for the General Equilibrium conditions 37 | %Should be written as LHS of general eqm eqn minus RHS, so that 38 | %the closer the value given by the function is to zero, the closer 39 | %the general eqm condition is to holding. 40 | GeneralEqmEqnParamNames(1).Names={}; 41 | GeneralEqmEqn_1 = @(AggVars,p) AggVars; %The requirement that the aggregate assets (lending and borrowing) equal zero 42 | GeneralEqmEqns={GeneralEqmEqn_1}; 43 | 44 | disp('sizes') 45 | n_a 46 | n_z 47 | n_p 48 | 49 | 50 | %% 51 | DiscountFactorParamNames={'beta'}; 52 | 53 | ReturnFn=@(aprime_val, a_val, s_val,mu,q) Huggett1993_ReturnFn(aprime_val, a_val, s_val,mu,q); 54 | ReturnFnParamNames={'mu','q'}; %It is important that these are in same order as they appear in 'Aiyagari1994_ReturnFn' 55 | 56 | %% Solve 57 | 58 | %Use the toolkit to find the equilibrium price index 59 | GEPriceParamNames={'q'}; 60 | 61 | disp('Calculating price vector corresponding to the stationary eqm') 62 | % tic; 63 | heteroagentoptions.pgrid=p_grid; 64 | [p_eqm,p_eqm_index, MarketClearance]=HeteroAgentStationaryEqm_Case1(n_d, n_a, n_z, n_p, pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, ReturnFnParamNames, FnsToEvaluateParamNames, GeneralEqmEqnParamNames, GEPriceParamNames,heteroagentoptions, simoptions); 65 | % findeqmtime=toc 66 | Params.q=p_eqm.q; 67 | save ./SavedOutput/Huggett1993Market.mat p_eqm p_eqm_index MarketClearance 68 | 69 | % Equilibrium interest rate (at annual rate; model period is 1/6th of a year) 70 | Params.r=(1+(1-Params.q)/Params.q)^6-1; 71 | 72 | % %Now that we know what the equilibrium price is, lets calculate a bunch of 73 | % %other things associated with the equilibrium 74 | p_eqm_index 75 | disp('Calculating various equilibrium objects') 76 | [~,Policy]=ValueFnIter_Case1(n_d,n_a,n_z,d_grid,a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, ReturnFnParamNames); 77 | 78 | % PolicyValues=PolicyInd2Val_Case1(Policy,n_d,n_a,n_s,d_grid,a_grid, Parallel); 79 | 80 | StationaryDist=StationaryDist_Case1(Policy,n_d,n_a,n_z,pi_z, simoptions); 81 | 82 | AggVars=EvalFnOnAgentDist_AggVars_Case1(StationaryDist, Policy, FnsToEvaluate,Params, FnsToEvaluateParamNames,n_d, n_a, n_z, d_grid, a_grid,z_grid); 83 | 84 | eqm_MC=real(GeneralEqmConditions_Case1(AggVars,Params.q, GeneralEqmEqns, Params, GeneralEqmEqnParamNames)); 85 | 86 | save ./SavedOutput/Huggett1993SSObjects.mat p_eqm Policy StationaryDist 87 | 88 | 89 | %% Display some output about the solution 90 | GraphString=['Huggett1993_MarketClearance_mu', num2str(Params.mu), 'alowerbar', num2str(abs(Params.alowerbar))]; 91 | GraphString=strrep(GraphString, '.', '_'); 92 | % Create a graph displaying the market clearance 93 | fig1=figure(1); 94 | plot(p_grid,MarketClearance, 'x',p_grid, zeros(n_p,1),p_eqm.q, 0, 'r o') 95 | title(['Market clearance: mu=', num2str(Params.mu), ' alowerbar=', num2str(Params.alowerbar)],'FontSize',18); 96 | xlabel('p','FontSize',16); ylabel('tilde(p)-p','FontSize',16); 97 | set(fig1, 'Color', 'white'); % white bckgr 98 | set(fig1, 'Unit', 'centimeters'); % set unit to cm 99 | set(fig1,'position',[0 0 20 10]); % set size 100 | saveas(fig1,['./SavedOutput/Graphs/',GraphString,'.png']) 101 | 102 | %plot(cumsum(sum(StationaryDist,2))) %Plot the asset cdf 103 | 104 | fprintf('For parameter values mu=%.2f, alowerbar=%.2f \n', [Params.mu,Params.alowerbar]) 105 | fprintf('The table elements are q=%.4f, r=%.4f \n',[Params.q,100*Params.r]) 106 | 107 | %% Outputs of the function 108 | % Tables: q,r 109 | 110 | Output.q=gather(Params.q); 111 | Output.r=gather(100*Params.r); 112 | Output.Policy=gather(Policy); 113 | Output.StationaryDist=gather(StationaryDist); 114 | Output.a_grid=gather(a_grid); 115 | 116 | end 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Huggett1993/Huggett1993_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=Huggett1993_ReturnFn(aprime_val, a_val, z_val,mu,q) 2 | % You can include comments in the return function file, but only on 3 | % seperate lines to the commands. If you try putting a comment on the same 4 | % line as a command (and following line is not blank) then this will cause 5 | % an error with the GPU codes. 6 | 7 | % Huggett (1993) refers to mu as sigma. 8 | 9 | F=-Inf; 10 | c=a_val+z_val-q*aprime_val; 11 | %c=a_t+e_t-q*a_{t+1} 12 | if c>0 13 | if mu==1 14 | F=log(c); 15 | else 16 | F=(c^(1-mu) -1)/(1-mu); 17 | end 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /Huggett1996/Huggett1996.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/Huggett1996/Huggett1996.pdf -------------------------------------------------------------------------------- /Huggett1996/Huggett1996_Fn.m: -------------------------------------------------------------------------------- 1 | function OutputResults=Huggett1996_Fn(Params, n_a,n_z,N_j, a_grid, ReturnFn, DiscountFactorParamNames, AgeWeightsParamNames, FnsToEvaluate, GEPriceParamNames, GeneralEqmEqns, heteroagentoptions, simoptions, vfoptions,CheckUniquenessOfGE) 2 | % Replication of Huggett (1996) - Wealth Distribution in Life Cycle Economies 3 | 4 | %% Need to create appropriate z_grid and pi_z 5 | Params.sigmasqy=Params.sigmasqepsilon./(1-Params.gamma.^2); 6 | % Initial distribution of income 7 | Params.sigmasqy1=0.38; 8 | 9 | % Huggett use 17 states equally spaced between +-4*sigmasqy1, with an 18th 10 | % state at 6*sigmasqy1, "The transition probabilities between states are 11 | % calculated by integrating the area under the normal distribution conditional on 12 | % the current value of the state." 13 | z_grid=[linspace(-4*sqrt(Params.sigmasqy1),4*sqrt(Params.sigmasqy1),17),6*sqrt(Params.sigmasqy1)]'; 14 | pi_z=nan(18,18); 15 | % Following lines implement the transition matrix, they are largely just a copy of some code from the TauchenMethod() command. 16 | sigma=sqrt(Params.sigmasqepsilon); %stddev of e 17 | for ii=1:length(z_grid) 18 | pi_z(ii,1)=normcdf(z_grid(1)+(z_grid(2)-z_grid(1))/2-Params.gamma*z_grid(ii),0,sigma); 19 | for jj=2:(length(z_grid)-1) 20 | pi_z(ii,jj)=normcdf(z_grid(jj)+(z_grid(jj+1)-z_grid(jj))/2-Params.gamma*z_grid(ii),0,sigma)-normcdf(z_grid(jj)-(z_grid(jj)-z_grid(jj-1))/2-Params.gamma*z_grid(ii),0,sigma); 21 | end 22 | pi_z(ii,end)=1-normcdf(z_grid(end)-(z_grid(end)-z_grid(end-1))/2-Params.gamma*z_grid(ii),0,sigma); 23 | end 24 | z_grid=gpuArray(z_grid); 25 | pi_z=gpuArray(pi_z); 26 | 27 | %% Initial distribution of agents at birth (j=1) 28 | jequaloneDist=zeros(n_a,n_z,'gpuArray'); 29 | [trash,zeroassets_index]=min(abs(a_grid)); 30 | % Place them on the existing z_grid based on Params.sigmasqy1 (the variance 31 | % of earnings at age 1) under assumption of normal distribution. 32 | % Following lines implement this, they are largely just a copy of some code from the TauchenMethod() command. 33 | sigma=sqrt(Params.sigmasqy1); %stddev of e 34 | for ii=1:length(z_grid) 35 | jequaloneDist(zeroassets_index,1)=normcdf(z_grid(1)+(z_grid(2)-z_grid(1))/2,0,sigma); 36 | for jj=2:(length(z_grid)-1) 37 | jequaloneDist(zeroassets_index,jj)=normcdf(z_grid(jj)+(z_grid(jj+1)-z_grid(jj))/2,0,sigma)-normcdf(z_grid(jj)-(z_grid(jj)-z_grid(jj-1))/2,0,sigma); 38 | end 39 | jequaloneDist(zeroassets_index,end)=1-normcdf(z_grid(end)-(z_grid(end)-z_grid(end-1))/2,0,sigma); 40 | end 41 | 42 | %% Solve for the General Equilibrium 43 | % Use the toolkit to find the equilibrium price index. There are two ways 44 | % to do this. In what follows I use the 'search' approach to calculate the 45 | % (initial) General equilibrium. Having used the search I then do a bunch 46 | % of looking around a p_grid to be 'certain' that this is the only 47 | % equilibrium, or at least the only one in the vicinity. 48 | 49 | % Without p_grid, just searching. Use n_p=0. (Setting the actual algorithm 50 | % used to 'search' can be done with heteroagentoptions.fminalgo) 51 | heteroagentoptions.verbose=1; 52 | [p_eqm,~, GeneralEqmEqnsValues]=HeteroAgentStationaryEqm_Case1_FHorz(jequaloneDist,AgeWeightsParamNames,0, n_a, n_z, N_j, 0, pi_z, 0, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames, heteroagentoptions, simoptions, vfoptions); 53 | Params.r=p_eqm.r; 54 | Params.b=p_eqm.b; 55 | Params.T=p_eqm.T; 56 | fprintf('search finds equilibrium r=%8.2f, b=%8.2f, T=%8.2f \n') 57 | save ./SavedOutput/Huggett1996.mat Params 58 | % load ./SavedOutput/Huggett1996.mat Params 59 | 60 | if CheckUniquenessOfGE==1 61 | % Using p_grid. This can be helpful if you want to, e.g., look for possibility of multiple equilibria. 62 | % We will use it as an informal double-check of the equilibrium we found previously 63 | % GEPriceParamNames={'r','b','T'}; % Already delared above. 64 | r_grid=linspace(0.5,2,21)'*Params.r; %okay 65 | b_grid=linspace(0.5,2,21)'*Params.b; %okay 66 | T_grid=linspace(0.5,2,21)'*Params.T; %good 67 | p_grid=[r_grid,b_grid, T_grid]; 68 | % 69 | disp('Calculating price vector corresponding to the stationary eqm') 70 | n_p=[length(r_grid),length(b_grid),length(T_grid)]; 71 | heteroagentoptions.pgrid=p_grid; 72 | heteroagentoptions.verbose=1; 73 | [p_eqm,p_eqm_index1, GeneralEqmEqnsValues1]=HeteroAgentStationaryEqm_Case1_FHorz(jequaloneDist,AgeWeightsParamNames,0, n_a, n_z, N_j, n_p, pi_z, 0, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames, heteroagentoptions, simoptions, vfoptions); 74 | Params.r=p_eqm.r; 75 | Params.b=p_eqm.b; 76 | Params.T=p_eqm.T; 77 | fprintf('course grid search finds equilibrium r=%8.2f, b=%8.2f, T=%8.2f \n') 78 | 79 | % Grid search again, just to be super sure and accurate 80 | r_grid=linspace(0.95,1.05,21)'*Params.r; %okay 81 | b_grid=linspace(0.95,1.05,21)'*Params.b; %okay 82 | T_grid=linspace(0.95,1.05,21)'*Params.T; %good 83 | p_grid=[r_grid,b_grid, T_grid]; 84 | [p_eqm,p_eqm_index2, GeneralEqmEqnsValues2]=HeteroAgentStationaryEqm_Case1_FHorz(jequaloneDist,AgeWeightsParamNames,0, n_a, n_z, N_j, n_p, pi_z, 0, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames, heteroagentoptions, simoptions, vfoptions); 85 | Params.r=p_eqm.r; 86 | Params.b=p_eqm.b; 87 | Params.T=p_eqm.T; 88 | fprintf('fine grid search finds equilibrium r=%8.2f, b=%8.2f, T=%8.2f \n') 89 | end 90 | 91 | %% Compute a few things about the equilibrium 92 | [V, Policy]=ValueFnIter_Case1_FHorz(0,n_a,n_z,N_j, 0, a_grid, z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [],vfoptions); 93 | StationaryDist=StationaryDist_FHorz_Case1(jequaloneDist,AgeWeightsParamNames,Policy,0,n_a,n_z,N_j,pi_z,Params,simoptions); 94 | 95 | % Start with some basics (these were previously being done inside return function): 96 | % Rearranging that r=MPK-delta gives the following eqn (MPK is marginal product of capital) 97 | KdivL=((Params.r+Params.delta)/(Params.alpha*Params.A))^(1/(Params.alpha-1)); 98 | % From K/Y, substituting the production function gives 99 | KdivY=(KdivL^(1-Params.alpha))/Params.A; 100 | % We know w=MPL (MPL is marginal product of labour) 101 | Params.w=Params.A*(1-Params.alpha)*(KdivL^Params.alpha); % wage rate (per effective labour unit) 102 | % Huggett (1996) calibrates tau to the following (see pg 478 for explanation) 103 | Params.tau=0.195/(1-Params.delta*KdivY); 104 | 105 | % Aggregate wealth transfers.% Start with some basics (these were previously being done inside return function): 106 | % Rearranging that r=MPK-delta gives the following eqn (MPK is marginal product of capital) 107 | KdivL=((Params.r+Params.delta)/(Params.alpha*Params.A))^(1/(Params.alpha-1)); 108 | % From K/Y, substituting the production function gives 109 | KdivY=(KdivL^(1-Params.alpha))/Params.A; 110 | % We know w=MPL (MPL is marginal product of labour) 111 | Params.w=Params.A*(1-Params.alpha)*(KdivL^Params.alpha); % wage rate (per effective labour unit) 112 | % Huggett (1996) calibrates tau to the following (see pg 478 for explanation) 113 | Params.tau=0.195/(1-Params.delta*KdivY); 114 | 115 | % Aggregate wealth transfers. 116 | AggregateWealthTransers=zeros(1,N_j); 117 | for jj=1:Params.J 118 | for ii=1:jj 119 | AggregateWealthTransers(jj)=AggregateWealthTransers(jj)+Params.T*(1+Params.r*(1-Params.tau))^(ii-1); 120 | end 121 | end 122 | AggregateWealthTransers=sum(Params.mewj.*AggregateWealthTransers); 123 | % Total wealth 124 | FnsToEvaluate2.TotalWealth = @(aprime_val,a_val,z_val) a_val; 125 | AggVars=EvalFnOnAgentDist_AggVars_FHorz_Case1(StationaryDist, Policy, FnsToEvaluate2, Params, [], 0, n_a, n_z,N_j, 0, a_grid, z_grid); 126 | % Transfer Wealth Ratio 127 | TransferWealthRatio=AggregateWealthTransers/AggVars.TotalWealth.Mean; 128 | 129 | 130 | % Calculate fraction of population with zero or negative wealth 131 | FnsToEvaluate3.ZeroOrNegAssets = @(aprime_val,a_val,z_val) (a_val<=0); % Indicator for ZeroOrNegAssets 132 | FractionWithZeroOrNegAssets=EvalFnOnAgentDist_AggVars_FHorz_Case1(StationaryDist, Policy, FnsToEvaluate3, Params, [], 0, n_a, n_z,N_j, 0, a_grid, z_grid); 133 | 134 | % Calculate wealth lorenz curve (and thus all percentile shares) and also 135 | % the that for earnings (in text at bottom of pg 480, top of pg 481, there 136 | % are a bunch of descriptions of model earnings, conditional on working age) 137 | AllLorenzCurves=EvalFnOnAgentDist_LorenzCurve_FHorz_Case1(StationaryDist, Policy, FnsToEvaluate, Params, [], 0, n_a, n_z,N_j, 0, a_grid, z_grid); 138 | TopWealthShares=100*(1-AllLorenzCurves.K([80,95,99],1)); % Need the 20,5, and 1 top shares for Tables of Huggett (1996) 139 | % Calculate the wealth gini 140 | WealthGini=Gini_from_LorenzCurve(AllLorenzCurves.K(:,1)); 141 | 142 | AgeConditionalStats=LifeCycleProfiles_FHorz_Case1(StationaryDist,Policy,FnsToEvaluate,[],Params,0,n_a,n_z,N_j,0,a_grid,z_grid); 143 | 144 | %% Put together a bunch of things that I want to return as output 145 | 146 | OutputResults.Params=Params; 147 | 148 | OutputResults.AgeConditionalStats=AgeConditionalStats; 149 | 150 | OutputResults.WealthGini=WealthGini; 151 | OutputResults.TopWealthShares=TopWealthShares; 152 | OutputResults.FractionWithZeroOrNegAssets=100*FractionWithZeroOrNegAssets.ZeroOrNegAssets.Mean; 153 | OutputResults.TransferWealthRatio=TransferWealthRatio; 154 | OutputResults.KdivY=KdivY; 155 | 156 | OutputResults.z_grid=gather(z_grid); 157 | OutputResults.pi_z=gather(pi_z); 158 | 159 | OutputResults.GeneralEqmEqnsValues=gather(GeneralEqmEqnsValues); % So can check accuracy of the eqm 160 | 161 | if CheckUniquenessOfGE==1 162 | % Some things to allow looking at whether the equilibrium was unique 163 | OutputResults.p_eqm_index1=p_eqm_index1; 164 | OutputResults.GeneralEqmEqnsValues1=GeneralEqmEqnsValues1; 165 | OutputResults.p_eqm_index2=p_eqm_index2; 166 | OutputResults.GeneralEqmEqnsValues2=GeneralEqmEqnsValues2; 167 | end 168 | 169 | OutputResults=gather(OutputResults); % Just to be sure everything is on cpu, not gpu 170 | 171 | 172 | 173 | end 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /Huggett1996/Huggett1996_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=Huggett1996_ReturnFn(aprime,a,z,sigma,r,ybarj,theta,b,bvec,T,delta,alpha,A,bc_equalsminusw) 2 | % We don't need w and tau as these can be imputed from the others. 3 | 4 | % Note that ybarj and b are both dependent on j 5 | 6 | % Rearranging that r=MPK-delta gives the following eqn (MPK is marginal product of capital) 7 | KdivL=((r+delta)/(alpha*A))^(1/(alpha-1)); 8 | % From K/Y, substituting the production function gives 9 | KdivY=(KdivL^(1-alpha))/A; 10 | % We know w=MPL (MPL is marginal product of labour) 11 | w=A*(1-alpha)*(KdivL^alpha); % wage rate (per effective labour unit) 12 | % Huggett (1996) calibrates tau to the following (see pg 478 for explanation) 13 | tau=0.195/(1-delta*KdivY); 14 | 15 | % Pensions: 16 | 17 | % The borrowing constraint 18 | % (will be -w if bc_equalsminusw==1, 0 if bc_equalsminusw==0) 19 | bc=-w*bc_equalsminusw; 20 | 21 | % What Hugget calls e(z,t) 22 | e_jz=exp(z+ybarj); 23 | 24 | % Budget constraint 25 | c=(1+r*(1-tau))*a+(1-tau-theta)*w*e_jz+b*bvec+T-aprime; 26 | 27 | F=-Inf; %(l by aprime) 28 | 29 | if c>0 && aprime>=bc 30 | F=(c.^(1-sigma)-1)/(1-sigma); 31 | end 32 | 33 | end 34 | -------------------------------------------------------------------------------- /Imrohoroglu1989/Imrohoroglu1989.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/Imrohoroglu1989/Imrohoroglu1989.pdf -------------------------------------------------------------------------------- /Imrohoroglu1989/Imrohoroglu1989_ConsFn.m: -------------------------------------------------------------------------------- 1 | function c=Imrohoroglu1989_ConsFn(aprime_val, a_val, s_val,z_val,r_l,r_b,y,theta,sigma) 2 | 3 | % s_val=rem(sz_val-1,2)+1; 4 | 5 | %F=-Inf; %model: (aprime,a,s) 6 | c=0; 7 | 8 | if aprime_val>=0 %If lending 9 | r=r_l; 10 | else %If borrowing 11 | r=r_b; 12 | end 13 | 14 | earnings=0; 15 | if s_val==1 %If employed 16 | earnings=y; 17 | elseif s_val==2 %If unemployed 18 | earnings=theta*y; 19 | end 20 | 21 | c=a_val-aprime_val/(1+r)+earnings; 22 | 23 | % if c>0 24 | % F=(c^(1-sigma))/(1-sigma); 25 | % end 26 | 27 | end -------------------------------------------------------------------------------- /Imrohoroglu1989/Imrohoroglu1989_IncomeFn.m: -------------------------------------------------------------------------------- 1 | function income=Imrohoroglu1989_IncomeFn(aprime_val, a_val, s_val,z_val,r_l,r_b,y,theta,sigma) 2 | 3 | if aprime_val>=0 %If lending 4 | r=r_l; 5 | else %If borrowing 6 | r=r_b; 7 | end 8 | 9 | earnings=0; 10 | if s_val==1 %If employed 11 | earnings=y; 12 | elseif s_val==2 %If unemployed 13 | earnings=theta*y; 14 | end 15 | 16 | income=a_val*r+earnings; 17 | 18 | end -------------------------------------------------------------------------------- /Imrohoroglu1989/Imrohoroglu1989_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=Imrohoroglu1989_ReturnFn(aprime_val, a_val, s_val,z_val,r_l,r_b,y,theta,sigma) 2 | 3 | % s_val=rem(sz_val-1,2)+1; 4 | 5 | F=-Inf; %model: (aprime,a,s) 6 | c=0; 7 | 8 | if aprime_val>=0 %If lending 9 | r=r_l; 10 | else %If borrowing 11 | r=r_b; 12 | end 13 | 14 | earnings=0; 15 | if s_val==1 %If employed 16 | earnings=y; 17 | elseif s_val==2 %If unemployed 18 | earnings=theta*y; 19 | end 20 | 21 | c=a_val-aprime_val/(1+r)+earnings; 22 | 23 | if c>0 24 | F=(c^(1-sigma))/(1-sigma); 25 | end 26 | 27 | end -------------------------------------------------------------------------------- /ImrohorogluImrohorogluJoines1995/IIJ1995_absOmega0minusOmega1.m: -------------------------------------------------------------------------------- 1 | function EqmCondns=IIJ1995_absOmega0minusOmega1(GEandLumpSum,Omega1,Params,jequaloneDist,AgeWeightsParamNames,n_d, n_a, n_z, N_j, pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, FnsToEvaluate2, GeneralEqmEqns, DiscountFactorParamNames, ReturnFnParamNames, FnsToEvaluateParamNames, FnsToEvaluateParamNames2, GeneralEqmEqnParamNames, GEPriceParamNames,heteroagentoptions,simoptions,vfoptions) 2 | % Welfare with compensation L in each period of life and without social security 3 | 4 | Params.r=GEandLumpSum(1); 5 | % Params.Tr_beq=0; 6 | Params.LumpSum=GEandLumpSum(2); 7 | 8 | GEprices=GEandLumpSum(1); 9 | 10 | N_z=prod(n_z); 11 | 12 | if heteroagentoptions.verbose==1 13 | fprintf('Currently evaluating: LumpSum=%8.4f \n', Params.LumpSum) 14 | end 15 | 16 | 17 | %% 18 | % If 'exogenous shock fn' is used and depends on GE parameters then 19 | % precompute it here (otherwise it is already precomputed). 20 | if isfield(vfoptions,'ExogShockFn') 21 | if ~isfield(vfoptions,'pi_z_J') % This is implicitly checking that ExogShockFn does depend on GE params (if it doesn't then this field will already exist) 22 | pi_z_J=zeros(N_z,N_z,N_j); 23 | z_grid_J=zeros(N_z,N_j); 24 | for jj=1:N_j 25 | if isfield(vfoptions,'ExogShockFnParamNames') 26 | ExogShockFnParamsVec=CreateVectorFromParams(Parameters, simoptions.ExogShockFnParamNames,jj); 27 | ExogShockFnParamsCell=cell(length(ExogShockFnParamsVec),1); 28 | for ii=1:length(ExogShockFnParamsVec) 29 | ExogShockFnParamsCell(ii,1)={ExogShockFnParamsVec(ii)}; 30 | end 31 | [z_grid,pi_z]=simoptions.ExogShockFn(ExogShockFnParamsCell{:}); 32 | else 33 | [z_grid,pi_z]=simoptions.ExogShockFn(jj); 34 | end 35 | pi_z_J(:,:,jj)=gather(pi_z); 36 | z_grid_J(:,:,jj)=gather(z_grid); 37 | end 38 | % Now store them in vfoptions and simoptions 39 | vfoptions.pi_z_J=pi_z_J; 40 | vfoptions.z_grid_J=z_grid_J; 41 | simoptions.pi_z_J=pi_z_J; 42 | simoptions.z_grid_J=z_grid_J; 43 | end 44 | end 45 | 46 | %% 47 | 48 | [V, Policy]=ValueFnIter_Case1_FHorz(n_d,n_a,n_z,N_j, d_grid, a_grid, z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, ReturnFnParamNames,vfoptions); 49 | StationaryDist=StationaryDist_FHorz_Case1(jequaloneDist,AgeWeightsParamNames,Policy,n_d,n_a,n_z,N_j,pi_z,Params,simoptions); 50 | 51 | % Calculate the general eqm conditions 52 | AggVars=EvalFnOnAgentDist_AggVars_FHorz_Case1(StationaryDist, Policy, FnsToEvaluate, Params, FnsToEvaluateParamNames, n_d, n_a, n_z,N_j, d_grid, a_grid, z_grid,[],simoptions); 53 | GeneralEqmConditionsVec=real(GeneralEqmConditions_Case1(AggVars,GEprices, GeneralEqmEqns, Params,GeneralEqmEqnParamNames)); 54 | 55 | % Calculate absOmega0minusOmega1 56 | ValuesOnGrid=EvalFnOnAgentDist_ValuesOnGrid_FHorz_Case1(Policy, FnsToEvaluate2, Params, FnsToEvaluateParamNames2, n_d, n_a, n_z, N_j, d_grid, a_grid, z_grid,[],simoptions); 57 | UtilityOnGrid=shiftdim(ValuesOnGrid(5,:,:,:),1); 58 | discountongrid=shiftdim(cumprod(Params.beta*Params.sj),-1); 59 | AgeConditionalStationaryDist=StationaryDist./sum(sum(StationaryDist,1),2); 60 | Omega0=sum(sum(sum(discountongrid.*AgeConditionalStationaryDist.*UtilityOnGrid))); 61 | absOmega0minusOmega1=abs(Omega0-Omega1); 62 | 63 | EqmCondns=[gather(abs(GeneralEqmConditionsVec)),gather(absOmega0minusOmega1)]; 64 | 65 | if heteroagentoptions.verbose==1 66 | fprintf('GEprices: r=%8.4f \n', Params.r) 67 | fprintf('GeneralEqmConditions: %8.4f \n', GeneralEqmConditionsVec) 68 | fprintf('Omega0 and Omega1: Omega0=%8.4f Omega1=%8.4f \n', Omega0, Omega1) 69 | end 70 | 71 | EqmCondns=sum([1,1].*(EqmCondns)); % Use the same weights 72 | 73 | 74 | 75 | end 76 | -------------------------------------------------------------------------------- /ImrohorogluImrohorogluJoines1995/ImrohorogluImrohorogluJoines1995.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/ImrohorogluImrohorogluJoines1995/ImrohorogluImrohorogluJoines1995.pdf -------------------------------------------------------------------------------- /ImrohorogluImrohorogluJoines1995/ImrohorogluImrohorogluJoines1995_ConsumptionFn.m: -------------------------------------------------------------------------------- 1 | function c=ImrohorogluImrohorogluJoines1995_ConsumptionFn(kprime,k,z,r,tau_u, tau_s,h,zeta,epsilon_j,I_j,alpha,delta, A,SSdivw, Tr_beq,workinglifeincome,g,agej,MedicalShock,LumpSum) %i 2 | 3 | w=(1-alpha)*(A^(1/(1-alpha)))*((r+delta)/alpha)^(alpha/(alpha-1)); 4 | % Yhat=(rhat+delta)/(1-alpha); 5 | 6 | earnings=z*w*h*epsilon_j*I_j; 7 | u=zeta*w*h; % Unemployment benefits are at replacement rate phi; 8 | unemploymentbenefit=(1-z)*u*I_j; 9 | socialsecuritybenefit=w*SSdivw*(1-I_j); 10 | if g>0 % So not using baseline model 11 | socialsecuritybenefit=w*SSdivw*(1-I_j)*workinglifeincome*(1/((1+g)^agej)); 12 | % Note: the actual social security benefit is constant, but the model 13 | % has been detrended by (1+g)^t and it is for these reason it here 14 | % appears to decrease with age. 15 | end 16 | % q=earnings+unemploymentbenefit+socialsecuritybenefit; % This is the notation used by IIJ1995 and is just here to ease comprehension. 17 | 18 | % IIJ1995 includes an extension to 'medical shocks' (see pg 110 of IIJ1995) 19 | medicalexpense=0; 20 | if MedicalShock>0 21 | % In retirement z now becomes the 'cost of illness' (when non-zero valued, the household is ill, when zero valued the household is healthy) 22 | % The cost of illness is measured as a fraction of employed wage (which is w*h) 23 | medicalexpense=(1-I_j)*z*w*h; % Note that this will be zero when working age (as I_j will be 1). 24 | end 25 | 26 | c=(1+r)*k+(1-tau_u-tau_s)*earnings+unemploymentbenefit+socialsecuritybenefit+Tr_beq-medicalexpense-kprime+LumpSum; 27 | 28 | % 29 | % F=-Inf; 30 | % 31 | % if c>0 32 | % F=(c.^(1-gamma))/(1-gamma); 33 | % end 34 | % 35 | % if kprime<0 && jj==N 36 | % % have to die with non-negative assets 37 | % F=-Inf; 38 | % end 39 | % 40 | % if kprimeJr % z now indicates 'illness', or more precisely 'cost of illness as percent of employed wage. 20 | if MedicalShock==1 21 | z_grid=[0;0.25]; % Cost of illness is 25 percent of employed wage 22 | pi_z=[0.9450, 0.0550; 0.25, 0.75]; % Implies stationarty distribution of [0.8197; 0.1903] 23 | elseif MedicalShock==2 24 | z_grid=[0;0.35]; % 35 percent of employed wage 25 | pi_z=[0.9753, 0.0247; 0.25, 0.75]; % Implies stationarty distribution of [0.9101; 0.0899] 26 | end 27 | end 28 | 29 | end -------------------------------------------------------------------------------- /ImrohorogluImrohorogluJoines1995/ImrohorogluImrohorogluJoines1995_IncomeFn.m: -------------------------------------------------------------------------------- 1 | function income=ImrohorogluImrohorogluJoines1995_IncomeFn(kprime,k,z,r,h,zeta, epsilon_j,I_j,alpha,delta, A,SSdivw, Tr_beq,workinglifeincome,g,agej) %i 2 | 3 | w=(1-alpha)*(A^(1/(1-alpha)))*((r+delta)/alpha)^(alpha/(alpha-1)); 4 | % Yhat=(rhat+delta)/(1-alpha); 5 | 6 | earnings=z*w*h*epsilon_j*I_j; 7 | u=zeta*w*h; % Unemployment benefits are at replacement rate phi; 8 | unemploymentbenefit=(1-z)*u*I_j; 9 | socialsecuritybenefit=w*SSdivw*(1-I_j); 10 | if g>0 % So not using baseline model 11 | socialsecuritybenefit=w*SSdivw*(1-I_j)*workinglifeincome*(1/((1+g)^agej)); 12 | % Note: the actual social security benefit is constant, but the model 13 | % has been detrended by (1+g)^t and it is for these reason it here 14 | % appears to decrease with age. 15 | end 16 | % q=earnings+unemploymentbenefit+socialsecuritybenefit; % This is the notation used by IIJ1995 and is just here to ease comprehension. 17 | 18 | % income=r*k+earnings+unemploymentbenefit+socialsecuritybenefit+Tr_beq; 19 | 20 | % From Figure 3 it became clear that above commented out formula was not what 21 | % is being plotted as the concept plotted does not include capital income 22 | % but does include the pension (can be seen from the shape of the income 23 | % profile during retirement) 24 | income=earnings+unemploymentbenefit+socialsecuritybenefit+Tr_beq; 25 | 26 | end -------------------------------------------------------------------------------- /ImrohorogluImrohorogluJoines1995/ImrohorogluImrohorogluJoines1995_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=ImrohorogluImrohorogluJoines1995_ReturnFn(kprime,k,z,r,tau_u, tau_s,gamma, h,zeta, epsilon_j,I_j,alpha,delta, A,SSdivw, Tr_beq,MedicalShock,workinglifeincome,g,agej,LumpSum) %i 2 | % Note: In baseline model MedicalShocks=0, workinglifeincome=1, and g=0 and 3 | % hence none of these inputs would be required if we just wanted to solve 4 | % the baseline model. agej would also not be needed. 5 | % LumpSum is zero. Is just needed for calculating the welfare benefits of various reforms. 6 | 7 | w=(1-alpha)*(A^(1/(1-alpha)))*((r+delta)/alpha)^(alpha/(alpha-1)); 8 | % Yhat=(rhat+delta)/(1-alpha); 9 | 10 | earnings=z*w*h*epsilon_j*I_j; 11 | u=zeta*w*h; % Unemployment benefits are at replacement rate phi; 12 | unemploymentbenefit=(1-z)*u*I_j; 13 | socialsecuritybenefit=w*SSdivw*(1-I_j); 14 | if g>0 % So not using baseline model 15 | socialsecuritybenefit=w*SSdivw*(1-I_j)*workinglifeincome*(1/((1+g)^agej)); 16 | % Note: the actual social security benefit is constant, but the model 17 | % has been detrended by (1+g)^t and it is for these reason it here 18 | % appears to decrease with age. 19 | end 20 | % q=earnings+unemploymentbenefit+socialsecuritybenefit; % This is the notation used by IIJ1995 and is just here to ease comprehension. 21 | 22 | % IIJ1995 includes an extension to 'medical shocks' (see pg 110 of IIJ1995) 23 | medicalexpense=0; 24 | if MedicalShock>0 25 | % In retirement z now becomes the 'cost of illness' (when non-zero valued, the household is ill, when zero valued the household is healthy) 26 | % The cost of illness is measured as a fraction of employed wage (which is w*h) 27 | medicalexpense=(1-I_j)*z*w*h; % Note that this will be zero when working age (as I_j will be 1). 28 | end 29 | 30 | c=(1+r)*k+(1-tau_u-tau_s)*earnings+unemploymentbenefit+socialsecuritybenefit+Tr_beq-medicalexpense-kprime+LumpSum; 31 | 32 | F=-Inf; 33 | 34 | if c>0 35 | F=(c.^(1-gamma))/(1-gamma); 36 | end 37 | 38 | % Borrowing constaint is imposed via grid on assets 39 | 40 | % if kprime<0 && jj==N 41 | % % have to die with non-negative assets 42 | % F=-Inf; 43 | % end 44 | % 45 | % if kprime0 20 | if rho==1 21 | F=log(c)+v_jJ*log(l); 22 | else 23 | F=(c^(1-rho))/(1-rho)+v_jJ*(l^(1-rho))/(1-rho); 24 | end 25 | end 26 | 27 | else 28 | % Because survival is part of the discount factor this is not really needed here 29 | % It does have to be finite else the 0 of discount factor times this 30 | % will give an error (i.e., cannot set it to -Inf) 31 | F=0; 32 | end 33 | 34 | 35 | end -------------------------------------------------------------------------------- /KulishKentSmith2010/Replication_KKS2010.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/KulishKentSmith2010/Replication_KKS2010.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vfitoolkit-matlab-replication 2 | Codes that use the VFI Toolkit to replicate existing papers. Replication is here considered to mean reproduce all tables and graphs (that are based on model). 3 | 4 | Each folder contains a replication of a paper: to use them run the file named after the paper (AuthorsYear.m), it will do everything (calling all the other scripts) and generate all the tables and figures as saved files. 5 | 6 | Each folder also contains a pdf that summarizes all the results with a brief outline of the model equations, the original and replication verions of all tables and figures, and a few comments relating to the replication. 7 | 8 | Submissions of codes replicating papers are most welcome. 9 | -------------------------------------------------------------------------------- /RestucciaRogerson2008/RestucciaRogerson2008.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/RestucciaRogerson2008/RestucciaRogerson2008.pdf -------------------------------------------------------------------------------- /RestucciaRogerson2008/RestucciaRogerson2008_Fn.m: -------------------------------------------------------------------------------- 1 | function Output=RestucciaRogerson2008_Fn(fixedsubsidy_c, normalize_employment, n_d,n_a,n_z,d_grid,a_grid,z_grid,pi_z,Params,ReturnFn,DiscountFactorParamNames, FnsToEvaluate, GEPriceParamNames, GeneralEqmEqns, EntryExitParamNames, vfoptions, simoptions, heteroagentoptions) 2 | % Only substantial change from the baseline codes is the need to determine 3 | % Params.subsidyrate in general eqm so as to get K to equal Kbaseline. 4 | % Note that "if Params.upsilon(:,1)>0" means that this is only done when 5 | % subsidies are being used. 6 | 7 | vfoptions.parallel=2; % use gpu 8 | 9 | if sum(Params.upsilon(:,1))>0 && fixedsubsidy_c==0 % If using subsidies 10 | 11 | % Obviously we have to add subsidies. Less obvious is that to 'enforce' 12 | % Kbaseline we not only need to add it as a general eqm condition, we 13 | % also now need to include labour market clearance (and so include Ne 14 | % as a general eqm price parameter) because our earlier trick of just 15 | % 'renormalizing' afterwards will break the Kbaseline condition. 16 | GEPriceParamNames={'w','subsidyrate', 'Ne'}; 17 | 18 | heteroagentoptions.specialgeneqmcondn={'condlentry','entry',0,0}; 19 | 20 | % A 'condlentry' general equilibrium condition will take values of greater 21 | % than zero for firms that decide to enter, less than zero for first that 22 | % decide not to enter (or more accurately, after entry decision they draw 23 | % their state, and then decide to cancel/abort their entry). 24 | 25 | GeneralEqmEqns.CondlEntry = @(ValueFn,beta) beta*ValueFn-0; % Conditional entry condition. 26 | GeneralEqmEqns.Entry = @(EValueFn,beta,ce) beta*EValueFn-ce; % Free entry conditions (expected returns equal zero in eqm); note that the first 'General eqm price' is ce, the fixed-cost of entry. 27 | GeneralEqmEqns.K = @(kbar,Kbaseline) kbar-Kbaseline; % K is unchanged (we choose subsidies to satisfy this, see RR2008 for explanation of why they wish to do this) 28 | GeneralEqmEqns.LabourMarket = @(nbar) nbar-1; % Labour market clearance (labour supply is perfectly inelastic and equal to one; we need labour demand to be equal to this; this condition determines mass of entering agents, Ne) 29 | end 30 | 31 | n_p=0; 32 | disp('Calculating price vector corresponding to the stationary eqm') 33 | % NOTE: EntryExitParamNames has to be passed as an additional input compared to the standard case. 34 | [p_eqm,~, ~]=HeteroAgentStationaryEqm_Case1(0, n_a, n_z, n_p, pi_z, [], a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames,heteroagentoptions, simoptions, vfoptions, EntryExitParamNames); 35 | Params.w=p_eqm.w; 36 | Params.ebar=p_eqm.ebar; 37 | if sum(Params.upsilon(:,1))>0 && fixedsubsidy_c==0 % If using subsidies 38 | Params.subsidyrate=p_eqm.subsidyrate; 39 | Params.Ne=p_eqm.Ne; 40 | end 41 | 42 | % Calculate some things in the general eqm 43 | [V,Policy]=ValueFnIter_Case1(n_d,n_a,n_z,[],a_grid,z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions); 44 | StationaryDist=StationaryDist_Case1(Policy,n_d,n_a,n_z,pi_z, simoptions, Params, EntryExitParamNames); 45 | 46 | 47 | AggVars=EvalFnOnAgentDist_AggVars_Case1(StationaryDist, Policy, FnsToEvaluate, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid, simoptions.parallel,simoptions,EntryExitParamNames); 48 | 49 | if sum(Params.upsilon(:,1))==0 || fixedsubsidy_c==1 % If no subsidies (or subsidy is fixed) 50 | % Without subsides we are not attempting to keep K unchanged (equal to 51 | % Kbaseline). 52 | % So we can do the labour market clearance condition here 53 | % as a renormalization without having to worry about this breaking 54 | % the K equals Kbaseline condition. 55 | % Impose the labour market clearance, which involves calculating Ne. 56 | % AggVars=EvalFnOnAgentDist_AggVars_Case1(StationaryDist, Policy, FnsToEvaluate, Params, [], n_d, n_a, n_z, d_grid, a_grid, z_grid, simoptions.parallel,simoptions,EntryExitParamNames); 57 | InitialNe=Params.Ne; 58 | Params.Ne=1/AggVars.nbar.Aggregate; % AggValues is presently equal to Nbar. This line is imposing/satisfying the labour market clearance condition. 59 | StationaryDist.mass=StationaryDist.mass*(Params.Ne/InitialNe); % Take advantage of linearity of the stationary distribution in new entrants distribution. 60 | end 61 | 62 | Output.Params=Params; 63 | 64 | %% Calculate various Aggregates, mostly related to Table 3 65 | 66 | % 67 | % FnsToEvaluateFn_kbar=FnsToEvaluate{1}; 68 | % FnsToEvaluateFn_nbar=FnsToEvaluate{2}; 69 | % FnsToEvaluateFn_output=FnsToEvaluate{3}; 70 | % FnsToEvaluateFn_subsidy=FnsToEvaluate{4}; 71 | % FnsToEvaluateFn_outputofsubsidised=FnsToEvaluate{5}; 72 | 73 | Output.Y=AggVars.output.Aggregate; 74 | Output.N=AggVars.nbar.Aggregate; 75 | Output.K=AggVars.kbar.Aggregate; 76 | Output.KdivY=Output.K/Output.Y; 77 | Output.S=AggVars.subsidy.Aggregate; 78 | Output.Ys=AggVars.outputofsubsidised.Aggregate; 79 | % Params.w 80 | Output.mass=StationaryDist.mass; % E in notation of RR2008 81 | Output.TFP=(Output.Y/Output.N)./((Output.K/Output.N)^Params.alpha); % RR2008 call this 'A'. 82 | Output.Ys_divY=AggVars.outputofsubsidised.Aggregate/AggVars.output.Aggregate; % The variable Ys/Y represents the output share of establishments that are receiving a subsidy 83 | Output.SdivY=AggVars.subsidy.Aggregate/AggVars.output.Aggregate; % The variable S /Y is the total subsidies paid out to establishments receiving subsidies as a fraction of output 84 | Output.tau_s=Params.subsidyrate; % The variable tau_s is the size of the subsidy required to generate a steady-state capital stock equal to that in the distortion-free economy 85 | 86 | %% Calculate outputs related to Table 4 87 | % Is just the TFP number, but for various different cases. So nothing further to calculate. 88 | 89 | %% Tables 5 to 9 are all based on the outputs already generated. 90 | % They just report the same statistics for different economies/cases. 91 | 92 | end -------------------------------------------------------------------------------- /RestucciaRogerson2008/RestucciaRogerson2008_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaRogerson2008_ReturnFn(aprime_val, a_val, s_val, tau_val,w,r,alpha,gamma,taurate, subsidyrate,cf) 2 | % Note that neither aprime_val nor a_val is actually used for anything in 3 | % this model. But VFI toolkit is not set up to handle that they do not exist. 4 | 5 | F=-Inf; 6 | 7 | tau=taurate*(tau_val>=0)-subsidyrate*(tau_val<0); % convert rate into the actual tax/subsidy which depends on firm type (as captured by tau_val) 8 | 9 | % RR2008, pg 711 explains how to derive the optimal decisions in closed form (conditional on remaining operational) 10 | 11 | % Physical capital: 12 | kbar=(alpha/r)^((1-gamma)/(1-gamma-alpha)) *(gamma/w)^(gamma/(1-gamma-alpha)) *(s_val*(1-tau))^(1/(1-alpha-gamma)); 13 | 14 | % Labour 15 | nbar=(((1-tau)*s_val*gamma)/w)^(1/(1-gamma)) *kbar^(alpha/(1-gamma)); 16 | 17 | % Substitute kbar, nbar in pi and compute W(s,kbar(s,theta)) 18 | pibar=(1-tau)*s_val*(kbar^alpha)*(nbar^gamma)-w*nbar-r*kbar-cf; 19 | 20 | F=pibar; 21 | 22 | end -------------------------------------------------------------------------------- /RestucciaRogerson2008/RestucciaRogerson2008_ReturnFn_CapitalTax.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaRogerson2008_ReturnFn_CapitalTax(aprime_val, a_val, s_val, tau_val,w,r,alpha,gamma,taurate, subsidyrate,cf) 2 | % Note that neither aprime_val nor a_val is actually used for anything in 3 | % this model. But VFI toolkit is not set up to handle that they do not exist. 4 | 5 | F=-Inf; 6 | 7 | tau=taurate*(tau_val>=0)-subsidyrate*(tau_val<0); % convert rate into the actual tax/subsidy which depends on firm type (as captured by tau_val) 8 | 9 | % RR2008, pg 711 explains how to derive the optimal decisions in closed form (conditional on remaining operational) 10 | 11 | % Physical capital: 12 | kbar=(alpha/((1+tau)*r))^((1-gamma)/(1-gamma-alpha)) *(gamma/w)^(gamma/(1-gamma-alpha)) *(s_val)^(1/(1-alpha-gamma)); 13 | 14 | % Labour 15 | nbar=((s_val*gamma)/w)^(1/(1-gamma)) *kbar^(alpha/(1-gamma)); 16 | 17 | % Substitute kbar, nbar in pi and compute W(s,kbar(s,theta)) 18 | pibar=s_val*(kbar^alpha)*(nbar^gamma)-w*nbar-(1+tau)*r*kbar-cf; 19 | 20 | F=pibar; 21 | 22 | end -------------------------------------------------------------------------------- /RestucciaRogerson2008/RestucciaRogerson2008_ReturnFn_LabourTax.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaRogerson2008_ReturnFn_LabourTax(aprime_val, a_val, s_val, tau_val,w,r,alpha,gamma,taurate, subsidyrate,cf) 2 | % Note that neither aprime_val nor a_val is actually used for anything in 3 | % this model. But VFI toolkit is not set up to handle that they do not exist. 4 | 5 | F=-Inf; 6 | 7 | tau=taurate*(tau_val>=0)-subsidyrate*(tau_val<0); % convert rate into the actual tax/subsidy which depends on firm type (as captured by tau_val) 8 | 9 | % RR2008, pg 711 explains how to derive the optimal decisions in closed form (conditional on remaining operational) 10 | 11 | % Physical capital: 12 | kbar=(alpha/r)^((1-gamma)/(1-gamma-alpha)) *(gamma/((1+tau)*w))^(gamma/(1-gamma-alpha)) *s_val^(1/(1-alpha-gamma)); 13 | 14 | % Labour 15 | nbar=((s_val*gamma)/((1+tau)*w))^(1/(1-gamma)) *kbar^(alpha/(1-gamma)); 16 | 17 | % Substitute kbar, nbar in pi and compute W(s,kbar(s,theta)) 18 | pibar=s_val*(kbar^alpha)*(nbar^gamma)-(1+tau)*w*nbar-r*kbar-cf; 19 | 20 | F=pibar; 21 | 22 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfitoolkit/vfitoolkit-matlab-replication/d6251bb018019abf64f6271d0ccc914b37397c56/RestucciaUrrutia2004/RestucciaUrrutia2004.pdf -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_Consumption.m: -------------------------------------------------------------------------------- 1 | function c=RestucciaUrrutia2004_Consumption(bhatprime,sprime,h,bhat,s,b,thetahat,earningsshock,j,w,g,gamma,tau,kappa0,kappa1,plowerbar, pupperbar,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % j: age (takes values of 1,2) 12 | 13 | % Return function of young. 14 | c=0; % Just a placeholder 15 | if j==1 16 | % bhat=G(b,e,g) and G(b,e,g)=b*(e+g)^gamma 17 | % Rearrange these to get e, 18 | % (Done in this way since we want bhatprime to stay on the 19 | % bhat grid and this is the easiest way to ensure this) 20 | e=(bhatprime/b)^(1/gamma)-g; 21 | c=(1-tau)*w*h*earningsshock-e; 22 | elseif j==2 23 | q_bhat=min(psi0*(1+bhat)^psi1,1); 24 | if s==0 % No college 25 | c=(1-tau)*(w*h*earningsshock+w*bhat); % Note: h1'=bhat (in notation of Restuccia & Urrutia, 2005) 26 | elseif s==1 && thetahat>q_bhat % Partial college 27 | Kappa_wh2=max(kappa1-kappa0*w*h*earningsshock,0); 28 | c=(1-tau)*(w*h*earningsshock+w*(plowerbar*bhat)*(1-nlowerbar))-(1-Kappa_wh2)*f*nlowerbar; % Note: h1'=plowerbar*bhat (in notation of Restuccia & Urrutia, 2005) 29 | elseif s==1 && thetahat<=q_bhat % Completed college 30 | Kappa_wh2=max(kappa1-kappa0*w*h*earningsshock,0); 31 | c=(1-tau)*(w*h*earningsshock+w*(pupperbar*bhat)*(1-nupperbar))-(1-Kappa_wh2)*f*nupperbar; % Note: h1'=pupperbar*bhat (in notation of Restuccia & Urrutia, 2005) 32 | end 33 | end 34 | 35 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_F.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaUrrutia2004_F(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | F=0; 14 | if agej==2 15 | q_bhat=min(psi0*(1+bhat)^psi1,1); 16 | if s==1 && thetahat>q_bhat % Partial college 17 | F=f*nlowerbar; 18 | elseif s==1 && thetahat<=q_bhat % Completed college 19 | F=f*nupperbar; 20 | end 21 | end 22 | 23 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_FnF.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaUrrutia2004_FnF(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | F=0; 14 | if agej==2 15 | q_bhat=min(psi0*(1+bhat)^psi1,1); 16 | if s==1 && thetahat>q_bhat % Partial college 17 | F=f*nlowerbar; 18 | elseif s==1 && thetahat<=q_bhat % Completed college 19 | F=f*nupperbar; 20 | end 21 | end 22 | 23 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_FnkappaF.m: -------------------------------------------------------------------------------- 1 | function kappaF=RestucciaUrrutia2004_FnkappaF(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,w,kappa0,kappa1,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | kappaF=0; 14 | if agej==2 15 | q_bhat=min(psi0*(1+bhat)^psi1,1); 16 | if s==1 && thetahat>q_bhat % Partial college 17 | Kappa_wh2=max(kappa1-kappa0*w*h,0); 18 | kappaF=Kappa_wh2*f*nlowerbar; 19 | elseif s==1 && thetahat<=q_bhat % Completed college 20 | Kappa_wh2=max(kappa1-kappa0*w*h,0); 21 | kappaF=Kappa_wh2*f*nupperbar; 22 | end 23 | end 24 | 25 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_HFn.m: -------------------------------------------------------------------------------- 1 | function hout=RestucciaUrrutia2004_HFn(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,plowerbar, pupperbar,nlowerbar,nupperbar,phi0,phi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | % Return function of young. 14 | hout=h; % This covers case of agej==1 15 | if agej==2 16 | q_bhat=min(phi0*(1+bhat)^phi1,1); 17 | if s==0 % Does not attend college 18 | hout=h+bhat; 19 | elseif s==1 && thetahat>q_bhat % Partial college 20 | hout=h+(plowerbar*bhat)*(1-nlowerbar); % Note: h1'=plowerbar*bhat (in notation of Restuccia & Urrutia, 2005) 21 | elseif s==1 && thetahat<=q_bhat % Completed college 22 | hout=h+(pupperbar*bhat)*(1-nupperbar); % Note: h1'=pupperbar*bhat (in notation of Restuccia & Urrutia, 2005) 23 | end 24 | end 25 | 26 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_PhiaprimeFn.m: -------------------------------------------------------------------------------- 1 | function Phi=RestucciaUrrutia2004_PhiaprimeFn(bhatprime,sprime,h,bhat,s,b,thetahat,earningsshock,agej,plowerbar,pupperbar,zeta,psi0,psi1,log_lb_h,log_ub_h,loghgridspacing,n_h,log_lb_bhat,log_ub_bhat,logbhatgridspacing,n_bhat) 2 | % Case 2, Finite Horizon. (d,a,z) % Note that j=1 requires d, and j=2 3 | % requires (a,z). But just has to use (d,a,z) as allowing this aspect to 4 | % depend on age is to complex for the moment. (Conceptually easy, but would 5 | % require some thought on how to code.) 6 | % bhatprime: (decision variable), acquired ability of child (only j==1) 7 | % sprime: (decision variable), send child to university (only j==1) 8 | % h: (endogenous state), human capital (both j==1 & 2) 9 | % bhat: (endogenous state), acquired ability of child (only j==2) 10 | % s: (endogenous state), went to high school or university (only j==2) 11 | % b: (exogenous state) innate ability of child (both j==1 & 2) 12 | % thetahat: (exogenous state), (determines whether) completed or only partial college (only j==2) 13 | % earningsshock: (exogenous state), only used for Table 7 14 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 15 | 16 | % j: age (takes values of 1,2) 17 | 18 | % The 'gridspacing' variables (loghgridspacing and logbhatgridspacing) are both 19 | % already measured in terms of the log grid, hence they do not need log 20 | % here. 21 | 22 | Phivec1=0; Phivec2=0; Phivec3=0; %(hprime,bhatprime,sprime) 23 | hprime=0; 24 | if agej==1 25 | % Next period (j==2) value of h is given by 26 | loghprime=log(zeta*h); %(note that h_grid is equally spaced in logs) 27 | % Find index of nearest point to hprime on h_grid 28 | if loghprime<=log_lb_h % If goes off bottom of grid 29 | Phivec1=1; 30 | elseif loghprime>=log_ub_h % If goes off top of grid 31 | Phivec1=n_h; 32 | else 33 | Phivec1=1+round((loghprime-log_lb_h)/loghgridspacing); 34 | % htemp=(hprime-log_lb_h)/loghgridspacing; 35 | % h_rem=htemp-floor(htemp); 36 | % if h_rem<=loghgridspacing/2 % Note that this trick requires h_grid to be both uniformly spaced and strictly positive 37 | % Phivec1=1+floor(htemp); 38 | % else 39 | % Phivec1=1+ceil(htemp); 40 | % end 41 | end 42 | % Next period (j==2) value of bhat is given by 43 | % Find index of nearest point to bhatprime on bhat_grid 44 | % Since bhat_grid is equally spaced in logs this is done in terms of logs. 45 | logbhatprime=log(bhatprime); 46 | if logbhatprime<=log_lb_bhat % If goes off bottom of grid 47 | Phivec2=1; 48 | elseif logbhatprime>=log_ub_bhat % If goes off top of grid 49 | Phivec2=n_bhat; 50 | else 51 | % bhattemp=(logbhatprime-log_lb_bhat)/logbhatgridspacing; 52 | Phivec2=1+round((logbhatprime-log_lb_bhat)/logbhatgridspacing); 53 | % bhat_rem=bhattemp-floor(bhattemp); 54 | % if bhat_rem<=logbhatgridspacing/2 % Note that this trick requires h_grid to be both uniformly spaced and strictly positive 55 | % Phivec2=1+floor(bhattemp); 56 | % else 57 | % Phivec2=1+ceil(bhattemp); 58 | % end 59 | end 60 | % Next period (j==2) value of s is given by 61 | Phivec3=sprime+1; % This one is trivial (sprime takes values 0 and 1) 62 | else %if agej==2 63 | % Next period (j==1) value of h is given by 64 | q_bhat=min(psi0*(1+bhat)^psi1,1); 65 | if s==0 66 | hprime=bhat; 67 | elseif s==1 && thetahat>q_bhat 68 | hprime=plowerbar*bhat; 69 | elseif s==1 && thetahat<=q_bhat 70 | hprime=pupperbar*bhat; 71 | end 72 | loghprime=log(hprime); %(note that h_grid is equally spaced in logs) 73 | % Find index of nearest point to hprime on h_grid 74 | if loghprime<=log_lb_h % If goes off bottom of grid 75 | Phivec1=1; 76 | elseif loghprime>=log_ub_h % If goes off top of grid 77 | Phivec1=n_h; 78 | else 79 | Phivec1=1+round((loghprime-log_lb_h)/loghgridspacing); 80 | % htemp=abs((hprime-log_lb_h))/loghgridspacing; 81 | % h_rem=htemp-floor(htemp); 82 | % if h_rem<=loghgridspacing/2 % Note that this trick requires (log of) h_grid to be both uniformly spaced and strictly positive 83 | % Phivec1=1+floor(htemp); 84 | % else 85 | % Phivec1=1+ceil(htemp); 86 | % end 87 | end 88 | % Next period (j==1) value of bhat is given by 89 | Phivec2=1; % Variable is not relevant to age j==1, and so is 'made to disappear' by setting it to just a single point. 90 | % Next period (j==1) value of theta is given by 91 | Phivec3=1; % Variable is not relevant to age j==1, and so is 'made to disappear' by setting it to just a single point. 92 | end 93 | 94 | % jplusone_ind=rem(agej,2)+1; 95 | % Phi=Phivec1+(Phivec2-1)*n_h*jplusone_ind+(Phivec3-1)*n_h*jplusone_ind*n_bhat*jplusone_ind; 96 | % Is just implementing sub2ind_homemade([n_h,n_bhat,n_theta],Phivec) 97 | 98 | Phi=Phivec1+(Phivec2-1)*n_h+(Phivec3-1)*n_h*n_bhat; 99 | % Is just implementing sub2ind_homemade([n_h,n_bhat,n_theta],Phivec) 100 | 101 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_ReturnFn.m: -------------------------------------------------------------------------------- 1 | function F=RestucciaUrrutia2004_ReturnFn(bhatprime,sprime,h,bhat,s,b,thetahat,earningsshock,j,w,g,gamma,tau,sigma,kappa0,kappa1,plowerbar, pupperbar,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % j: age (takes values of 1,2) 12 | 13 | % Return function of young. 14 | c=0; % Just a placeholder 15 | e=0; % Just a placeholder 16 | if j==1 17 | % bhat=G(b,e,g) and G(b,e,g)=b*(e+g)^gamma 18 | % Rearrange these to get e, 19 | % (Done in this way since we want bhatprime to stay on the 20 | % bhat grid and this is the easiest way to ensure this) 21 | e=(bhatprime/b)^(1/gamma)-g; 22 | c=(1-tau)*w*h*earningsshock-e; 23 | elseif j==2 24 | q_bhat=min(psi0*(1+bhat)^psi1,1); 25 | if s==0 % No college 26 | c=(1-tau)*(w*h*earningsshock+w*bhat); % Note: h1'=bhat (in notation of Restuccia & Urrutia, 2005) 27 | elseif s==1 && thetahat>q_bhat % Partial college 28 | Kappa_wh2=max(kappa1-kappa0*w*h*earningsshock,0); 29 | c=(1-tau)*(w*h*earningsshock+w*(plowerbar*bhat)*(1-nlowerbar))-(1-Kappa_wh2)*f*nlowerbar; % Note: h1'=plowerbar*bhat (in notation of Restuccia & Urrutia, 2005) 30 | elseif s==1 && thetahat<=q_bhat % Completed college 31 | Kappa_wh2=max(kappa1-kappa0*w*h*earningsshock,0); 32 | c=(1-tau)*(w*h*earningsshock+w*(pupperbar*bhat)*(1-nupperbar))-(1-Kappa_wh2)*f*nupperbar; % Note: h1'=pupperbar*bhat (in notation of Restuccia & Urrutia, 2005) 33 | end 34 | end 35 | 36 | F=-Inf; 37 | if c>0 38 | F=(c.^(1-sigma)-1)/(1-sigma); 39 | end 40 | 41 | if j==1 && e<0 42 | F=-Inf; 43 | end 44 | 45 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_a_gridfn.m: -------------------------------------------------------------------------------- 1 | function a_grid=RestucciaUrrutia2004_a_gridfn(agej,g,gamma,pupperbar, sigma_b,rho_b, n_b,n_bhat,n_h, tauchenq, maxgridptparam) 2 | 3 | % n_a=[n_h, n_h; 1, n_bhat;1,n_s]; % h,bhat,s 4 | 5 | % I use 8g rather than 5g used by RU2004 to set top of bhat as I had people 6 | % running into the top of the grid on h (have called this maxgridptparam) 7 | 8 | if agej==1 9 | [b_grid, ~]=TauchenMethod(0,sigma_b, rho_b, n_b, tauchenq); 10 | b_grid=exp(b_grid); 11 | minh=b_grid(1)*g^gamma; 12 | maxh=pupperbar*b_grid(end)*(maxgridptparam*g)^gamma; 13 | h_grid=exp(linspace(log(minh),log(maxh),n_h)'); 14 | bhat_grid=1; 15 | s_grid=1; 16 | elseif agej==2 17 | [b_grid, ~]=TauchenMethod(0,sigma_b, rho_b, n_b, tauchenq); 18 | b_grid=exp(b_grid); 19 | minbhat=b_grid(1)*g^gamma; 20 | maxbhat=b_grid(end)*(maxgridptparam*g)^gamma; 21 | minh=b_grid(1)*g^gamma; % =minbhat 22 | maxh=pupperbar*b_grid(end)*(maxgridptparam*g)^gamma; % = pupperbar*maxbhat; 23 | h_grid=exp(linspace(log(minh),log(maxh),n_h)'); 24 | bhat_grid=exp(linspace(log(minbhat),log(maxbhat),n_bhat)'); 25 | s_grid=[0;1]; 26 | end 27 | 28 | a_grid=[h_grid; bhat_grid; s_grid]; 29 | 30 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_d_gridfn.m: -------------------------------------------------------------------------------- 1 | function d_grid=RestucciaUrrutia2004_d_gridfn(agej,g,gamma, sigma_b,rho_b, n_b,n_bhat, tauchenq,maxgridptparam) 2 | 3 | % n_d=[n_bhatprime,1; n_s; 1]; % bhatprime,s 4 | 5 | if agej==1 6 | [b_grid, ~]=TauchenMethod(0,sigma_b, rho_b, n_b, tauchenq); 7 | b_grid=exp(b_grid); 8 | minbhat=b_grid(1)*g^gamma; 9 | maxbhat=b_grid(end)*(maxgridptparam*g)^gamma; 10 | bhatprime_grid=exp(linspace(log(minbhat),log(maxbhat),n_bhat)'); 11 | s_grid=[0;1]; 12 | elseif agej==2 13 | bhatprime_grid=1; 14 | s_grid=1; 15 | end 16 | 17 | d_grid=[bhatprime_grid; s_grid]; 18 | 19 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_kappaF.m: -------------------------------------------------------------------------------- 1 | function kappaF=RestucciaUrrutia2004_kappaF(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,w,kappa0,kappa1,nlowerbar,nupperbar,f,psi0,psi1) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | kappaF=0; 14 | if agej==2 15 | q_bhat=min(psi0*(1+bhat)^psi1,1); 16 | if s==1 && thetahat>q_bhat % Partial college 17 | Kappa_wh2=max(kappa1-kappa0*w*h,0); 18 | kappaF=Kappa_wh2*f*nlowerbar; 19 | elseif s==1 && thetahat<=q_bhat % Completed college 20 | Kappa_wh2=max(kappa1-kappa0*w*h,0); 21 | kappaF=Kappa_wh2*f*nupperbar; 22 | end 23 | end 24 | 25 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_logEarnings.m: -------------------------------------------------------------------------------- 1 | function logwH=RestucciaUrrutia2004_logEarnings(bhatprime,sprime,h,bhat,s,b,thetahat,earningshock,agej,plowerbar, pupperbar,nlowerbar,nupperbar,phi0,phi1,w) 2 | % Case 2, Finite Horizon. 3 | % bhatprime: (decision variable), acquired ability of child (only j==1) 4 | % h: (endogenous state), human capital (both j==1 & 2) 5 | % bhat: (endogenous state), acquired ability of child (only j==2) 6 | % theta: (endogenous state), completed or only partial college (only j==2) 7 | % b: (exogenous state) innate ability of child (both j==1 & 2) 8 | % Note: I use theta to take different values to those used by Restuccia & Urrutia (2005) 9 | % Note: The VFI toolkit is used to shrink the 'grid' of these variables to just a single point for the ages in which they are irrelevant. 10 | 11 | % agej: age (takes values of 1,2) 12 | 13 | % Return function of young. 14 | H=h; 15 | if agej==2 16 | q_bhat=min(phi0*(1+bhat)^phi1,1); 17 | if s==1 && thetahat>q_bhat % Partial college 18 | H=H+(plowerbar*bhat)*(1-nlowerbar); % Note: h1'=plowerbar*bhat (in notation of Restuccia & Urrutia, 2005) 19 | elseif s==1 && thetahat<=q_bhat % Completed college 20 | H=H+(pupperbar*bhat)*(1-nupperbar); % Note: h1'=pupperbar*bhat (in notation of Restuccia & Urrutia, 2005) 21 | end 22 | end 23 | logwH=log(w*h*earningshock); 24 | 25 | end -------------------------------------------------------------------------------- /RestucciaUrrutia2004/RestucciaUrrutia2004_z_gridfn.m: -------------------------------------------------------------------------------- 1 | function [z_grid,pi_z]=RestucciaUrrutia2004_z_gridfn(agej, sigma_b,rho_b,earningsshocksize, n_b,n_thetahat,n_earnings, tauchenq) 2 | 3 | % The actual z_grid on 'innate ability' is same for all ages, but transitions are only possible between generations. 4 | if agej==1 5 | [b_grid, ~]=TauchenMethod(0,(1-rho_b^2)*sigma_b^2, rho_b, n_b, tauchenq); 6 | b_grid=exp(b_grid); 7 | pi_b=eye(n_b,n_b,'gpuArray'); 8 | thetahat_grid=1; 9 | pi_thetahat=ones(1,n_thetahat)/n_thetahat; % Uniform distribution 10 | if n_earnings==1 11 | earnings_grid=1; 12 | pi_earnings=1; 13 | elseif n_earnings==2 14 | earnings_grid=[1-earningsshocksize; 1+earningsshocksize]; 15 | pi_earnings=[1,0;0,1]; 16 | end 17 | elseif agej==2 18 | [b_grid, pi_b]=TauchenMethod(0,(1-rho_b^2)*sigma_b^2, rho_b, n_b, tauchenq); 19 | b_grid=exp(b_grid); 20 | thetahat_grid=linspace(0,1-1/n_thetahat,n_thetahat)'; % I deliberately make the top point less than one, so q(bhat) above this have 'probability one of college completion'. (round the 99%ers up rather than down) 21 | pi_thetahat=ones(n_thetahat,1); % Goes to the only next period value with certainty 22 | if n_earnings==1 23 | earnings_grid=1; 24 | pi_earnings=1; 25 | elseif n_earnings==2 26 | earnings_grid=[1-earningsshocksize; 1+earningsshocksize]; 27 | pi_earnings=[0.5,0.5;0.5,0.5]; 28 | end 29 | end 30 | % I have not enforced the mean(b)=1, so this might be slightly out. 31 | 32 | z_grid=[b_grid; thetahat_grid; earnings_grid]; 33 | pi_z=kron(pi_earnings, kron(pi_thetahat,pi_b)); % Note, this always is done in 'reverse order' 34 | 35 | end -------------------------------------------------------------------------------- /Tauchen1986/Tauchen1986.m: -------------------------------------------------------------------------------- 1 | % Replicate Tauchen (1986) - Finite State Markov-Chain Approximations to Univariate and Vector Auotregressions 2 | % REPLICATION IS INCOMPLETE. NEED TO GENERATE THE TABLES AND DO THE REGRESSIONS 3 | 4 | tauchenoptions.parallel=0; 5 | 6 | % Demonstrates how to use TauchenMethod and TauchenMethodVAR functions of VFI Toolkit 7 | 8 | 9 | %% The AR(1) approximation 10 | znum=9 % Tauchen uses 9 % Number of points must be odd (also tries out 5; see his Table 1) 11 | T=10^5 % Tauchen uses 50 12 | q=3 % Tauchen uses 3 13 | 14 | % Use command TauchenMethod(mew,sigmasq,rho,znum,q,tauchenoptions) 15 | mew=0; 16 | rho_vec=[0.1,0.8,0.9]; % See Tauchen Table 1 17 | sigmasq_vec=[0.101,0.167,0.229].^2; % See Tauchen Table 1 18 | 19 | Table1Case=1; % 1,2, or 3 20 | rho=rho_vec(Table1Case); 21 | sigmasq=sigmasq_vec(Table1Case); 22 | 23 | [z_grid, pi_z]=TauchenMethod(mew,sigmasq,rho,znum,q,tauchenoptions); 24 | 25 | 26 | % Simulate the resulting markov chain 27 | burnin=1000; 28 | cumsum_pi_z=cumsum(pi_z,2); 29 | z_simindexes=zeros(T,1); 30 | z_simindexes(1)=ceil(znum/2); 31 | for t=2:burnin 32 | temp_cumsum_pi_z=cumsum_pi_z(z_simindexes(1),:); 33 | temp_cumsum_pi_z(temp_cumsum_pi_z<=rand(1,1))=2; 34 | [~,z_simindexes(1)]=min(temp_cumsum_pi_z); 35 | end 36 | for t=2:T 37 | temp_cumsum_pi_z=cumsum_pi_z(z_simindexes(t-1),:); 38 | temp_cumsum_pi_z(temp_cumsum_pi_z<=rand(1,1))=2; 39 | [~,z_simindexes(t)]=min(temp_cumsum_pi_z); 40 | end 41 | z_simvals=nan(1,T); 42 | for t=1:T 43 | z_simvals(t)=z_grid(z_simindexes(t)); 44 | end 45 | 46 | % Check the mean values of the simulation 47 | mean(z_simvals) 48 | % They should be equal to the analytical 49 | ((1-rho)^(-1))*mew 50 | 51 | %% The VAR(1) approximation 52 | znum=[25;25] % Tauchen uses [9;9] % Number of points in each dimension must be odd. 53 | T=10^5 % Tauchen uses 50 54 | q=[3;3] % Tauchen uses [3;3] 55 | 56 | % Use command TauchenMethodVAR(mew,sigmasq,rho,znum,q,tauchenoptions) 57 | % Create states vector and transition matrix for the discrete markov process approximation of n-variable VAR(1) process z'=mew+rho*z+e, e~N(0,sigmasq), by Tauchens method 58 | % (Abuse of notation: sigmasq in codes is a column vector, in the VAR notation it is a matrix in which all of the non-diagonal elements are zeros) 59 | mew=[0;0]; 60 | rho=[0.7,0.3; 0.2,0.5]; 61 | sigmasq=[0.1;0.1]; 62 | 63 | [z_grid, pi_z]=TauchenMethodVAR(mew,sigmasq,rho,znum,q,tauchenoptions); 64 | 65 | % Simulate the resulting markov chain 66 | burnin=1000; 67 | cumsum_pi_z=cumsum(pi_z,2); 68 | z_simindexes=zeros(T,1); 69 | z_simindexes(1)=ceil(prod(znum)/2); 70 | for t=2:burnin 71 | temp_cumsum_pi_z=cumsum_pi_z(z_simindexes(1),:); 72 | temp_cumsum_pi_z(temp_cumsum_pi_z<=rand(1,1))=2; 73 | [~,z_simindexes(1)]=min(temp_cumsum_pi_z); 74 | end 75 | for t=2:T 76 | temp_cumsum_pi_z=cumsum_pi_z(z_simindexes(t-1),:); 77 | temp_cumsum_pi_z(temp_cumsum_pi_z<=rand(1,1))=2; 78 | [~,z_simindexes(t)]=min(temp_cumsum_pi_z); 79 | end 80 | z_simvals=nan(2,T); 81 | for t=1:T 82 | ind=z_simindexes(t); 83 | sub=ind2sub_homemade([znum(1),znum(2)],ind); 84 | z_simvals(1,t)=z_grid(sub(1)); 85 | z_simvals(2,t)=z_grid(sub(2)); 86 | end 87 | 88 | % Check the mean values of the simulation 89 | mean(z_simvals') 90 | % They should be equal to the analytical 91 | ((eye(2,2)-rho)^(-1))*mew 92 | 93 | --------------------------------------------------------------------------------