CPM.Kalman.filter: CPM.Kalman.filter

Description Usage Arguments Details Value References Examples

View source: R/Kalman-Filter.R

Description

\loadmathjax

Given a set of parameters of the N-factor model, filter term structure data using the Kalman filter.

Usage

1
2
3
4
5
6
7
8
9
CPM.Kalman.filter(
  parameter.values,
  parameters,
  log.futures,
  dt,
  TTM,
  verbose = FALSE,
  debugging = FALSE
)

Arguments

parameter.values

Vector of parameter values of an N-factor model. The CPM.Kalman.filter function is designed for application to optim type functions, and thus parameter values and corresponding parameters different inputs within the function.

parameters

Vector of parameter names. Each element of parameters must correspond to its respective value element in object parameter.values.

log.futures

Object of class matrix corresponding to the natural logarithm of observable futures prices. NA's are allowed within the matrix. Every column of the matrix must correspond to a particular futures contract, with each row corresponding to a quoted price on a given date.

dt

Constant, discrete time step of observations

TTM

Object of class 'vector' or 'matrix' that specifies the time to maturity of observed futures contracts. time to maturity can be either constant (ie. class 'vector') or time homogeneous (ie. class 'matrix'). When the time to maturity of observed futures contracts is time homogeneous, the dimensions of TTM must be identical to that of log.futures. Every element of TTM corresponds to the time to maturity, in years, of a futures contract at a given observation date.

verbose

logical. Should additional information be output? see values. When verbose = F, the CPM.Kalman.filter function is significantly faster, see details

debugging

logical. Should additional filtering information be output? see values

Details

CPM.Kalman.filter applies the Kalman filter algorithm for observable log.futures prices against the input parameters of an N-factor model provided through the parameter.values and parameters input vectors.

The CPM.Kalman.filter function is designed for subsequent input into optimization functions and is called within the N-factor parameter estimation function CPM.MLE. The first input to the CPM.Kalman.filter function is a vector of parameters of an N-factor model, with elements of this vector corresponding to the parameter names within the elements of input vector parameters. When logical input verbose = F, the CPM.Kalman.filter function calls the fkf_SP function of the FKF_SP package, which itself is a wrapper of a routine of the Kalman filter written in C utilizing Sequential Processing for maximum computational efficiency (see fkf_SP for more details). When verbose = T, the CPM.Kalman.filter instead applies a Kalman filter algorithm written in base R and outputs several other list objects, including filtered values and measures for model fit and robustness (see Returns)

The N-factor model The N-factor model was first presented in the work of Cortazar and Naranjo (2006, equations 1-3). The N-factor framework describes the spot price process of a commodity as the correlated sum of \mjeqnNN state variables \mjeqnx_tx[t].

When GBM = TRUE: \mjdeqnlog(S_t) = \sum_i=1^N x_i,tlog(S[t]) = sum_i=1^n x[i,t] When GBM = FALSE: \mjdeqnlog(S_t) = E + \sum_i=1^N x_i,tlog(S[t]) = E + sum_i=1^n x[i,t]

Additional factors within the spot-price process are designed to result in additional flexibility, and possibly fit to the observable term structure, in the spot price process of a commodity. The fit of different N-factor models, represented by the log-likelihood can be directly compared with statistical testing possible through a chi-squared test.

Flexibility in the spot price under the N-factor framework allows the first factor to follow a Brownian Motion or Ornstein-Uhlenbeck process to induce a unit root. In general, an N-factor model where GBM = T allows for non-reversible behaviour within the price of a commodity, whilst GBM = F assumes that there is a long-run equilibrium that the commodity price will revert to in the long-term.

State variables are thus assumed to follow the following processes:

When GBM = TRUE: \mjdeqndx_1,t = \mu^*dt + \sigma_1 dw_1tdx[1,t] = mu^* dt + sigma[1] dw[1]t

When GBM = FALSE: \mjdeqndx_1,t = - (\lambda_1 + \kappa_1x_1,t)dt + \sigma_1 dw_1tdx[1,t] = - (lambda[1] + kappa[1] x[1,t]) dt + sigma[1] dw[t]t

And: \mjdeqndx_i,t =_i\neq 1 - (\lambda_i + \kappa_ix_i,t)dt + \sigma_i dw_itdx[i,t] =_(i != 1) - (lambda[i] + kappa[i] x[i,t]dt + sigma[i] dw[i]t)

where: \mjdeqnE(w_i)E(w_j) = \rho_i,jE(w[i])E(w[j])

The following constant parameters are defined as:

param \mjeqn\mumu: long-term growth rate of the Brownian Motion process.

param \mjeqnEE: Constant equilibrium level.

param \mjeqn\mu^*=\mu-\lambda_1mu^* = mu-lambda[1]: Long-term risk-neutral growth rate

param \mjeqn\lambda_ilambda[i]: Risk premium of state variable \mjeqnii.

param \mjeqn\kappa_ikappa[i]: Reversion rate of state variable \mjeqnii.

param \mjeqn\sigma_isigma[i]: Instantaneous volatility of state variable \mjeqnii.

param \mjeqn\rho_i,j \in [-1,1]rho[i,j] in [-1,1]: Instantaneous correlation between state variables \mjeqnii and \mjeqnjj.

Measurement Error:

The Kalman filtering algorithm assumes a given measure of measurement error (ie. matrix \mjeqnHH). Measurement errors can be interpreted as error in the model's fit to observed prices, or as errors in the reporting of prices (Schwartz and Smith, 2000).

var \mjeqns_is[i] is the standard deviation of observation error of contract \mjeqnii.

When S.Constant = T, the values of parameter \mjeqns_is[i] are assumed constant and equal to object 'sigma.contracts'. When S.Constant = F, the observation error of futures contracts \mjeqns_is[i] is equal to parameter 'sigma.contract_' [i].

Kalman filtering

The following section describes the Kalman filter equations used to filter the N-factor model.

The Kalman filter iteration is characterised by a transition and measurement equation. The transition equation develops the vector of state variables between discretised time steps (whilst considering a given level of covariance between state variables over time). The measurement equation relates the unobservable state vector to a vector of observable measurements (whilst also considering a given level of measurement error). The typical Kalman filter algorithm is a Gaussian process state space model.

Transition Equation: \mjdeqn\hat x_t|t-1 = c_t + G_t \hat x_t-1 + Q_t \eta_t hat(x)[t|t-1] = c[t] + G[t] * hat(x)[t-1] Measurement Equation: \mjdeqn\hat y_t = d_t + Z_t \hat x_t|t-1 + H_t \epsilon_that(y)[t] = d[t] + Z[t] * hat(x)[t|t-1]

\mjdeqn

t = 1, \cdots, n t = 1, ..., n

Where \mjeqn\eta_teta[t] and \mjeqn\epsilon_tepsilon[t] are IID \mjeqnN(0,I(m))N(0,I(m)) and iid \mjeqnN(0,I(d))N(0,I(d)) respectively.

The state vector follows a normal distribution, \mjeqnx_1 \sim N(a_1, P_1)x[1] ~ N(a[1], P[1]), with \mjeqna_1a[1] and \mjeqnP_1P[1] as the mean vector and variance matrix of the initial state vector \mjeqnx_1x[1], respectively.

When verbose = F, the CPM.Kalman.filter function performs Kalman filtering through the fkf.SP function of the FKF.SP package for maximum filtering efficiency, which is crucial when filtering and estimating parameters of term structure data under the N-factor model, which generally has many observations, contracts and unknown parameters. When verbose = T, the CPM.Kalman.filter function instead performs Kalman filtering in R, returning greater details of filtered objects (see Value)

The Kalman filter can be used for parameter estimation through the maximization of the Log-Likelihood value. See CPM.MLE.

Filtering the N-factor model

let \mjeqnmm represent the number of observations at time \mjeqntt

let \mjeqnnn represent the number of factors in the N-factor model

observable futures prices: \mjeqny_t = [ln(F(t,T_1)), ln(F(t,T_2)), \cdots, ln(F(t,T_m))]'y[t] = [ln(F(t,T[1])), ln(F(t,T[2])), ..., ln(F(t,T[m]))]'

State vector: \mjeqnx_t=[x_1t,x_2t,\cdots,x_nt ]'x[t] = [x[1t], x[2t], ..., x[nt]]'

Measurement error: \mjeqndiag(H) = [s_1^2, s_2^2, \cdots, s_n^2]diag(H) = [s[1]^2, s[2]^2, ..., s[n]^2]

Where \mjeqns_is[i] == "sigma.contract_" [i] when the logical of function CPM.Parameters S.constant = F

When S.constant = T, \mjeqns_1 = s_2 = \cdots = s_n = s[1] = s[2] = ... = s[n] = "sigma.contracts"

var \mjeqnZZ is an \mjeqnm \times nm X n matrix, where each element \mjeqn[i,j][i,j] is equal to:

\mjdeqn

Z_i,j = e^-\kappa_i T_jZ[i,j] = e^(-kappa[i] * T[j])

var \mjeqnd_td[t] is an \mjeqnm \times 1m X 1 vector:

\mjdeqn

d_t=[A(T_1), A(T_2), \cdots, A(T_m)]'d[t]=[A(T[1]), A(T[2]), ..., A(T[m])]'

Under the assumption that Factor 1 follows a Brownian Motion, A(T) is given by: \mjdeqnA(T) = \mu^*T-\sum_i=1^N - \frac1-e^-\kappa_i T\lambda_i\kappa_i+\frac12(\sigma_1^2T + \sum_i.j\neq 1 \sigma_i \sigma_j \rho_i,j \frac1-e^-(\kappa_i+\kappa_j)T\kappa_i+\kappa_j)A(T) = mu^* * T - sum_i=1^N (1-e^(-kappa[i] T) lambda[i])/(kappa[i]) + 1/2 (sigma[1]^2 * T) + sum_i.j != 1 sigma[i] sigma[j] rho[i,j] (1 - e^(-(kappa[i] + kappa[j]) * T)) / (kappa[i] + kappa[j])

var \mjeqnv_tv[t] is a \mjeqnn \times 1n X 1 vector of serially uncorrelated Guassian disturbances with \mjeqnE(V_t) = 0E(V[t]) = 0 and \mjeqncov(v_t)=R^2cov(v[t])=R^2

Where:

\mjeqn

diag(G_t) = [e^-\kappa_1 \tau, e^-\kappa_2 \tau, \cdots, e^-\kappa_n \tau]diag(G[t]) = [e^-kappa[1] tau, e^-kappa[2] tau, ..., e^-kappa[n] tau

Where \mjeqn \tau =T-ttau = T - t

var \mjeqnw_tw[t] is an \mjeqnn \times 1n X 1 vector of serially uncorrelated Guassian disturbances where: \mjdeqnE(w_t) = 0E(w[t]) = 0 and \mjeqncov(w_t) = Q_tcov(w[t]) = Q[t]

var \mjeqnc_t=[\mu \Delta t,0,\cdots,0]'c[t] = [mu * Delta t, 0, ..., 0]' is an \mjeqnN \times 1N X 1 vector of the intercept of the transition equation.

var \mjeqnQ_tQ[t] is equal to the covariance function, given by:

\mjdeqn

Cov_1,1(x_1,t,x_1,t) = \sigma_1^2tCov[1,1](x[1,t],x[1,t]) = sigma[1]^2 * t \mjdeqnCov_i,j(x_i,t,x_j,t) = \sigma_i\sigma_j\rho_i,j\frac1-e^-(\kappa_i+\kappa_j)t\kappa_i+\kappa_jCov[i,j](x[i,t],x[j,t]) = sigma[i] sigma[j] rho[i,j] (1-e^-(kappa[i]+kappa[j]) * t) / (kappa[i] + kappa[j]) (see also cov_func)

Penalising poorly specified models

The Kalman filter returns non-real log-likelihood scores when the function of the covariance matrix becomes singular or its determinant becomes negative. This occurs when a poorly specified parameter set is input. Non-real log-likelihood scores can break optimization algorithms. To circumvent this, the CPM.Kalman.filter returns a heavily penalized log-likelihood score whilst also returning a warning. Penalized log-likelihood scores are calculated by:

stats::runif(1, -1.5e6, -1e6)

Diffuse Kalman filtering

If the initial values of the state vector are not supplied within the parameters and parameter.values vectors (ie. Initial.State = F within the CPM.Parameters function), a 'diffuse' assumption is used within the Kalman filtering algorithm. Factors that follow an Ornstein-Uhlenbeck are assumed to equal zero. When Estimate.Initial.State = F and GBM = T, the initial value of the first state variable is assumed to equal the first element of log.futures. This is an assumption that the initial estimate of the spot price is equal to the closest to maturity observed futures price.

The initial covariance of the state vector for the Kalman filtering algorithm assumed to be equal to matrix \mjeqnQQ

Initial states of factors that follow an Ornstein-Uhlenbeck have a transient effect on future observations, however the initial value of a random walk variable persists across observations and therefore influencing model fit more (see Schwartz and Smith (2000) for more details).

Value

CPM.Kalman.filter returns a numeric object when verbose = F, which corresponds to the log-likelihood of observations. When verbose = T, the CPM.Kalman.filter function returns a list object of length seven with the following objects:

LL Log-Likelihood of observations
X.t vector. The final observation of the state vector
X matrix. All observations of the state vector, after the updating equation has been applied
Y matrix. Estimated futures prices at each observation
V matrix. Estimation error of each futures contracts at each observation
TSFit.Error matrix. The Mean Error (Bias), Mean Absolute Error, Standard Deviation of Error and Root Mean Squared Error (RMSE) of each observed contract, matching the column names of log.futures
TSFit.Volatility matrix. The theoretical and empirical volatility of futures returns for each observed contract as returned from the TSFit.Volatility function

When debugging = T, 9 objects are returned in addition to those returned when verbose = T:

P_t array. The covariance matrix at each observation point, with the third dimension indexing across time
F_t vector. The function of the Kalman filter covariance matrix at each observation point, with the third dimension indexing across time
K_t matrix. The Kalman Gain at each observation point, with the third dimension indexing across time
d matrix. \mjeqnd_td[t] (see details)
Z matrix. \mjeqnZ_tz[t] (see details)
G_t matrix. \mjeqnG_tG[t] (see details)
c_t vector. \mjeqnC_tc[t] (see details)
Q_t matrix. \mjeqnQ_tQ[t] (see details)
H matrix. \mjeqnHH (see details)

References

Anderson, B. D. O. and J. B. Moore, (1979). Optimal filtering Englewood Cliffs: Prentice-Hall.

Fahrmeir, L. and G. tutz,(1994) Multivariate Statistical Modelling Based on Generalized Linear Models. Berlin: Springer.

Schwartz, E. S., and J. E. Smith, (2000). Short-Term Variations and Long-Term Dynamics in Commodity Prices. Manage. Sci., 46, 893-911.

Cortazar, G., and L. Naranjo, (2006). An N-factor Gaussian model of oil futures prices. Journal of Futures Markets: Futures, Options, and Other Derivative Products, 26(3), 243-268.

Durbin, J., and S. J. Koopman, (2012). Time series analysis by state space methods. Oxford university press.

Examples

 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
##Example 1 - Replicating the Schwartz and Smith (2000)
##Two-Factor Crude Oil commodity pricing model:

Schwartz.Smith.Oil.Stitched <- CPM.Kalman.filter(
 parameter.values = SS.Oil$Two.Factor,
 parameters = names(SS.Oil$Two.Factor),
 log.futures = log(SS.Oil$Stitched.Futures),
 TTM = SS.Oil$Stitched.TTM,
 dt = SS.Oil$dt,
 verbose = TRUE)

##Not Run - Replicate Figure 4 of Schwartz and Smith (2000):
# SS.Figure.4 <- cbind(`Equilibrium Price` =
#                      exp(Schwartz.Smith.Oil.Stitched$X[,1]),
#                     `Spot Price` =
#                      Schwartz.Smith.Oil.Stitched$Y[,"filtered Spot"])

# matplot(as.Date(rownames(SS.Figure.4)), SS.Figure.4, type = 'l',
# xlab = "", ylab = "Oil Price ($/bbl, WTI)", col = 1,
#  main = "Estimated Spot and Equilibrium Prices for the Futures Data")

##Example 2 - Running the Schwartz and Smith (2000) Two-Factor Model
##on all observable Contracts:

SS.Oil.Two.Factor <- SS.Oil$Two.Factor
##Assume constant white noise in parameters:
SS.Oil.Two.Factor <- SS.Oil.Two.Factor[!grepl("sigma.contract",
                                     names(SS.Oil.Two.Factor))]
SS.Oil.Two.Factor["sigma.contracts"] <- 0.01

#Run the Kalman filter
Schwartz.Smith.Oil.Contract <- CPM.Kalman.filter(
 parameter.values = SS.Oil.Two.Factor,
 parameters = names(SS.Oil.Two.Factor),
 log.futures = log(SS.Oil$Contracts),
 TTM = SS.Oil$Contract.Maturities,
 dt = SS.Oil$dt,
 verbose = TRUE)

TomAspinall/TSE documentation built on Jan. 7, 2021, 7:43 p.m.