Description Usage Arguments Details Value References Examples
View source: R/Kalman-Filter.R
Given a set of parameters of the N-factor model, filter term structure data using the Kalman filter.
1 2 3 4 5 6 7 8 9 | CPM.Kalman.filter(
parameter.values,
parameters,
log.futures,
dt,
TTM,
verbose = FALSE,
debugging = FALSE
)
|
parameter.values |
Vector of parameter values of an N-factor model. The |
parameters |
Vector of parameter names. Each element of |
log.futures |
Object of class |
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
|
verbose |
|
debugging |
|
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]
\mjdeqnt = 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:
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:
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:
\mjeqndiag(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:
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).
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) |
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.
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)
|
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.