-
Notifications
You must be signed in to change notification settings - Fork 6
/
shadowrateABCdraws.m
124 lines (86 loc) · 3.9 KB
/
shadowrateABCdraws.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
function Xdraws = shadowrateABCdraws(A, B, C, Ydata, yNaNndx, X0, sqrtSigma, Ndraws, rndStream)
% SHADOWRATEABCDRAW
% ....
% Coded by Elmar Mertens, em@elmarmertens.com
%% parse inputs
Nx = size(A, 1);
[Ny, T] = size(Ydata);
Ydata = permute(Ydata, [1 3 2]);
Nw = size(B,2);
if nargin < 8 || isempty(Ndraws)
Ndraws = 1;
end
if nargin < 9 || isempty(rndStream)
rndStream = getDefaultStream;
end
%% init Variables and allocate memory
I = eye(Nx);
yDataNdx = ~yNaNndx;
%% allocate memory
[Sigmattm1, ImKC] = deal(zeros(Nx, Nx, T));
invSigmaYttm1 = zeros(Ny, Ny, T);
Ytilde = zeros(Ny, 1, T);
Yplustilde = zeros(Ny, Ndraws, T);
[XtT, Xttm1] = deal(zeros(Nx, 1, T));
[Xplus, XplustT, Xplusttm1] = deal(zeros(Nx, Ndraws, T));
%% generate plus data
wplus = randn(rndStream, Nw, Ndraws, T);
X0plus = repmat(X0, [1 Ndraws]); % redundant given Matlab's implict matrix expansion since 2016a
%% Forward Loop: Kalman Forecasts
Sigmatt = zeros(Nx,Nx);
Xtt = X0;
Xplustt = repmat(X0, 1, Ndraws);
disturbanceplus = zeros(Nx, Ndraws, T);
for t = 1 : T
% "plus" States and priors
Bsv = B * diag(sqrtSigma(:,t));
disturbanceplus(:,:,t) = Bsv * wplus(:,:,t);
BSigmaB = Bsv * Bsv';
if t == 1
% Xplus(:,:,t) = A * X0plus + disturbanceplus(:,:,t);
Xlagplus = X0plus;
else
% Xplus(:,:,t) = A * Xplus(:,:,t-1) + disturbanceplus(:,:,t);
Xlagplus = Xplus(:,:,t-1);
end
Xplus(:,:,t) = A * Xlagplus + disturbanceplus(:,:,t);
% priors
Sigmattm1(:,:,t) = A * Sigmatt * A' + BSigmaB;
Xttm1(:,:,t) = A * Xtt;
Xplusttm1(:,:,t) = A * Xplustt;
% observed innovation
Yplus = C(:,:,t) * Xplus(:,:,t);
SigmaYttm1 = C(:,:,t) * Sigmattm1(:,:,t) * C(:,:,t)';
Ytilde(:,:,t) = Ydata(:,:,t) - C(:,:,t) * Xttm1(:,:,t);
Yplustilde(:,:,t) = Yplus - C(:,:,t) * Xplusttm1(:,:,t);
% Block Inverse of Y-VCV, accounting for missing obs (with zero VCV)
invSigmaYttm1(yDataNdx(:,t),yDataNdx(:,t),t) = eye(sum(yDataNdx(:,t))) / SigmaYttm1(yDataNdx(:,t),yDataNdx(:,t));
% test whether pos def
% omega = SigmaYttm1(yDataNdx(:,t),yDataNdx(:,t));
% [~, pd] = chol(omega);
% if ~pd
% warning('SigmaY not p.d. max/min eig: %e / %e', max(eig(omega)), min(eig(omega)))
% end
% Kalman Gain
K = (Sigmattm1(:,:,t) * C(:,:,t)') * invSigmaYttm1(:,:,t);
ImKC(:,:,t) = I - K * C(:,:,t);
% posteriors
Sigmatt = ImKC(:,:,t) * Sigmattm1(:,:,t) * ImKC(:,:,t)'; % Joseph form for better numerical stability
Xtt = Xttm1(:,:,t) + K * Ytilde(:,:,t);
Xplustt = Xplusttm1(:,:,t) + K * Yplustilde(:,:,t);
end
%% Backward Loop: Disturbance Smoother
XplustT(:,:,T) = Xplustt;
XtT(:,T) = Xtt;
StT = C(:,:,T)' * (invSigmaYttm1(:,:,T) * Ytilde(:,T));
SplustT = C(:,:,T)' * (invSigmaYttm1(:,:,T) * Yplustilde(:,:,T));
for t = (T-1) : -1 : 1
Atilde = A * ImKC(:,:,t);
StT = Atilde' * StT + C(:,:,t)' * (invSigmaYttm1(:,:,t) * Ytilde(:,:,t));
XtT(:,:,t) = Xttm1(:,:,t) + Sigmattm1(:,:,t) * StT;
SplustT = Atilde' * SplustT + C(:,:,t)' * (invSigmaYttm1(:,:,t) * Yplustilde(:,:,t));
XplustT(:,:,t) = Xplusttm1(:,:,t) + Sigmattm1(:,:,t) * SplustT;
end
%% sample everything together (and reorder output dimensions)
Xdraws = XtT - XplustT + Xplus; % bsxfun(@minus, XtT, XplustT) + Xplus;
Xdraws = permute(Xdraws, [1 3 2]);