Kalman Hull Supertrend

Category: Indicators By: Iván González Created: February 4, 2026, 11:31 AM
February 4, 2026, 11:31 AM
Indicators
4 Comments

Introduction

 

The Kalman Hull Supertrend is a sophisticated technical indicator that combines state-of-the-art mathematical filtering with classic trend-following logic. By integrating a Kalman Filter into the Hull Moving Average (HMA) formula and using that as the engine for a Supertrend, this indicator offers a remarkably smooth baseline that remains highly responsive to price action.

 

Traditional Supertrends often suffer from “whipsaws” in noisy markets. This version addresses that by replacing standard price inputs with a multi-state Kalman filter, significantly reducing market noise while maintaining minimal lag.

 

Core Concepts

 

1. The Kalman Filter

Unlike simple moving averages, the Kalman Filter is an iterative mathematical process that estimates the “true” state of a price series by filtering out random noise. It uses a series of measurements observed over time, containing statistical noise and other inaccuracies, and produces estimates of unknown variables. In this code, it is used to pre-filter the price source before any trend calculations occur.

 

2. The Hull MA Integration

The Hull Moving Average is known for its ability to reduce lag while improving smoothness. By feeding Kalman-filtered data into the HMA calculation, we get a “Kalman HMA” (KalmanHMA). This serves as the central spine of the indicator, providing a cleaner trend bias than a standard average.

 

3. Supertrend Logic

The final layer applies the Supertrend algorithm to the KalmanHMA. It uses the Average True Range (ATR) to create dynamic volatility bands. When price closes above the upper band or below the lower band, the trend direction shifts, and a visual signal is generated.

 

Key Features

 

  • Recursive Filtering: Uses three distinct Kalman states to refine price data and the final HMA curve.
  • Volatility-Adjusted Bands: Adapts to market conditions using ATR to widen or tighten the trend-following stops.
  • Visual Signals: Automatically plots cyan (bullish) and red (bearish) arrows on the chart when a trend reversal is detected.

 

Parameter Configuration

 

ParameterDefault ValueDescriptionPriceSourceCustomCloseThe price data used for filtering (Open, Close, Typical, etc.).

Measurement Noise3Controls how much the filter “trusts” the incoming price. Higher = Smoother.

Process Noise0.01Controls the filter’s agility. Lower = Smoother.

ATR Period12The look-back period for volatility calculation.

Factor1.7The multiplier for the ATR bands. Higher = Fewer signals.

 

Trading Utility

 

  • Long Signals: Indicated by a cyan “▲” below the low of the bar. The Supertrend line will turn cyan, acting as a trailing support.
  • Short Signals: Indicated by a red “▼” above the high of the bar. The Supertrend line will turn red, acting as a trailing resistance.
  • Trend Filter: The KalmanHMA line can be used independently to determine the overall market bias before entering a trade.

 

ProBuilder Code

 

//--------------------------------------------------------------//
//PRC_Kalman Hull Supertrend
//version = 0
//28.05.24
//Iván González @ www.prorealcode.com
//Sharing ProRealTime knowledge
//--------------------------------------------------------------//
//-----Inputs---------------------------------------------------//
pricesource=customclose
measurementNoise=3
processNoise=0.01
atrPeriod=12
factor=1.7
showkalman=1
paintCandles=1
showlongshort=1
//--------------------------------------------------------------//
//-----Kalman Price Filter Function-----------------------------//
N=5
if not isset($stateEstimate1[0]) then
   for j=0 to N-1 do
      $stateEstimate1[j]=pricesource
      $errorCovariance1[j]=1
   next
endif

for i=0 to N-1 do
   $predictedStateEstimate1[i]=$stateEstimate1[i]
   $predictedErrorCovariance1[i]=$errorCovariance1[i]+processNoise
next

for k=0 to N-1 do
   kg1=$predictedErrorCovariance1[k]/($predictedErrorCovariance1[k]+measurementNoise)
   $kalmanGain1[k]=kg1
   $stateEstimate1[k]=$predictedStateEstimate1[k]+kg1*(pricesource-$predictedStateEstimate1[k])
   $errorCovariance1[k]=(1-kg1)*$predictedErrorCovariance1[k]
next
Kalman1=$stateEstimate1[0]
//--------------------------------------------------------------//
//-----Hull Moving Average with Kalman--------------------------//
//Kalman2
if not isset($stateEstimate2[0]) then
   for j=0 to N-1 do
      $stateEstimate2[j]=pricesource
      $errorCovariance2[j]=1
   next
endif

for i=0 to N-1 do
   $predictedStateEstimate2[i]=$stateEstimate2[i]
   $predictedErrorCovariance2[i]=$errorCovariance2[i]+processNoise
next

for k=0 to N-1 do
   kg2=$predictedErrorCovariance2[k]/($predictedErrorCovariance2[k]+measurementNoise/2)
   $kalmanGain2[k]=kg2
   $stateEstimate2[k]=$predictedStateEstimate2[k]+kg2*(pricesource-$predictedStateEstimate2[k])
   $errorCovariance2[k]=(1-kg2)*$predictedErrorCovariance2[k]
next
Kalman2=$stateEstimate2[0]
//Kalman Hull MA
src=2*Kalman2-Kalman1
length=round(sqrt(measurementNoise))
if not isset($stateEstimate3[0]) then
   for j=0 to N-1 do
      $stateEstimate3[j]=src
      $errorCovariance3[j]=1
   next
endif

for i=0 to N-1 do
   $predictedStateEstimate3[i]=$stateEstimate3[i]
   $predictedErrorCovariance3[i]=$errorCovariance3[i]+processNoise
next

for k=0 to N-1 do
   kg3=$predictedErrorCovariance3[k]/($predictedErrorCovariance3[k]+length)
   $kalmanGain3[k]=kg3
   $stateEstimate3[k]=$predictedStateEstimate3[k]+kg3*(src-$predictedStateEstimate3[k])
   $errorCovariance3[k]=(1-kg3)*$predictedErrorCovariance3[k]
next
KalmanHMA=$stateEstimate3[0]
//--------------------------------------------------------------//
//-----SuperTrend Function--------------------------------------//
if barindex <= atrperiod then
   upperband=kalmanHMA
   lowerband=kalmanHMA
   direction=1
else
   atr=averagetruerange[atrPeriod](close)
   upperband=kalmanHMA+factor*atr
   lowerband=kalmanHMA-factor*atr
   prevlowerband=lowerband[1]
   prevupperband=upperband[1]
   
   if lowerband>prevlowerband or close[1]<prevlowerband then
      lowerband=lowerband
   else
      lowerband=prevlowerband
   endif
   
   if upperband<prevupperband or close[1]>prevupperband then
      upperband=upperband
   else
      upperband=prevupperband
   endif
   
   prevST=ST[1]
   if prevST=prevupperband then
      if close > upperband then
         direction=-1
      else
         direction=1
      endif
   else
      if close < lowerband then
         direction=1
      else
         direction=-1
      endif
   endif
   if direction=-1 then
      ST=lowerband
   else
      ST=upperband
   endif
endif
//--------------------------------------------------------------//
//-----Conditional Trend----------------------------------------//
once trend=0
SuperTrendLong=direction crosses under 0
SuperTrendShort=direction crosses over 0
if SupertrendLong and not SuperTrendShort then
   trend=1
   r=0
   g=188
   b=212
   drawtext("▲",barindex,low)coloured(r,g,b)
elsif SuperTrendShort then
   trend=-1
   r=255
   g=82
   b=82
   drawtext("▼",barindex,high)coloured(r,g,b)
endif
//--------------------------------------------------------------//
//--------------------------------------------------------------//
return ST as "Kalman Hull SuperTrend" coloured(r,g,b), KalmanHMA

Download
Filename: PRC_Kalman-Hull-Supertrend.itf
Downloads: 73
Iván González Master
Code artist, my biography is a blank page waiting to be scripted. Imagine a bio so awesome it hasn't been coded yet.
Author’s Profile

Comments

Logo Logo
Loading...