2. Regression channels: the trend and its volatility
Level 6: Regression and Pricing Models
Before getting into the mathematical description of pricing models, it is worth seeing how traders use regression in technical analysis, because it is the most direct and intuitive use of all.
In technical analysis, the linear regression indicator and regression channels stand out as tools that give the trader two things at once: a view on the direction of the trend and a measure of the potential volatility around that trend. Underneath they are pure statistical analysis applied to a chart: a quantifiable approach to market dynamics.
Channels are an important component of technical analysis and there are quite a few different techniques: the Fibonacci channel, Andrews' pitchfork, the Keltner channel. The linear regression channel is a three-line indicator that marks out the ceiling, the floor and the center of the price movement being analyzed.
The central line is the regression line fitted to the price. The upper channel line (UCL) and the lower one (LCL) are drawn a given number of standard deviations above and below, normally two. The space between UCL and LCL represents the range of movement expected for the asset given its past trend and volatility. When the price leaves the channel, it may be signaling an overextension and a possible return to the mean.
It is common to combine Bollinger bands and a regression channel to build strategies:
import pandas as pd
import yfinance as yf
import mplfinance as mpf
import pandas_ta as ta
import numpy as np
# 1. We download the NVIDIA data
start_date = '2020-08-01'
end_date = '2021-01-01'
stock_symbol = 'NVDA'
data = yf.download(stock_symbol, start=start_date, end=end_date)
# 2. Bollinger bands with pandas-ta
data.ta.bbands(close='Close', length=20, append=True)
# 3. Regression channel
x = np.array(range(len(data)))
y = data['Close'].values
slope, intercept = np.polyfit(x, y, 1)
data['Regression'] = slope * x + intercept
residuals = y - data['Regression']
std_error = np.std(residuals)
data['Upper Regression'] = data['Regression'] + (2 * std_error)
data['Lower Regression'] = data['Regression'] - (2 * std_error)Note a detail that gets overlooked constantly: the variable x is not dates, it is an ordinal counter 0, 1, 2, 3... By regressing the price against that counter, the slope is read as dollars gained per bar, and weekend or holiday gaps disappear from the calculation.
And a still more important warning: this channel is fitted over the whole sample at once. The line at day 10 has been computed using the prices of day 100 as well. As a descriptive snapshot of a past stretch it is perfectly valid, but if you use it as it stands inside a backtest you are introducing look-ahead bias, because you are deciding with information that did not exist at that moment. To trade for real, the channel has to be recomputed at each bar using only the preceding window.
And a conceptual difference with Bollinger: Bollinger bands are drawn around a moving average that is recomputed bar by bar, whereas the regression channel is drawn around a static line fitted to the whole stretch.
To go deeper into this lesson
- Volatilityin the glossary
- Factor (factor investing)in the glossary