Skip to content

Commit

Permalink
Merge pull request #2 from davidakelley/revision
Browse files Browse the repository at this point in the history
Revision to "A Practitioner's Guide and Matlab Toolbox for Mixed Frequency State Space Models"
  • Loading branch information
davidakelley authored May 28, 2020
2 parents af62537 + 1897352 commit 6b92c97
Show file tree
Hide file tree
Showing 20 changed files with 331 additions and 40 deletions.
Binary file not shown.
31 changes: 24 additions & 7 deletions docs/user_guide.tex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
\documentclass{article}
\usepackage{amsmath}
\usepackage{color,textcomp}
\usepackage{color,textcomp,lmodern,listings}
\setlength\topmargin{0pt}
\addtolength\topmargin{-\headheight}
\addtolength\topmargin{-\headsep}
Expand All @@ -16,11 +16,17 @@

\begin{document}
\maketitle
\tableofcontents
\tableofcontents

\section{Introduction}

This document is designed to provide the technical details on how to use MFSS. It assumes that the reader is familiar with linear state space models and the mixed-frequency specification in ``A Practitioner's Guide and Matlab Toolbox for Mixed Frequency State Space Models''.

Code for each of the examples is included with MFSS in the \texttt{examples} folder. File names are provided with each example.

\section{Defining Accumulators}

MFSS supports two types of accumulators: sum and averages. For details on how these are set up, see ``A Practitioner's Guide and Matlab Toolbox for Mixed Frequency State Space Models''.
MFSS supports two types of accumulators: sums and averages. While ``triangle averages''

This section describes how to implement these accumulators with a model. To do so, set up the model (likely a \texttt{StateSpaceEstimation} or \texttt{MFVAR} object, but possibly a \texttt{StateSpace} object if all parameters are known) as if the data were observed at the base frequency, define an \texttt{Accumulator} object, and use the accumulator to augment the model to respect the mixed-frequency nature of the observe data.

Expand Down Expand Up @@ -67,7 +73,7 @@ \section{Examples}

These examples hopefully show how to use the toolbox more fully. For details on how to

\subsection{Example 1: Dynamic Factor Model}
\subsection{Dynamic Factor Model}

See \texttt{examples/pgmtmfss1\_dfm.m}.

Expand All @@ -81,7 +87,7 @@ \subsection{Example 1: Dynamic Factor Model}
\end{itemize}
The monthly series are normalized have a mean of zero and a standard deviation of one. Data retreived from FRED as of August 2, 2018. Identification requires a sign and scale normalization which is accomplished through setting the loading on GDP (in the $Z$ matrix) to 1.

\subsection{Example 2: Vector Autoregression}
\subsection{Vector Autoregression}

See \texttt{examples/pgmtmfss2\_var.m}.

Expand All @@ -94,7 +100,7 @@ \subsection{Example 2: Vector Autoregression}
\end{itemize}
For a monthly VAR, GDP is replaced by the log-level of All Employees: Total Nonfarm Payrolls. Data retrieved from FRED as of October 10, 2018.

\subsection{Example 3: Trend-Cycle Decomposition}
\subsection{Trend-Cycle Decomposition}

See \texttt{examples/pgmtmfss3\_trend\_cycle.m}.

Expand All @@ -117,7 +123,7 @@ \subsection{Example 3: Trend-Cycle Decomposition}
\end{align*}


\subsection{Example 4: Natural Rate of Interest}
\subsection{Natural Rate of Interest}

See \texttt{examples/pgmtmfss4\_r\_star.m}.

Expand Down Expand Up @@ -179,5 +185,16 @@ \subsection{Example 4: Natural Rate of Interest}
\end{align*}
where $\lambda_g$ and $\lambda_z$ are the ratio of variances set according to the Stock \& Watson median-unbiased treatment estimated by Laubach \& Williams, available at \texttt{https://www.newyorkfed.org/research/policy/rstar/overview}.


\subsection{Related Series Disaggregation}\label{sec:RSDisagg}

VARs can also be used in less structural applications. Here, we present an application where a related series may be used to interpolate the higher frequency movements of a series that is otherwise unavailable at a given frequency. This technique is particularly useful as a preparatory step in data analysis. For example, many price indexes for NIPA aggregates are only available at a quarterly frequency but relevant nominal activity indicators are available at a monthly frequency. To deflate the activity indicator, a related monthly price index can be used to disaggregate the quarterly price index and the estimated monthly price index can then be used to deflate the monthly activity variable.

For this application, we consider the weekly Freddie Mac Primary Mortgage Market Survey 30-year fixed rate. Each week, Freddie Mac collects a survey of the prevailing quoted rates of primary mortgage originators. This survey is circulated from Monday through Wednesday. Given the timing of when this survey is in the field, we consider the reported data to be the average of quoted rates on those three days.

To disaggregate this series into the equivalent daily series, we estimate a bivariate VAR(1) of the 10-year constant maturity Treasury yield the 30-year mortgage rate at a daily frequency. To handle the timing of the mortgage rate survey, observations of the mortgage rate are placed on the Wednesday and a nonstandard accumulator is defined such that each Wednesday observation is the average of the daily observations from Monday to Wednesday. The accumulator definition for Thursdays and Fridays is irrelevant since no data is ever observed on those days and is set to be the high-frequency estimate for simplicity. Since the VAR will be estimated in levels, the simple average accumulator is used and the horizon is set to one.


With the VAR coefficients estimated, the high frequency series can be obtained via the Kalman smoother. A comparison of the weekly series and estimated daily series over the course of the first quarter of 2020 are plotted in Figure \ref{fig:disagg}. The estimated daily series shows substantially more volatility than would be implied by univariate disaggregation methods while still respecting movements in the low frequency time series.

\end{document}
Binary file added examples/data_trade.mat
Binary file not shown.
Binary file added examples/data_var_disagg.mat
Binary file not shown.
File renamed without changes.
1 change: 1 addition & 0 deletions examples/pgmtmfss1_dfm.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

LB = ssE.ThetaMapping.LowerBound;
UB = ssE.ThetaMapping.UpperBound;
LB.Z(2:5,1) = 0;
LB.T(1,1) = -1;
UB.T(1,1) = 1;
ssE.ThetaMapping = ssE.ThetaMapping.addRestrictions(LB, UB);
Expand Down
2 changes: 1 addition & 1 deletion examples/pgmtmfss2_var.m → examples/pgmtmfss2_var_irf.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
% See Also:
% pgmtmfss_replication.m - Replication code runner script

load('data_var');
load('data_var_irf');

nSeries = 4;
varLagsQ = 2;
Expand Down
47 changes: 47 additions & 0 deletions examples/pgmtmfss3_var_disagg.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
% 2-variable VAR that generates a daily series from a weekly series
%
% The data in rateLevels and rateChanges are 2 time series:
% - The 10-Year Treasury Constant Maturity Rate
% - The 30-Year Fixed Rate Mortgage Average in the United States
% Data retrieved from FRED as of April 1, 2020.
%
% See Also:
% pgmtmfss_replication.m - Replication code runner script

load('data_var_disagg');

%% Code Example 3: Estimating a daily VAR weekly mortgage rate survey
Y = rateLevels;

% Set up accumulator
cal = [repmat([1; 2; 3; 1; 1;], size(Y,1)/5, 1); 1];
accum = Accumulator(2, cal, ones(size(cal)));

% Set up MFVAR object and estimate
mdl = MFVAR(Y, 1, accum);
mdlE = mdl.estimate();

% Get daily interest rate changes
alpha = mdlE.smooth(mdl.Y);


%% Plot time series of interest rates
% Make a plot of the spread using the daily mortgage rate and the weekly rate
% where the weekly rate is the average of Mon-Wed rate placed on Tuesday.
startInx = 9394;
rateDisaggRS = alpha(:,2);
rateDisaggNan = rateLevels(:,2);

figure('Color', ones(1,3));
plot(dates(startInx:end), rateDisaggRS(startInx:end), 'LineWidth', 2);
hold on;
plot(dates(startInx:end), rateDisaggNan(startInx:end), 'x', 'MarkerSize', 10);
box off;
datetick('x', 'keeplimits')
xlim([dates(startInx), dates(end)]);
legend('Related series disaggregation', 'Observed data', ...
'Location', 'sw', 'Orientation', 'vertical');
legend boxoff
ylabel('Percent');

print 'pgmtmfss3_var_disagg.png' -dpng
52 changes: 52 additions & 0 deletions examples/pgmtmfss3_vol.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
%
%

% See Also:
% pgmtmfss_replication.m - Replication code runner script

load('data_trade');

%% Code Example 3:
Y = log(data_diffl.^2);

% Set up accumulator
accum = Accumulator.GenerateFromDates(dates, 1, {'Month'}, {'avg'});

% Set up state space parameters
Z = ones(2,1);
d = nan(2,1);
H = diag(nan(2,1));
T = nan;
Q = nan;

% Set up MFVAR object with one lag and estimate coefficients
mdl = StateSpaceEstimation(Z, H, T, Q, 'd', d);
mdlA = accum.augmentStateSpaceEstimation(mdl);
mdlA.P0 = diag(Inf(2,1));

% Estimate parameters
mdlMLE = mdlA.estimate(Y);

% Get smoothed estimate of volatility parameter
alpha = mdlMLE.smooth(Y);
alphaSim = mdlMLE.smoothSample(Y, [], [], [], 100);
sigmaHat = exp(0.5 .* alpha(:,1));
sigmaHatDraws = squeeze(exp(0.5 .* alphaSim(:,1,:)));
sigmaHatBands = prctile(sigmaHatDraws, [5 95], 2);

%% Plot time series of estimated volatility
startInx = 1;

figure('Color', ones(1,3));
hold on
fill([dates(startInx:end); flipud(dates(startInx:end))], ...
[sigmaHatBands(startInx:end,1); flipud(sigmaHatBands(startInx:end,2))], ...
0.6 * ones(1,3), 'EdgeColor', 'none');
plot(dates(startInx:end), sigmaHat(startInx:end), ...
'LineWidth', 2, 'Color', [0 0.4470 0.7410]);
box off;
datetick('x', 'keeplimits')
ylabel('Estimated volatility');
xlim([dates(startInx)-15, dates(end)+15]);

print 'pgmtmfss3_vol.png' -dpng
File renamed without changes.
10 changes: 5 additions & 5 deletions examples/pgmtmfss4_r_star.m → examples/pgmtmfss5_r_star.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
lambda_z = 0.04195394;

%% Estimate the models
pgmtmfss4_r_star_quarterly
pgmtmfss4_r_star_monthly
pgmtmfss5_r_star_quarterly
pgmtmfss5_r_star_monthly

%% Decompose r* by data series that determine it
% Monthly model
Expand Down Expand Up @@ -65,7 +65,7 @@
plot(datesm(startPadM:end), plotDataM(startPadM:end,2:end), 'LineWidth', 1.5);
plot([datesm(startPadM), datesm(end)], [0 0], 'k', 'LineWidth', 0.25);
datetick('x');
xlim([datesm(8+startPadM), datesm(end)]);
xlim([datesm(startPadM), datesm(end)]);
title('Contributions to Monthly r*');
xticklabels([]);
ylabel('percent');
Expand All @@ -76,8 +76,8 @@
l2 = plot(datesq(startPadQ:end), plotDataQ(startPadQ:end,2:end), 'LineWidth', 1.5);
plot([datesq(startPadQ), datesq(end)], [0 0], 'k', 'LineWidth', 0.25);
datetick('x');
xlim([datesq(8+startPadQ), datesq(end)]);
xlim([datesq(startPadQ), datesq(end)]);
title('Contributions to Quarterly r*');
ylabel('percent');

print pgmtmfss4_rstar.png -dpng
print pgmtmfss5_rstar.png -dpng
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
%
% See Also:
% pgmtmfss_r_star.m - Mixed-frequency Laubach & Williams Natural Rate of Interest

%
%% Data
YM = [100*gdpM(27:end) inflationMA(27:end)];
XM = [inflationMA(26:end-1) (inflationMA(25:end-2)+inflationMA(24:end-3)+inflationMA(23:end-4))/3 ...
(inflationMA(22:end-5)+inflationMA(21:end-6)+inflationMA(20:end-7)+inflationMA(19:end-8))/4 ...
oilMA(26:end-1) importMA(27:end)];
endpos = 711;
YM = [100*gdpM(25:endpos) inflationMA(25:endpos)];
XM = [inflationMA(24:endpos-1) (inflationMA(23:endpos-2)+inflationMA(22:endpos-3)+inflationMA(21:endpos-4))/3 ...
(inflationMA(20:endpos-5)+inflationMA(19:endpos-6)+inflationMA(18:endpos-7)+inflationMA(17:endpos-8))/4 ...
oilMA(24:endpos-1) importMA(25:endpos)];
XM(isnan(XM)) = 0;
WM = [realrateM(26:end) realrateM(25:end-1)];
WM = [realrateM(24:endpos) realrateM(23:endpos-1)];

datesm = linspace((dates(8))-60, dates(end), size(YM,1))';
datesm = datenum([kron((1961:2017)',ones(12,1)); repmat(2018,3,1)],[repmat((1:12)',2017-1961+1,1); [1; 2; 3]],ones(size(YM,1),1));

%% Model
% The observed data is organized
Expand All @@ -26,7 +27,7 @@
% See Also:
% pgmtmfss_replication.m - Replication code runner script

syms a1 a2 a3 b1 b2 b3 b4 b5 c sigma2Ystar sigma2IS sigma2PC
syms a1 a2 a3 b1 b2 b3 b4 b5 c sigma2IS sigma2PC sigma2Ystar

Z = [0 0 1 0 zeros(1,5);
-b3 0 b3 0 zeros(1,5)];
Expand All @@ -41,8 +42,8 @@
gamma = [zeros(2); a3/2 a3/2; zeros(6,2)];
R = [1 0 0 0; zeros(1,4);
1 0 1 0 ; zeros(1,4);
0 lambda_g/3 0 0; zeros(1,4);
0 0 0 lambda_z/(3*a3); zeros(1,4);
0 lambda_g 0 0; zeros(1,4);
0 0 0 lambda_z/a3; zeros(1,4);
zeros(1,4)];
Q = diag([sigma2Ystar sigma2Ystar sigma2IS sigma2IS]);

Expand All @@ -58,7 +59,7 @@

%% Initial state
interpGDP = interp1(3:3:size(gdpM,1), gdpM(3:3:end), 1:size(gdpM))';
lagGDP = 100*interpGDP(25:26)';
lagGDP = 100*interpGDP(23:24)';
gInit = 0.9394933/3;
ystarInit = [809.7823659 809.7823659-gInit];
rstarInit = 12*gInit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
% The exogenous series in the measurement equation are
% [GDP_t-1 GDP_t-2 r_t-1 r_t-2 pi_t-1 avg1(pi)_t avg2(pi)_t oil_t-1 import_t]'

syms a1 a2 a3 b1 b2 b3 b4 b5 c sigma2Ystar sigma2IS sigma2PC
syms a1 a2 a3 b1 b2 b3 b4 b5 c sigma2IS sigma2PC sigma2Ystar

Z = [ 1 -a1 -a2 -c*a3*2 -c*a3*2 -a3/2 -a3/2 0;
0 -b3 0 0 0 0 0 0];
Expand Down
16 changes: 10 additions & 6 deletions examples/pgmtmfss_replication.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
% Replication code for A Practitioner’s Guide and Matlab Toolbox for Mixed Frequency
% State Space Models by Scott A. Brave, R. Andrew Butters and David Kelley.
% Replication code for A Practitioner’s Guide and Matlab Toolbox for Mixed
% Frequency State Space Models by Scott A. Brave, R. Andrew Butters and
% David Kelley.
%
% To replicate the figures in the paper, run this file.

%% Install the toolbox
%% Check that the toolbox is installed
assert(exist('StateSpaceEstimation.m', 'file') == 2, ...
'MFSS toolbox not installed.');

Expand All @@ -12,10 +13,13 @@
pgmtmfss1_dfm

clear
pgmtmfss2_var
pgmtmfss2_var_irf

clear
pgmtmfss3_trend_cycle
pgmtmfss3_vol

clear
pgmtmfss4_r_star
pgmtmfss4_trend_cycle

clear
pgmtmfss5_r_star
File renamed without changes.
File renamed without changes.
47 changes: 47 additions & 0 deletions examples/ug_var_disagg.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
% 2-variable VAR that generates a daily series from a weekly series
%
% The data in rateLevels and rateChanges are 2 time series:
% - The 10-Year Treasury Constant Maturity Rate
% - The 30-Year Fixed Rate Mortgage Average in the United States
% Data retrieved from FRED as of April 1, 2020.
%
% See Also:
% pgmtmfss_replication.m - Replication code runner script

load('data_var_disagg');

%% Code Example 3: Estimating a daily VAR weekly mortgage rate survey
Y = rateLevels;

% Set up accumulator
calendar = [repmat([1; 2; 3; 1; 1;], size(Y,1)/5, 1); 1];
accum = Accumulator(2, calendar, ones(size(calendar)));

% Set up MFVAR object with one lag and estimate coefficients
mdl = MFVAR(Y, 1, accum);
mdlE = mdl.estimate();

% Get daily interest rate changes
alpha = mdlE.smooth(mdl.Y);


%% Plot time series of interest rates
% Make a plot of the spread using the daily mortgage rate and the weekly rate
% where the weekly rate is the average of Mon-Wed rate placed on Tuesday.
startInx = 9394;
rateDisaggRS = alpha(:,2);
rateDisaggNan = rateLevels(:,2);

figure('Color', ones(1,3));
plot(dates(startInx:end), rateDisaggRS(startInx:end), 'LineWidth', 2);
hold on;
plot(dates(startInx:end), rateDisaggNan(startInx:end), 'x', 'MarkerSize', 10);
box off;
datetick('x', 'keeplimits')
xlim([dates(startInx), dates(end)]);
legend('Related series disaggregation', 'Observed data', ...
'Location', 'sw', 'Orientation', 'vertical');
legend boxoff
ylabel('Percent');

print 'pgmtmfss3_var_disagg.png' -dpng
Loading

0 comments on commit 6b92c97

Please sign in to comment.