Enter time-varying coefficient matrices by using functions

Discussion of State Space and Dynamic Stochastic General Equilibrium Models
jonasdovern
Posts: 97
Joined: Sat Apr 11, 2009 10:30 am

Enter time-varying coefficient matrices by using functions

Unread post by jonasdovern »

Hi,
I have a question on how I should enter time-varying coefficient matrices in a DLM using functions. What I want to estimate are the states in a multivariate SSM with a vector of observables, a vector of states and time-varying coefficient matrices (that I estimate previous to running the KF).
In the code shown below, I get an error message as RATS doesn't seem to like the function expressions in the DLM-command (allthough they seem to work fine when just printing the matrices for a specific time period).

Code: Select all

function afunc A reset beta_q time
	type vec[rec] 	A
	type series	  	reset
	type vector		beta_q
	type integer  	time
	type rect	  	afunc
	local integer k i j
	local rec temp
	*
	dim afunc(%rows(A)*%rows(A(1))+2,%rows(A)*%rows(A(1))+2)
	comp afunc = %const(0.0)
	do k=1,%rows(A)
		do i=1,%rows(A(1))
			do j=1,%cols(A(1))
				comp afunc(i,(k-1)*%rows(A(1))+j) = A(k)(i,j)
			end do j
		end do i
		if k>1 {
			do i=1,%rows(A(1))
				do j=1,%cols(A(1))
					comp afunc((k-1)*%rows(A(1))+i,(k-2)*%rows(A(1))+j) = i==j
				end do j
			end do i
		}
		do i=1,%cols(A(1))
			comp temp = tr(beta_q)*%xsubmat(A(k),1,%rows(A(k)),i,i)
			comp afunc(%rows(afunc)-1,(k-1)*%rows(A(1))+i) = temp(1,1)
			comp afunc(%rows(afunc),(k-1)*%rows(A(1))+i) = temp(1,1)
		end do i
	end do k
	comp afunc(%rows(afunc),%cols(afunc)) = reset(time)
end function afunc
*
function yfunc monthly quarterly time
	type vec[int]	monthly
	type series		quarterly
	type integer	time
	type vec		yfunc
    local integer	k
	*
	dim yfunc(%rows(monthly)+1)
	do k=1,%rows(monthly)
		comp yfunc(k) = ([series] monthly(k))(time)
	end do k
	comp yfunc(%rows(yfunc)) = quarterly(time)
end function yfunc
*
function cfunc Lambda p
	type rec 		Lambda
	type integer	p
	type rec 		cfunc
	local integer	i j
	*
	dim cfunc(%rows(Lambda)+1,%cols(Lambda)*p+2)
	comp cfunc = %const(0.0)
	do i=1,%rows(Lambda)
		do j=1,%cols(Lambda)
			comp cfunc(i,j) = Lambda(i,j)
		end do j
	end do i
	comp cfunc(%rows(cfunc),%cols(cfunc)) = 1
	comp cfunc = tr(cfunc)
end function cfunc
*
function zfunc mu_q r p
	type real 	mu_q
	type int	r
	type int	p
	type vect	zfunc
	*
	comp zfunc = %zeros(r*p+2,1)
	comp zfunc(%rows(zfunc)-1) = (1./3)*mu_q
	comp zfunc(%rows(zfunc)) = (1./3)*mu_q
end function zfunc
*
function ffunc B p
	type rect	B
	type int	p
	type rec	ffunc
	*
	comp ffunc = B~~%zeros(%rows(B)*(p-1)+2,%cols(B))
end function ffunc


PROCEDURE NOWCAST QUARTERLY START END
	*
	type series	quarterly
	type int		start end
	*
	option choice	method	1 factor
	option switch	print 	0
	option switch	intres	0
	option switch	graph	0
	option integer	fsteps 	0
	option integer	ftime
	option integer	p		1; * lag order for factor VAR
	option integer	r		3; * number of factors
	option integer	q		2; * number of shocks
	*
	local integer	nind lstart lend i time
	local vec[int]	monthly
	local real		mu_q Sigma_q
	local vec[rea]	mu beta_q
	local rec[rea]	z x D V F Lambda Psi Sigma B
	local vec[rec]	A
	local vec[ser]	F_q F_m
	local series	reset
	local vec[str]	F_lab
	local ser[vec]	st_vec
	local ser[sym]	st_var
	*
	if method==1 {
      *
      * Here follows some other code...
		*
		*----------------------------------------------------------------------------------------------
		* Implementation of Kalman filter
		if intres; disp "ESTIMATES OF THE VARIOUS MATRICES SUCCESSFULLY ESTIMATED! GOING ON WITH KALMAN FILTER..."
		*
		* The state vector, kf_X_t, includes the following [f_t f_t-1 ... f_t-p+1 y_hat y_hat_q]'
		* The vector of observables, kf_Y_t, includes the following [z1_t z2_t ... zn_t y_q]'
		* The matrix that relates the state vector to the observables, kf_c, is constant and includes the factor loadings
		* The transition matrix for the state vector, kf_A_t, includes the coefficients from the factor VAR, beta_q, and an indicator to "re-set" the quarterly series (y_hat_q)
		* The shift vector for the state, kf_z, includes the unconditional mean of y_q

		set reset lstart lend = %mod(t,3)<>1

		*disp yfunc(monthly,quarterly,lend)
		disp afunc(A,reset,beta_q,lend) 
		*disp cfunc(Lambda,p) 
		*disp zfunc(mu_q,r,p) 
		*disp ffunc(B,p) 
                * Checking dimensions of the matrices
		if intres; disp "kf_Y:" @10 %rows(yfunc(monthly,quarterly,lend)) "by" %cols(yfunc(monthly,quarterly,lend))
		if intres; disp "kf_A:" @10 %rows(afunc(A,reset,beta_q,lend)) "by" %cols(afunc(A,reset,beta_q,lend))
		if intres; disp "kf_c:" @10 %rows(cfunc(Lambda,p)) "by" %cols(cfunc(Lambda,p))
		if intres; disp "kf_Z:" @10 %rows(zfunc(mu_q,r,p)) "by" %cols(zfunc(mu_q,r,p))
		if intres; disp "kf_F:" @10 %rows(ffunc(B,p)) "by" %cols(ffunc(B,p))


		* Estimation of states (factors and monthly GDP) by Kalman filter
		dlm(var=known,presample=ergodic,method=bfgs,a=afunc(A,reset,beta_q,t),y=yfunc(monthly,quarterly,t),c=cfunc(Lambda,p),z=zfunc(mu_q,r,p),f=ffunc(B,p),	$
			sw=%identity(q),sv=Sigma~\%zeros(1,1)~\Sigma_q,type=filter) lstart lend st_vec st_var
	}
	*
end procedure 
Note that all inputs (like A,Lambda,etc...) are properly defined in the code that I skipped to make this post more readable. afunc is properly displayed, but for the dlm-command I get the following error message, when sourcing the procedure:

Code: Select all

## SX22. Expected Type SERIES, Got REAL Instead
>>>>gs,a=afunc(A,reset,<<<<
Does anybody have an example of a similar multivariate SSM?
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Enter time-varying coefficient matrices by using functions

Unread post by TomDoan »

You're running into a problem because you're passing a series to a function, when that function is being referenced in a formula (such as the one for the Y option on DLM). When you do that, the series reference is converted immediately into the series(t) value. That's the interpretation that allows you to just use series names alone in transformations, but it causes problems when you need the entire series in a function. (It's a bug, but not an easy one to fix).

Fortunately, there's almost always a workaround, and here it looks as if you can simply replace the SERIES parameters with REALs and use those directly, instead of, say RESET(T)---you never use any value of the series other than the current one.
Post Reply