$Title A Standard CGE Model in Calibrated Share Format
$ontext
Thomas F. Rutherford
Center for Energy Policy and Economics
Department of Management, Technology and Economics
ETH Zurich
It seems that students are nearly always looking for a "cook book" on
how to implement and analyze equilibrium models. I have posted lots
of models on the internet over the years, figuring that this should
provide enough clues for the interested student. (For a recent post,
see http://www.mpsge.org/oecdio.zip.)
Students seem so convinced that the process of numerical modeling is
something mysterious and requires special incantations rather than
just logic and attention to detail. Well, let them eat cake.
So here is yet another attempt at codifying the steps involved in
implementing a GAMS/MGE equilibrium model. The same steps are
involved whether working with a small or large scale dataset. My
notes from 2003 on a larger scale example are here:
http://www.mpsge.org/tza/index.html
STEPS
1. Read the source benchmark data (The oecdio model illustrates
yet another method for extracting data from Excel workbooks.)
2. Verify consistency of the benchmark dataset in original format
and balance as necessary. (See the TZA example for an example of the
balancing procedure.)
3. Partition the source data into model-relevant parameters. This
typically involves use of GAMS tuples which link the address space of
the source data to the labels used in the model.
4. Verify consistency of the benchmark dataset in model-consistent
format.
5. Read "free parameters" (i.e. elasticties).
6. Define the GAMS/MPSGE model.
7. Write out the corresponding algebraic model in GAMS/MCP. This is
really just a mechanical process, relying on the calibrated share
format. (Google for "calibrated share for nested CES" and you find
some lecture notes from 1995).
8. Replicate the benchmark equilibrium in both the MGE and MCP
formats, using .iterlim=0 approach.
9. Compute a counterfactual simulation with either the MGE or MCP model and
then verify (using .iterlim=0) that the equilibrum conditions are
satisfied in the other format.
For a worked example on how to debug MPSGE and MCP models in parallel,
see http://www.mpsge.org/mcpdebug.html
I've included a homework assignment below. This was a question on the
University of Colorado computational economics PhD field exam in 1996.
$offtext
* -----------------------------------------------------------------
* 1. Read the source data. In this case, we have a balanced social
* accounting matrix.
set u SAM accounts / BRD, MLK, CAP, LAB, IDT, TRF, HOH, GOV, INV, EXT/
alias (u,v);
table sam(u,v) social accounting matrix
BRD MLK CAP LAB IDT
BRD 21 8
MLK 17 9
CAP 20 30
LAB 15 25
IDT 5 4
TRF 1 2
HOH 50 40
GOV 9
INV
EXT 13 11
+ TRF HOH GOV INV EXT
BRD 20 19 16 8
MLK 30 14 15 4
CAP
LAB
IDT
TRF
HOH
GOV 3 23
INV 17 2 12
EXT;
* -----------------------------------------------------------------
* 2. Verify consistency of the social accounting matrix.
parameter samchk Consistency check on the SAM;
samchk(u,"rowsum") = sum(v, sam(u,v));
samchk(u,"colsum") = sum(v, sam(v,u));
samchk(u,"diff") = samchk(u,"rowsum") - samchk(u,"colsum") + eps;
display samchk;
* -----------------------------------------------------------------
* 3. Partition the source data into matrices defined over
* sets employed in the model.
set i(u) Goods /BRD, MLK/
h(u) Factors /CAP, LAB/;
alias (i,j), (h,k);
parameter y0(j) composite factor
f0(h,j) the h-th factor input by the j-th firm
x0(i,j) intermediate input
z0(j) output of the j-th good
xp0(i) household consumption of the i-th good
xg0(i) government consumption
xv0(i) investment demand
e0(i) exports
m0(i) imports
q0(i) Armington's composite good
d0(i) domestic good
sp0 private saving
sg0 government saving
td0 direct tax
tz0(j) production tax
tm0(j) import tariff
ff(h) factor endowment of the h-th factor
Sf foreign saving in US dollars
pWe(i) export price in US dollars
pWm(i) import price in US dollars
tauz(i) production tax rate
taum(i) import tariff rate,
taud Direct tax rate,
pm0(i) Reference price of imports;
td0 =sam("gov","hoh");
tz0(j) =sam("idt",j);
tm0(j) =sam("trf",j);
f0(h,j) =sam(h,j);
y0(j) =sum(h, f0(h,j));
x0(i,j) =sam(i,j);
z0(j) =y0(j) +sum(i, x0(i,j));
m0(i) =sam("ext",i);
tauz(j) =tz0(j)/z0(j);
taum(j) =tm0(j)/m0(j);
xp0(i) =sam(i,"hoh");
ff(h) =sam("hoh",h);
xg0(i) =sam(i,"gov");
xv0(i) =sam(i,"inv");
e0(i) =sam(i,"ext");
q0(i) =xp0(i)+xg0(i)+xv0(i)+sum(j, x0(i,j));
d0(i) =(1+tauz(i))*z0(i)-e0(i);
sp0 =sam("inv","hoh");
sg0 =sam("inv","gov");
sf =sam("inv","ext");
pwe(i) =1;
pwm(i) =1;
taud =td0/sum(h, ff(h));
pm0(i) = 1 + taum(i);
* -----------------------------------------------------------------
* 4. Verify benchmark consistency of the partitioned data.
* The accounting identities employed here are the same which
* enter into the modl.
parameter profit(i,*) Zero profit for domestic production
market(i,*) Goods market clearance,
income Income balance;
profit(i,"d0") = d0(i);
profit(i,"e0") = e0(i);
profit(i,"tauz") = -tauz(i)*z0(i);
profit(i,"x0") = -sum(j,x0(j,i));
profit(i,"f0") = -sum(h, f0(h,i));
alias (uni,*);
profit(i,"chk") = sum(uni, profit(i,uni)) + eps;
display profit;
* Convert the production tax from a net to a gross basis:
tauz(i) = tauz(i)*z0(i)/(e0(i)+d0(i));
market(i,"d0") = d0(i);
market(i,"m0") = m0(i);
market(i,"taum") = taum(i)*m0(i);
market(i,"x0") = -sum(j,x0(i,j));
market(i,"xp0") = -xp0(i);
market(i,"xg0") = -xg0(i);
market(i,"xv0") = -xv0(i);
market(i,"chk") = sum(uni, market(i,uni)) + eps;
display market;
income("ra","ff") = sum(h, ff(h));
income("ra","taud") = -sum(h,taud*ff(h));
income("ra","sp0") = -sp0;
income("ra","xp0") = -sum(i,xp0(i));
income("govt","tauz") = sum(i,tauz(i)*z0(i));
income("govt","taum") = sum(i,taum(i)*m0(i));
income("govt","xg0") = -sum(i,xg0(i));
income("govt","taud") = taud*sum(h,ff(h));
income("govt","sg0") = -sg0;
income("investor","sg0") = sg0;
income("investor","sp0") = sp0;
income("investor","sf") = sf;
income("investor","xv0") = -sum(i,xv0(i));
set agent /ra, govt, investor/;
income(agent,"chk") = sum(uni, income(agent,uni)) + eps;
display income;
* -----------------------------------------------------------------
* 5. Read in the "free parameters" -- elasticities of substitution
* and trnasformation:
parameter sigma(i) Elasticity of substitution
psi(i) Elasticity of transformation
eta(i) Substitution elasticity parameter
phi(i) Transformation elasticity parameter;
sigma(i)=2;
psi(i) =2;
eta(i)=(sigma(i)-1)/sigma(i);
phi(i)=(psi(i)+1)/psi(i);
* -----------------------------------------------------------------
* 6. Define the model using MPSGE.
$ONTEXT
$MODEL: stdmge
$SECTORS:
Z(j) ! Output of the j-th good
Q(i) ! Armington's composite good
$COMMODITIES:
PD(i) ! Domestic good price
PQ(i) ! Armington's composite good price
PF(h) ! Factor price
ER ! Exchange rate
$CONSUMERS:
RA
GOVT
Investor
* Production:
$prod:Z(i) t:psi(i) s:0 a(s):1
o:PD(i) q:d0(i) a:govt t:tauz(i)
o:ER q:(pwe(i)*e0(i)) p:(1/pwe(i)) a:govt t:tauz(i)
i:PQ(j) q:x0(j,i)
i:PF(h) q:f0(h,i) a:
* Armington composite:
$prod:Q(i) s:sigma(i)
o:PQ(i) q:q0(i)
i:PD(i) q:d0(i)
i:ER q:(pwm(i)*m0(i)) a:govt p:(pm0(i)/pwm(i)) t:taum(i)
$report:
v:E(i) o:ER PROD:Z(i)
v:M(i) I:ER PROD:Q(i)
* Private households:
$demand:RA s:1
d:PQ(i) q:xp0(i)
e:PF(h) q:((1-taud)*ff(h))
e:ER q:(-sp0)
* government - public goods demands are fixed. any
* excess of tax
$demand:GOVT s:0
d:PQ(i) q:xg0(i)
e:PF(h) q:(taud*ff(h))
e:ER q:(-sg0)
* investor allocates savings among new capital goods
* with fixed budget shares:
$demand:INVESTOR s:0
e:ER q:(sg0+sp0+sf)
d:PQ(i) q:xv0(i)
$offtext
$sysinclude mpsgeset stdmge
* -----------------------------------------------------------------
* 7. Write out the corresponding algebraic model so that
* we are sure that we know hat we are doing.
* There is one equation for each variable in the model --
* zero profit for each $sector, market clearance for each
* $commodity and and income balance for each $consumer:
equations
prf_Z(j) Output of the j-th good
prf_Q(i) Armington's composite good
mkt_PD(i) Domestic good price
mkt_PQ(i) Armington's composite good price
mkt_PF(h) Factor price
mkt_ER Exchange rate
bal_RA Income balance for the representative agent,
bal_GOVT Income balance for the government
bal_Investor Income balance for the investor;
* At this point we need to calculate benchmark value shares:
parameter thetad(i) Domestic output value share,
thetaf(h,i) Primary factor value share;
thetad(i) = d0(i)/(d0(i)+e0(i));
thetaf(h,i) = f0(h,i)/sum(k,f0(k,i));
* Unit revenue revenue function (calibrated CET format):
$macro R(i) ((thetad(i)*PD(i)**(1+psi(i)) + \
(1-thetad(i))*(ER*pwe(i))**(1+psi(i)))**(1/(1+psi(i))))
* Unit cost function for facgtors (Cobb Douglas):
alias (h,h_);
$macro C(i) (prod(h_, PF(h_)**thetaf(h_,i)))
prf_Z(i).. C(i)*sum(h,f0(h,i)) + sum(j, PQ(j)*x0(j,i)) =e=
(d0(i)+e0(i)) * R(i) * (1-tauz(i));
* Compensated supply functions (CET):
$macro ZD(i) (d0(i)*(PD(i)/R(i))**psi(i))
$macro ZE(i) (pwe(i)*e0(i)*(ER*pwe(i)/R(i))**psi(i))
* Compensated factor demand function (Cobb Douglas):
$macro FD(h,i) (f0(h,i)*C(i)/PF(h))
parameter thetam(i) Import value share;
thetam(i) = m0(i)*pm0(i)/(m0(i)*pm0(i)+d0(i));
* Armington unit cost function (calibrated share CES format):
$MACRO CDM(i) (((1-thetam(i))*PD(i)**(1-sigma(i)) + \
thetam(i)*(ER*(1+taum(i))*pwm(i)/pm0(i))**(1-sigma(i)))**(1/(1-sigma(i))))
* Zero profit condition for Armington supply:
prf_Q(i).. CDM(i)*(d0(i)+m0(i)*pm0(i)) =e= PQ(i)*q0(i);
* Compensated demand functions for domestic and imported
* goods (CES):
$macro QD(i) (d0(i)*(CDM(i)/PD(i))**sigma(i))
$macro QM(i) (pwm(i)*m0(i)*(CDM(i)*pm0(i)/(ER*(1+taum(i))*pwm(i)))**sigma(i))
* Market clearance condition for domestic goods:
mkt_PD(i).. Z(i)*ZD(i) =e= QD(i)*Q(i);
* Cobb-Douglas final demand -- we need value shares to
* write down the demand function:
parameter alphac(i) Consumption budget shares;
alphac(i) = xp0(i)/sum(j,xp0(j));
* Market clearance for goods:
mkt_PQ(i).. q0(i)*Q(i) =e= sum(j, x0(i,j)*Z(j)) + alphac(i)*RA/PQ(i)
+ xg0(i)*GOVT/sum(j,PQ(j)*xg0(j))
+ xv0(i)*INVESTOR/sum(j,PQ(j)*xv0(j));
* Market clearance for primary factors:
mkt_PF(h).. ff(h) =e= sum(i, FD(h,i)*Z(i));
* Current account balance:
mkt_ER.. sf + sum(i, ZE(i)*Z(i)) =e= sum(i, QM(i)*Q(i));
* Private income:
bal_RA.. RA =e= (1-taud)*sum(h,PF(h)*ff(h)) - ER*sp0;
* Government income (including tax flows):
bal_GOVT.. GOVT =e= taud*sum(h,PF(h)*ff(h)) - ER*sg0
+ ER*sum(i,taum(i)*QM(i)*Q(i))
+ sum(i, R(i)*Z(i)*tauz(i)*(d0(i)+e0(i)));
* Investor income:
bal_Investor.. INVESTOR =e= ER*(sg0+sp0+sf);
model stdmcp /
prf_Z.Z, prf_Q.Q,
mkt_PD.PD, mkt_PQ.PQ,
mkt_PF.PF, mkt_ER.ER,
bal_RA.RA, bal_GOVT.GOVT, bal_Investor.Investor /;
* -----------------------------------------------------------------
* 8. Replicate the benchmark equilibrium with both the
* MGE and MCP models.
stdmge.iterlim = 0;
$include stdmge.gen
solve stdmge using MCP;
abort$(stdmge.objval > 1e-4) "MGE model does not calibrate.";
stdmcp.iterlim = 0;
SOLVE stdmcp USING MCP;
abort$(stdmcp.objval > 1e-4) "MCP model does not calibrate.";
* Note: if you want to evaluate macros which depend on
* variables, you can do so with the $ondotl macro:
$ondotl
parameter calibchk Cross check on algebraic calibration;
calibchk("R",i) = R(i);
calibchk("C",i) = C(i);
calibchk("ZE",i) = ZE(i)/e0(i);
calibchk("ZD",i) = ZD(i)/d0(i);
calibchk("QD",i) = QD(i)/d0(i);
calibchk("QM",i) = QM(i)/m0(i);
calibchk("cdm",i) = CDM(i);
display calibchk;
* -----------------------------------------------------------------
* 9. Compute a counterfactual with the MGE model and then
* verify that the MCP model is consistent.
taum(i) = 0;
stdmge.iterlim = 10000;
$include stdmge.gen
solve stdmge using MCP;
stdmcp.iterlim = 0;
SOLVE stdmcp USING MCP;
abort$(stdmcp.objval > 1e-4) "MCP model inconsistent with the MGE model.";
$ontext
Homework exercise:
Show that the model as specified is equivalent toon in which the
import and export activities are explicitly represented:
$prod:Z(i) t:psi(i) s:0 a(s):1
o:PD(i) q:d0(i) a:govt t:tauz(i)
o:PE(i) q:e0(i) a:govt t:tauz(i)
i:PQ(j) q:x0(j,i)
i:PF(h) q:f0(h,i) a:
$prod:Q(i) s:sigma(i)
o:PQ(i) q:q0(i)
i:PD(i) q:d0(i)
i:PM(i) q:(pm0(i)*m0(i))
$prod:E(i)
o:ER q:(pwe(i)*e0(i))
i:PE(i) q:e0(i)
$prod:M(i)
o:PM(i) q:(m0(i)*pm0(i))
i:ER q:(pwm(i)*m0(i)) a:govt t:taum(i)
Proof by testimonial (implement and verify consistency) is a good
starting point, but to answer the homework assignment you need to
explain why the world market price levels, pwe(i) and pwm(i), enter
the MPSGE model above in both the Q: and P: fields of the associated
foreign exchange coefficient, but in this alternative formulation, the
world market prices only enter the Q: field.
$offtext