Closed $2\times2$ Economy with Intermediate Inputs and Nesting

This model is available in a notebook file here.

Consider the following social accounting matrix.

MarketsXYWCONS
PX120-20-100
PY-20120-100
PW200-200
PL-40-60100
PK-60-40100

We are going to use this matrix to construct a simple CES nesting structure that permits the modeler to specify different elasticities of substitution between different groups of inputs.

Model Initialization

First we import MPSGE and initialize the model.

using MPSGE

M = MPSGEModel()

Defining Variables

This model has:

  1. Three sectors X, Y, and W
  2. Five commodities PX, PY, PW, PL, and PK
  3. One consumer CONS

Let's add these to the model.

@sectors(M, begin
    X
    Y
    W
end)

@commodities(M, begin
    PX
    PY
    PW
    PL
    PK
end)

@consumer(M, CONS)

We use the plural version of both sector and commodity because we have multiple of each. Each of these variables has been added to the local namespace, so we can type X and it will display X. This is useful as we continue to build the model. These can also be accessed directly from the model, M[:X].

Parameters

In this model we will want a two parameters, tax and σ. This will allow us to apply various shocks without recompiling the model.

@parameters(M, begin
    tax, 0
    σ, .5
end)

The parameter block requires that you set initial values for each parameter.

Production

In this model we will have three production blocks, one for each sector.

We'll detail the X production block as it has the most interesting structure. Here is the full production block,

@production(M, X, [s = σ, t = 0, va => s = 1], begin
    @Output PX 120 t
    @Input  PY 20  s
    @Input  PL 40  va taxes = [Tax(CONS,tax)]
    @Input  PK 60  va taxes = [Tax(CONS,tax)]
end)

there is a lot going on in this, let's break it down piece by piece. The first few pieces, @production(M, X, are self-explanatory, model and sector.

This brings us to [s = σ, t = 0, va => s = 1] which defines the nesting structure. There are two top level nests s and t with respective elasticities of σ and 0. Compare this to the other nest, va, which sits under s, this is denoted with va => s and the = 1 sets the elasticity to 1. One thing to notice is that σ is a previously defined parameter. In general, any quantity can be either a number or parameter.

Finally, inputs and outputs. These must be wrapped in the begin .. end syntax. The syntax of building an output is the same as an input, so we'll describe an output. The required information is a commodity, quantity, and nest. We have used Julia macro syntax to suppress parentheses and commas, but you could equivalently defined these as

@Output(PX, 120, t)

Outputs have two possible keywords, reference_price and taxes. reference_price is a simple quantity whereas taxes is an array of Tax objects, as illustrated in the PK input.

Link to the I/O macro documentation. 

The remaining production blocks are similar,

@production(M, Y, [t = 0, s = .75, va => s = 1], begin 
    @Output PY 120 t
    @Input  PX 20 s
    @Input  PL 60 va
    @Input  PK 40 va
end)

@production(M, W, [t = 0, s = 1], begin
    @Output PW 200 t
    @Input  PX 100 s
    @Input  PY 100 s
end)

Demand

Each consumer will have a corresponding demand block. Here is the demand block for CONS

@demand(M, CONS, begin
    @final_demand(PW, 200)    
    @endowment(PL, 100)
    @endowment(PK,100)
end)

The first two inputs are the model and the consumer. Then there are two begin .. end blocks, the first is for final demand and the second is endowments. This may get improved in the future to be a single block.

Solving the Model

To solve the model, you call solve! on the model. You can also pass PATH options view keyword arguments. In this case we are testing the benchmark calibration so we set the cumulative iteration limit to 0.

solve!(M; cumulative_iteration_limit = 0)

While the solver output can be useful, it's more useful to see the values and the marginal values. Any non-zero marginal value should be investigated. LINK TO MODEL DEBUGGING INFORMATION HERE.

df_benchmark = generate_report(M)

This will return a Julia dataframe, which you can manipulate using any dataframe technique. If you plan to manipulate this dataframe, it will be useful to use the DataFrames package

using DataFrames.jl

You can also retrieve information using standard JuMP functions, for example

value(X)

will give you the value of X.

We can solve a counterfactual by changing the value of a parameter. In this case we'll also fix PW to 1 to pin a specific solution.

fix(PW,1)
set_value!(tax,.5)

solve!(M)
df = generate_report(M)