Introduction
The Kalman Filter is a mathematical method frequently employed in trading and other financial applications for time series analysis. It plays a crucial role in technical analysis due to its ability to estimate the hidden state of a dynamic system, such as a financial market, based on a series of noisy observations. This filter provides a framework for predicting the future state of the system and updating those predictions as new observations become available.
Origins of the Kalman Filter
The Kalman Filter is a recursive algorithm invented by Rudolf E. Kálmán, a Hungarian-American electrical engineer and mathematician. He introduced it in his seminal paper, “A New Approach to Linear Filtering and Prediction Problems” published in 1960. The original purpose of it was tracking a moving target from noisy measurements of its position and predicting its future position. Over time, this concept has been applied to pricing data, used to detect smooth trend lines within the data that represent the true value of the market before being disturbed by market noise. It has wide applicability in various fields beyond finance and has become a fundamental topic in control theory and signal processing.
Mathematical Construction
The Kalman Filter operates in two stages: prediction and update. In the prediction stage, it predicts the current state based on the last state, taking noise into account. In the update stage, it takes measured values and updates the state estimate. This makes it a more accurate smoothing/prediction algorithm than the moving average because it is adaptive: it accounts for estimation errors and tries to adjust its predictions from the information it learned in the previous stage.
Theoretically, the filter consists of measurement and transition components. The measurement component relates an unobservable price trend to the observable price variable, manifested as a deviation of predicted to actual price. The transition component specifies the price trend to either increase or decrease, manifested as the price smoothing component.
It also includes a parameter called NoiseCovRatio
, which is the ratio of measurement noise to process noise variance. Large values of NoiseCovRatio
make the estimated trend smoother, but slow down the filter’s reaction to changes in the trend. Conversely, small values of NoiseCovRatio
make the noise smoothing worse, but keep a good reaction to changes in the trend. This parameter allows you to adjust the balance between the smoothness of the estimated trend and the speed of the filter’s reaction to changes in the trend.
In the Kalman Filter Python code provided in this post, the NoiseCovRatio
is not explicitly set. This is because the PyKalman library, which is used in the code, automatically estimates the noise covariances from the data. However, if you want to manually set the NoiseCovRatio
, you would need to adjust the observation_covariance
and transition_covariance
parameters of the KalmanFilter
object in the PyKalman library. We show you how to do this later in this post.
Kalman Filter Equations
The Kalman Filter is a recursive algorithm that involves a series of mathematical equations. It operates in two stages: prediction and update. Here’s a detailed explanation of the mathematical formulas involved in each stage:
1. Prediction Stage
The prediction stage involves predicting the current state and its uncertainty. It uses the following equations:
- Predicted State Estimate:
x̂_k|k-1 = F_k * x̂_k-1|k-1 + B_k * u_k
\hat{x}_{k|k-1} = F_k \cdot \hat{x}_{k-1|k-1} + B_k \cdot u_k
- Predicted Estimate Uncertainty: P_k|k-1 = F_k * P_k-1|k-1 * F_k’ + Q_k
P_{k|k-1} = F_k \cdot P_{k-1|k-1} \cdot F_k' + Q_k
Here:
x̂_k|k-1
is the predicted state estimate. It is calculated based on the previous state estimatex̂_k-1|k-1
, the control inputu_k
, and the state transition modelF_k
and control-input modelB_k
.P_k|k-1
is the predicted estimate uncertainty. It is calculated based on the previous estimate uncertaintyP_k-1|k-1
, the state transition modelF_k
, and the process noise covarianceQ_k
.
2. Update Stage
The update stage involves updating the predicted state by using the new measurement. It uses the following equations:
Kalman Gain:Â K_k = P_k|k-1 * H_k' * (H_k * P_k|k-1 * H_k' + R_k)^-1
K_k = P_{k|k-1} \cdot H_k' \cdot (H_k \cdot P_{k|k-1} \cdot H_k' + R_k)^{-1}
Updated State Estimate: x̂_k|k = x̂_k|k-1 + K_k * (z_k - H_k * x̂_k|k-1)
\hat{x}_{k|k} = \hat{x}_{k|k-1} + K_k \cdot (z_k - H_k \cdot \hat{x}_{k|k-1})
Updated Estimate Uncertainty:Â P_k|k = (I - K_k * H_k) * P_k|k-1
P_{k|k} = (I - K_k \cdot H_k) \cdot P_{k|k-1}
Here:
K_k
is the Kalman Gain. It is calculated based on the predicted estimate uncertaintyP_k|k-1
, the observation modelH_k
, and the measurement noise covarianceR_k
.x̂_k|k
is the updated state estimate. It is calculated based on the predicted state estimatex̂_k|k-1
, the Kalman GainK_k
, and the difference between the actual measurementz_k
and the predicted measurementH_k * x̂_k|k-1
.P_k|k
is the updated estimate uncertainty. It is calculated based on the Kalman GainK_k
, the observation modelH_k
, and the predicted estimate uncertaintyP_k|k-1
.
In the context of trading, the “state” could be the underlying trend in a time series of asset prices, the “control input” could be external factors influencing the prices, the “measurement” could be the observed asset prices, and the “uncertainty” represents the estimation error.
The Kalman Filter is quite complex and requires a good understanding of linear algebra, probability, and statistics to use effectively. Additionally, like all models, it makes certain assumptions that may not hold in all situations.
Purpose and Design
The primary purpose of the Kalman Filter is to estimate the underlying trend in a time series of asset prices. This can help traders to identify opportunities for long or short trades. It is also used to estimate the dynamic hedge ratio between a pair of securities in pairs trading, which is used to determine the number of shares to buy and sell. It can also be used to estimate the volatility of a security’s returns, which can be used for risk management and position sizing.
Interpreting Trade Signals
The Kalman Filter’s output provides valuable insights into market trends and potential trading opportunities. For instance, when applied to a time series of asset prices, the Kalman Filter can help identify the underlying trend, which can be used to spot opportunities for long or short trades.
In pairs trading, the Kalman Filter can be used to estimate the dynamic hedge ratio between a pair of securities. When the prices of the two securities diverge, the security that is underpriced is bought, and the one that is overpriced is sold. This dynamic hedge ratio, estimated by the Kalman Filter, is used to determine the number of shares to buy and sell.
Pros and Cons
One of the main advantages of the Kalman Filter is its efficiency. As a recursive algorithm, it only requires the estimated state from the previous time step and the current observation to compute the estimate for the current state. This makes it highly suitable for real-time applications.
As already noted the Kalman Filter is complex, requiring a good understanding of linear algebra, probability, and statistics to use effectively, it also makes certain assumptions (e.g., about the Gaussian distribution of errors) that may not hold in all scenarios.
Kalman Filter Python Tutorial
Python is a popular language for financial analysis due to its simplicity and the wide range of financial and mathematical libraries available. In this section, we will provide a step-by-step tutorial on how to implement the Kalman Filter Python code.
Before we start, make sure you have the necessary libraries installed. If not, you can install them using pip:
pip install numpy pandas pykalman
Here’s a simple example of how to implement the Kalman Filter using the PyKalman library:
import numpy as np
from pykalman import KalmanFilter
# Define the transition_matrix, observation_matrix, initial_state_mean and initial_state_covariance
transition_matrix = np.array([[1, 1], [0, 1]])
observation_matrix = np.array([[1, 0]])
kf = KalmanFilter(transition_matrices=transition_matrix,
observation_matrices=observation_matrix,
initial_state_mean=np.zeros(2),
initial_state_covariance=np.ones((2, 2)))
# Generate sample data
n_timesteps = 50
n_dim_state = 2
random_state = np.random.RandomState(0)
states = np.zeros((n_timesteps, n_dim_state))
for t in range(n_timesteps - 1):
if t == 0:
states[t] = [0, 0]
else:
states[t] = np.dot(transition_matrix, states[t - 1]) + random_state.randn(n_dim_state)
# Apply the Kalman Filter
mean, cov = kf.filter(states)
This code first sets up the Kalman Filter with the transition and observation matrices. It then generates some sample data and applies the Kalman Filter to this data.
Choosing a Stock and Making a Plot of the Kalman Estimation
Suppose we want to apply the Kalman filter to a stock’s bar chart, such as AMC, which might be interesting because of its violent volatile history, and we wish run it using the free software from Microsoft VSCode. We would need to fetch the stock data first which we can do by using the yfinance
library.
The full script that you can run from VSCode would then be:
import numpy as np
import pandas as pd
import mplfinance as mpf
from pykalman import KalmanFilter
import yfinance as yf
# Fetch the stock data
data = yf.download('AMC', start='2020-01-01', end='2023-12-31')
# Define the transition_matrix, observation_matrix, initial_state_mean and initial_state_covariance
transition_matrix = np.array([[1, 1], [0, 1]])
observation_matrix = np.array([[1, 0]])
kf = KalmanFilter(transition_matrices=transition_matrix,
observation_matrices=observation_matrix,
initial_state_mean=np.zeros(2),
initial_state_covariance=np.ones((2, 2)))
# Apply the Kalman Filter
state_means, state_covariances = kf.filter(data['Close'].values)
# Create a new DataFrame for Kalman Filter data
kf_df = pd.DataFrame(state_means[:, 0], index=data.index, columns=['Kalman Filter'])
# Create OHLC bar chart and overlay with Kalman Filter line
mpf.plot(data, type='ohlc', figratio=(14,8),
title='AMC Stock Price: Kalman Filter Estimation',
ylabel='Price ($)',
addplot=mpf.make_addplot(kf_df['Kalman Filter'], color='r'))
This script will create an OHLC bar chart for the AMC stock price and overlay it with the Kalman Filter estimation line.
Again, you need to have the yfinance
, mplfinance
, pandas
, numpy
, and pykalman
libraries installed. You can install them using pip:
pip install yfinance mplfinance pandas numpy pykalman
The chart created should then look similar to mine:
If we then zoom in on the spike we can get more clarity:
What are we Looking at?
The line printed by the code is a plot of the AMC stock prices along with the Kalman Filter estimation. The Kalman Filter estimation is represented by a red line on the plot. (A bar chart open price is marked on the left of a bar and its close on the right)
The Kalman Filter is used here to estimate the underlying state of the system, which in this case is the true value of the AMC stock. The Kalman Filter takes into account the uncertainty in the measurements (the observed closing prices) and the model (the transition and observation matrices) to provide a more accurate estimate of the true stock value. This line is smoother than the actual stock prices because it represents the underlying trend in the stock prices, with the noise (random fluctuations) filtered out.
In other words, the line printed by the code provides a visual representation of the Kalman Filter’s estimate of the true stock value, which can be useful for understanding the underlying trend in the stock prices and making trading decisions.
In the provided code, the Kalman Filter’s estimate is updated once per bar, using the closing price of the bar:
The line state_means, state_covariances = kf.filter(data['Close'].values)
applies the Kalman Filter to the closing prices (data['Close'].values
).
This means that the estimate would remain fixed when the current bar opens and would not be updated until the closing price for that bar is known. At that point, the Kalman Filter uses the new closing price to update its estimate.
The Kalman Filter’s estimate does not need to stay fixed for the current bar when it opens though. The Kalman Filter is a recursive algorithm, which means it could be coded to update its estimate continuously as new data comes in. It could be made so that when a new bar opens, the Kalman Filter uses the opening price to update its estimate of the underlying state (the true stock value). As the price moves during the bar, the Kalman Filter could continue to update its estimate based on the newly traded prices.
Refer back to the section, ‘Mathematical Construction of the Kalman Filter‘ near the start of this post and note how you might wish to adjust the NoiseCovRatio
for your needs, as it is not explicitly set in our Python code example but instead automatically estimated by the PyKalman library. A large NoiseCovRatio would smooth the red line more and reduce its reactivity to price and trend changes when compared to a small NoiseCovRatio which would react faster but have worse noise smoothing ability.
How to Manually Set NoiseCovRatio in PyKalman:
The NoiseCovRatio
is a hypothetical parameter that represents the ratio of measurement noise to process noise variance. In the PyKalman
library, this would translate to the observation_covariance
and transition_covariance
parameters respectively.
Given:
\text{NoiseCovRatio} = \frac{\text{Measurement Noise Variance}}{\text{Process Noise Variance}}
You can set the observation_covariance
(Measurement Noise Variance) and transition_covariance
(Process Noise Variance) parameters of the KalmanFilter
object based on your desired NoiseCovRatio
.
Here’s how you can do it:
- Decide on a base value for the Process Noise Variance. Let’s call this PNV.
- Calculate the Measurement Noise Variance (MNV) as:
MNV = \text{NoiseCovRatio} \times PNV
- Set these values in the
KalmanFilter
object.
Python Example:
# Given
NoiseCovRatio = 2.0 # This is just an example value; you can set it to whatever you want
PNV = 1.0 # Base value for Process Noise Variance
# Calculate MNV based on the NoiseCovRatio
MNV = NoiseCovRatio * PNV
# Initialize the KalmanFilter object with the calculated values
kf = KalmanFilter(transition_matrices=transition_matrix,
observation_matrices=observation_matrix,
initial_state_mean=np.zeros(2),
initial_state_covariance=np.ones((2, 2)),
observation_covariance=MNV,
transition_covariance=PNV)
This approach allows you to manually control the balance between the measurement noise and process noise in the Kalman Filter, which can influence the smoothness and reactivity of the filter’s estimates. Adjusting the NoiseCovRatio
allows you to experiment with this balance to get the desired output.
How Might you Trade this?
In terms of trading, the Kalman Filter’s estimate can be used as a kind of “target” price. If the actual price moves away from the Kalman Filter’s estimate, this could be seen as a trading opportunity. For example, if the actual price is above the Kalman Filter’s estimate, this could be seen as an indication that the stock is overpriced, and a trader might decide to sell. Conversely, if the actual price is below the Kalman Filter’s estimate, this could be seen as an indication that the stock is under-priced, and a trader might decide to buy.
However, it’s important to note that this is a very simplistic interpretation of the Kalman Filter’s estimate, and actual trading decisions should take into account many other factors.
Key Takeaways
- Understanding the Kalman Filter: This filter is a mathematical method used in time series analysis, particularly in financial applications. It estimates the hidden state of a dynamic system based on noisy observations and updates these predictions as new observations become available.
- Mathematical Construction: It operates in two stages: prediction and update. It uses a series of mathematical equations to predict the current state and its uncertainty, and then updates these predictions with new measurements.
- Application in Trading: In the context of trading, it can be used to estimate the underlying trend in a time series of asset prices. It can help traders identify opportunities for long or short trades, estimate the dynamic hedge ratio in pairs trading, and estimate the volatility of a security’s returns.
- Python Implementation: The post provides a step-by-step tutorial on how to implement a Kalman Filter Python script, using the PyKalman library. It also shows how to apply the Kalman Filter to a stock’s bar chart and interpret the results.
Further Reading
For further reading and a deeper understanding of the Kalman Filter in general and its applications in trading, you can look into these:
“Kalman Filter Made Easy: A Beginners Guide to the Kalman Filter and Extended Kalman Filter with Real Life Examples Supported by Python Source Code” William Franklin (2022)
“Application of Kalman Filter in the Prediction of Stock Price” by Xu Yan, Zhang Guosheng (2015) This short paper presents a real-world application of the Kalman Filter in predicting stock prices. Available at: https://www.atlantis-press.com/proceedings/kam-15/25464
“Kalman Filtering: Theory and Practice Using MATLAB” by Mohinder S. Grewal and Angus P. Andrews. (2014)
Leave a Reply