[{"url":".","title":"Behavioural Macro and Finance","tags":["homepage"],"text":""},{"url":"installation/","title":"Running the notebooks","tags":["start"],"text":"Running the notebooksNotebooks 00–04 and the cheatsheet have their output already computed, so you can\nread them without installing anything. These are saved examples: online controls do not\nrerun the model. To change inputs and run exercises, open the notebooks locally in Pluto.\nNotebook 05 is also available online in reading mode, with explanations, code and\nexercises. To generate observations and fit the neural estimators, run it locally\nwith Julia and Python; follow the inference setup guide.RequirementsJulia 1.12 or later — install it with juliaup.\nThe committed Manifest.toml was resolved on 1.12.1; on an older Julia, delete it and\nlet Pkg.instantiate() re-resolve, which loses exact version pinning.Notebook 05 additionally pulls a Python environment (sbi) through PythonCall/CondaPkg\non first run — a few hundred megabytes. Notebooks 00–04 are pure Julia.SetupClone the repository, then run this once:git clone https://github.com/SGHoekstra/Behavioural_Macro_and_Finance.git\ncd Behavioural_Macro_and_Finance/pluto_tutorial\njulia setup.jl\nThat installs Pluto into your global Julia environment and every tutorial package into\nthe shared pluto_tutorial environment. Then launch Pluto:julia -t auto -e 'using Pluto; Pluto.run()'\nOpen any notebook from the Pluto file browser. Each notebook activates the shared\nenvironment itself, so the same package versions are used throughout. The first\nopening can still compile packages and functions; allow it to finish before changing\ncontrols. Keep the terminal running while you use Pluto.OrderWork through 01 to 05 in sequence — each assumes the previous ones. 00 is an optional Julia\nand Pluto primer, and cheatsheet.jl is a standalone reference to keep open in a second\ntab. Exercises and interpretation checks are at the bottom of each notebook. Use fresh\nvariable names in your exercise cells; Pluto allows one defining cell per global\nvariable. Prefer Apply settings controls for expensive examples so changing several\ninputs launches one new calculation rather than a sequence of reruns.Notebook 05 uses staged run controls and small demonstration budgets. Installing\nits Python environment and increasing simulation or training budgets can take\nconsiderably longer. Follow its guide before launching a full inference exercise.A useful workflowRead the question and predict a result before running the example.Record the calibration, seed, horizon and measurement units.Change one setting or mechanism at a time and compare like with like.Explain the result economically, including one assumption that limits the conclusion.Complete a core exercise before moving to the advanced extension.If a run appears slow, check Pluto’s running-cell indicator and the terminal before\nlaunching another simulation. Start with the supplied defaults. Restarting Pluto is\nuseful after changing a model type or its methods, because those definitions can\npersist within the Julia process."},{"url":"lectures/","title":"Lecture slides","tags":["lectures"],"text":"Lecture slidesBoth decks are below, one page per slide. Scroll inside a deck to move through\nit, or open it full screen to read it properly. LaTeX sources live alongside\nthe PDFs in the repository.Lecture 1 — Introduction to agent-based modelsWhat an ABM is, why macroeconomics reaches for one, and the Assenza et al. (2015)\nmodel where fluctuations are entirely endogenous.Open Lecture 1 full screen · 28 slides · PDFLecture 2 — Stock-flow consistent ABMsThe Poledna et al. macro ABM: agents and the input–output network, the sequence of\nevents in a quarter, stock-flow consistent accounting, the five exogenous AR(1)\nprocesses, expectations and the Taylor rule, and forecast validation.Open Lecture 2 full screen · 61 slides · PDFThe tutorial notebooks follow Lecture 2 closely — each one names the slides it covers."},{"url":"notebook05/","title":"Running inference exercises","tags":["start"],"text":"Running Notebook 05 inference exercisesRead the full notebook online.\nIt displays its explanations, code, exercises and saved figures from an actual\ndefault run: the synthetic observation and the ABC, NPE and NRE-B results. The online\ncontrols do not rerun the experiment. This guide explains\nhow to run its simulations and neural training in a local Julia/Python environment,\ngenerate posterior draws and inspect how well the coefficients are recovered.Open the notebook sourceThe questionIn Notebook 04, you chose how strongly CANVAS firms pass demand, costs and expected\ninflation into their prices. Can inflation and GDP growth reveal those three\ncoefficients instead?Notebook 05 uses a known-truth recovery experiment. It generates a synthetic\nobservation at chosen coefficients, then gives the estimator only the observation.\nThe true coefficients provide a reference for interpreting the inferred distribution.\nAll other model parameters and the pricing mechanism remain fixed.Before running, predict which pricing channel could be hardest to distinguish from\nthe others using just two aggregate series.Three ways to infer the coefficientsMethodWhat it doesWhat to inspectABCDraw coefficients from the prior, simulate data, retain draws close to the observationDistance definition, tolerance and accepted countNPETrain a conditional density of coefficients given simulated outputsNetwork fit, posterior shape and parameter correlationsNRE-BTrain a contrastive classifier to estimate a likelihood-to-evidence ratio, combine it with the prior and sample with MCMCNetwork fit, chain mixing and effective sample sizeThe executable example runs one prior-sampled round of each neural method. It uses\nengines that can also run sequentially; calling an engine “SNPE” or “SNRE” does not\nby itself add a second simulation round. The optional sequential exercise focuses\nnew simulations on the current posterior and explains why NPE needs a proposal\ncorrection.A sharper histogram is not automatically a better posterior. Weak identification,\nnetwork error and a misspecified simulator can all affect the result.Run in stagesAfter cloning the course repository, follow the installation page and run:cd Behavioural_Macro_and_Finance/pluto_tutorial\njulia setup.jl\njulia -t auto -e 'using Pluto; Pluto.run()'\nOpen 05_likelihood_free_calibration.jl in Pluto. Opening the notebook starts in\nreading mode: saved results and their plots are available, while new simulation\nand training stages are disabled. Enabling the local\nenvironment may install Python, PyTorch and sbi on first use.Enable the local environment. Read the observation protocol and small-budget settings.Generate the synthetic observation. Twelve quarterly inflation rates and twelve growth rates form a 24-value vector.Generate the ABC bank, optionally. Move its tolerance slider to reuse the stored distances without new ABM runs.Generate the neural training bank. Inspect the coefficient/output matrix dimensions and any failed simulations.Train NPE. Interpret all three marginals and inspect their joint relationships.Train NRE-B, optionally. It reuses the neural bank and samples using MCMC.The default experiment uses four simulated paths per output, 100 ABC parameter\ndraws and 200 neural training draws. NPE draws 1,000 approximate posterior\nsamples; the optional NRE run draws 200 MCMC samples. These are teaching budgets,\nnot an accuracy guarantee. Runtime varies by computer; start with the defaults\nbefore increasing the cost.Match the observation to the simulatorThe synthetic observation and every training output use the same horizon, units,\nfour-path averaging and data transformations, with distinct seeds. Coefficient draws\nuse a separate random-number generator from the economy simulations.This averaged observation is an idealised experiment. An empirical application must\nspecify how data from one economy, measurement errors and transformations enter the\nobservation model. Changing the observation protocol requires changing training too.\nFailed or non-finite simulations block neural fitting rather than being silently\nremoved from the estimation sample.Recovery, diagnostics and validationRecovery asks whether inference locates chosen coefficients in data from the same simulator.Inference calibration checks posterior probabilities across repeated held-out synthetic experiments.Posterior prediction asks whether posterior draws reproduce observed or additional features.Model and policy validation require independent data, alternative mechanisms or intervention responses.A same-model recovery exercise cannot establish that the model represents the real\neconomy or predicts a policy intervention reliably. Even good prediction of the two\nfitted series can leave different pricing mechanisms observationally similar.Exercises to start withThe full notebook gives six exercises with hints. Begin with the two that need no\nnew economy simulations: vary the ABC tolerance and plot cost-push versus expectation\ncoefficients from the NPE draws. Then compare a coarser data representation, generate\na small posterior-predictive sample, discuss a misspecification test, or attempt a\nsecond sequential round.For background, see Dyer et al. (2024),\nBlack-Box Bayesian Inference for Agent-Based Models,\nand the official sbi Bayesian workflow\nand sequential-inference guide."},{"url":"search/","title":"Search results","tags":[],"text":"window.init_search();SearchResults\nLoading..."},{"url":"sidebar data/","title":"sidebar data","tags":[],"text":"Dict main \"Getting started\" collections \"start\" .pages, \"Lectures\" collections \"lectures\" .pages, \"Tutorial\" collections \"tutorial\" .pages, , about Dict TODO replace these with real staff pages before the course goes live. authors name \"Steven Hoekstra\", url \"https github.com SGHoekstra\" , name \"Cars Hommes\", url \"https www.uva.nl\" , , title \"Behavioural Macro and Finance\", subtitle \"Agent based models of the macroeconomy\", term \"Amsterdam School of Economics\", institution \"University of Amsterdam\", institution url \"https www.uva.nl\", institution logo \"uva logo.svg\", institution logo darkmode \"uva logo.svg\", "},{"url":"notebooks/00_julia_pluto_primer/","title":"Julia + Pluto primer","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.4 frontmatter title \"Julia Pluto primer\" order 1 layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end "},{"url":"notebooks/01_meet_the_model/","title":"Meet the model","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.24 frontmatter order 2 title \"Meet the model\" layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off return quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end begin import Pkg Pkg.activate joinpath DIR , \"..\", \"..\", \"pluto tutorial\" io devnull import BeforeIT as Bit import Random using Plots, StatsPlots, PlutoUI, HypertextLiteral, DataFrames, Statistics, LinearAlgebra end md\"\"\" Notebook 01 — Meet the model Question this notebook answers what does the Austrian macro economy do over the next five years according to the Poledna et al. 2023 agent based model — and what is actually inside the box? We run the model first and look at its output, then open it up who the agents are, how they trade through the input–output network, what happens in a quarter, and whether the accounting closes. Lecture 2 slides covered Model overview slide \"What are agent based model typical elements again?\" Sequence of events in each quarter slide \" i Expectations → … → v Accounting\" How big is the model? agent count table Household behaviour and heterogeneity four types Firms Leontief production function , labour market search and matching Input output network , and the remaining sectors government, bank, central bank, rest of world Learning goals After this notebook you will be able to 1. Initialise, step and run the BeforeIT model, and plot any tracked series. 2. Name the agent types and read their counts off `model.prop`. 3. Visualise the production network and compare sector intensities. 4. Trace the per quarter event sequence by stepping manually. 5. Verify the GDP accounting identity — the stock flow consistency check. How to work through it first predict a direction of change, then run a short simulation, inspect the relevant quantities, and explain the mechanism. The online version has saved outputs use local Pluto to change inputs. Start with the default 20 quarter run and leave longer simulations until the end. A simulated path conditional on a 2010 calibration is not an assessment of forecasting accuracy. Forecast comparisons and Monte Carlo ensembles come in Notebook 02. \"\"\" md\"\"\" 1 — Load the Austria 2010 Q1 calibration The model ships with a fully pre calibrated parametrisation of the Austrian economy at the start of Q1 2010. The bundled parameters and initial conditions are calibrated using national accounts and additional statistical inputs. The calibration also involves behavioural specifications and estimated relationships loading the bundle does not remove modelling assumptions or establish its predictive accuracy. A few headline values from `Bit.AUSTRIA2010Q1` VAT \\tau^ VAT 15.29%, MPC \\psi 90.97%, corporate tax \\tau^ FIRM 7.70%. Read any of them off `model.prop` directly. \"\"\" begin nb1 p Bit.AUSTRIA2010Q1.parameters nb1 ic Bit.AUSTRIA2010Q1.initial conditions \"Parameters and initial conditions loaded ✓\" end md\"\"\" 2 — Initialise the model `Bit.Model` builds every agent and wires up the full stock flow consistent balance sheet structure. Note the scale. Lecture 2 quotes ~9.9 million agents for the actual Austrian economy, but `Bit.AUSTRIA2010Q1` ships a 1 1000 scaled version — about 10,000 agents — so a run takes seconds rather than hours. Simulated agents represent larger populations. Aggregates and shares target the calibration, but integer rounding and a smaller economy can change finite population variation and network outcomes. These are synthetic agents, not individual administrative records. Part 2 below reports the simulated counts. \"\"\" nb1 model Bit.Model nb1 p, nb1 ic md\"\"\" Inspect what's inside the model. Each field is a container of agents or an aggregate tracker \"\"\" fieldnames typeof nb1 model md\"\"\" For example, the `bank` agent holds \"\"\" fieldnames typeof nb1 model.bank md\"\"\" 3 — Run the model Each call to `Bit.step ` advances the model by one quarter , running the full sequence from Lecture 2 | Step | What happens | | | | | i | Growth and inflation expectations are updated using fitted time series rules | | ii | Exogenous shocks drawn from 5 AR 1 processes | | iii | Credit and labour markets solved search and matching | | iv | Goods markets solved search and matching | | v | Accounting update balance sheets, check insolvencies, compute profits, taxes, transfers | We can step manually to see this \"\"\" begin model demo Bit.Model nb1 p, nb1 ic Bit.step model demo parallel true one quarter Bit.collect data model demo save the time series \"Stepped one quarter. GDP round model demo.data.real gdp end , digits 2 \" end md\"\"\" 4 — Simulate for T quarters `Bit.run ` is the convenient wrapper that calls `step ` `collect data ` in a loop. The default path runs when this notebook opens. Change the horizon and seed together, then press Apply simulation settings . Unconfirmed slider changes do not launch another simulation. Repeat simulation reruns the confirmed configuration a fixed seed should reproduce the same path in the same environment. Runtime depends on your machine and horizon. \"\"\" bind nb1 controls PlutoUI.confirm PlutoUI.combine do Child htl \"\"\" div p Horizon quarters Child \"horizon\", PlutoUI.Slider 4 4 40, default 20, show value true p p Random seed Child \"seed\", PlutoUI.Slider 1 100, default 42, show value true p div \"\"\" end label \"Apply simulation settings\", begin T horizon nb1 controls.horizon rng seed nb1 controls.seed nothing end bind run single PlutoUI.Button \"▶ Repeat simulation\" Markdown.parse \"Confirmed horizon T horizon quarters T horizon ÷ 4 years . Random seed rng seed . The time series includes the initial observation at quarter 0.\" begin run single Random.seed rng seed m Bit.Model nb1 p, nb1 ic nb1 initial model deepcopy m preserve the same population before mutation Bit.run m, T horizon parallel false quarters T horizon, seed rng seed, initial gdp m.data.real gdp 1 , final gdp m.data.real gdp end end md\"\"\" 5 — Plot the results `Bit.plot data` knows how to plot any of the tracked time series. The 9 panel dashboard below shows the same quantities reported in Poledna et al. 2023 Table 4. \"\"\" begin ps Bit.plot data begin run single m end, quantities real gdp, real household consumption, real government consumption, real capitalformation, real exports, real imports, wages, euribor, gdp deflator, , plot ps..., layout 3, 3 , size 900, 700 end md\"\"\" Before changing the seed which quantities do you expect to be most variable? Then apply a second seed and compare. Both aggregate innovations and agent level random draws can change across seeds, and endogenous feedback can alter the path. A single seed cannot separate those sources of variation or identify an economic effect. Monte Carlo simulation quantifies variation under the specified model it does not capture every source of model uncertainty. \"\"\" md\"\"\" Part 2 — Anatomy of the model You have run it and seen the output. Now open the box who the agents are, how they are wired together, what happens inside a quarter, and whether the books balance. \"\"\" md\"\"\" 6 — Who are the agents? The Lecture 2 table \"How big is the model?\" reports ~9.9 million agents for Austria 2010 Q4 — the real economy. `Bit.AUSTRIA2010Q1` is scaled 1 1000 so that a run finishes in seconds, so expect counts around a thousandth of the lecture's. Counts describe the scaled calibration small rounding differences are possible. \"\"\" begin p nb1 model.prop agent table DataFrame \"Agent type\" \"Active persons including investor households \", \"Inactive persons\", \"Domestic firms\", \"Government entities\", \"Foreign consumers\", \"Foreign firms imports sectors\" , \"Count\" p.H act, p.H inact, p.I, p.J, p.L, p.G , agent table end md\"\"\" Total nb1 model.prop.H act nb1 model.prop.H inact nb1 model.prop.I nb1 model.prop.J nb1 model.prop.L nb1 model.prop.G agents — about 1 1000 of the lecture's 9.9 million, as expected from the scaling. One label needs care `prop.G` is the number of production sectors 62, the NACE breakdown , which doubles as the count of foreign supplier firms because imports arrive one representative firm per sector. It is the same `g` index used in `P bar g` and `firms.G i`. The four household types from Lecture 2 Employed `nb1 model.w act` — labour supplied to a specific sector. Unemployed — subset of `nb1 model.w act` with no current job. Investors — firm owners and the bank owner, receive dividends. Inactive `nb1 model.w inact` — outside the labour force, receive social transfers. \"\"\" md\"\"\" Let's inspect a single active worker \"\"\" fieldnames typeof nb1 model.w act md\"\"\" And a single firm \"\"\" fieldnames typeof nb1 model.firms md\"\"\" 7 — Household heterogeneity Lecture 2 identifies four household types . Regular workers are stored in worker arrays investor households are attached to firms and the bank | Type | Struct | Description | | | | | | Employed workers | `nb1 model.w act` `O h 0` | Earn wages, pay income tax, buy consumption goods | | Unemployed workers | `nb1 model.w act` `O h 0` | Receive unemployment benefits \\theta^ UB w , job search | | Inactive persons | `nb1 model.w inact` | Out of labour force, receive social transfers | | Investor households | `nb1 model.firms` and `nb1 model.bank` | Own a firm or the bank, receive dividends \\theta^ DIV 1 \\tau^ FIRM \\Pi i | Employed unemployed live in `w act` the `O h` field records which firm employs each worker 0 unemployed . There are `prop.I` firm owner households and one bank owner household. Their incomes and deposits are attached to the firm and bank objects. Therefore `length w act.O h prop.I 1 prop.H act` do not count firm owners twice or omit the bank owner when computing household shares. \"\"\" begin w act holds all regular workers employed unemployed O h 0 means unemployed O h regular nb1 model.w act.O h n employed reg sum O h regular . 0 n unemployed sum O h regular . 0 n investors nb1 model.prop.I 1 n inactive nb1 model.prop.H inact n total nb1 model.prop.H act n inactive het table DataFrame \"Household type\" \"Employed workers\", \"Unemployed workers\", \"Investor households firms bank \", \"Inactive persons\" , \"Count\" n employed reg, n unemployed, n investors, n inactive , \"Share of adults % \" round. n employed reg, n unemployed, n investors, n inactive . n total . 100, digits 1 , het table end begin p wealth plot layout 2,3 , size 900,550 , left margin 4Plots.mm, bottom margin 4Plots.mm for row, snapshot, stage in enumerate nb1 initial model, \"Initial population\" , m, \"After simulation\" occupied snapshot.w act.O h . 0 groups snapshot.w act.D h occupied , \"Employed\", steelblue , snapshot.w act.D h . occupied , \"Unemployed\", crimson , snapshot.w inact.D h, \"Inactive\", mediumseagreen for column, deposits, group, colour in enumerate groups subplot id row 1 3 column if isempty deposits histogram p wealth, deposits subplot subplot id, bins 30, color colour, alpha 0.7, label \"\", title \" stage group n length deposits \", xlabel \"Deposits per simulated agent model units \", ylabel \"Count\", titlefontsize 8 else plot p wealth subplot subplot id, title \" stage group empty \" end end end p wealth end md\"\"\" Read the two rows as a comparison of the same simulated population. The top row is copied before the run the bottom row shows the population after the confirmed horizon. Membership can change through employment transitions, so these are group distributions rather than a panel comparison of fixed individuals. Initial deposits are assigned using the aggregate balance sheet calibration and model incomes. Equal assigned incomes can create narrow distributions within a group. Such distributions reflect initialisation assumptions, not observed microdata on household wealth. Simulation then changes deposits and employment status. Investor households are excluded from these three panels their deposits are attached to firms and the bank. Do not draw conclusions about their relative wealth from this figure. Income and wealth affect consumption budgets, but a heterogeneous deposit distribution does not itself imply heterogeneous marginal propensities to consume. Check your interpretation what would you need to compare these distributions with household survey or register data? Consider population weights, units, household definitions and the reference date. \"\"\" md\"\"\" 8 — The input–output production network Firms buy intermediate inputs from other sectors. The entry a sg describes input purchases from supplier sector s within buyer sector g 's intermediate input bundle. Columns are normalised over suppliers it is not the fraction of supplier s 's output sold to buyer g . This is the heatmap shown in Lecture 2 Figure \"Intermediate consumption between 19 industries\" . We plot the full matrix available in this calibration 62 sectors . \"\"\" begin nb1 a sg nb1 model.prop.a sg I O matrix rows supplier sector, cols buyer product heatmap nb1 a sg, color viridis, title \"Input Output technology matrix a sg\\n 62 NACE sectors × product types \", xlabel \"Buyer product g\", ylabel \"Supplier sector s\", aspect ratio equal, size 600, 550 , clims 0, quantile vec nb1 a sg nb1 a sg . 0 , 0.99 , cap colorscale at 99th pct end md\"\"\" Reading the heatmap a bright cell at row s , column g means supplier s has a large weight in buyer g 's input bundle. The diagonal entries represent within sector intermediate use e.g., agriculture buying agricultural products . Off diagonal bright cells reveal key supply chain dependencies — an upstream disruption can affect its customers. The size and persistence of that effect also depend on quantities, substitution restrictions, inventories, financing and market matching a bright cell alone does not establish a bankruptcy cascade. \"\"\" md\"\"\" 9 — Leontief coefficients by sector Recall the production function from Lecture 2 Y i,t \\min\\ \\left Q^S i,t ,\\ \\beta i M i,t ,\\ \\bar\\alpha i,t N i,t ,\\ \\kappa i K i,t 1 \\right The three coefficients \\bar\\alpha i labour productivity , \\beta i material efficiency , \\kappa i capital productivity determine which input is the binding constraint in each sector. \"\"\" begin Each coefficient is a vector over firms take the mean per sector G sectors nb1 model.prop.G number of product sector types I s nb1 model.prop.I s vector of firm counts per sector Build sector indices sector id vcat fill s, I s s for s in 1 length I s ... leontief DataFrame \"Sector\" 1 length I s , \"Firms\" I s, \"ᾱ labour prod. \" mean nb1 model.firms.alpha bar i sector id . s for s in 1 length I s , \"β material eff. \" mean nb1 model.firms.beta i sector id . s for s in 1 length I s , \"κ capital prod. \" mean nb1 model.firms.kappa i sector id . s for s in 1 length I s , leontief end md\"\"\" 10 — Stepping through the quarter sequence Instead of running all T quarters at once with `Bit.run `, let's step manually and observe what changes. Each call to `Bit.step ` runs the full five stage sequence from Lecture 2 expectations → shocks → credit labour → goods → accounting . \"\"\" begin nb1 model step Bit.Model nb1 p, nb1 ic Snapshot before step gdp before nb1 model step.agg.Y e expected aggregate output emp before sum nb1 model step.firms.N i total employed workers rate before nb1 model step.cb.r bar policy rate Take one step Bit.step nb1 model step parallel true Bit.collect data nb1 model step gdp after nb1 model step.agg.Y e emp after sum nb1 model step.firms.N i rate after nb1 model step.cb.r bar DataFrame \"Variable\" \"Expected output Y e\", \"Total employment ΣN i\", \"Policy rate r bar\" , \"Before\" round gdp before, sigdigits 6 , round emp before, sigdigits 6 , round rate before, sigdigits 6 , \"After Q1\" round gdp after, sigdigits 6 , round emp after, sigdigits 6 , round rate after, sigdigits 6 , end md\"\"\" The small changes after one step reflect the exogenous AR 1 shock draw and the OLS expectation update. Multiple steps accumulate into the time series we plotted in Notebook 01. \"\"\" md\"\"\" 11 — SFC accounting check ✓ Stock flow consistency the central feature of the Lecture 2 model implies that the GDP expenditure identity must hold at every time step Y t C t I t G t X t M t BeforeIT computes GDP via the production approach internally, but also tracks each expenditure component. Let's verify they match. \"\"\" bind T sfc PlutoUI.confirm PlutoUI.Slider 4 4 40, default 20, show value true label \"Apply accounting check horizon\" bind run sfc PlutoUI.Button \"▶ Run SFC check\" begin run sfc Random.seed 1 m sfc Bit.Model nb1 p, nb1 ic Bit.run m sfc, T sfc C m sfc.data.real household consumption I inv m sfc.data.real capitalformation G m sfc.data.real government consumption X m sfc.data.real exports M m sfc.data.real imports Y prod m sfc.data.real gdp production side GDP Y exp C . I inv . G . X . M expenditure side GDP residual Y exp . Y prod max err maximum abs. residual rel err max err mean Y prod 100 DataFrame \"Stat\" \"Max |residual| model units \", \"Max relative error % \" , \"Value\" round max err, sigdigits 4 , round rel err, sigdigits 4 , end begin run sfc plot 1 T sfc 1, Y prod, label \"GDP production \", lw 2, color steelblue, xlabel \"Quarter\", ylabel \"Real GDP model units \", title \"Expenditure vs production GDP T sfc quarters \", plot 1 T sfc 1, Y exp, label \"C I G X − M\", lw 2, ls dash, color crimson plot 1 T sfc 1, residual . mean Y prod , label \"Residual shifted to mean \", lw 1, color grey, alpha 0.6 end md\"\"\" The two GDP measures should overlay almost exactly residual near zero , confirming stock flow consistency in the simulated data. Note small floating point deviations 0.01\\% are expected from rounding in search and matching they are not macroeconomically meaningful. \"\"\" md\"\"\" 11b — Check identities without cancelling errors BeforeIT exposes a `get accounting identities` utility that checks three simultaneous accounting identities. Let's run it and verify all pass. \"\"\" begin run sfc data sfc m sfc.data income residual data sfc.nominal gva . data sfc.compensation employees . data sfc.operating surplus . data sfc.taxes production nominal residual data sfc.nominal gdp . data sfc.nominal household consumption . data sfc.nominal government consumption . data sfc.nominal capitalformation . data sfc.nominal exports . data sfc.nominal imports real residual data sfc.real gdp . data sfc.real household consumption . data sfc.real government consumption . data sfc.real capitalformation . data sfc.real exports . data sfc.real imports cb bal, bank bal Bit.get accounting identity banks m sfc checked residuals maximum abs. income residual , maximum abs. nominal residual , maximum abs. real residual , abs cb bal , abs bank bal sfc table DataFrame \"Identity\" \"Income production nominal GVA \", \"GDP expenditure nominal \", \"GDP expenditure real \", \"Central bank balance sheet\", \"Bank balance sheet\" , \"Scope\" \"Maximum over recorded quarters\", \"Maximum over recorded quarters\", \"Maximum over recorded quarters\", \"Final model state\", \"Final model state\" , \"Absolute residual\" round. checked residuals, sigdigits 4 , \"Below 1e 3 model units\" checked residuals . 1e 3, sfc table end md\"\"\" The first three rows use the maximum absolute residual across recorded quarters . Summing signed residuals could conceal offsetting errors. The bank checks concern the final model state, not every previous quarter. The tolerance is stated in model units for comparisons across calibrations, inspect residuals relative to the size of the relevant flows too. Passing these identities checks accounting consistency. It does not validate behavioural rules, forecasts or policy counterfactuals. \"\"\" md\"\"\" 12 — The firm size distribution Inspect the calibrated firm size distribution. A histogram helps describe heterogeneity, but does not test whether its tail follows a power law \"\"\" begin firm sizes nb1 model.firms.N i initial employment per firm histogram log10. firm sizes firm sizes . 0 . 1 , bins 50, title \"Firm size distribution at t 0\\n log₁₀ employees \", xlabel \"log₁₀ employees 1 \", ylabel \"Count\", label \"\", color steelblue, alpha 0.7, end md\"\"\" A concentration of small firms and a few large firms is compatible with several distributions. A power law claim requires a tail threshold, an estimated exponent and comparisons with alternatives such as a lognormal. Here the figure describes the initial calibration it is not evidence that the model endogenously generates the empirical firm size distribution. \"\"\" md\"\"\" ✔ What you learned Running it `Bit.Model parameters, initial conditions ` builds the full agent population. `Bit.step model parallel true ` `Bit.collect data model ` advance one quarter `Bit.run model, T ` is the wrapper for T of them. `Bit.plot data model, quantities ... ` gives the built in dashboard, and `model.data.real gdp` reaches any tracked series. What is inside it About 10,000 agents across 6 types, stored struct of arrays. The real Austrian economy has ~9.9 million `Bit.AUSTRIA2010Q1` is scaled 1 1000 so a run takes seconds. `model.prop.G` is 62 — the number of NACE sectors , which also fixes the count of foreign supplier firms, one per sector. The I O matrix `nb1 model.prop.a sg` encodes the production network — bright cells are supply chain dependencies. Leontief coefficients \\bar\\alpha i, \\beta i, \\kappa i vary across those 62 sectors. Stepping manually with `Bit.step ` lets you watch state change quarter by quarter. The GDP expenditure identity Y C I G X M holds to floating point precision — stock flow consistency confirmed. Exercises Exercise 01.1 — Sort the `leontief` table by \\bar\\alpha i labour productivity . Which sector has the highest labour productivity most output per worker ? Which sector has the lowest \\bar\\alpha i — i.e., is most labour intensive requires the most workers per unit of output ? Do capital productivity and labour productivity tend to move together across sectors? Exercise 01.2 — Compute the out degree of each sector in the I O matrix the number of sectors it supplies to `sum a sg . threshold, dims 2 ` . Plot as a bar chart. Which sector is the most interconnected supplier? Exercise 01.3 stretch — Form a hypothesis about which supplier disruption would be most damaging. Explain why out degree might be informative and why it could mislead. In Notebook 03, distinguish a model intervention from empirical evidence about a real sector. Starter code and checks Use new variable names in your exercise cells so Pluto does not see duplicate definitions. ```julia ex01 sorted sort leontief, \"ᾱ labour prod. \" rev true ex01 threshold 0.01 a 1% input bundle share, not a universal network definition ex01 links nb1 a sg . ex01 threshold ex01 outdegree vec sum ex01 links dims 2 ex01 indegree vec sum ex01 links dims 1 ``` Check 1 both degree vectors have one entry per sector. Summing all out degrees must equal summing all in degrees both count the same edges. Check 2 repeat at thresholds 0.001, 0.01 and 0.05. Does the most connected supplier change? State the threshold when reporting a ranking. Check 3 compare degree with weighted column shares, sector size and initial employment. Explain why a network count is not a welfare measure. Before Notebook 02 identify the initial observation at index 1 quarter 0 , the measurement units, and the difference between an accounting check and a forecast evaluation. \"\"\" "},{"url":"notebooks/02_calibration_and_forecasting/","title":"Calibration, no-burn-in and forecasting","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.24 frontmatter order 3 title \"Calibration, no burn in and forecasting\" layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off return quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end begin import Pkg Pkg.activate joinpath DIR , \"..\", \"..\", \"pluto tutorial\" io devnull import BeforeIT as Bit import Random using Plots, PlutoUI, DataFrames, Statistics, StatsBase end md\"\"\" Notebook 02 — Calibration, no burn in and forecasting Economic question how does a model start from an observed economy, and what evidence would make its forecasts credible? First inspect the calibration and balance sheets, then compare two initialisation experiments and two countries. Next build a Monte Carlo forecast and an AR 1 benchmark. Their final comparison shows forecast disagreement , not accuracy there are no held out outcomes in it. Lecture 2 slides covered Data based initialisation & no burn in , Data Sources and How big is the model? Calibration Process and The full parameter set almost no free parameters Out of sample forecast performance and Quarterly out of sample GDP forecast decomposition Learning goals 1. Distinguish data derived quantities, estimated coefficients and calibration choices. 2. Read initial sector balance sheets and recognise their units. 3. Test whether GDP remains near its initial level under different exogenous processes. 4. Compare country calibrations without attributing every difference to one parameter. 5. Build and interpret a fan chart, an AR 1 forecast and a horizon comparison table. How to work through this notebook Predict an effect before running an experiment, inspect the plot, and explain any surprise using the model's mechanisms. Defaults run when the notebook opens so the online version contains plots. For the expensive Monte Carlo section, change settings together and press Apply . Repeat buttons rerun the current settings they do not pause other reactive cells. \"\"\" begin nb2 p AT Bit.AUSTRIA2010Q1.parameters nb2 ic AT Bit.AUSTRIA2010Q1.initial conditions nb2 p IT Bit.ITALY2010Q1.parameters nb2 ic IT Bit.ITALY2010Q1.initial conditions \"Calibrations loaded Austria and Italy ✓\" end md\"\"\" 1 — Where do the parameters come from? The lecture groups the calibration into census business demography, input output tables, government statistics, regulatory or behavioural choices, and estimated time series blocks. The table below is a selection , not the complete dictionary. Some quantities live in `model.prop` firm characteristics and central bank coefficients live in their own objects. Counts are simulated agents , shares and tax rates are fractions, and the inflation target is a quarterly rate. Tax rates derived from accounts are effective rates rather than necessarily statutory rates. The consumption propensity `ψ` is a behavioural rule calibrated from income and consumption its label does not imply an independently identified causal marginal propensity. Before inspecting the values which quantities describe the initial economy, and which tell agents how to behave? Explore the full dictionary with `sort collect keys nb2 p AT `. \"\"\" begin nb03 m p Bit.Model nb2 p AT, nb2 ic AT p nb03 m p.prop param table DataFrame \"Source block\" \"Census scaled counts\", \"Census scaled counts\", \"Census scaled counts\", \"Scaled counts\", \"I O tables\", \"I O sector accounts\", \"I O tables\", \"Government sector accounts\", \"Government sector accounts\", \"Government sector accounts\", \"Government sector accounts\", \"Government sector accounts\", \"Government sector accounts\", \"Regulatory calibration choice\", \"Regulatory calibration choice\", \"Benefit calibration\", \"Estimated export AR 1 \", \"Estimated export AR 1 \", \"Estimated government AR 1 \", \"Policy target Taylor rule \", \"Estimated Taylor rule \", \"Estimated Taylor rule \", \"Estimated Taylor rule \", , \"Quantity\" \"H act\", \"H inact\", \"I firms \", \"J government entities \", \"a sg matrix dimensions \", \"ᾱ i mean labour productivity \", \"b HH g mean consumption share \", \"τ^INC\", \"τ^VAT\", \"τ^FIRM\", \"τ^SIF\", \"ψ consumption propensity \", \"θ^DIV payout share \", \"ζ capital requirement \", \"ζ LTV\", \"θ UB benefit replacement rate \", \"α E export persistence \", \"β E export intercept \", \"σ G government innovation scale \", \"π quarterly target \", \"ρ rate smoothing \", \"ξ^π inflation response \", \"ξ^γ growth response \", , \"Value\" p.H act, p.H inact, p.I, p.J, \" size p.a sg \", round mean nb03 m p.firms.alpha bar i , digits 4 , round mean p.b HH g , digits 4 , round p.tau INC, digits 4 , round p.tau VAT, digits 4 , round p.tau FIRM, digits 4 , round p.tau SIF, digits 4 , round p.psi, digits 4 , round p.theta DIV, digits 4 , round p.zeta, digits 4 , round p.zeta LTV, digits 4 , round p.theta UB, digits 4 , round nb2 p AT \"alpha E\" , digits 4 , round nb2 p AT \"beta E\" , digits 4 , round nb2 p AT \"sigma G\" , digits 4 , round nb03 m p.cb.pi star, digits 4 , round nb03 m p.cb.rho, digits 4 , round nb03 m p.cb.xi pi, digits 4 , round nb03 m p.cb.xi gamma, digits 4 , , param table end md\"\"\" Read the table critically. Data discipline many quantities, but the calibration also includes estimated exogenous processes, a policy rule and adopted behavioural regulatory choices. The last rows are examples of estimated blocks, not all estimated coefficients. Initialising from data does not by itself validate forecasts or policy experiments. The mean consumption share hides composition because shares sum to one inspect `p.b HH g` itself. An unweighted mean of firm productivity also hides its sectoral distribution. Matching an aggregate need not reproduce the heterogeneity relevant to an economic mechanism. \"\"\" md\"\"\" 2 — Initial balance sheets National and sector accounts supply aggregate stocks, which initialisation allocates across simulated agents. This is a data consistent construction, not an observed balance sheet for every individual household. The household sector includes active and inactive workers, firm owners and the bank owner counting active workers alone would omit some household deposits. Units matter deposits, loans and equity are stocks in the calibration's monetary units, whereas the policy rate is a fraction per quarter. Do not interpret a raw value as an individual amount in euros, or compare a rate with a monetary stock. \"\"\" begin model AT Bit.Model nb2 p AT, nb2 ic AT nb2 household deposits sum model AT.w act.D h sum model AT.w inact.D h sum model AT.firms.D h model AT.bank.D h bs table DataFrame \"Quantity\" \"Household deposits all household types \", \"Firm deposits sum \", \"Firm debt sum \", \"Bank equity\", \"Government debt\", \"Initial policy rate\" , \"Value\" round nb2 household deposits, sigdigits 5 , round sum model AT.firms.D i , sigdigits 5 , round sum model AT.firms.L i , sigdigits 5 , round model AT.bank.E k, sigdigits 5 , round model AT.gov.L G, sigdigits 5 , round model AT.cb.r bar, digits 5 , \"Unit\" fill \"Calibration monetary units\", 5 \"Fraction per quarter\" , bs table end md\"\"\" 3 — Testing the no burn in idea A burn in discards an initial stretch of simulation because the starting state creates artificial transients. Data based initialisation aims to make the model useful from the reference quarter. The lecture's stronger diagnostic suppresses growth processes and asks whether the model fluctuates around its initial conditions. The experiment below is narrower it changes three correlated innovations while retaining the empirical histories used to form expectations. Compare two scenarios over 20 quarters five years 1. Baseline Austria 2010 Q1 with its normal stochastic processes. 2. Correlated innovations off `C 0` zero the covariance matrix for euro area GDP, export demand and import supply. Their deterministic AR 1 terms remain. Government consumption and euro area inflation still draw innovations using separate scalar `σ` values. A no growth comparison needs an expectations rule too. `Bit.STEADY STATE2010Q1` fixes exogenous processes and policy, and flattens the histories used by adaptive expectations. A constant history cannot identify an AR 1 slope and intercept separately the default refitting can fail numerically. That calibration is therefore not simulated in this exercise. An initial accounting balance alone does not establish a dynamically stable steady state. The horizontal line in the plot marks initial GDP, not a simulated steady state path. Predict, then inspect should removing these innovations reduce drift? Why is `C 0` not a complete no growth experiment? Compare the paths, but do not treat either as a full test of the lecture's no burn in claim or a proof that the calibrated economy is an exact fixed point. \"\"\" bind run noburn PlutoUI.CounterButton \"↻ Repeat initialisation comparison 2 × 20 quarters \" begin run noburn Random.seed 42 model shocks on Bit.Model nb2 p AT, nb2 ic AT Bit.run model shocks on, 20 C silences three correlated innovations, not all stochasticity. Random.seed 42 model no shocks Bit.Model nb2 p AT, nb2 ic AT model no shocks.prop.C . 0.0 Bit.run model no shocks, 20 \"Two 20 quarter simulations complete. A fixed seed aids reproducibility each scenario has different dynamics.\" end begin gdp on model shocks on.data.real gdp gdp off model no shocks.data.real gdp Index each simulated scenario to its own initial value. nb2 index on 100 . gdp on . first gdp on nb2 index off 100 . gdp off . first gdp off nothing end begin p3 plot 0 20, nb2 index on, label \"Baseline\", lw 2, color steelblue, title \"Initialisation comparison real GDP\", xlabel \"Quarters after initialisation\", ylabel \"Index own t 0 100 \" plot p3, 0 20, nb2 index off, label \"Correlated innovations off C 0 \", lw 2, color crimson, ls dash hline p3, 100 , label \"Initial GDP reference \", color grey, ls dot p4 plot 0 20, nb2 index on . 100, label \"Baseline\", color steelblue, lw 2, title \"GDP deviation from each scenario's initial value\", xlabel \"Quarters after initialisation\", ylabel \"Percent deviation\" plot p4, 0 20, nb2 index off . 100, label \"Correlated innovations off C 0 \", color crimson, lw 2, ls dash hline p4, 0 , color black, lw 1, label \"\" plot p3, p4, layout 2, 1 , size 750, 580 end begin dev on maximum abs. nb2 index on . 100 dev off maximum abs. nb2 index off . 100 Markdown.parse \"\"\" | Scenario | Maximum absolute GDP deviation from own t 0 20 quarters | | | | | Baseline | round dev on, digits 2 % | | Correlated innovations off `C 0` | round dev off, digits 2 % | The table measures the largest departure along each single path. It is neither a forecast error nor an across path standard deviation. In the `C 0` run, deterministic terms, the two remaining exogenous innovations and market matching can still move GDP. Interpretation task does the observed ordering agree with your prediction? Explain remaining movement before generalising. These paths illustrate initialisation under two stochastic specifications. Fixed seeds make the examples reproducible a difference between single paths does not measure an isolated causal effect. Neither establishes that every country or policy experiment starts at an exact fixed point. \"\"\" end md\"\"\" 4 — Austria vs Italy Compare the Austria and Italy 2010 Q1 calibrations. Counts refer to the scaled simulation, not literal national populations. Taxes, spending rules, industry structure, initial stocks and exogenous processes all change together. Prediction select one row and explain how it could affect demand or income. The country comparison shows joint differences identifying that row's effect would require changing it alone while holding the rest of the calibration fixed. \"\"\" begin pAT Bit.Model nb2 p AT, nb2 ic AT .prop pIT Bit.Model nb2 p IT, nb2 ic IT .prop comparison DataFrame \"Parameter\" \"Consumption propensity ψ\", \"τ^INC\", \"τ^VAT\", \"τ^FIRM\", \"θ^UB unempl. benefit \", \"θ^DIV dividend payout \", \"ζ min. capital ratio \", \"H act\", \"I firms \" , \"Austria\" pAT.psi, pAT.tau INC, pAT.tau VAT, pAT.tau FIRM, pAT.theta UB, pAT.theta DIV, pAT.zeta, pAT.H act, pAT.I , \"Italy\" pIT.psi, pIT.tau INC, pIT.tau VAT, pIT.tau FIRM, pIT.theta UB, pIT.theta DIV, pIT.zeta, pIT.H act, pIT.I , comparison end bind run countries PlutoUI.CounterButton \"↻ Repeat Austria–Italy comparison 20 quarters each \" begin run countries Random.seed 42 m AT Bit.Model nb2 p AT, nb2 ic AT Bit.run m AT, 20 Random.seed 42 m IT Bit.Model nb2 p IT, nb2 ic IT Bit.run m IT, 20 gdp AT norm m AT.data.real gdp . first m AT.data.real gdp . 100 gdp IT norm m IT.data.real gdp . first m IT.data.real gdp . 100 inf AT m AT.data.nominal gdp . m AT.data.real gdp inf IT m IT.data.nominal gdp . m IT.data.real gdp p1 plot 0 20, gdp AT norm, label \"Austria\", lw 2, color steelblue, title \"Real GDP\", xlabel \"Quarters after initialisation\", ylabel \"Index own t 0 100 \" plot p1, 0 20, gdp IT norm, label \"Italy\", lw 2, color tomato p2 plot 0 20, inf AT, label \"Austria\", lw 2, color steelblue, title \"GDP deflator\", xlabel \"Quarters after initialisation\", ylabel \"Price index t 0 1 \" plot p2, 0 20, inf IT, label \"Italy\", lw 2, color tomato plot p1, p2, layout 1, 2 , size 800, 350 , legend topright end md\"\"\" Read both panels GDP is indexed to compare growth paths, not country size. The deflator is `nominal gdp real gdp`, a price level index, not an inflation rate . Quarter on quarter inflation would be `100 . diff deflator . deflator 1 end 1 `. Different paths do not establish that an MPC, tax or benefit parameter caused the whole difference. Even with the same seed, differing calibrations do not imply identical shocks. \"\"\" md\"\"\" Part 2 — Forecasting Data based initialisation gives the forecast an observed reference point without discarding an artificial spin up. It does not guarantee forecast accuracy. We now separate three questions where does the model predict GDP will go, how dispersed are its paths, and what held out data would be needed to decide whether it forecasts well? \"\"\" md\"\"\" Forecasting learning goals 1. Build a multi path Monte Carlo forecast and distinguish path quantiles from confidence intervals. 2. Estimate a simple AR 1 benchmark using only the pre forecast history. 3. Compare forecasts in the same units at horizons that were actually simulated. 4. Explain how conditional forecasting changes the available information. The lecture's forecast comparisons refer to the Poledna et al. study, published in 2023 earlier drafts appear in the slides . This short experiment teaches the workflow it does not reproduce the published forecast evaluation. \"\"\" md\"\"\" 5 — Monte Carlo fan chart A fan chart summarises simulated paths conditional on the same calibration and aggregate initial conditions . Each path constructs a fresh model, including random initial firm level allocations. Dispersion therefore includes uncertainty about the initial micro allocation as well as subsequent stochastic dynamics. The published forecasting exercise uses hundreds of paths per reference quarter. Start here with 10 paths over eight quarters , then increase the budget only when you need a more stable estimate of the mean or quantiles. All paths start from Austria's 2010 Q1 calibration. One quarter is one model step, and array entry `h 1` is horizon `h` because the first entry is the initial state. We index each path to 100 at that point. The 10–90% and 25–75% bands describe model generated dispersion they are not confidence intervals for the ensemble mean or empirically verified coverage probabilities. Make a prediction will increasing the number of paths remove economic uncertainty, or only make its simulation estimate less noisy? Change settings below, then press Apply once. \"\"\" bind nb2 fc settings PlutoUI.confirm PlutoUI.combine do Child md\"\"\" Forecast settings Paths Child \"paths\", PlutoUI.Slider 5, 10, 20, 50, 100, 200 , default 10, show value true Quarters ahead Child \"horizon\", PlutoUI.Slider 4 4 40, default 8, show value true Random seed Child \"seed\", PlutoUI.Slider 1 3000, default 2019, show value true, max steps 3000 \"\"\" end begin n mc fc nb2 fc settings.paths T fc nb2 fc settings.horizon seed fc nb2 fc settings.seed Markdown.parse \"Applied budget n mc fc paths × T fc quarters seed seed fc . The initial state adds one observation to every path.\" end bind run fc PlutoUI.CounterButton \"↻ Repeat forecast with the applied settings and seed\" begin run fc Random.seed seed fc Serial execution makes this small teaching example reproducible independently of thread count. mc models Bit.ensemblerun Bit.Model nb2 p AT, nb2 ic AT for in 1 n mc fc , T fc parallel false, \"Forecast complete n mc fc paths × T fc quarters.\" end begin Rows are horizons 0 T fc columns are Monte Carlo paths. nb2 gdp mat hcat m.data.real gdp for m in mc models ... nb2 gdp index mat 100 . nb2 gdp mat . nb2 gdp mat 1 1, nb2 gdp mean vec mean nb2 gdp index mat, dims 2 nb2 gdp p10 quantile nb2 gdp index mat t, , 0.10 for t in 1 T fc 1 nb2 gdp p25 quantile nb2 gdp index mat t, , 0.25 for t in 1 T fc 1 nb2 gdp p75 quantile nb2 gdp index mat t, , 0.75 for t in 1 T fc 1 nb2 gdp p90 quantile nb2 gdp index mat t, , 0.90 for t in 1 T fc 1 nothing end begin Draw bands by their endpoints a skewed distribution's mean need not lie inside every band. p fan plot 0 T fc, nb2 gdp p10, fillrange nb2 gdp p90, fillalpha 0.15, color steelblue, lw 0, label \"10th–90th percentiles\", title \"ABM real GDP forecast n mc fc paths \", xlabel \"Quarters ahead\", ylabel \"Index 2010 Q1 100 \" plot p fan, 0 T fc, nb2 gdp p25, fillrange nb2 gdp p75, fillalpha 0.25, color steelblue, lw 0, label \"25th–75th percentiles\" plot p fan, 0 T fc, nb2 gdp mean, color steelblue, lw 2, label \"Ensemble mean\" end md\"\"\" Reading the fan the darker band estimates the central 50% range of the model distribution at each horizon the lighter band estimates the central 80% range. Their endpoints are interpolated sample quantiles, so a finite ensemble need not place exactly those percentages of its paths inside the bands. The mean is a separate line. Dispersion comes from random initial micro allocations, subsequent stochastic processes and matching, with parameters fixed. Longer horizons often have wider bands, but mean reversion, nonlinear dynamics and a small Monte Carlo sample can make widths non monotonic. More paths stabilise estimated quantiles they need not systematically narrow the underlying forecast distribution. \"\"\" md\"\"\" 6 — Historical trajectory and forecast overlay The history in `initial conditions \"Y\" ` follows the historical real GDP trajectory, rescaled to the model's output units during calibration. Its raw level is therefore not the same object as the model's value added measure `data.real gdp`. Index each series to 100 at its own 2010 Q1 value before overlaying them. The black line ends at the forecast origin. It supplies information available for fitting the benchmark it is not a held out future trajectory against which accuracy can be assessed. \"\"\" begin Y hist raw vec nb2 ic AT \"Y\" T hist length Y hist raw Y hist norm 100 . Y hist raw . last Y hist raw fc norm mean nb2 gdp mean fc norm p10 nb2 gdp p10 fc norm p90 nb2 gdp p90 x hist T hist 1 0 x fc 0 T fc p hist plot x hist, Y hist norm, lw 2, color black, label \"Historical trajectory indexed \", title \"History and forecast Austria 2010 Q1\", xlabel \"Quarters relative to 2010 Q1\", ylabel \"Index 2010 Q1 100 \" plot p hist, x fc, fc norm p10, fillrange fc norm p90, fillalpha 0.15, color steelblue, lw 0, label \"ABM 10–90% path band\" plot p hist, x fc, fc norm mean, color steelblue, lw 2, label \"ABM ensemble mean\" vline p hist, 0 , lw 1.5, ls dash, color grey, label \"Forecast origin\" end md\"\"\" Check the join both history and forecast equal 100 at horizon zero. Indexing preserves relative movements but removes differences in level and units. It is useful for this teaching comparison it does not establish equality of the original accounting quantities. The fan reflects stochastic paths at a fixed parameter calibration, including random matching, rather than parameter uncertainty. A proper out of sample evaluation repeats the forecast at multiple reference quarters and compares predictions with subsequently observed GDP. The published application evaluates a sequence of reference quarters rather than this single origin. \"\"\" md\"\"\" 7 — A simple AR 1 benchmark Construct an intentionally simple benchmark using only the history up to the forecast origin `y t β α y t 1 ε t`. OLS chooses the intercept `β` and persistence `α`. Recursively applying `β α y` gives a point forecast no random innovation is added to it. Follow the code in three steps 1. Align `y lag` and `y now` so each row contains adjacent observations. 2. Add a column of ones for the intercept, then solve the least squares system with `X \\\\ y now`. 3. Start the recursive forecast at the last historical value, then index it to 100 for comparison. This is an AR 1 in levels , not an exact replication of the lecture's benchmark scripts, which use log differences for GDP and other variables. Transformations, estimation windows and data vintages matter when comparing forecast accuracy. A levels estimate near or above unit persistence can imply drifting or explosive long horizon paths inspect `α`. \"\"\" begin Y hist vec nb2 ic AT \"Y\" assert length Y hist 3 && all isfinite, Y hist \"AR 1 needs a finite historical series.\" y lag Y hist 1 end 1 y now Y hist 2 end A row of X is 1, y t 1 coefficients are intercept, persistence . X hcat ones length y lag , y lag coef X \\ y now β ar1, α ar1 coef ar1 forecast zeros T fc 1 ar1 forecast 1 last Y hist for t in 2 T fc 1 ar1 forecast t β ar1 α ar1 ar1 forecast t 1 end persistence round α ar1, digits 4 , intercept round β ar1, digits 4 end begin ar1 norm 100 . ar1 forecast . first ar1 forecast nothing end begin gdp norm nb2 gdp mean p10 norm nb2 gdp p10 p90 norm nb2 gdp p90 p benchmark plot 0 T fc, p10 norm, fillrange p90 norm, fillalpha 0.15, color steelblue, lw 0, label \"ABM 10–90% path band\", title \"Forecast disagreement ABM and levels AR 1 \", xlabel \"Quarters ahead\", ylabel \"Index 2010 Q1 100 \" plot p benchmark, 0 T fc, gdp norm, color steelblue, lw 2, label \"ABM ensemble mean\" plot p benchmark, 0 T fc, ar1 norm, color tomato, lw 2, ls dash, label \"AR 1 point forecast\" end md\"\"\" 8 — Forecast divergence at selected horizons Compare the indexed AR 1 point forecast with the indexed ABM distribution. The table reports Absolute mean gap forecast disagreement in index points. ABM path standard deviation across path dispersion in the same units. Gap ABM standard deviation disagreement relative to model dispersion undefined when dispersion is zero. Within the 10–90% band whether the benchmark lies between those path quantiles. A gap of one standard deviation is a descriptive scale, not a significance test. Being inside the fan does not make the AR 1 accurate, and being outside does not make the ABM accurate. Neither forecast is compared with a realised outcome here. Only horizons within the applied simulation length are included. \"\"\" begin horizons filter h h T fc, 1, 2, 4, 8 nb2 mean gaps Float64 nb2 path spreads Float64 nb2 scaled gaps Union Missing, Float64 nb2 inside band Bool for h in horizons ar1 val ar1 norm h 1 abm val nb2 gdp mean h 1 gap abs ar1 val abm val spread std nb2 gdp index mat h 1, push nb2 mean gaps, gap push nb2 path spreads, spread push nb2 scaled gaps, spread 0 ? gap spread missing push nb2 inside band, nb2 gdp p10 h 1 ar1 val nb2 gdp p90 h 1 end nb2 divergence table DataFrame \"Horizon quarters \" horizons, \"Absolute mean gap index points \" round. nb2 mean gaps, digits 3 , \"ABM path std index points \" round. nb2 path spreads, digits 3 , \"Gap ABM std\" map x ismissing x ? missing round x, digits 2 , nb2 scaled gaps , \"Within 10–90% path band\" nb2 inside band, nb2 divergence table end md\"\"\" What would a proper forecast evaluation add? For each reference quarter, use only the information available then, simulate the required horizons, and compare point forecasts with held out observed values . For a fixed horizon, RMSE is `sqrt mean forecast . realised .^2 ` across forecast origins. Report its units and compare benchmarks using the same origins, horizons, information and transformations. Across path standard deviation is not RMSE, and the ABM mean is not observed truth. The lecture repository's `.. lecture 2 sfc abm tabs error table .jl` scripts show the larger evaluation workflow and require their own data. This notebook does not run that pipeline. Conditional forecasting fixes selected exogenous paths, for example external demand or government consumption, instead of drawing them. Realised future paths provide hindsight scenario paths supply assumed information. Such forecasts can reveal how external developments contribute to errors, but should be compared with benchmarks given the same information. \"\"\" md\"\"\" ✔ What you learned Data derived initial stocks, estimated coefficients and calibration choices have different roles. Aggregate household deposits include workers, inactive households and owners. Financial stocks and quarterly rates need separate unit labels. `C 0` removes three correlated innovations it leaves deterministic dynamics, two other exogenous innovations and random matching. A full no growth diagnostic also needs a well defined expectations rule an accounting reference is not a simulated steady state. GDP indices and deflator levels describe different objects inflation is a change in the deflator. Monte Carlo quantiles describe fixed calibration path dispersion, not uncertainty in the mean. A levels AR 1 is a teaching benchmark. Indexed forecast disagreement is not out of sample accuracy. Exercises — predict, implement, explain Work through 02.1–02.3 first. For simulations, construct a fresh model for every treatment `run ` mutates its argument, so running it again extends that path. Keep budgets small while debugging. Save an economic prediction before looking at the new plot. 02.1 — Compare like with like. Which rate or share differs most between Austria and Italy? Compare agent counts separately. Explain one mechanism linking your chosen parameter to demand or income, then state why the country comparison alone cannot identify its effect. Hint form `comparison.Italy . comparison.Austria`, but do not rank counts and fractions together. A consumption share vector contains more structural information than its mean. 02.2 — Covariance versus shock amplitude. In a fresh Austria model, apply `model.prop.C . 0.5` and compare its indexed GDP path with the baseline and `C 0` cases. Predict the change first. Which two exogenous innovations remain? Hint multiplying a covariance matrix by `f` multiplies standard deviations by `sqrt f `. To halve the correlated innovations' standard deviations, use `f 0.25`, not `0.5`. 02.3 — A small sensitivity experiment. Start with `f` in ` 0.0, 0.25, 1.0 `, a fresh model and the same seed for each run. Compute maximum absolute GDP deviation from each path's own initial value and plot it against `f`. Extend to ` 0.0, 0.1, 0.25, 0.5, 0.75, 1.0 ` if useful. Is the relationship linear? Hint maximum deviation along one path is not a volatility estimator. Drift and nonlinear feedback can dominate it. Repeat a small set of seeds before claiming a monotonic relationship. 02.4 — More paths, the same economic uncertainty. Change the applied budget from 10 to 20 paths, keeping horizon and seed fixed. Compare the mean and 10–90% band. Try 200 paths only as an optional, more expensive precision check. Hint more paths reduce Monte Carlo error in estimated means and quantiles they do not remove model generated risk. A small change in band width can have either sign. 02.5 — Relative forecast dispersion. Compute the GDP coefficient of variation at horizons 1, 4 and 8 that fit within `T fc`. Does it increase monotonically? Hint for horizon `h`, use the row `nb2 gdp index mat h 1, `. Compute `std row mean row `, or multiply by 100 to report percent. Take the standard deviation across paths, not across time. 02.6 — An endpoint rather than a whole trajectory. Apply 20 paths and `T fc 20`, then compare the mean and standard deviation of GDP at horizon 20. Reuse the existing ensemble rather than running every model for another 20 quarters. Hint raw levels are in `nb2 gdp mat 21, ` indexed values are in `nb2 gdp index mat 21, `. State which units you report. Compare spread relative to the mean. 02.7 — Longer horizon diagnostic stretch . Compare fresh Austria and Italy models with `C 0` over 20 quarters, then extend a small set of seeds to 80 quarters. Which country departs more from its starting GDP, and does that ordering persist? Outline what else would need to change to construct the lecture's no growth diagnostic. Hint index each path to its own initial value, report the metric and horizon, and do not treat a single path as a stability proof. Removing all exogenous drifts and innovations is a stronger change than `C 0` flat histories also require an explicit expectations rule rather than an unidentified AR 1 fit. Future realised exogenous paths would instead change the information set of a conditional forecast. \"\"\" "},{"url":"notebooks/03_shocks_expectations_policy/","title":"Shocks, expectations and policy","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.24 frontmatter order 4 title \"Shocks, expectations and policy\" layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off return quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end begin import Pkg Pkg.activate joinpath DIR , \"..\", \"..\", \"pluto tutorial\" io devnull import BeforeIT as Bit import Random using Plots, StatsPlots, PlutoUI, Statistics end md\"\"\" Notebook 03 — Shocks, expectations and policy Question how does a change to productivity or household spending propagate through a heterogeneous economy? Before running anything Predict which variable moves first, which balance sheets bear the cost, and whether the change is temporary or persistent. Then compare the prediction with the plots. The online page shows saved outputs use Pluto locally to change the controls. Lecture 2 slides covered What drives fluctuations? Five exogenous AR 1 processes Endogenous crises the bankruptcy cascade Expectations and fiscal monetary closure Learning goals 1. Distinguish external disturbances from endogenous propagation. 2. Design a matched shock baseline comparison and read its units and simulation uncertainty. 3. Test proportionality without mistaking Monte Carlo noise for non linearity. 4. Compare expectation rules and explain the euro area policy closure. \"\"\" begin nb3 p Bit.AUSTRIA2010Q1.parameters nb3 ic Bit.AUSTRIA2010Q1.initial conditions \"Calibration loaded ✓\" end md\"\"\" 1 — Five external processes, several propagation mechanisms The Poledna ABM models five external processes with AR 1 rules estimated from data. Their entry points differ the final GDP effect depends on the economy's response. | Process | Where it enters | First mechanism to investigate | | | | | | Export demand | `model.agg.epsilon E` | Foreign purchases of domestic output | | Import supply | `model.agg.epsilon I` | Availability of imported goods and inputs | | Government consumption | Government expenditure rule | Demand for goods | | Euro area GDP growth | `model.agg.epsilon Y EA` | The central bank's Taylor rule | | Euro area inflation | `rotw` inflation rule | The central bank's Taylor rule | The innovations for exports, imports and euro area output are drawn jointly using `model.prop.C`, a calibrated 3×3 covariance matrix. Government consumption and euro area inflation draw separately from their scalar standard deviations. Random goods market matching and innovations in learned forecasts add further simulation randomness. Read the dashboard carefully these are aggregate outcomes, not plots of the five innovations themselves. Co movement in one simulated path does not identify a causal effect. \"\"\" bind run baseline PlutoUI.Button \"▶ Run baseline 20 quarters \" begin run baseline m base Bit.Model nb3 p, nb3 ic Bit.run m base, 20 \"Baseline run complete ✓\" end begin run baseline plot Bit.plot data m base, quantities real gdp, real exports, real imports, real government consumption, euribor, wages ..., layout 2, 3 , size 850, 500 , title \"Real GDP\" \"Exports\" \"Imports\" \"Gov. consumption\" \"Policy rate quarterly fraction \" \"Nominal wage bill\" , end md\"\"\" 2 — Design a shock experiment BeforeIT calls `shock model ` every quarter after setting macro expectations and the policy rate, but before firms' pricing, production and household budgets. Our callable struct changes a parameter only when `model.agg.t 1`. Timing matters the productivity change and the consumption propensity change below remain in place after quarter 1. They are persistent parameter interventions, not one quarter pulses. The model continues to draw its usual stochastic disturbances. Change the controls and press Confirm together. The Run button repeats the confirmed experiment. Pluto also evaluates a modest default experiment when the notebook opens. \"\"\" begin nb3 shock controls bind shock settings PlutoUI.confirm PlutoUI.combine do Child md\"\"\" Shock type Child \"kind\", PlutoUI.Select \"Productivity\", \"Consumption MPC \" , default \"Productivity\" Multiplier 1.0 no change Child \"multiplier\", PlutoUI.Slider 0.80 0.01 1.20, default 0.95, show value true Monte Carlo paths Child \"paths\", PlutoUI.Slider 8, 16, 32 , default 8, show value true \"\"\" end shock type shock settings.kind shock size shock settings.multiplier n shock mc shock settings.paths nb3 shock controls end begin struct Nb3ProductivityShock mult Float64 end struct Nb3ConsumptionShock mult Float64 end function s Nb3ProductivityShock model model.agg.t 1 && model.firms.alpha bar i . s.mult end function s Nb3ConsumptionShock model model.agg.t 1 && model.prop.psi s.mult end Seed each replicate explicitly serial market matching avoids thread order noise. Resetting seeds aligns initial random draws. Endogenous branches can later consume different numbers of draws, so it does not guarantee identical future disturbances. function nb3 paths n shock Bit.NoShock , seed 4040, T 20 map 1 n do i Random.seed seed i Bit.run Bit.Model nb3 p, nb3 ic , T shock shock, parallel false end end end bind run shock PlutoUI.Button \"▶ Run shocked vs baseline\" begin run shock chosen shock shock type \"Productivity\" ? Nb3ProductivityShock shock size Nb3ConsumptionShock shock size models base nb3 paths n shock mc models shocked nb3 paths n shock mc shock chosen shock \"Matched shock experiment complete ✓\" end begin run shock nb3 dashboard map real gdp, \"Real GDP\", \"Change % \" , wages, \"Nominal wage bill\", \"Change % \" , euribor, \"Quarterly policy rate\", \"Difference percentage points \" , real household consumption, \"Real household consumption\", \"Change % \" , do field, panel title, units b hcat getfield m.data, field for m in models base ... s hcat getfield m.data, field for m in models shocked ... effects field euribor ? 100 . s . b 100 . s . b . 1 avg vec mean effects, dims 2 se vec std effects, dims 2 . sqrt n shock mc panel plot 0 20, avg ribbon se, fillalpha 0.2, lw 2, title panel title, xlabel \"Quarter\", ylabel units, label \"Mean paired effect ± 1 MC SE\", color steelblue hline panel, 0.0 label \"No effect\", color black, ls dash, lw 1 panel end plot nb3 dashboard... layout 2, 2 , size 900, 620 end md\"\"\" First check confirm a multiplier of 1.0 . All four differences should be zero, up to numerical tolerance. A GDP effect of −2 means GDP is 2% below its matched baseline a policy rate difference of 0.1 means 0.1 percentage points , not 10% higher rates. Next use 0.95. A lower productivity norm can tighten production capacity a lower `psi` reduces planned consumption relative to expected income. Trace the outcomes rather than assuming that both changes operate through the same mechanism. \"\"\" md\"\"\" Reading the four panels GDP and consumption show real quantity effects relative to their baselines. `data.wages` is the total nominal wage bill employment, wage rates and prices can all change it. The policy rate responds to euro area , not domestic, conditions. A domestic shock does not directly trigger an ECB rate cut in this model. Later rate differences can arise if the simulations' random draws diverge. The ribbon is one standard error of the mean paired simulation effect. It measures Monte Carlo precision, not parameter uncertainty or an empirical confidence interval. A persistent GDP loss alone does not prove a bankruptcy cascade. Inspect firm insolvency, bank equity or input shortages to distinguish mechanisms. Insolvent firms are refinanced in the baseline model they are not simply removed forever. Nonlinear DSGE models can also contain financial constraints, so this plot is not a general ABM versus DSGE verdict. \"\"\" md\"\"\" 3 — Is the response proportional to the intervention? Vary the productivity multiplier and compare real GDP at quarter 20 with one shared baseline ensemble. Each replicate uses the same seed across settings, and the no change case reuses the baseline itself. This supplies a useful zero effect check. The plot reports the mean of paired percentage changes, with a one Monte Carlo standard error ribbon. It is the terminal response, not the deepest recession within the horizon. A curved relationship is evidence to investigate, but a jagged small sample line is not by itself evidence of economic non linearity. Increase the number of paths before drawing that conclusion. The scan has seven settings to keep the default runtime manageable. \"\"\" bind run nonlinear PlutoUI.Button \"▶ Scan seven productivity settings\" begin run nonlinear shock mults 0.80, 0.90, 0.95, 1.0, 1.05, 1.10, 1.20 scan base nb3 paths n shock mc seed 4042 scan base mat hcat m.data.real gdp for m in scan base ... terminal effects Float64 terminal se Float64 for mult in shock mults scan shocked mult 1.0 ? scan base nb3 paths n shock mc shock Nb3ProductivityShock mult , seed 4042 shocked mat hcat m.data.real gdp for m in scan shocked ... effects 100 . shocked mat end, . scan base mat end, . 1 push terminal effects, mean effects push terminal se, std effects sqrt n shock mc end plot shock mults, terminal effects ribbon terminal se, fillalpha 0.2, xlabel \"Productivity multiplier\", ylabel \"GDP change at quarter 20 % \", title \"Proportionality check persistent productivity change\", marker circle, lw 2, color steelblue, label \"Mean paired effect ± 1 MC SE\" hline 0.0 label \"Baseline\", color grey, ls dash vline 1.0 label \"No change\", color grey, ls dot end md\"\"\" Test a prediction under a locally linear response, a −10% intervention would give approximately twice the effect of −5%. Compare the 0.90 and 0.95 points and their ribbons. Do not call any departure a bankruptcy threshold without checking the underlying firm and bank outcomes. The graph combines all model mechanisms. \"\"\" md\"\"\" Part 2 — Expectations and policy Separate two mechanisms domestic expectations feed production and pricing decisions, while the policy rate is set from euro area conditions. The second mechanism does not provide direct feedback from Austrian inflation to the ECB in this calibration. \"\"\" md\"\"\" Question how do forecast rules and the monetary policy closure shape the simulated path? Learning goals 1. Read the learned AR 1 rule in the units used by the implementation. 2. Compare it with a last observation rule without calling either rational expectations. 3. Change one Taylor rule parameter at a time under the same initial seed. 4. Distinguish one illustrative trajectory from evidence across many simulations. \"\"\" md\"\"\" 4 — Learned AR 1 forecasts For a history `z`, `Bit.estimate next value z ` fits an AR 1 with an intercept and returns z^e t 1 \\alpha t z t \\beta t \\varepsilon^e t 1 . The coefficients are re estimated by OLS each quarter. The implementation also draws a forecast innovation from the fitted residual variance this is a stochastic learned forecast , not just the conditional mean and not perfect foresight. `Bit.growth inflation expectations` applies the rule to log aggregate gross output `agg.Y`, the sum of firm output and stored log price changes . It exponentiates the forecasts to obtain an output level and simple inflation rate expected growth is forecast output divided by the latest output, minus one. BeforeIT uses this output series as a GDP proxy for expectations. Reported real GDP instead deducts intermediate consumption and includes product taxes, so changes in sector composition can make the two growth rates differ. OLS fits the chosen forecasting rule to its history. It does not establish that the rule is optimal for the evolving economy or that expectations are rational. \"\"\" md\"\"\" 5 — Learned AR 1 versus last observation forecasts Learned AR 1 the default fitted rule, including its forecast innovation. Last observation hold the aggregate output proxy constant and repeat the last observed inflation rate. Both use past observations. “Forward looking” versus “backward looking” would obscure that shared information set. The last observation rule also removes the default forecast innovation, so this comparison changes both the forecast rule and its noise. We specialise `Bit.growth inflation expectations` on a new model type rather than replacing a package wide function. That keeps the default rule intact for the other experiments. \"\"\" begin Bit. object mutable struct Nb3LastValueModel Bit.Model Bit.AbstractModel end function Bit.growth inflation expectations model Nb3LastValueModel idx model.prop.T prime model.agg.t 1 last output model.agg.Y idx last inflation expm1 model.agg.pi idx return last output, zero last output , last inflation end bind run expectations PlutoUI.Button \"▶ Compare expectation rules 40 quarters \" end begin run expectations Random.seed 1234 nb3 model ar1 Bit.Model nb3 p, nb3 ic Bit.run nb3 model ar1, 40 parallel false Random.seed 1234 nb3 const initial Bit.Model nb3 p, nb3 ic Wrap components that Bit.Model has ALREADY initialised. Reinitialising the tuple here would apply the shared balance sheet normalisation twice. nb3 model const Nb3LastValueModel nb3 const initial.w act, nb3 const initial.w inact, nb3 const initial.firms, nb3 const initial.bank, nb3 const initial.cb, nb3 const initial.gov, nb3 const initial.rotw, nb3 const initial.agg, nb3 const initial.prop, nb3 const initial.data Bit.run nb3 model const, 40 parallel false \"Illustrative expectations comparison complete ✓\" end begin run expectations p exp gdp plot 0 40, nb3 model ar1.data.real gdp, label \"Learned AR 1 \", lw 2, color steelblue, title \"Real GDP\", xlabel \"Quarter\", plot p exp gdp, 0 40, nb3 model const.data.real gdp, label \"Last observation\", lw 2, color tomato, ls dash p exp defl plot 0 40, nb3 model ar1.data.nominal gdp . nb3 model ar1.data.real gdp, label \"Learned AR 1 \", lw 2, color steelblue, title \"GDP deflator\", xlabel \"Quarter\", plot p exp defl, 0 40, nb3 model const.data.nominal gdp . nb3 model const.data.real gdp, label \"Last observation\", lw 2, color tomato, ls dash plot p exp gdp, p exp defl, layout 1, 2 , size 800, 350 end md\"\"\" What does this comparison establish? The two rules can generate different paths, but one path does not establish which forecasts better or creates more volatility. The same initial seed gives the same starting draws removing forecast innovations changes subsequent random number use, so later external disturbances need not match. For a stronger comparison, measure forecast errors and outcome dispersion across many seeds, and explicitly replay the same external disturbances. Distinguish uncertainty across simulations from fluctuations over time within one simulation. \"\"\" md\"\"\" 6 — The Taylor rule The implemented rule includes a real rate intercept and a zero lower bound \\bar r t \\max\\ \\left\\ 0,\\ \\rho\\bar r t 1 1 \\rho \\left r^ \\pi^ \\xi^\\pi \\pi^ EA t \\pi^ \\xi^\\gamma\\gamma^ EA t\\right \\right\\ . It responds to euro area inflation and output growth, not Austrian conditions. Rates, growth and inflation are quarterly fractions in the code. Multiplying a rate by 100 displays its quarterly percentage it does not annualise it. The sliders start at this notebook's actual calibration values. Confirm a change to one coefficient, keeping the others fixed, then compare policy rates and domestic outcomes. \"\"\" begin nb3 taylor controls bind taylor settings PlutoUI.confirm PlutoUI.combine do Child md\"\"\" Smoothing ρ Child \"rho\", PlutoUI.Slider sort unique vcat collect 0.0 0.05 0.95 , 0.99, Float64 nb3 p \"rho\" default Float64 nb3 p \"rho\" , show value true Inflation weight ξπ Child \"pi\", PlutoUI.Slider sort unique vcat collect 0.0 0.1 3.0 , Float64 nb3 p \"xi pi\" default Float64 nb3 p \"xi pi\" , show value true Growth weight ξγ Child \"gamma\", PlutoUI.Slider sort unique vcat collect 0.0 0.1 3.0 , Float64 nb3 p \"xi gamma\" default Float64 nb3 p \"xi gamma\" , show value true \"\"\" end rho val taylor settings.rho xi pi val taylor settings.pi xi gamma val taylor settings.gamma nb3 taylor controls end bind run taylor PlutoUI.Button \"▶ Run Taylor rule experiment 20 quarters \" begin run taylor Random.seed 42 Default calibration nb3 m default Bit.Model nb3 p, nb3 ic Bit.run nb3 m default, 20 Custom Taylor rule via parameter modification nb3 params custom deepcopy nb3 p nb3 params custom \"rho\" rho val nb3 params custom \"xi pi\" xi pi val nb3 params custom \"xi gamma\" xi gamma val Random.seed 42 nb3 m custom Bit.Model nb3 params custom, nb3 ic Bit.run nb3 m custom, 20 \"Taylor experiment complete ✓\" end begin run taylor nb3 p1 plot 0 20, nb3 m default.data.euribor . 100, label \"Calibrated rule\", lw 2, color steelblue, title \"Quarterly policy rate\", xlabel \"Quarter\", ylabel \"% per quarter\", plot nb3 p1, 0 20, nb3 m custom.data.euribor . 100, label \"Custom ρ rho val , ξᵖ xi pi val , ξᵞ xi gamma val \", lw 2, color tomato, ls dash nb3 p2 plot 0 20, nb3 m default.data.real gdp, label \"Default\", lw 2, color steelblue, title \"Real GDP\", xlabel \"Quarter\", plot nb3 p2, 0 20, nb3 m custom.data.real gdp, label \"Custom\", lw 2, color tomato, ls dash nb3 p3 plot 0 20, nb3 m default.data.nominal gdp . nb3 m default.data.real gdp, label \"Default\", lw 2, color steelblue, title \"GDP deflator\", xlabel \"Quarter\", plot nb3 p3, 0 20, nb3 m custom.data.nominal gdp . nb3 m custom.data.real gdp, label \"Custom\", lw 2, color tomato, ls dash plot nb3 p1, nb3 p2, nb3 p3, layout 1, 3 , size 900, 320 , legend bottomright end md\"\"\" Guided experiment first confirm the calibrated settings. The default and custom paths should coincide. Next change only ρ, then only ξπ, returning to the calibration between trials. Lower ρ reduces interest rate smoothing check the rate panel before interpreting GDP. Higher ξπ increases the response to euro area inflation, conditional on the lower bound. ξγ 0 removes the growth term it leaves the intercept, inflation response and smoothing. Record the quarterly rate difference in percentage points and the quarter 20 GDP difference in percent. One seed illustrates a mechanism repeat seeds before ranking policy rules. \"\"\" md\"\"\" Fiscal closure taxes, transfers, government purchases and interest payments enter the stock flow accounts. Accounting consistency tells us where a payment goes it does not by itself show that fiscal behaviour is empirically correct. These plots do not decompose taxes or government debt, so answering a fiscal question requires inspecting those series separately. \"\"\" md\"\"\" ✔ What you learned Persistent parameter changes differ from temporary shocks the model still draws other disturbances. A paired no change experiment should have zero effect. Seed each replicate and keep units explicit. Small ensembles can look nonlinear because of simulation noise a GDP path alone does not identify a cascade. The default AR 1 rule is learned and stochastic. Our alternative is scoped to a new model type. The Taylor rule reacts to euro area conditions, includes a real rate intercept and floors rates at zero. Exercises — predict, run, explain, check 03.1 — A diagnostic, not a result. Set the shock multiplier to 1.0 and confirm. Check all four panels. Why would independent unpaired simulations fail to give exact zero? Hint compare each baseline path with its own unchanged copy before averaging. 03.2 — Intervention timing. Compare productivity multipliers 0.95 and 0.90 at quarter 20. Is the larger effect twice the smaller one, within simulation precision? Check use the same seeds and increase paths before interpreting curvature. Explain why this is a persistent productivity change even though the hook mutates the parameter once. 03.3 — Policy closure. Set ξπ 0, leaving other coefficients calibrated. Before running, identify the external series the central bank now ignores. Check distinguish a GDP deflator level from an inflation rate and a quarterly rate from an annual rate. Do not infer a direct response to Austrian inflation. 03.4 — Two meanings of volatility. Run each expectation rule under at least eight seeds. Compute GDP's standard deviation across runs at quarter 20 , then compare it with the standard deviation over time within a run . They answer different questions. Hint `data.real gdp 21 ` is quarter 20 because index 1 is the initial observation. Report the seed count and avoid a universal ranking from one trajectory. 03.5 — Stretch a different monetary institution. Create a custom model type and specialise `Bit.central bank rate model YourModel `. Use domestic inflation in the rule, converting stored log inflation with `expm1`, and retain its intercept and zero lower bound. Check this changes the monetary closure it is no longer Austria taking the ECB rate as given. \"\"\" "},{"url":"notebooks/04_extensions_canvas/","title":"Extending the model: CANVAS","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.24 frontmatter order 5 title \"Extending the model CANVAS\" layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off return quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end md\"\"\" Notebook 04 — Extending the model CANVAS advanced Question how does a persistent increase in firms' wage norms propagate, and how do firms' price and quantity rules affect its transmission? Before running anything Predict the first direct effect household income, firms' wage costs, or both? Then distinguish an inflation rate from a permanently higher price level . The online page shows saved outputs run Pluto locally to change the controls. Lecture 2 slides covered Pricing mechanism CANVAS Demand pull mechanisms CANVAS pricing mechanism implicit assumptions Sectoral inflation decomposition Learning goals 1. Add model specific price and quantity decisions without replacing the base model's method. 2. Read the local demand price signals used in CANVAS. 3. Compare shock effects against each model's own matched baseline. 4. Distinguish channel isolation experiments from an additive causal decomposition. \"\"\" begin import Pkg Pkg.activate joinpath DIR , \"..\", \"..\", \"pluto tutorial\" io devnull import BeforeIT as Bit import Random using Plots, PlutoUI, Statistics, StatsPlots nb4 p Bit.AUSTRIA2010Q1.parameters nb4 ic Bit.AUSTRIA2010Q1.initial conditions end md\"\"\" 1 — BeforeIT's extension architecture BeforeIT uses Julia's multiple dispatch system to allow clean model extensions. The pattern is 1. Create a new model type inheriting from `Bit.AbstractModel`. 2. Define new method s for the function you want to override, specialised on your new type. 3. Julia automatically calls your method when the model is of your type. This is the \"open closed principle\" in action you extend behaviour without modifying the original source code. ```julia Step 1 new model type Bit. object mutable struct MyModel Bit.Model Bit.AbstractModel end Step 2 override a single function function Bit.firms expectations and decisions model MyModel your implementation here ... end Step 3 initialise fresh components with your type model MyModel w act, w inact, firms, bank, cb, gov, rotw, agg, prop, data Bit.run model, 1 calls your method, then records the quarter's outcomes ``` The tuple constructor performs the shared initialisation, including worker–firm assignment, balance sheets and the initial data point. For fresh components, calling the field constructor directly would skip those steps. `build canvas model` below uses the tuple constructor and then initialises CANVAS's planned supply field. \"\"\" md\"\"\" 2 — Read the CANVAS pricing equation P i t P i t 1 \\underbrace 1 \\phi^ DP \\pi i^d t \\text demand pull \\underbrace 1 \\phi^ CP \\pi i^c t \\text cost push \\underbrace 1 \\phi^ AE \\pi^e t \\text aggregate expectations . Each factor is a gross price multiplier. The channel signals are rates expressed as fractions a signal of 0.02 with a coefficient of 0.5 contributes a multiplier of 1.01. The product of the factors, not their sum, determines the price change. | Last demand versus planned supply | Firm price versus sector average | Adjustment | | | | | | Demand at least as high as supply | Below average | Price signal | | Demand at least as high as supply | At or above average | Output signal | | Demand below supply | At or above average | Price signal | | Demand below supply | Below average | Output signal | A coefficient of 1 applies the full computed channel signal it does not mean a 10% wage intervention becomes 10% inflation. A smaller coefficient attenuates that channel's direct effect. Its effect on persistence is a question for the model experiment, not a guaranteed consequence of the equation. \"\"\" md\"\"\" Information, timing and assumptions The firm compares its lagged realised demand with its planned supply and its own price with the sector average. Excess demand at a relatively low price signals scope to raise prices excess supply at a relatively high price signals a price cut. The other two quadrants adjust planned output. At equal demand and supply the adjustment signal is zero. Zero demand and zero supply states the relative demand signal cannot be used when supply is zero, and full pass through of a zero demand price signal would set the quote to zero. For either boundary, this teaching extension instead targets observed demand adjusted for expected growth and leaves the demand price multiplier at one. Zero demand therefore gives a zero quantity target positive demand restarts a firm that previously supplied nothing. Cost and expectation effects still apply. This is an explicit behavioural assumption it does not imply firm exit or override BeforeIT's minimum employment rule. Invalid quantities or nonpositive price quotes raise an error rather than propagating NaNs. The comparison with BeforeIT changes both pricing and quantity planning in positive price adjustment quadrants CANVAS retains previous planned supply, while BeforeIT targets previous demand. Differences between these models therefore reflect both mechanisms. This is a behavioural rule based on local information, not a derivation of optimal price setting. The experiment varies its coefficients by hand it does not estimate price stickiness or reproduce an empirical inflation decomposition. Check before coding changing a pricing method also affects production, profits, employment, expectations and later demand. Those feedbacks prevent a simple interpretation of each plotted line as an isolated direct price elasticity. \"\"\" md\"\"\" 3 — Implementing the CANVAS extension \"\"\" begin The CANVAS model lives in canvas model.jl so that this notebook and Notebook 05 share one definition instead of two copies that can drift. include joinpath DIR , \"..\", \"..\", \"pluto tutorial\", \"canvas model.jl\" \"CANVASModel, its pricing override and build canvas model loaded ✓\" end md\"\"\" 4 — Matched pass through experiments The intervention increases `firms.w bar i`, the firm specific wage norm , by 10% at quarter 1 and leaves it elevated. The model subsequently computes actual wages from this norm and production conditions actual wages and the aggregate wage bill need not rise by exactly 10%. Changing only `w i` at this hook would fail `set firms wages ` recomputes that field later in the same quarter. This is why understanding the step order matters when writing shocks. Compare each model's shocked path with its own unshocked baseline. Both model families use the same calibration and seeded replicate list changes to the pricing architecture can still alter later random number use. We run eight paths serially for a practical, reproducible default. Confirm the three coefficients together before rerunning. \"\"\" begin nb4 controls bind canvas settings PlutoUI.confirm PlutoUI.combine do Child md\"\"\" Demand pull ϕDP Child \"dp\", PlutoUI.Slider 0.0 0.1 1.0, default 1.0, show value true Cost push ϕCP Child \"cp\", PlutoUI.Slider 0.0 0.1 1.0, default 1.0, show value true Aggregate expectations ϕAE Child \"ae\", PlutoUI.Slider 0.0 0.1 1.0, default 1.0, show value true \"\"\" end phi dp canvas settings.dp phi cp canvas settings.cp phi ae canvas settings.ae nb4 controls end bind run canvas PlutoUI.Button \"▶ Run CANVAS comparison 16 quarters \" begin struct Nb4WageShock mult Float64 end function s Nb4WageShock model model.agg.t 1 && model.firms.w bar i . s.mult end function nb4 ensemble builder shock Bit.NoShock , seed 7, n 8, T 16 map 1 n do i Random.seed seed i Bit.run builder , T shock shock, parallel false end end ens field ens, field hcat getfield m.data, field for m in ens ... nb4 defl ens ens field ens, nominal gdp . ens field ens, real gdp nb4 infl d diff d, dims 1 . selectdim d, 1, 1 size d, 1 1 Exact price level gap. Its log is the cumulative difference in log inflation. nb4 price gap ens s, ens b 100 . nb4 defl ens s . nb4 defl ens b . 1 nb4 log gap ens s, ens b 100 . log. nb4 defl ens s . nb4 defl ens b The shared Ref is restored even if a simulation fails. function run isolated pair phi val shock Nb4WageShock 1.10 , seed 7, n 8, T 16 previous phi CANVAS PHI try CANVAS PHI phi val builder build canvas model nb4 p, nb4 ic ens b nb4 ensemble builder seed, n, T ens s nb4 ensemble builder shock, seed, n, T return ens b, ens s finally CANVAS PHI previous phi end end end begin run canvas wage shock Nb4WageShock 1.10 poledna builder Bit.Model nb4 p, nb4 ic ens poledna base nb4 ensemble poledna builder ens poledna shock nb4 ensemble poledna builder shock wage shock nb4 selected phi dp phi dp, cp phi cp, ae phi ae ens canvas base, ens canvas shock run isolated pair nb4 selected phi shock wage shock \"Matched CANVAS comparison complete ✓\" end begin run canvas p1 errorline 0 16, nb4 price gap ens poledna shock, ens poledna base errorstyle ribbon, errortype sem, label \"Poledna baseline pricing\", lw 2, color steelblue, title \"GDP deflator after a 10% wage norm increase\", xlabel \"Quarter\", ylabel \"Price level above own baseline % \" errorline p1, 0 16, nb4 price gap ens canvas shock, ens canvas base errorstyle ribbon, errortype sem, label \"CANVAS ϕDP phi dp , ϕCP phi cp , ϕAE phi ae \", lw 2, color tomato, ls dash hline p1, 0.0 color black, lw 1, label \"No effect\" p2 errorline 0 16, 100 . ens field ens poledna shock, real gdp . ens field ens poledna base, real gdp . 1 errorstyle ribbon, errortype sem, label \"Poledna\", lw 2, color steelblue, title \"Real GDP shock versus own baseline\", xlabel \"Quarter\", ylabel \"GDP change % \" errorline p2, 0 16, 100 . ens field ens canvas shock, real gdp . ens field ens canvas base, real gdp . 1 errorstyle ribbon, errortype sem, label \"CANVAS\", lw 2, color tomato, ls dash hline p2, 0.0 color black, lw 1, label \"No effect\" plot p1, p2 layout 1, 2 , size 900, 410 , legend topright end md\"\"\" Read these units a price level gap of 2 means the GDP deflator is 2% above that model's baseline. It does not mean inflation remains 2 percentage points higher every quarter. A flat positive gap means the price level stays higher while the additional inflation has ended. Ribbons show one Monte Carlo standard error of the mean paired effect, not uncertainty about estimated parameters. 5 — Channel isolation experiments For a fixed reference with all three coefficients equal to 1, activate one channel at a time and compare its wage intervention with its own baseline. This reference is independent of the sliders above it always means all three coefficients equal to 1 . The decomposition uses 100 × log price level ratio , exactly the cumulative difference in log inflation. Isolated experiments generally do not add up to the full response. The plotted remainder collects the non additivity of all feedbacks it is not a uniquely identified structural contribution or only a second order cross product in the price equation. This experiment alone does not establish bias in an empirical regression. \"\"\" bind run decomp PlutoUI.Button \"▶ Compare isolated channels and fixed full reference\" begin run decomp ens b dp, ens s dp run isolated pair dp 1.0, cp 0.0, ae 0.0 ens b cp, ens s cp run isolated pair dp 0.0, cp 1.0, ae 0.0 ens b ae, ens s ae run isolated pair dp 0.0, cp 0.0, ae 1.0 ens b full, ens s full run isolated pair dp 1.0, cp 1.0, ae 1.0 ei dp iso nb4 log gap ens s dp, ens b dp ei cp iso nb4 log gap ens s cp, ens b cp ei ae iso nb4 log gap ens s ae, ens b ae ei full nb4 log gap ens s full, ens b full ei interact ei full . ei dp iso . ei cp iso . ei ae iso assert isapprox ei full, ei dp iso . ei cp iso . ei ae iso . ei interact qs 0 16 p decomp errorline qs, ei dp iso errortype sem, lw 2, color tomato, ls dash, label \"Demand pull only\" errorline p decomp, qs, ei cp iso errortype sem, lw 2, color steelblue, ls dash, label \"Cost push only\" errorline p decomp, qs, ei ae iso errortype sem, lw 2, color goldenrod, ls dash, label \"Expectations only\" errorline p decomp, qs, ei interact errortype sem, lw 1, color grey, ls dot, label \"Non additivity remainder\" errorline p decomp, qs, ei full errortype sem, lw 3, color black, label \"All three coefficients 1\" hline p decomp, 0.0 lw 1, color grey, label \"No effect\" plot p decomp title \"Wage norm intervention channel isolation\", xlabel \"Quarter\", ylabel \"Cumulative log inflation difference 100 × log ratio \", legend topleft, size 850, 420 end md\"\"\" Interpretation checklist 1. All curves start at zero the intervention is applied after the initial observation. 2. Explain why raising wage norms changes both household income and firms' wage costs. 3. Compare a lower cost push coefficient with the full setting. Do not presume it lowers the total inflation response or increases persistence other channels can compensate. 4. The remainder is defined so the curves add up numerically. This identity checks the calculation, not the empirical validity of the channels. All coefficients here are chosen by hand. Notebook 05 introduces inference these runs are mechanism illustrations, not evidence about estimated Austrian or Dutch pass through. \"\"\" md\"\"\" ✔ What you learned Model type dispatch changes price and quantity rules while retaining the base model's method. CANVAS combines demand relative price signals with cost push and aggregate expectations. A wage norm intervention must survive the model's wage update step. Each treatment needs its own baseline price level gaps and inflation rate differences use different units. Channel isolation experiments include economy wide feedbacks, so they are not additive direct effect estimates. This notebook changes price and quantity decisions the upstream CANVAS example also changes monetary policy learning. Exercises — predict, run, explain, check 04.1 — A no intervention check. Replace `Nb4WageShock 1.10 ` with `Nb4WageShock 1.0 ` in the main comparison. What should both panels show? Check use the same seed list. Restore 1.10 afterward. This changes the main experiment the fixed channel isolation experiment separately constructs its 1.10 intervention. 04.2 — Price level versus inflation. Run the default comparison. Find a quarter where the price level gap is approximately flat. Is the inflation rate difference also large? Hint compute simple inflation with `nb4 infl nb4 defl ensemble `, then compare each shocked path with its own baseline. Multiply rate differences by 100 for percentage points. 04.3 — Turn off direct cost push. Set ϕCP 0, keep the other coefficients at 1, and confirm. Predict whether higher household income can still alter demand and prices. Check compare the full reference with the cost push only curve. Zeroing one pricing channel does not switch off wage payments or the other channels. 04.4 — Persistence without assuming it. Compare ϕAE 1 and ϕAE 0 with the same other settings. Record the quarter 16 price level gap and the quarterly inflation differences. Hint a higher terminal price level and persistent extra inflation are different claims. Repeat the seed list before drawing a general conclusion about expectation feedback. 04.5 — Interpret the remainder. Verify that the isolated curves plus the remainder recover the full reference curve. Explain why this arithmetic identity does not identify an empirical interaction coefficient or prove that a single equation estimate is biased. \"\"\" "},{"url":"notebooks/05_likelihood_free_calibration/","title":"Likelihood-free calibration: ABC, NPE, SNRE","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.24 Saved demo SHA256 5141b65e8e817f1df4a0675e9ca1fcea524a6be3a381ebf79b76d2e804006b88 frontmatter order 6 title \"Likelihood free calibration ABC, NPE, SNRE\" layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils This Pluto notebook uses bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of bind gives bound variables a default value instead of an error . macro bind def, element format off return quote local iv try Base.loaded modules Base.PkgId Base.UUID \"6e696c72 6542 2067 7265 42206c756150\" , \"AbstractPlutoDingetjes\" .Bonds.initial value catch b missing end local el esc element global esc def Core.applicable Base.get, el ? Base.get el iv el el end format on end md\"\"\" Notebook 05 — Likelihood free calibration advanced Question can inflation and GDP growth tell us how strongly CANVAS firms pass demand, cost and expectation changes into prices? Work through Notebook 04 first. Here, the pricing rule stays fixed and its three pass through coefficients become unknown. We use a known truth recovery experiment simulate observations at chosen coefficients, hide those coefficients from the estimator, and see what the data can recover. Route through the notebook 1. Define the unknown parameters, prior and observation protocol. 2. Build one simulator and generate a synthetic observation. 3. Use ABC to retain parameter draws that reproduce similar data. 4. Reuse simulated parameter–data pairs for NPE and NRE B . 5. Separate parameter recovery, inference diagnostics and model validation. The code runs one round of each neural method. The `sbi` engines also support sequential inference an optional exercise explains what a second round changes. Read online, run locally the website displays the explanations, code and saved figures from a real run of the default experiment the synthetic observation, ABC, NPE and NRE B. Simulations and training are disabled online changing controls requires opening the notebook locally. Follow the local setup guide https sghoekstra.github.io Behavioural Macro and Finance notebook05 , enable the environment below, then press the numbered buttons in order. First time Python setup may download packages subsequent stages can take several minutes depending on your computer. Before running predict which coefficient could be hardest to identify from two aggregate series. What would a broad posterior mean? \"\"\" begin import Pkg Pkg.activate joinpath DIR , \"..\", \"..\", \"pluto tutorial\" io devnull import BeforeIT as Bit using PlutoUI, Statistics, Distributions, LinearAlgebra, Random, Dates, JLD2, SHA end "},{"url":"notebooks/cheatsheet/","title":"BeforeIT cheatsheet","tags":["tutorial"],"text":" A Pluto.jl notebook v0.20.4 frontmatter title \"BeforeIT cheatsheet\" order 7 layout \"layout.jlhtml\" tags \"tutorial\" using Markdown using InteractiveUtils "}]