function result = tvp_markov(y,x,parm,info) % PURPOSE: time-varying parameter model with Markov switching error variances % y(t) = X(t)*B(t) + e(t), e(t) = N(0,R_S1t) % B(t) = B(t-1) + v(t), v(t) = N(0,Q_S2t) % Q_S2t = Q1*a1,1t + Q2*a2,1t + Q3*a3,1t + Q4*a4,1t + ... + Sm*am,1t % R_S1t = R1*b1,1t + R2*b2,2t + R3*b3,2t + R4*b4,2t + ... + Rm*bm,2t % where: ak,jt = 1 if S_kt = j, ak,jt = 0 if S_kt ~= j % k=1,2 j=1,...,m % S_1t, S_2t evolve according to a 1st-order Markov process % ------------------------------------------------------------------- % USAGE: result = tvp_markov(y,x,parm,info); % or: result = tvp(y,x,parm); for default options % where: y = dependent variable vector % x = explanatory variable matrix % parm = (k+4)x1 vector of starting values % parm(1,1) = p, Pr[St=1 | St-1=1] % parm(2,1) = q, Pr[St=0 | St-1=0] % parm(3:3+k-1,1) = diagonal transition equation std deviations % parm(3+k,1) = noise std deviation in state 1 % parm(4+k,1) = noise std deviation in state 2 % info = a structure variable containing optimization options % info.b0 = a (kx1) vector with initial period B0 (default: zeros(k,1)) % info.v0 = a (kxk) matrix with initial period std(B0) % (default = eye(k)*1e+3, a relatively diffuse prior) % info.start = starting observation (default: 1) % --- optimization options --- % info.prt = 1 for printing basic intermediate results (default = 0) % = 2 for printing detailed stuff % info.delta = Increment in numerical derivs [.000001] % info.hess = Hessian method: ['dfp'], 'bfgs', 'gn', 'marq', 'sd' % info.maxit = Maximium iterations [100] % info.lamda = Minimum eigenvalue of Hessian for Marquardt [.01] % info.cond = Tolerance level for condition of Hessian [1000] % info.btol = Tolerance for convergence of parm vector [1e-4] % info.ftol = Tolerance for convergence of objective function [sqrt(eps)] % info.gtol = Tolerance for convergence of gradient [sqrt(eps)] % ------------------------------------------------------------------- % NOTES: only works for a 2-state model, i.e., m=2 (see above) % therefore the x-matrix should not contain lagged dependent variables % ------------------------------------------------------------------- % RETURNS: a result structure % result.meth = 'tvp_markov' % result.parm = (k+4) x 1 vector of ML parameter estimates % result.vcov = (k+4,k+4) matrix with variance-covariance of the ML estimates % result.stdhat = (k+4) x 1 vector with std deviation of estimates % result.prob1 = (start:n x 1) vector with probability of state 1 % result.prob2 = (start:n x 1) vector with probability of state 2 % result.tstat = a (k+4) x 1 vector of t-stats based on vcov % result.beta1 = an (start:n x k) matrix of time-varying beta hats for state 1 % result.beta2 = an (start:n x k) matrix of time-varying beta hats for state 2 % result.bvar1 = an (start:n x kxk) matrix of time-varying variances for beta1 % result.bvar2 = an (start:n x kxk) matrix of time-varying variances for beta2 % result.fvar = an (start:n x 2) conditional variance decompostion % column1 = forecast error variance due to beta variation, % column2 = forecast error variance due to heteroscedasticity % result.rsqr = R-squared, based on yhat(start:n) % result.rbar = R-bar squared, based on yhat(start:n) % result.yhat = (start:n x 1) vector of proability weigthed predicted values % result.y = (nx1) vector of actual values % result.like = log likelihood (at solution values) % result.iter = # of iterations taken % result.start = # of starting observation % result.time = time (in seconds) for solution % ------------------------------------------------------------------- % NOTE: to generate tvp betas, probs, etc., based on max-lik parm vector use: % [p0s,p1s,b0s,b1s,v0s,v1s,yhat] = tvp_markov_filter(parm,y,x,b0,v0) % ------------------------------------------------------------------- % SEE ALSO: prt(), plt(), prt_tvp, plt_tvp, tvp_markov_like, tvp_markov_like % ------------------------------------------------------------------- % REFERENCES: Kim and Nelson (1999) % State-Space Models with Regime Switching % ------------------------------------------------------------------- % James P. LeSage, Dept of Economics % University of Toledo % 2801 W. Bancroft St, % Toledo, OH 43606 % jlesage@spatial-econometrics.com [n k] = size(x); IK = eye(k); % default initial values priorb0 = zeros(k,1); priorv0 = IK*1000; infoz.maxit = 500; % default optimization options start = 1; if nargin == 4 % we need to reset optimization defaults if ~isstruct(info) error('tvp: optimization options should be in a structure variable'); end; % parse options fields = fieldnames(info); nf = length(fields); for i=1:nf if strcmp(fields{i},'maxit') infoz.maxit = info.maxit; elseif strcmp(fields{i},'btol') infoz.btol = info.btol; elseif strcmp(fields{i},'ftol') infoz.ftol = info.ftol; elseif strcmp(fields{i},'gtol') infoz.gtol = info.gtol; elseif strcmp(fields{i},'hess') infoz.hess = info.hess; elseif strcmp(fields{i},'cond') infoz.cond = info.cond; elseif strcmp(fields{i},'prt') infoz.prt = info.prt; elseif strcmp(fields{i},'delta') infoz.delta = info.delta; elseif strcmp(fields{i},'lamda') infoz.lambda = info.lamda; elseif strcmp(fields{i},'start') start = info.start; elseif strcmp(fields{i},'b0') priorb0 = info.b0; elseif strcmp(fields{i},'v0') priorv0 = info.v0; end; end; end; b0 = priorb0; v0 = priorv0; if length(parm) ~= 3+k+1 error('tvp_markov: Wrong # of initial parameter values entered'); end; oresult = maxlik('tvp_markov_lik',parm,infoz,y,x,start,b0,v0); niter = oresult.iter; like = -oresult.f; vcov = inv(oresult.hess); time = oresult.time; parm1 = abs(oresult.b); % compute numerical hessian at the solution cov0 = inv(fdhess('tvp_markov_lik',parm1,y,x,start,b0,v0)); grad = fdjac('ham_trans',parm1); vcov = grad*cov0*grad'; stdhat = sqrt(diag(vcov)); result2 = tvp_markov_filter(parm1,y,x,start,b0,v0); % transform parameters parm = ham_trans(parm1); tstat = parm./stdhat; yhat = result2.yhat; resid = y(start:n,1) - yhat; sigu = resid'*resid; ym = y(start:n,1) - mean(y(start:n,1)); rsqr1 = sigu; rsqr2 = ym'*ym; result.rsqr = 1.0 - rsqr1/rsqr2; % r-squared rsqr1 = rsqr1/(n-k-start); rsqr2 = rsqr2/(n-1.0); result.rbar = 1 - (rsqr1/rsqr2); % rbar-squared stdhat = sqrt(diag(vcov)); tstat = parm1./stdhat; % return results structure information result.parm = parm; result.prob1 = result2.p0; result.prob2 = result2.p1; result.beta1 = result2.b0; result.beta2 = result2.b1; result.bvar1 = result2.v0; result.bvar2 = result2.v1; result.fvar = result2.fvar; result.vcov = vcov; result.stdhat = stdhat; result.tstat = tstat; result.yhat = yhat; result.y = y; result.resid = resid; result.like = like; result.time = time; result.nobs = n; result.nvar = k; result.iter = niter; result.meth = 'tvp_markov'; result.start = start; function result = tvp_markov_filter(parm,y,x,start,b0,v0) % PURPOSE: Kalman filtering for Markov-switching TVP model % y(t) = X(t)*B(t) + e(t), e(t) = N(0,R_S1t) % B(t) = B(t-1) + v(t), v(t) = N(0,Q_S2t) % Q_S2t = Q1*a1,1t + Q2*a2,1t + Q3*a3,1t + Q4*a4,1t + ... + Sm*am,1t % R_S1t = R1*b1,1t + R2*b2,2t + R3*b3,2t + R4*b4,2t + ... + Rm*bm,2t % where: ak,jt = 1 if S_kt = j, ak,jt = 0 if S_kt ~= j % k=1,2 j=1,...,m % S_1t, S_2t evolve according to a 1st-order Markov process % ------------------------------------------------- % USAGE: result = tvp_markov_filter(parm,y,x,start,b0,v0) % where: parm = a vector with ML parameter estimates % parm(1,1) = p, Pr[St=1 | St-1=1] % parm(2,1) = q, Pr[St=0 | St-1=0] % parm(3:3+k-1,1) = diagonal transition equation variance % parm(3+k,1) = noise std in state 1 % parm(3+k+1,1) = noise std in state 2 % y = dependent variable (nx1) vector % x = (nxk) matrix of explanatory variables % start = starting observation (default: 1) % b0 = prior b0 (default: diffuse = 0) % v0 = prior v0 (default: diffuse = 1000) % ------------------------------------------------- % NOTES: 1) the filter starts at obs=1, but only returns information % from start onward % 2) only works for a 2-state model, i.e., m=2 (see above) % therefore the x-matrix should not contain lagged dependent variables % ------------------------------------------------- % RETURNS: result = a structure variable with fields: % result.p0 = (start:n x 1) probabilities for state0 % result.p1 = (start:n x 1) probabilities for state1 % result.b0 = (start:n x k) state0 TVP estimates % result.b1 = (start:n x k) state1 TVP estimates % result.v0 = (start:n x kxk) state0 TVP variances % result.v1 = (start:n x kxk) state1 TVP variances % result.yhat = (start:n x 1) predicted values based on probabilities % yhat(i,1) = x(t,:)*b0*prob0 + x(t,:)*b1*prob1; % result.fvar = (start:n x 2) vector with forecast error variance % decomposition. Column 1 = conditional variance due to changing beta % Column 2 = conditional variance due to heterscedasticity % Column 1 = x_t-1 *P_t|t-1 x'_t-1, % where: P_t|t_1 = probability weighted sum over both states, % Column 2 = sig = probability weighted sum over both states, % % ------------------------------------------------- % James P. LeSage, Dept of Economics % University of Toledo % 2801 W. Bancroft St, % Toledo, OH 43606 % jlesage@spatial-econometrics.com [n k] = size(x); IK = eye(k); if nargin == 3 priorb0 = zeros(k,1); priorv0 = IK*1000; start = 1; elseif nargin == 4 priorb0 = zeros(k,1); priorv0 = IK*1000; elseif nargin == 6 priorb0 = b0; priorv0 = v0; else error('tvp_markov_filter: Wrong # of arguments'); end; parm = ham_trans(parm); % 1/(1+exp(-parm)) ppr = parm(1,1); % Pr[St=1 | St-1=1] qpr = parm(2,1); % Pr[St=0 | St-1=0] aa = eye(k); prob1 = (1-qpr)/(2-ppr-qpr); % Pr[St-1=1 | Yt-1], STEADY STATE PROB prob0 = 1-prob1; % Pr[ST-1=0 | Yt-1], STEADY STATE PROB b0 = priorb0; b1 = b0; v0 = priorv0; v1 = v0; tmp = parm(3:3+k-1,1); % transition equation std deviations tmp2 = tmp.*tmp; qq = diag(tmp2); sig0 = parm(3+k,1); sig1 = parm(3+k+1,1); like = 0; % storage for return values fcast = zeros(n,1); b0s = zeros(n,k); b1s = zeros(n,k); v0s = zeros(n,k,k); v1s = zeros(n,k,k); p0s = zeros(n,1); p1s = zeros(n,1); fvar = zeros(n,2); for i=1:n; H = x(i,:); % prediction postb00 = aa*b0; % for St-1 = 0, St = 0 postb01 = aa*b0; % for St-1 = 0, St = 1 postb10 = aa*b1; % for St-1 = 1, St = 0 postb11 = aa*b1; % for St-1 = 1, St = 1 postv00 = aa*v0*aa' + qq; postv01 = aa*v0*aa' + qq; postv10 = aa*v1*aa' + qq; postv11 = aa*v1*aa' + qq; fcast00 = y(i,1) - H*postb00; fcast01 = y(i,1) - H*postb01; fcast10 = y(i,1) - H*postb10; fcast11 = y(i,1) - H*postb11; ss00 = H*postv00*H' + sig0*sig0; ss01 = H*postv01*H' + sig1*sig1; ss10 = H*postv10*H' + sig0*sig0; ss11 = H*postv11*H' + sig1*sig1; % DEBUG if (ss00 <= 0 | ss01 <= 0 | ss10 <= 0 | ss11 <= 0) [ss00 ss01 ss10 ss11] pause; end; kg00 = postv00*H' / ss00; kg01 = postv01*H' / ss01; kg10 = postv10*H' / ss10; kg11 = postv11*H' / ss11; b00 = postb00 + kg00*fcast00; b01 = postb01 + kg01*fcast01; b10 = postb10 + kg10*fcast10; b11 = postb11 + kg11*fcast11; v00 = (IK - kg00*H)*postv00; v01 = (IK - kg01*H)*postv01; v10 = (IK - kg10*H)*postv10; v11 = (IK - kg11*H)*postv11; prv00 = vprob(fcast00,ss00)*qpr*prob0; % pr[St, Yt | Yt-1] prv01 = vprob(fcast01,ss01)*(1-qpr)*prob0; prv10 = vprob(fcast10,ss10)*(1-ppr)*prob1; prv11 = vprob(fcast11,ss11)*ppr*prob1; % step 3 denominator prval = prv00+prv01+prv10+prv11; % pr[Yt | Yt-1] % step 3 pr00 = prv00/prval; pr01 = prv01/prval; pr10 = prv10/prval; pr11 = prv11/prval; % step 4 prob0 = pr00 + pr10; % pr[St=0 | Yt] prob1 = pr01 + pr11; % pr[St=1 | Yt] % avoid division by zero in cases % where all probability weight gets placed on one state if prob0 == 0 prob0 = 0.001; elseif prob0 == 1 prob0 = 0.999; end; if prob1 == 0 prob1 = 0.001; elseif prob1 == 1 prob1 = 0.999; end; % collapse terms eq 2.13' from Kim's article b0 = (pr00*b00 + pr10*b10)/prob0; b1 = (pr10*b10 + pr11*b11)/prob1; % eq 2.14' v0 = (pr00*(v00+(b0-b00)*(b0-b00)') ... +pr10*(v10+(b0-b10)*(b0-b10)'))/prob0; v1 = (pr01*(v01+(b1-b01)*(b1-b01)') ... +pr11*(v11+(b1-b11)*(b1-b11)'))/prob1; % compute forecast error decomposition % see page 119 Kim-Nelson fvar(i,1) = prob0*H*postv00*H' + prob1*H*postv11*H'; fvar(i,2) = fvar(i,1) + sig0*sig0*prob0 + sig1*sig1*prob1; b0s(i,:) = b0'; b1s(i,:) = b1'; fcast(i,1) = H*b0*prob0 + H*b1*prob1; p0s(i,1) = prob0; p1s(i,1) = prob1; v0s(i,:,:) = v0; v1s(i,:,:) = v1; end; % end of loop over observations result.b0 = b0s(start:n,:); result.b1 = b1s(start:n,:); result.yhat = fcast(start:n,1); result.p0 = p0s(start:n,1); result.p1 = p1s(start:n,1); result.v0 = v0s(start:n,1); result.v1 = v1s(start:n,1); result.fvar = fvar(start:n,:);