Learn R Programming

NFCP (version 0.1.0)

NFCP.Kalman.filter: NFCP.Kalman.filter

Description

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

Usage

NFCP.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 NFCP.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 NFCP.Kalman.filter function is significantly faster, see details

debugging

logical. Should additional filtering information be output? see values

Value

NFCP.Kalman.filter returns a numeric object when verbose = F, which corresponds to the log-likelihood of observations. When verbose = T, the NFCP.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. d_td[t] (see details)

Z

matrix. Z_tz[t] (see details)

G_t

matrix. G_tG[t] (see details)

c_t

vector. C_tc[t] (see details)

Q_t

matrix. Q_tQ[t] (see details)

H

matrix. HH (see details)

Details

NFCP.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 NFCP.Kalman.filter function is designed for subsequent input into optimization functions and is called within the N-factor parameter estimation function NFCP.MLE. The first input to the NFCP.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 NFCP.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 NFCP.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 NN state variables x_tx[t].

When GBM = TRUE: log(S_t) = _i=1^N x_i,tlog(S[t]) = sum_i=1^n x[i,t] When GBM = FALSE: log(S_t) = E + _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: dx_1,t = ^*dt + _1 dw_1tdx[1,t] = mu^* dt + sigma[1] dw[1]t

When GBM = FALSE: dx_1,t = - (_1 + _1x_1,t)dt + _1 dw_1tdx[1,t] = - (lambda[1] + kappa[1] x[1,t]) dt + sigma[1] dw[t]t

And: dx_i,t =_i 1 - (_i + _ix_i,t)dt + _i dw_itdx[i,t] =_(i != 1) - (lambda[i] + kappa[i] x[i,t]dt + sigma[i] dw[i]t)

where: E(w_i)E(w_j) = _i,jE(w[i])E(w[j])

The following constant parameters are defined as:

param mu: long-term growth rate of the Brownian Motion process.

param EE: Constant equilibrium level.

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

param _ilambda[i]: Risk premium of state variable ii.

param _ikappa[i]: Reversion rate of state variable ii.

param _isigma[i]: Instantaneous volatility of state variable ii.

param _i,j [-1,1]rho[i,j] in [-1,1]: Instantaneous correlation between state variables ii and jj.

Measurement Error:

The Kalman filtering algorithm assumes a given measure of measurement error (ie. matrix HH). 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) and are assumed independent.

var s_is[i] Observation error of contract ii.

When S.Constant = T, the values of parameter s_is[i] are assumed constant and equal to parameter object 'sigma.contracts'. When S.Constant = F, observation errors are assumed unique, where the error of futures contracts s_is[i] is equal to parameter object 'sigma.contract_' [i] (i.e. 'sigma.contract_1', 'sigma.contract_2', ...).

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: x_t|t-1 = c_t + G_t x_t-1 + Q_t _t hat(x)[t|t-1] = c[t] + G[t] * hat(x)[t-1] Measurement Equation: y_t = d_t + Z_t x_t|t-1 + H_t _that(y)[t] = d[t] + Z[t] * hat(x)[t|t-1]

t = 1, , n t = 1, ..., n

Where _teta[t] and _tepsilon[t] are IID N(0,I(m))N(0,I(m)) and iid N(0,I(d))N(0,I(d)) respectively.

The state vector follows a normal distribution, x_1 N(a_1, P_1)x[1] ~ N(a[1], P[1]), with a_1a[1] and P_1P[1] as the mean vector and variance matrix of the initial state vector x_1x[1], respectively.

When verbose = F, the NFCP.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 NFCP.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 NFCP.MLE.

Filtering the N-factor model

let mm represent the number of observations at time tt

let nn represent the number of factors in the N-factor model

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

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

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

Where s_is[i] == "sigma.contract_" [i] when the logical of function NFCP.Parameters S.constant = F

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

var ZZ is an m nm X n matrix, where each element [i,j][i,j] is equal to:

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

var d_td[t] is an m 1m X 1 vector:

d_t=[A(T_1), A(T_2), , 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: A(T) = ^*T-_i=1^N - 1-e^-_i T_i_i+12(_1^2T + _i.j 1 _i _j _i,j 1-e^-(_i+_j)T_i+_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 v_tv[t] is a n 1n X 1 vector of serially uncorrelated Guassian disturbances with E(V_t) = 0E(V[t]) = 0 and cov(v_t)=R^2cov(v[t])=R^2

Where:

diag(G_t) = [e^-_1 , e^-_2 , , e^-_n ]diag(G[t]) = [e^-kappa[1] tau, e^-kappa[2] tau, ..., e^-kappa[n] tau

Where =T-ttau = T - t

var w_tw[t] is an n 1n X 1 vector of serially uncorrelated Guassian disturbances where: E(w_t) = 0E(w[t]) = 0 and cov(w_t) = Q_tcov(w[t]) = Q[t]

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

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

Cov_1,1(x_1,t,x_1,t) = _1^2tCov[1,1](x[1,t],x[1,t]) = sigma[1]^2 * t Cov_i,j(x_i,t,x_j,t) = _i_j_i,j1-e^-(_i+_j)t_i+_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 NFCP.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 NFCP.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 QQ

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).

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

Run this code
# NOT RUN {
##Example 1 - complete, stitched data.
##Replicating the Schwartz and Smith (2000)
##Two-Factor commodity pricing model applied to crude oil:

Schwartz.Smith.Oil.Stitched <- NFCP.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 = FALSE)


##Example 2 - incomplete, contract data.
##Replicating the Schwartz and Smith (2000)
##Two-Factor commodity pricing model applied to all available
##crude oil contracts:

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

#Kalman filter
Schwartz.Smith.Oil.Contracts <- NFCP.Kalman.filter(
 parameter.values = SS.Oil.2F,
 parameters = names(SS.Oil.2F),
 ## All available contracts are considered
 log.futures = log(SS.Oil$Contracts),
 ## Respective 'TTM' of these contracts are input
 TTM = SS.Oil$Contract.Maturities,
 dt = SS.Oil$dt,
 verbose = FALSE)
# }

Run the code above in your browser using DataLab