BLD ehlers super smoother filter added

This commit is contained in:
Kevin Johnson
2020-11-10 14:49:27 -08:00
parent b89222cde0
commit 69988b7fe2
8 changed files with 121 additions and 9 deletions
+3 -1
View File
@@ -461,7 +461,7 @@ print(bothhl2.name) # "pre_HL2_post"
|:--------:|
| ![Example MACD](/images/SPY_MACD.png) |
### **Overlap** (27)
### **Overlap** (28)
* _Double Exponential Moving Average_: **dema**
* _Exponential Moving Average_: **ema**
@@ -482,6 +482,7 @@ print(bothhl2.name) # "pre_HL2_post"
* _WildeR's Moving Average_: **rma**
* _Sine Weighted Moving Average_: **sinwma**
* _Simple Moving Average_: **sma**
* _Ehler's Super Smoother Filter_: **ssf**
* _Supertrend_: **supertrend**
* _Symmetric Weighted Moving Average_: **swma**
* _T3 Moving Average_: **t3**
@@ -621,6 +622,7 @@ trading account, or fund..
* _Quantitative Qualitative Estimation_ (**qqe**) The Quantitative Qualitative Estimation (QQE) is like SuperTrend for a Smoothed RSI. See: ```help(ta.qqe)```
* _SMI Ergodic_ (**smi**) Developed by William Blau, the SMI Ergodic Indicator is the same as the True Strength Index (TSI) except the SMI includes a signal line and oscillator.
* _Squeeze_ (**squeeze**). A Momentum indicator. Both John Carter's TTM **and** Lazybear's TradingView versions are implemented. The default is John Carter's, or ```lazybear=False```. Set ```lazybear=True``` to enable Lazybear's.
* _Ehler's Super Smoother Filter_ (**ssf**). Ehler's solution to reduce lag and remove aliasing noise compared to other common moving average indicators. See: ```help(ta.ssf)```
* _Stochastic RSI_ (**stochrsi**) "Stochastic RSI and Dynamic Momentum Index" was created by Tushar Chande and Stanley Kroll. In line with Trading View's calculation. See: ```help(ta.stochrsi)```
* _TTM Trend_ (**ttm_trend**). A trend indicator inspired from John Carter's book "Mastering the Trade"
issue of Stocks & Commodities Magazine. It is a moving average based trend
+7 -7
View File
@@ -49,21 +49,21 @@ Category = {
"overlap": [
"dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku",
"kama", "linreg", "midpoint", "midprice", "ohlc4", "pwma", "rma",
"sinwma", "sma", "supertrend", "swma", "t3", "tema", "trima", "vwap",
"vwma", "wcp", "wma", "zlma"
"sinwma", "sma", "ssf", "supertrend", "swma", "t3", "tema", "trima",
"vwap", "vwma", "wcp", "wma", "zlma"
],
# Performance
"performance": ["log_return", "percent_return", "trend_return"],
# Statistics
"statistics": [
"entropy", "kurtosis", "mad", "median", "quantile", "skew",
"stdev", "variance", "zscore"
"entropy", "kurtosis", "mad", "median", "quantile", "skew", "stdev",
"variance", "zscore"
],
# Trend
"trend": [
"adx", "amat", "aroon", "chop", "cksp", "decay", "decreasing",
"dpo", "increasing", "long_run", "psar", "qstick", "short_run",
"ttm_trend", "vortex"
"adx", "amat", "aroon", "chop", "cksp", "decay", "decreasing", "dpo",
"increasing", "long_run", "psar", "qstick", "short_run", "ttm_trend",
"vortex"
],
# Volatility
"volatility": [
+5
View File
@@ -1057,6 +1057,11 @@ class AnalysisIndicators(BasePandasObject):
result = sma(close=close, length=length, offset=offset, **kwargs)
return self._post_process(result, **kwargs)
def ssf(self, length=None, poles=None, offset=None, **kwargs):
close = self._get_column(kwargs.pop("close", "close"))
result = ssf(close=close, length=length, poles=poles, offset=offset, **kwargs)
return self._post_process(result, **kwargs)
def supertrend(self, length=None, multiplier=None, offset=None, **kwargs):
high = self._get_column(kwargs.pop("high", "high"))
low = self._get_column(kwargs.pop("low", "low"))
+1
View File
@@ -16,6 +16,7 @@ from .pwma import pwma
from .rma import rma
from .sinwma import sinwma
from .sma import sma
from .ssf import ssf
from .supertrend import supertrend
from .swma import swma
from .t3 import t3
+86
View File
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
from numpy import cos as npCos
from numpy import exp as npExp
from numpy import pi as npPi
from numpy import sqrt as npSqrt
from pandas import Series
from pandas_ta.utils import get_offset, verify_series
def ssf(close, length=None, poles=None, offset=None, **kwargs):
"""Indicator: Ehler's Super Smoother Filter (SSF)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
poles = int(poles) if poles in [2, 3] else 2
offset = get_offset(offset)
# Calculate Result
m = close.size
ssf = close.copy()
ssf[poles:] = 0
if poles == 3:
x = npPi / length # x = PI / n
a0 = npExp(-x) # e^(-x)
b0 = 2 * a0 * npCos(npSqrt(3) * x) # 2e^(-x)*cos(3^(.5) * x)
c0 = a0 * a0 # e^(-2x)
c4 = c0 * c0 # e^(-4x)
c3 = -c0 * (1 + b0) # -e^(-2x) * (1 + 2e^(-x)*cos(3^(.5) * x))
c2 = c0 + b0 # e^(-2x) + 2e^(-x)*cos(3^(.5) * x)
c1 = 1 - c2 - c3 - c4
for i in range(0, m):
ssf.iloc[i] = c1 * close.iloc[i] + c2 * ssf.iloc[i - 1] + c3 * ssf.iloc[i - 2] + c4 * ssf.iloc[i - 3]
else: # poles == 2
x = npPi * npSqrt(2) / length # x = PI * 2^(.5) / n
a0 = npExp(-x) # e^(-x)
a1 = -a0 * a0 # -e^(-2x)
b1 = 2 * a0 * npCos(x) # 2e^(-x)*cos(x)
c1 = 1 - a1 - b1 # e^(-2x) - 2e^(-x)*cos(x) + 1
for i in range(0, m):
ssf.iloc[i] = c1 * close.iloc[i] + b1 * ssf.iloc[i - 1] + a1 * ssf.iloc[i - 2]
# Offset
if offset != 0:
ssf = ssf.shift(offset)
# Name & Category
ssf.name = f"SSF_{length}_{poles}"
ssf.category = "overlap"
return ssf
ssf.__doc__ = \
"""Ehler's Super Smoother Filter (SSF)
Ehler's solution to reduce lag and remove aliasing noise with his research in
aerospace analog filter design. © 2013 John F. Ehlers
Sources:
http://www.stockspotter.com/files/PredictiveIndicators.pdf
https://www.tradingview.com/script/VdJy0yBJ-Ehlers-Super-Smoother-Filter/
https://www.mql5.com/en/code/588
https://www.mql5.com/en/code/589
Calculation:
Default Inputs:
length=10, poles=[2, 3]
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
poles (int): The number of poles to use, either 2 or 3. Default: 2
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+1 -1
View File
@@ -17,7 +17,7 @@ setup(
"pandas_ta.volatility",
"pandas_ta.volume"
],
version=".".join(("0", "2", "25b")),
version=".".join(("0", "2", "26b")),
description=long_description,
long_description=long_description,
author="Kevin Johnson",
+9
View File
@@ -103,6 +103,15 @@ class TestOverlapExtension(TestCase):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "SMA_10")
def test_ssf_ext(self):
self.data.ta.ssf(append=True, poles=2)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "SSF_10_2")
self.data.ta.ssf(append=True, poles=3)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "SSF_10_3")
def test_swma_ext(self):
self.data.ta.swma(append=True)
self.assertIsInstance(self.data, DataFrame)
+9
View File
@@ -242,6 +242,15 @@ class TestOverlap(TestCase):
except Exception as ex:
error_analysis(result, CORRELATION, ex)
def test_ssf(self):
result = pandas_ta.ssf(self.close, poles=2)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, "SSF_10_2")
result = pandas_ta.ssf(self.close, poles=3)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, "SSF_10_3")
def test_swma(self):
result = pandas_ta.swma(self.close)
self.assertIsInstance(result, Series)