
Our previous article on Kalman filter gave us a simple linear regression output. The model is designed to handle noisy data, but not on streaming data and time adaptive parameters. This post we will study more general usage of the Kalman filter.
Simple Pairs Trading
From the linear regression result between S&P 500 and Dow Jons ETFs, a simple strategy can be easily derived. The regression parameters
to a two-sigma event detector below
When
we might just long the S&P 500 ETF (SPY) and short the Doe Jons ETF (DIA) and wait for them to converge, and vice versa for the case when
Moreover, we close the position when the prices converge within the
| parameters | coef | std err | t value | [95.0% Conf. Int.] |
|---|---|---|---|---|
| -2.0651 | 0.385 | -5.364 | [-2.820, -1.310] | |
| 0.8903 | 0.003 | 264.258 | [0.884, 0.897] |
Python code implementation is included in the IPython Notebook file. Let’s check the outcome:
There are two difficulties with the strategy.
- The linear regression is derived from the whole history of data. It is impossible for us to use the linear regressed pair to trade from the beginning.
-
From our last finding, the parameters
should not be constant.
We expect to resolve the issues by Kalman filter.
Kalman Filter
The full model of a Kalman filter can be characterized as
and
where
are the latent vector, are the observation vector, are the transition matrices, are the observation matrices, are the transition white noise following the distribution , are the measurement white noise following the distribution .
By letting
So how this Kalman Filter improve the model?
One of the advantages using Kalman Filter is to find the latent factor distributions. The inferences on these parameters can give us more thoughts on building a mean-reverting trading strategy.
The noise
Okay, now what do we have? We can observe the prices from the market. We assume the linear relationship between the prices dynamics. Time adaptive parameters need an updating mechanism taking in streaming data. Kalman filter has another advantage for online optimization. It can be accomplished by using
filter_update function
from pykalman module.
For pairs trading with Kalman filter, we need to decide the two timings:
- When to buy and sell?
- When to close?
The updated state variance in Kalman filter provides a hint on this part since it indicates upper and lower bounds of the difference between DIA and SPY prices derived from the model. Each iteration Kalman filter outputs the updated mean and variance of
and use it to identify the divergent event. That is, we trade the pair when
By setting
Improved Kalman Filter Pairs Trading
We can increase the accuracy of the linear regression prediction by estimating the changing speed and acceleration of future regression parameters. It is a common method used in signal processing. Through Taylor expansion, we have
where
However, the measurement matrices is defined as
to maintain the same simple linear regression form.
Just to make the model simpler, we set
Creating Kalman Filter
[sourcecode language=”python” light=”true” wraplines=”false” collapse=”false”]
# Create a Kalman Filter Object
kf = KalmanFilter(n_dim_obs=1,
n_dim_state=4,
transition_matrices=A,
transition_covariance=Q,
observation_covariance=R,
observation_matrices=array_SPY)
kf = kf.em(df_data.ix[‘1999’][‘DIA’].values)# Linear Regression Outputs
alpha = kf.initial_state_mean[3]
beta = kf.initial_state_mean[0]
[/sourcecode]
Kalman Filter Update
[sourcecode language=”python” light=”true” wraplines=”false” collapse=”false”]
for row in df_data.ix[‘2000’:].iterrows():
price_spy = row[1][‘SPY’]
price_dia = row[1][‘DIA’]# Kalman filter update
updated_mean, updated_variance = kf.filter_update(filtered_state_mean=updated_mean,
filtered_state_covariance=updated_variance,
observation_matrix=np.expand_dims(np.array([price_spy, 0, 1, 0]), 0),
observation=np.array([price_dia])
)
[/sourcecode]
Partial rule of buying and selling: to long SPY and short DIA we check if
Trading (Long SPY, Short DIA)
[sourcecode language=”python” light=”true” wraplines=”false” collapse=”false”]
if (price_dia > price_spy * beta + alpha + 1*P and
not long_spy_short_dia): # Long SPY-DIA Spread
if short_spy_long_dia:
total_wealth += shares_spy * (price_spy – cost_spy) + shares_dia * (price_dia – cost_dia)
short_spy_long_dia = False
shares_spy = total_wealth / price_spy
shares_dia = -1 * total_wealth / price_dia
cost_spy = price_spy
cost_dia = price_dia
long_spy_short_dia = True
[/sourcecode]
Performance is improved.
What’s Next?
We have shown how Kalman filter can used for pairs trading between S&P 500 ETF and Dow Jons ETF. We double the Sharpe ratio by implementing a second-order time adaptive linear regression based on Kalman filter and Taylor expansion. In our next topic on Kalman filter, we will examine the

