Add shocks(surprise) block (for occbin)

Ref. #68
var-models
Sébastien Villemot 2021-07-13 17:07:53 +02:00
parent f0002c5ac6
commit 2e696a2e0d
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
8 changed files with 115 additions and 3 deletions

View File

@ -172,6 +172,7 @@ class ParsingDriver;
%token NUMBER_OF_POSTERIOR_DRAWS_AFTER_PERTURBATION MAX_NUMBER_OF_STAGES
%token RANDOM_FUNCTION_CONVERGENCE_CRITERION RANDOM_PARAMETER_CONVERGENCE_CRITERION NO_INIT_ESTIMATION_CHECK_FIRST_OBS
%token HETEROSKEDASTIC_FILTER TIME_SHIFT STRUCTURAL TERMINAL_STEADY_STATE_AS_GUESS_VALUE
%token SURPRISE
/* Method of Moments */
%token METHOD_OF_MOMENTS MOM_METHOD
%token BARTLETT_KERNEL_LAG WEIGHTING_MATRIX WEIGHTING_MATRIX_SCALING_FACTOR ANALYTIC_STANDARD_ERRORS ANALYTIC_JACOBIAN PENALIZED_ESTIMATOR VERBOSE
@ -1028,6 +1029,9 @@ pound_expression: '#' symbol EQUAL hand_side ';'
shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); }
| SHOCKS '(' OVERWRITE ')' ';' shock_list END ';' { driver.end_shocks(true); }
| SHOCKS '(' OVERWRITE ')' ';' END ';' { driver.end_shocks(true); }
| SHOCKS '(' SURPRISE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(false); }
| SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(true); }
;
shock_list : shock_list shock_elem
@ -1049,6 +1053,10 @@ det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
{ driver.add_det_shock($2, $5, $8, false); }
;
surprise_shock_list : surprise_shock_list det_shock_elem
| det_shock_elem
;
heteroskedastic_shocks : HETEROSKEDASTIC_SHOCKS ';' heteroskedastic_shock_list END ';'
{ driver.end_heteroskedastic_shocks(false); }
| HETEROSKEDASTIC_SHOCKS '(' OVERWRITE ')' ';' heteroskedastic_shock_list END ';'

View File

@ -761,6 +761,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>uniform_pdf {return token::UNIFORM_PDF;}
<DYNARE_BLOCK>weibull_pdf {return token::WEIBULL_PDF;}
<DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;}
<DYNARE_BLOCK>surprise {return token::SURPRISE;}
<DYNARE_BLOCK>; {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK># {return Dynare::parser::token_type (yytext[0]);}

View File

@ -700,6 +700,12 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_surprise_present && !occbin)
{
cerr << "ERROR: the 'shocks(surprise)' block can only be used in conjunction with occbin commands." << endl;
exit(EXIT_FAILURE);
}
if (!mod_file_struct.ramsey_model_present)
cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl;
else
@ -985,8 +991,9 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
// May be later modified by a shocks block
mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl;
// Initialize M_.det_shocks and M_.heteroskedastic_shocks
// Initialize M_.det_shocks, M_.surprise_shocks and M_.heteroskedastic_shocks
mOutputFile << "M_.det_shocks = [];" << endl
<< "M_.surprise_shocks = [];" << endl
<< "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl;

View File

@ -798,6 +798,13 @@ ParsingDriver::end_mshocks(bool overwrite)
det_shocks.clear();
}
void
ParsingDriver::end_shocks_surprise(bool overwrite)
{
mod_file->addStatement(make_unique<ShocksSurpriseStatement>(overwrite, det_shocks, mod_file->symbol_table));
det_shocks.clear();
}
void
ParsingDriver::end_heteroskedastic_shocks(bool overwrite)
{

View File

@ -149,7 +149,8 @@ private:
OptimWeightsStatement::var_weights_t var_weights;
//! Temporary storage of covariances from optim_weights
OptimWeightsStatement::covar_weights_t covar_weights;
//! Temporary storage for deterministic shocks
/* Temporary storage for deterministic shocks. Also used for
conditional_forecast paths and for surprise shocks. */
ShocksStatement::det_shocks_t det_shocks;
//! Temporary storage for variances of shocks
ShocksStatement::var_and_std_shocks_t var_shocks;
@ -436,9 +437,12 @@ public:
void end_shocks(bool overwrite);
//! Writes a mshocks statement
void end_mshocks(bool overwrite);
//! Writes a shocks(surprise) statement
void end_shocks_surprise(bool overwrite);
//! Writes a heteroskedastic_shocks statement
void end_heteroskedastic_shocks(bool overwrite);
//! Adds a deterministic shock or a path element inside a conditional_forecast_paths block
/* Adds a deterministic shock, a path element inside a
conditional_forecast_paths block, or a surprise shock */
void add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool conditional_forecast);
//! Adds a heteroskedastic shock (either values or scales)
void add_heteroskedastic_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool scales);

View File

@ -428,6 +428,69 @@ MShocksStatement::writeJsonOutput(ostream &output) const
output << "}";
}
ShocksSurpriseStatement::ShocksSurpriseStatement(bool overwrite_arg,
AbstractShocksStatement::det_shocks_t surprise_shocks_arg,
const SymbolTable &symbol_table_arg) :
overwrite{overwrite_arg}, surprise_shocks{move(surprise_shocks_arg)},
symbol_table{symbol_table_arg}
{
}
void
ShocksSurpriseStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
mod_file_struct.shocks_surprise_present = true;
}
void
ShocksSurpriseStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
if (overwrite)
output << "M_.surprise_shocks = [" << endl;
else
output << "M_.surprise_shocks = [ M_.surprise_shocks;" << endl;
for (const auto &[id, shock_vec] : surprise_shocks)
{
for (const auto &[period1, period2, value] : shock_vec)
{
output << "struct('exo_id'," << symbol_table.getTypeSpecificID(id)+1
<< ",'periods'," << period1 << ":" << period2
<< ",'value',";
value->writeOutput(output);
output << ");" << endl;
}
}
output << "];" << endl;
}
void
ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "shocks")"
<< R"(, "surprise": true)"
<< R"(, "surprise_shocks": [)";
for (auto it = surprise_shocks.begin(); it != surprise_shocks.end(); ++it)
{
if (it != surprise_shocks.begin())
output << ", ";
output << R"({"var": ")" << symbol_table.getName(it->first) << R"(", )"
<< R"("values": [)";
for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1)
{
auto [period1, period2, value] = *it1;
if (it1 != it->second.begin())
output << ", ";
output << R"({"period1": )" << period1 << ", "
<< R"("period2": )" << period2 << ", "
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
output << "]}";
}
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(AbstractShocksStatement::det_shocks_t paths_arg,
const SymbolTable &symbol_table_arg) :
paths{move(paths_arg)},

View File

@ -86,6 +86,26 @@ public:
void writeJsonOutput(ostream &output) const override;
};
/* Represents a shocks(surprise) block.
Given the differences with the plain shocks block, it was easier to make
it a separate class. */
class ShocksSurpriseStatement : public Statement
{
public:
//! Does this "shocks(surprise)" statement replace the previous ones?
const bool overwrite;
const AbstractShocksStatement::det_shocks_t surprise_shocks;
private:
const SymbolTable &symbol_table;
public:
ShocksSurpriseStatement(bool overwrite_arg,
AbstractShocksStatement::det_shocks_t surprise_shocks_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class ConditionalForecastPathsStatement : public Statement
{
private:

View File

@ -145,6 +145,8 @@ public:
/* Lists symbol IDs of parameters that appear in a “planner_discount” option.
See dynare#1173 for more details. */
set<int> parameters_in_planner_discount;
// Whether a shocks(surprise) block appears
bool shocks_surprise_present{false};
};
class Statement