Kalman Filtering for Oil Price Models and Futures-Based Calibration
Summary
The document describes calibrating a one-factor mean-reverting log-price model for oil using futures prices at multiple maturities as observations. It specifies a latent spot-price state, a measurement equation linking that state to log futures prices, and a discrete-time transition equation. The model distinguishes physical and risk-neutral mean levels through a market price of risk and proposes maximum likelihood estimation of its parameters.
The responses point to Kalman filtering tools and give generic examples for filtering a series and estimating time-varying regression parameters. They do not implement the stated futures measurement and transition equations or show a maximum-likelihood calibration for this oil model. The code examples are therefore starting points rather than a validated solution. The stated discretization and covariance assumptions, as well as the mapping from latent state to futures observations, need to be checked against the intended model before calibration results are interpreted.
Key ideas
- A one-factor Ornstein–Uhlenbeck process can represent a mean-reverting latent log spot price.
- Futures prices across maturities are modeled as noisy observations of the hidden state.
- The model separates physical and risk-neutral long-run levels through a market price of risk.
- Kalman filtering can estimate latent states within linear Gaussian state-space models.
- The provided examples do not perform the requested maximum-likelihood calibration of the specified futures model.
Tags
Full text
# Oil price model calibration with Kalman Filter and MLE in python
# Oil price model calibration with Kalman Filter and MLE in python
I am trying to calibrate a one-factor mean-reverting process in python 3. The process is defined as:
\begin{equation} dX = k(\alpha - X)dt + \sigma dW , \end{equation}
where $\alpha = \mu - \frac{\sigma^2}{2k}$ is the long-run mean log price and $k$ is the speed of adjustment. Under the risk neutral probability $Q$ we write the previous equation as
\begin{equation} dX = k(\alpha^* - X)dt + \sigma dW^*. \end{equation}
Here $\alpha^*= \alpha - \lambda$, where $\lambda$ is the market price of risk. Based on Girsanov's Theorem $dW^*$ is a Brownian Motion under the martingale measure $Q$.
My measurement and transition equations are:
- The measurement equation relates the time series of observable variables, in my case futures prices for different maturities, to the unobservable state variable, the spot price:
\begin{equation} y_{t} = Z_{t}X_{t} + d_{t} + \epsilon_{t}, \qquad t = 1, ..., NT \end{equation}
where
$y_{t}=\left[\ln F\left(T_{i}\right)\right]$, $i=1,...,N$, $N\times 1$ vector of observables,
$d_{t}=\left[\left(1-e^{-\kappa T_{1}}\right) \alpha^{*}+\frac{\sigma^{2}}{4 \kappa}\left(1-e^{-2 k T_{1}}\right)\right], \quad i=1, \ldots, N, \quad N \times 1$ vector,
$Z_{t}=\left[e^{-\kappa T_{i}}\right], \quad i=1, \ldots, N, \quad N \times 1$ vector,
$\epsilon_{t}, \quad N\times 1$ vector of serially uncorrelated disturbances with $\mathbb{E}(\epsilon_{t}) = 0$ and $Var(\epsilon_{t}) = H$.
- The transition equation is a discrete-time version of the O-U oil price stochastic process:
\begin{equation} X_{t}=c_{t}+Q_{t} X_{t-1}+\eta_{t}, \quad t=1, \ldots, N T \label{eq:38}, \end{equation}
where
$c_{t}=\kappa \alpha \Delta t$
$Q_{t}=1-\kappa \Delta t$
$\eta_{t}$, serially uncorrelated disturbances with $\mathbb{E}(\eta_{t}) = 0$ and $Var(\eta_{t}) = \sigma^2 \Delta t$.
The aim is to calibrate the model parameters using the time series of different maturities Futures prices via MLE. Any help with the coding part (in python 3) would be much appreciated!
## Answer by amdopt (score 5, accepted)
https://quant.stackexchange.com/a/55700
Expanding on the answer by @ir7, here is some `pykalman` code/psuedocode to help get you started. This can be adjusted in many ways but I have left in some parameters to give you an idea. I left a documentation link at the bottom as well. The functions will setup Kalman Filters that are applied to your data and subsequently that data is fed to a regression that is subsequently called in a backtest function:
```
import pandas as pd
import numpy as np
from pykalman import KalmanFilter
def your_function_name(x):
your_filter_name = KalmanFilter(transition_matrices = [1],
observation_matrices = [1],
observation_covariance=1,
transition_covariance=.01,
initial_state_mean = 0,
initial_state_covariance = 1)
state_means, _ = kf.filter(x.values)
state_means = pd.Series(state_means.flatten(), index=x.index)
return state_means
def your_regression_filter(x, y):
delta = 1e-3
trans_cov = delta / (1 - delta) * np.eye(2) #random walk wiggle
obs_mat = np.expand_dims(np.vstack([[x], [np.ones(len(x))]]).T, axis=1)
kf = KalmanFilter(n_dim_obs=1,
n_dim_state=2,
initial_state_mean=[0,0],
initial_state_covariance=np.ones((2, 2)),
transition_matrices=np.eye(2),
observation_matrices=obs_mat,
observation_covariance=2,
transition_covariance=trans_cov)
# Use the observations y to get running estimates and errors for the state parameters
state_means, state_covs = kf.filter(y.values)
return state_means
```
With these 2 functions your would define a backtest function in which you would pull `state_means` by calling:
`state_means = your_regression_filter(your_function_name(x), your_function_name(y))`
How you use `state_means` from here depends on you.
For more info: pykalman documentation
## Answer by ir7 (score 2)
https://quant.stackexchange.com/a/55694
One resource that has Kalman Filter and Smoother, and Expectation-Maximization algorithms for a Linear Gaussian Model is pykalman module. You can check out statsmodels module too.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.