Dynare Reference Manual: Macro-processing language

Next: Verbatim inclusion, Previous: Displaying and saving results, Up: The Model file [Contents][Index]

### 4.23 Macro-processing language

It is possible to use “macro” commands in the `.mod` file for doing the following tasks: including modular source files, replicating blocks of equations through loops, conditionally executing some code, writing indexed sums or products inside equations…

The Dynare macro-language provides a new set of macro-commands which can be inserted inside `.mod` files. It features:

- file inclusion
- loops (`for` structure)
- conditional inclusion (`if/then/else` structures)
- expression substitution

Technically, this macro language is totally independent of the basic Dynare language, and is processed by a separate component of the Dynare pre-processor. The macro processor transforms a `.mod` file with macros into a `.mod` file without macros (doing expansions/inclusions), and then feeds it to the Dynare parser. The key point to understand is that the macro-processor only does text substitution (like the C preprocessor or the PHP language). Note that it is possible to see the output of the macro-processor by using the `savemacro` option of the `dynare` command (see Dynare invocation).

The macro-processor is invoked by placing macro directives in the `.mod` file. Directives begin with an at-sign followed by a pound sign (`@#`). They produce no output, but give instructions to the macro-processor. In most cases, directives occupy exactly one line of text. In case of need, two anti-slashes (`\\`) at the end of the line indicates that the directive is continued on the next line. The main directives are:

- `@#includepath`, paths to search for files that are to be included,
- `@#include`, for file inclusion,
- `@#define`, for defining a macro-processor variable,
- `@#if`, `@#ifdef`, `@#ifndef`, `@#else`, `@#endif` for conditional statements,
- `@#for`, `@#endfor` for constructing loops.

The macro-processor maintains its own list of variables (distinct of model variables and of MATLAB/Octave variables). These macro-variables are assigned using the `@#define` directive, and can be of four types: integer, character string, array of integers, array of strings.

Next: Macro directives, Up: Macro-processing language [Contents][Index]

#### 4.23.1 Macro expressions

It is possible to construct macro-expressions which can be assigned to macro-variables or used within a macro-directive. The expressions are constructed using literals of the four basic types (integers, strings, arrays of strings, arrays of integers), macro-variables names and standard operators.

String literals have to be enclosed between double quotes (like `"name"`). Arrays are enclosed within brackets, and their elements are separated by commas (like `[1,2,3]` or `["US", "EA"]`).

Note that there is no boolean type: false is represented by integer zero and true is any non-null integer. Further note that, as the macro-processor cannot handle non-integer real numbers, integer division results in the quotient with the fractional part truncated (hence, ).

The following operators can be used on integers:

- arithmetic operators: `+`, `-`, `*`, `/`
- comparison operators: `<`, `>`, `<=`, `>=`, `==`, `!=`
- logical operators: `&&`, `||`, `!`
- integer ranges, using the following syntax: `INTEGER1:INTEGER2` (for example, `1:4` is equivalent to integer array `[1,2,3,4]`)

The following operators can be used on strings:

- comparison operators: `==`, `!=`
- concatenation of two strings: `+`
- extraction of substrings: if `s` is a string, then `s[3]` is a string containing only the third character of `s`, and `s[4:6]` contains the characters from 4th to 6th

The following operators can be used on arrays:

- dereferencing: if `v` is an array, then `v[2]` is its 2nd element
- concatenation of two arrays: `+`
- difference `-`: returns the first operand from which the elements of the second operand have been removed
- extraction of sub-arrays: e.g. `v[4:6]`
- testing membership of an array: `in` operator (for example: `"b" in ["a", "b", "c"]` returns `1`)
- getting the length of an array: `length` operator (for example: `length(["a", "b", "c"])` returns `3` and, hence, `1:length(["a", "b", "c"])` is equivalent to integer array `[1,2,3]`)

Macro-expressions can be used at two places:

- inside macro directives, directly;
- in the body of the `.mod` file, between an at-sign and curly braces (like `@{expr}`): the macro processor will substitute the expression with its value.

In the following, MACRO_EXPRESSION designates an expression constructed as explained above.

Next: Typical usages, Previous: Macro expressions, Up: Macro-processing language [Contents][Index]

#### 4.23.2 Macro directives

Macro directive: @ #includepath "PATH"
Macro directive: @ #includepath MACRO_VARIABLE

  This directive adds the colon-separated paths contained in PATH to the list of those to search when looking for a `.mod` file specified by @#include. Note that these paths are added after any paths passed using -I.

  Example

      @#include "/path/to/folder/containing/modfiles:/path/to/another/folder"
      @#include folders_containing_mod_files

Macro directive: @ #include "FILENAME"
Macro directive: @ #include MACRO_VARIABLE

  This directive simply includes the content of another file at the place where it is inserted. It is exactly equivalent to a copy/paste of the content of the included file. Note that it is possible to nest includes (i.e. to include a file from an included file). The file will be searched for in the current directory. If it is not found, the file will be searched for in the folders provided by -I and @#includepath.

  Example

      @#include "modelcomponent.mod"
      @#include location_of_modfile

Macro directive: @ #define MACRO_VARIABLE = MACRO_EXPRESSION

  Defines a macro-variable.

  Example 1

      @#define x = 5              // Integer
      @#define y = "US"           // String
      @#define v = [ 1, 2, 4 ]    // Integer array
      @#define w = [ "US", "EA" ] // String array
      @#define z = 3 + v[2]       // Equals 5
      @#define t = ("US" in w)    // Equals 1 (true)

  Example 2

      @#define x = [ "B", "C" ]
      @#define i = 2

      model;
        A = @{x[i]};
      end;

  is strictly equivalent to:

      model;
        A = C;
      end;

Macro directive: @ #if MACRO_EXPRESSION
Macro directive: @ #ifdef MACRO_VARIABLE
Macro directive: @ #ifndef MACRO_VARIABLE
Macro directive: @ #else
Macro directive: @ #endif

  Conditional inclusion of some part of the `.mod` file. The lines between `@#if`, `@#ifdef` or `@#ifndef` and the next `@#else` or `@#endif` is executed only if the condition evaluates to a non-null integer. The `@#else` branch is optional and, if present, is only evaluated if the condition evaluates to `0`.

  Example

  Choose between two alternative monetary policy rules using a macro-variable:

      @#define linear_mon_pol = 0 // or 1
      ...
      model;
      @#if linear_mon_pol
        i = w*i(-1) + (1-w)*i_ss + w2*(pie-piestar);
      @#else
        i = i(-1)^w * i_ss^(1-w) * (pie/piestar)^w2;
      @#endif
      ...
      end;

  Example

  Choose between two alternative monetary policy rules using a macro-variable. As `linear_mon_pol` was not previously defined in this example, the second equation will be chosen:

      model;
      @#ifdef linear_mon_pol
        i = w*i(-1) + (1-w)*i_ss + w2*(pie-piestar);
      @#else
        i = i(-1)^w * i_ss^(1-w) * (pie/piestar)^w2;
      @#endif
      ...
      end;

  Choose between two alternative monetary policy rules using a macro-variable. As `linear_mon_pol` was not previously defined in this example, the first equation will be chosen:

      model;
      @#ifndef linear_mon_pol
        i = w*i(-1) + (1-w)*i_ss + w2*(pie-piestar);
      @#else
        i = i(-1)^w * i_ss^(1-w) * (pie/piestar)^w2;
      @#endif
      ...
      end;

Macro directive: @ #for MACRO_VARIABLE in MACRO_EXPRESSION
Macro directive: @ #endfor

  Loop construction for replicating portions of the `.mod` file. Note that this construct can enclose variable/parameters declaration, computational tasks, but not a model declaration.

  Example

      model;
      @#for country in [ "home", "foreign" ]
        GDP_@{country} = A * K_@{country}^a * L_@{country}^(1-a);
      @#endfor
      end;

  is equivalent to:

      model;
        GDP_home = A * K_home^a * L_home^(1-a);
        GDP_foreign = A * K_foreign^a * L_foreign^(1-a);
      end;

Macro directive: @ #echo MACRO_EXPRESSION

  Asks the preprocessor to display some message on standard output. The argument must evaluate to a string.

Macro directive: @ #error MACRO_EXPRESSION

  Asks the preprocessor to display some error message on standard output and to abort. The argument must evaluate to a string.

Next: MATLAB/Octave loops versus macro-processor loops, Previous: Macro directives, Up: Macro-processing language [Contents][Index]

#### 4.23.3 Typical usages

Next: Indexed sums or products, Up: Typical usages [Contents][Index]

#### 4.23.3.1 Modularization

The `@#include` directive can be used to split `.mod` files into several modular components.

Example setup:

`modeldesc.mod`

  Contains variable declarations, model equations and shocks declarations

`simul.mod`

  Includes `modeldesc.mod`, calibrates parameters and runs stochastic simulations

`estim.mod`

  Includes `modeldesc.mod`, declares priors on parameters and runs Bayesian estimation

Dynare can be called on `simul.mod` and `estim.mod`, but it makes no sense to run it on `modeldesc.mod`.

The main advantage is that it is no longer needed to manually copy/paste the whole model (at the beginning) or changes to the model (during development).

Next: Multi-country models, Previous: Modularization, Up: Typical usages [Contents][Index]

#### 4.23.3.2 Indexed sums or products

The following example shows how to construct a moving average:

    @#define window = 2

    var x MA_x;
    ...
    model;
    ...
    MA_x = 1/@{2*window+1}*(
    @#for i in -window:window
            +x(@{i})
    @#endfor
           );
    ...
    end;

After macro-processing, this is equivalent to:

    var x MA_x;
    ...
    model;
    ...
    MA_x = 1/5*(
            +x(-2)
            +x(-1)
            +x(0)
            +x(1)
            +x(2)
           );
    ...
    end;

Next: Endogeneizing parameters, Previous: Indexed sums or products, Up: Typical usages [Contents][Index]

#### 4.23.3.3 Multi-country models

Here is a skeleton example for a multi-country model:

    @#define countries = [ "US", "EA", "AS", "JP", "RC" ]
    @#define nth_co = "US"

    @#for co in countries
    var Y_@{co} K_@{co} L_@{co} i_@{co} E_@{co} ...;
    parameters a_@{co} ...;
    varexo ...;
    @#endfor

    model;
    @#for co in countries
     Y_@{co} = K_@{co}^a_@{co} * L_@{co}^(1-a_@{co});
    ...
    @# if co != nth_co
     (1+i_@{co}) = (1+i_@{nth_co}) * E_@{co}(+1) / E_@{co}; // UIP relation
    @# else
     E_@{co} = 1;
    @# endif
    @#endfor
    end;

Previous: Multi-country models, Up: Typical usages [Contents][Index]

#### 4.23.3.4 Endogeneizing parameters

When doing the steady state calibration of the model, it may be useful to consider a parameter as an endogenous (and vice-versa).

For example, suppose production is defined by a CES function:

The labor share in GDP is defined as:

`lab_rat`

In the model, is a (share) parameter, and `lab_rat` is an endogenous variable.

It is clear that calibrating is not straightforward; but on the contrary, we have real world data for `lab_rat`, and it is clear that these two variables are economically linked.

The solution is to use a method called variable flipping, which consist in changing the way of computing the steady state. During this computation, will be made an endogenous variable and `lab_rat` will be made a parameter. An economically relevant value will be calibrated for `lab_rat`, and the solution algorithm will deduce the implied value for .

An implementation could consist of the following files:

`modeqs.mod`

  This file contains variable declarations and model equations. The code for the declaration of and `lab_rat` would look like:

      @#if steady
       var alpha;
       parameter lab_rat;
      @#else
       parameter alpha;
       var lab_rat;
      @#endif

`steady.mod`

  This file computes the steady state. It begins with:

      @#define steady = 1
      @#include "modeqs.mod"

  Then it initializes parameters (including `lab_rat`, excluding ), computes the steady state (using guess values for endogenous, including ), then saves values of parameters and endogenous at steady state in a file, using the `save_params_and_steady_state` command.

`simul.mod`

  This file computes the simulation. It begins with:

      @#define steady = 0
      @#include "modeqs.mod"

  Then it loads values of parameters and endogenous at steady state from file, using the `load_params_and_steady_state` command, and computes the simulations.

Previous: Typical usages, Up: Macro-processing language [Contents][Index]

#### 4.23.4 MATLAB/Octave loops versus macro-processor loops

Suppose you have a model with a parameter , and you want to make simulations for three values: . There are several ways of doing this:

With a MATLAB/Octave loop

      rhos = [ 0.8, 0.9, 1];
      for i = 1:length(rhos)
        rho = rhos(i);
        stoch_simul(order=1);
      end

  Here the loop is not unrolled, MATLAB/Octave manages the iterations. This is interesting when there are a lot of iterations.

With a macro-processor loop (case 1)

      rhos = [ 0.8, 0.9, 1];
      @#for i in 1:3
        rho = rhos(@{i});
        stoch_simul(order=1);
      @#endfor

  This is very similar to previous example, except that the loop is unrolled. The macro-processor manages the loop index but not the data array (`rhos`).

With a macro-processor loop (case 2)

      @#for rho_val in [ "0.8", "0.9", "1"]
        rho = @{rho_val};
        stoch_simul(order=1);
      @#endfor

  The advantage of this method is that it uses a shorter syntax, since list of values directly given in the loop construct. Note that values are given as character strings (the macro-processor does not know floating point values). The inconvenience is that you can not reuse an array stored in a MATLAB/Octave variable.

Previous: Typical usages, Up: Macro-processing language [Contents][Index]