Swiss Army Knife - High-Pass Filter (SWAK_HP)
Summary
The high-pass row of John Ehlers' Swiss Army Knife filter: a one-pole detrender that removes what is slower than the cutoff period and keeps what is faster.
Read it as an oscillator, not as price. Its DC gain is 0, so a flat market returns zero and a trending one returns the trend's departure from itself rather than its level. That is the point of a detrender: what remains is the cyclic part of the series, centred on zero, which can then be measured or compared across instruments whose price levels differ by orders of magnitude.
The alpha is the cutoff-period one. Ehlers notes that it "is computed exactly the same as it is for the EMA", meaning the same construction, not TA_EMA's 2/(n+1).
Chart
Chart metadata i
Outputs
outReal:line·zero·positive·negative
Formula
w = 2 * pi / optInTimePeriod
a1p = (cos(w) + sin(w) - 1) / cos(w)
c0 = 1 - a1p / 2
a1 = 1 - a1p
y[i] = c0 * (x[i] - x[i-1]) + a1 * y[i-1]The filter is seeded in the steady state of a constant input equal to its first bar: the input slot starts at that bar and the output slot at zero, which is what a gain-0 row answers for a constant.
Notes
The period range starts at 5 because of arithmetic rather than taste. At a period of 4, cos(w) is zero and so is the numerator, so a1p is 0/0 and no filter comes out of it. At a period of 2, cos(w) is -1 and c0 is 0, a filter that answers nothing at all. No contiguous range below 5 avoids both.
Every term of the recurrence exists at the first bar, so there is no structural lookback. What the first bars carry is the seed, which decays rather than ending: set TA_FUNC_UNST_SWAK_HP to discard bars until that transient is below whatever matters for the caller.
The output may alias the input. This row reads x[i-1], which an aliased write would already have overwritten, so it is carried in a local and never re-read from the input array.
Inputs
inReal— The series to detrend; Ehlers' default is the bar midpoint(H+L)/2, which the caller passes asTA_MEDPRICEoutput
Outputs
outReal— The detrended line, centred on zero
Parameters
| Parameter | Type | Default | Accepted values | Description |
|---|---|---|---|---|
optInTimePeriod | integer | 20 | 5–100000 | Cutoff period; cycles longer than it are removed, cycles shorter pass |
Properties
Numerical Stability: Initial Unstable Period
| ☐ Overlap Input |
| ✅ Independent Y-Axis i |
| ☐ Candlestick |
| ☐ Display Shift |
| ☐ Can Output NaN or ±Inf |
| ☐ Identity at Period 1 |
| ✅ Uses Transcendental i |
| ☐ Input Must Be Positive |
Example
#include <stdio.h>
#include <ta_libc.h>
int n = 252;
double series[252]; /* your data, oldest first */
double out[252];
int outBegIdx, outNBElement;
TA_Initialize();
TA_SWAK_HP( 0, n - 1, series, 20, &outBegIdx, &outNBElement, out );
printf( "%d values from bar %d; last out = %f\n", outNBElement, outBegIdx, out[outNBElement - 1] );use ta_lib::Core;
let series = vec![0.0; 252]; // your data, oldest first
let mut out = vec![0.0; 252];
let core = Core::new();
let range = core.swak_hp(0, series.len() - 1, &series, 20, &mut out)?;
println!("{} values from bar {}; last out = {}", range.count, range.beg_idx, out[range.count - 1]);import io.github.talib.Core;
import io.github.talib.OutRange;
double[] series = new double[252]; // your data, oldest first
double[] out = new double[252];
Core core = Core.DEFAULT;
OutRange r = core.swakHp(0, series.length - 1, series, 20, out);
System.out.println(r.count() + " values from bar " + r.begIdx() + "; last out = " + out[r.count() - 1]);using System;
using TALib;
var series = new double[252]; // your data, oldest first
var outReal = new double[252];
var core = Core.Default;
OutRange r = core.SwakHp(0, series.Length - 1, series, 20, outReal);
Console.WriteLine($"{r.Count} values from bar {r.BegIdx}; last outReal = {outReal[r.Count - 1]}");import { swakHp } from 'ta-lib';
const series = new Float64Array(252); // your data, oldest first
const { begIdx, values } = swakHp(series, { timePeriod: 20 });
console.log(values.length + ' values from bar ' + begIdx + '; last values = ' + values[values.length - 1]);import (
"fmt"
"log"
talib "ta-lib.github.io/go"
)
series := make([]float64, 252) // your data, oldest first
out := make([]float64, 252)
core := talib.NewCore()
r, err := core.SWAK_HP(0, len(series)-1, series, 20, out)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d values from bar %d; last out = %.4f\n", r.NBElement, r.BegIdx, out[r.NBElement-1])Implementation
Added in 0.8.3 (ta-lib-python 0.8.3).
TA-Lib Definition: swak_hp.c · swak_hp.yaml
| Native | File |
|---|---|
| C | ta_SWAK_HP.c |
| Rust | swak_hp.rs |
| Java | Core_SWAK_HP.java |
| C# | Core_SWAK_HP.cs |
| TypeScript | swakHp.ts |
| Go | swak_hp.go |
Python: talib.SWAK_HP (ta-lib-python 0.8.3 or later), see ta-lib-python.
TA-Lib is also available for R and more using a wrapper.
Aliases
Swiss Army Knife High-Pass Filter, SWAK HP, Ehlers High-Pass Filter
See Also
SWAK_2PHP · SWAK_BP · MEDPRICE
References
- Ehlers, John F. "Swiss Army Knife Indicator." Technical Analysis of Stocks & Commodities V.24:1 (January 2006), pp. 28-31, 50-53.