In his book, Algorithmic Trading: Winning Strategies and Their Rationale, Ernie Chan shows how to use a Kalman filter to improve the returns of a cointegrated portfolio. Recall that the state equation is: $$\beta_t=\alpha\cdot\beta_{t-1}+\omega_{t-1}$$ Here, $\alpha$ is the state transition matrix, $\beta_t$ is the state vector, and $\omega_t$ is the process noise vector.

In his Kalman filter code, Chan sets the state transition matrix, $\alpha$, to the identity matrix. However, I would argue that this is wrong. Recall that the state vector is used in the measurement equation: $$y_t=\beta_t\cdot x_t + \epsilon_t$$

For k cointegrating time series, the observation vector, $x_t$, the state vector, $\beta_t$, and the observable, $y_t$, are: $$x_t=(1,\;x_{2,t},\;x_{3,t},\;...\;,\;x_{k,t})$$ $$\beta_t=(\beta_{1,t},\;\beta_{2,t},\;\beta_{3,t},\;...\;,\;\beta_{k,t})$$ $$y_t = x_{1,t}$$

The state vector is related to the static weights ($w_1,w_2,...,w_k$) obtained from the Johansen procedure because these weights give a stationary time series, $y_{\text{port}}$: $$y_{\text{port}}=w_1\cdot x_1\:+\:w_2\cdot x_2\:+\:w_3\cdot x_3\:+\:...\:+\:w_k\cdot x_k$$ Solving for $y=x_1$, we get: $$x_1=(y_{\text{port}}\:-\:w_2\cdot x_2\:-\:w_3\cdot x_3\:-\:...\:-\:w_k\cdot x_k)\,/\,w_1$$ Therefore, from the measurement equation, the initial state vector at time $t$ must be: $$\beta_t=(y_{\text{port},t}/w_1,\;-w_2/w_1,\;-w_3/w_1,\;...\;,\;-w_k/w_1)$$ The first column of matrix $\beta$ is $y_{\text{port}}/w_1$, which is stationary because $y_{\text{port}}$ is stationary. Therefore, the state estimate for this component of $\beta$ at time $t$ is: $$\beta_{1,t}=\alpha_{11}\cdot\beta_{1,t-1}$$ where $\alpha_{11}$ must be less than 1 for the stationary case. This analysis indicates that the correct state transition matrix is not the identity matrix, but rather: $$\alpha=\left[ \begin{array}{cccc} \alpha_{11} & 0 & 0 & ... & 0\\ 0 & 1 & 0 & ... & 0\\ 0 & 0 & 1 & ... & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & 0 & ... & 1 \end{array} \right]$$ In other words, the state transition matrix is the identity matrix, except for the (1,1) element, which must be less than 1 (for stationarity).

How do we calculate $\alpha_{11}$? Right-multiply both sides of the state equation by $\beta_{t-1}^T$, take the expectation value, and solve for $\alpha_{11}$:

$$\alpha_{11}=\frac{\sum_{t=2}^n\beta_{1,t}\cdot\beta_{1,t-1}^T}{\sum_{t=2}^n \beta_{1,t-1}\cdot\beta_{1,t-1}^T}$$

I’m currently trading with a cointegrated triplet of ETFs that give a stationary portfolio, $y_{\text{port}}$. When I apply a unit root test (which measures stationarity) to $y_{\text{port}}$, I get the following p-values using a state transition matrix in the Kalman filter with different values for the (1,1) element of the state transition matrix, $\alpha$:

\begin{array}{|c|c|} \hline \alpha_{11} & p\\ \hline 1 & 0.00086\\ \hline 0.93 & 0.00058\\ \hline 0.007 & 3\times10^{-13}\\ \hline \end{array}

Smaller values of p suggest greater likelihood of stationarity. All of these p-values indicate stationarity, but the modified transition matrix ($\alpha_{11}=0.93$) gives better results than the identity matrix ($\alpha_{11}=1$). In the last example ($\alpha_{11}=0.007$), I iterated the Kalman filter calculation 1000 times, each time recalculating $\alpha_{11}$, as well as the process noise covariance matrix, the observation noise variance, the initial state vector, and the initial state covariance matrix, with each iteration (a procedure known as "adaptive tuning" of the Kalman filter). This gave very high stationarity for the $y_{\text{port}}$ array. (This is also reflected in higher returns in backtesting of the trading algorithm.)

I haven't seen this analysis in the literature on Kalman filter in financial time series. Can anyone find fault with it?

  • I sent Mr. Chan a link to this post. his reply: "Amanda's analysis assumes that the system is cointegrating. But actually the Kalman Filter implementation I described does not assume that. In fact, system that has varying hedge ratio cannot be considered stationary, and thus alpha is not always <1." Ernest Chan. – Alex C Aug 5 at 15:10
  • It seems to me that the goal of the Johansen procedure is to obtain a weighted portfolio that is, at least partially, stationary. My observation with the Kalman filter is that the varying hedge ratio makes the weighted portfolio time series have a smaller p-value for the unit root test, and so, more stationary. This needn't always be the case, but it is for the portfolio that I'm trading. – Amanda G. Aug 5 at 18:12
  • @AmandaG.: Would you mind sending your comment to Ernie Chan and report back his reaction? I would very much like to keep abreast of the discussion. Thank you. – Hans Aug 8 at 18:03
  • I've emailed Ernie Chan. I'll let you know if he responds. – Amanda G. Aug 8 at 19:19
  • @Hans: I received an email reply from Ernie Chan. In response to my statement, "I think that, all things being equal, a stationary weighted portfolio offers greater opportunities for profitable trading than a non-stationary one. Am I wrong?", Ernie wrote, "Yes, I agree that if the portfolio is in fact stationary, it can be more profitable. For this special case, the analysis presented may be correct, but my calculation was for the general case." Ernest Chan. – Amanda G. Aug 8 at 21:22
up vote 6 down vote accepted

In addition to getting the right transition model for the Kalman filter, the main obstacle to optimizing filter performance is to implement an optimal initialization. I use an iterative approach to initialize or "tune" the Kalman filter, known as adaptive tuning. I do this because I've found alternative methods of initializing the Kalman filter (such as the autocovariance least squares method mentioned by Chan) to give mediocre results. In my experience, adaptive tuning can produce a highly stationary portfolio suitable for mean-reversion trading.

There are four quantities that have to be initialized:

  1. The initial state vector, $\beta(0)$
  2. The $k\times k$ initial state covariance matrix, $\text{cov}(\beta(0))$
  3. The measurement noise variance, $\nu_e$
  4. the $k\times k$ state noise covariance matrix, $\nu_\omega$

Furthermore, one has to make a reasonable initial choice for these quantities on the first pass through the filter. Subsequent passes through the filter may use a different calculation (for reasons that I hope will become clear).

Noise (Co)variance Initialization

For the initial value of the measurement noise variance, $\nu_e(0)$, I use the variance of the first component of $\beta_1$ (the other components are constant):


However, any reasonable initial value will probably work, if you're using the adaptive tuning approach.

For subsequent passes through the Kalman filter, I solve the measurement equation for the measurement noise, $\epsilon_t$, and take the expectation value of its square to get the measurement noise variance, $\nu_e$:

$$\epsilon_t=y_t-\beta_t\cdot x_t$$ $$\nu_e=E\left[\epsilon_t \cdot \epsilon_t^T\right]=\frac{\sum_{t=1}^{n}\epsilon_t\cdot\epsilon_t^T}{n}$$

For the initial value of the state noise covariance, I first calculate the state transition matrix, $\alpha$, using the formula shown in my original post, to calculate $\alpha_{1,1}$. Then I post-multiply the state equation by its transpose (outer product), and take expectations:


This can be solved for the initial state noise covariance matrix, $\nu_\omega(0)$:


where $\Gamma$ is:


$\nu_\omega(0)$ should be diagonalized (off-diagonal elements set to zero). Then only the (1,1) component of $\nu_\omega(0)$ will be non-zero.

For subsequent passes of the Kalman filter, I solve the state equation for the process noise vector, $\omega_t$, and take the expectation of the outer product of the process noise vector with itself to get the state noise covariance matrix, $\nu_\omega$:

$$\omega_t=\beta_{t+1}-\alpha\cdot\beta_t$$ $$\nu_\omega=E\left[\omega_t\otimes\omega_t^T\right]=\frac{\sum_{t=1}^{n-1}(\beta_{t+1}-\alpha\cdot\beta_t)\otimes(\beta_{t+1}-\alpha\cdot\beta_t)^T}{n-1}$$

However, I'm not quite done. $\beta_1$ is stationary, so I have to replace the (1,1) component of $\nu_\omega$ with the stationary solution that I used in my original post:


Finally, $\nu_\omega$ should be diagonalized.

State and State Covariance Initialization

To get the initial state, start with the initial state vector I calculated in my original post:


The $\beta_{t,1}$ component is stationary, and so the expectation value of this component is zero. (See the derivation in Kalman Filter Initialization - The Stationary Case.) Therefore, the initial state vector, $\beta(0)$, is:


This initialization for $\beta_1$ should be used at the start of each iteration of the Kalman filter.

The state covariance initialization is much trickier. For the first pass through the Kalman filter, I calculate the initial state covariance matrix, $\text{cov}(\beta(0))$, using the Inverse of Information Matrix calculation of Gemson (eq. 3.4, section 3.8.2):

$$\text{cov}(\beta(0))=\nu_e\left[\frac{\sum_{t=1}^n(\alpha^T\cdot x_t^T)\otimes(x_t\cdot\alpha)}{n}\right]^{-1}$$

However, any reasonable $k\times k$ matrix will probably work, provided that it is diagonalized, and all diagonal elements are $>0$. (Any zero diagonal element will cause the corresponding Kalman filter gain element to be zero, preventing the state and state covariance updates from updating.)

For subsequent passes of the Kalman filter, we can calculate the initial state covariance, $\text{cov}(\beta(0))$, from the state matrix, $\beta$, using the traditional definition of covariance$^*$:

$$\text{cov}(\beta(0))=E\left[(\beta-E[\beta])(\beta-E[\beta])\right]=\frac{\sum_{t=1}^n(\beta_t-\beta_m)\otimes(\beta_t-\beta_m)^T}{n-1}$$ $$\beta_m=(\text{mean}(\beta_1),\;\text{mean}(\beta_2),\;...\;,\;\text{mean}(\beta_k))$$

$^*$Edit 8/18/18: $n$ in denominator of $\text{cov}\beta(0)$ changed to $n-1$ for unbiased covariance calculation.

This works well, but what I've found is that I can get a more stationary portfolio (and so, a higher average-yearly-return/maximum-drawdown ratio in my backtesting), $y_\text{port}$, by using a different expression for $\beta_m$ in my $\text{cov}(\beta(0))$ calculation:


In other words, for the expectation value of $E(\beta)$, I use the mean of the initial state vector, $\beta_t$, that I calculated in my original post. Why does this seem to work better? I think it's because the initial state vector is calculated from the Johansen weights, which is the optimal cointegration weighting (for static weights), and so is the "true" expectation value. In any case, I go with what works best. Use your own judgement in this.

Implementation Notes

If you use the state transition matrix, $\alpha$, derived in my opening post, you need to use the correct state prediction and state covariance prediction equations in your Kalman filter. The state prediction equation should be: $$\beta_t=\alpha\cdot\beta_{t-1}$$ and the state covariance prediction equation should be: $$\text{cov}(\beta_t)=\alpha\cdot \text{cov}(\beta_{t-1})\cdot \alpha^T\;+\;\nu_\omega$$ where $\nu_\omega$ is the $k \times k$ state noise covariance matrix.

Also, all of the $k\times k$ matrices, $\alpha$, $\text{cov}(\beta(0))$, $\nu_\omega$, $\Gamma$, should be diagonalized -- all off-diagonal elements set to zero.

Currently, I'm using about 2000 iterations of the Kalman filter for my triplet ETF portfolio to settle into fixed values for all of the quantities. This takes about 1 minute, but I only do this once a week, and use the dynamic weights I've obtained from this procedure for trading during the week. The advantage is that I'm obtaining a highly stationary portfolio, $y_{\text{port}}$.

To show effect of the Kalman filter, here is the weighted portfolio using the static Johansen weights (prior to the Kalman filter):

Static Johansen Weights

Here is the same portfolio, except using the dynamic portfolio weights from the Kalman filter:

enter image description here

That's much more stationary!

I will continue to check in at least once a day, for a while, and try to answer any questions that may come up. I appreciate any feedback.

  • I appreciate the detailed description of your tuning for the Kalman filter. I would very much like to see how you initialize the state vector and the state covariance matrix. – Hans Aug 14 at 5:33
  • Could you please merge this into one answer? – Bob Jansen Aug 14 at 18:57
  • @Bob Jansen: The answers are somewhat long. Wouldn't it be easier on the reader to read them separately? – Amanda G. Aug 14 at 20:31
  • 1
    You can make headings to structure the answer. If you keep them as separate answers the order might change and it goes against convention which will probably confuse readers unnecessarily. – Bob Jansen Aug 14 at 20:42
  • 3
    @BobJansen: Done. – Amanda G. Aug 14 at 22:25

Your Answer


By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.