ENH added Chande Kroll Stop indicator

This commit is contained in:
Kevin Johnson
2020-05-19 16:00:14 -07:00
parent 2b739d1c7f
commit 028aafbe85
8 changed files with 120 additions and 3 deletions
+8 -1
View File
@@ -1,3 +1,8 @@
[![Python Version](https://img.shields.io/pypi/pyversions/pandas_ta.svg)](https://pypi.org/project/pandas_ta/)
[![PyPi Version](https://img.shields.io/pypi/v/pandas_ta.svg)](https://pypi.org/project/pandas_ta/)
[![Package Status](https://img.shields.io/pypi/status/pandas_ta.svg)](https://pypi.org/project/pandas_ta/)
[![Downloads](https://img.shields.io/pypi/dm/pandas_ta.svg?style=flat)](https://pypistats.org/packages/pandas_ta)
# Technical Analysis Library in Python 3.7
![Example Chart](/images/TA_Chart.png)
@@ -21,6 +26,7 @@ All the indicators return a named Series or a DataFrame in uppercase underscore
* Added indicators:
- __Bias__ (bias)
- __Choppiness Index__ (chop)
- __Chande Kroll Stop__ (cksp)
- __KDJ__ (kdj)
- __Parabolic Stop and Reverse__ (psar)
- __Price Distance__ (pdist)
@@ -212,12 +218,13 @@ Use parameter: cumulative=**True** for cumulative results.
|:--------:|
| ![Example Z Score](/images/SPY_ZScore.png) |
## _Trend_ (13)
## _Trend_ (14)
* _Average Directional Movement Index_: **adx**
* _Archer Moving Averages Trends_: **amat**
* _Aroon Oscillator_: **aroon**
* _Choppiness Index_: **chop**
* _Chande Kroll Stop_: **cksp**
* _Decreasing_: **decreasing**
* _Detrended Price Oscillator_: **dpo**
* _Increasing_: **increasing**
+1
View File
@@ -92,6 +92,7 @@ from .trend.adx import adx
from .trend.amat import amat
from .trend.aroon import aroon
from .trend.chop import chop
from .trend.cksp import cksp
from .trend.decreasing import decreasing
from .trend.dpo import dpo
from .trend.increasing import increasing
+9
View File
@@ -767,6 +767,15 @@ class AnalysisIndicators(BasePandasObject):
self._append(result, **kwargs)
return result
def cksp(self, high=None, low=None, close=None, p=None, x=None, q=None, offset=None, **kwargs):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from pandas_ta.trend.cksp import cksp
result = cksp(high=high, low=low, close=close, p=p, x=x, q=q, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def decreasing(self, close=None, length=None, asint=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
from pandas_ta.trend.decreasing import decreasing
+89
View File
@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..volatility.atr import atr
from ..utils import get_offset, verify_series
def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
"""Indicator: Chande Kroll Stop (CKSP)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
p = int(p) if p and p > 0 else 10
x = float(x) if x and x > 0 else 1
q = int(q) if q and q > 0 else 9
offset = get_offset(offset)
# Calculate Result
atr_ = atr(high=high, low=low, close=close, length=p)
long_stop_ = high.rolling(p).max() - x * atr_
long_stop = long_stop_.rolling(q).max()
short_stop_ = high.rolling(p).min() + x * atr_
short_stop = short_stop_.rolling(q).min()
# Offset
if offset != 0:
long_stop = long_stop.shift(offset)
short_stop = short_stop.shift(offset)
# Handle fills
if 'fillna' in kwargs:
long_stop.fillna(kwargs['fillna'], inplace=True)
short_stop.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
long_stop.fillna(method=kwargs['fill_method'], inplace=True)
short_stop.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
_props = f"_{p}_{x}_{q}"
long_stop.name = f"CKSPl{_props}"
short_stop.name = f"CKSPs{_props}"
long_stop.category = short_stop.category = 'trend'
# Prepare DataFrame to return
ckspdf = DataFrame({long_stop.name: long_stop, short_stop.name: short_stop})
ckspdf.name = f"CKSP{_props}"
ckspdf.category = 'trend'
return ckspdf
cksp.__doc__ = \
"""Chande Kroll Stop (CKSP)
The Tushar Chande and Stanley Kroll in their book
“The New Technical Trader”. It is a trend-following indicator,
identifying your stop by calculating the average true range of
the recent market volatility.
Sources:
https://www.multicharts.com/discussion/viewtopic.php?t=48914
Calculation:
Default Inputs:
p=10, x=1, q=9
ATR = Average True Range
LS0 = high.rolling(p).max() - x * ATR(length=p)
LS = LS0.rolling(q).max()
SS0 = high.rolling(p).min() + x * ATR(length=p)
SS = SS0.rolling(q).min()
Args:
close (pd.Series): Series of 'close's
p (int): ATR and first stop period. Default: 10
x (float): ATR scalar. Default: 1
q (int): Second stop period. Default: 9
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.DataFrame: long and short columns.
"""
+2 -1
View File
@@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension with 95+ Technical
setup(
name ="pandas_ta",
packages =['pandas_ta', 'pandas_ta.momentum', 'pandas_ta.overlap', 'pandas_ta.performance', 'pandas_ta.statistics', 'pandas_ta.trend', 'pandas_ta.volatility', 'pandas_ta.volume'],
version ="0.1.45b",
version ="0.1.46b",
description =long_description,
long_description =long_description,
author ="Kevin Johnson",
@@ -20,6 +20,7 @@ setup(
license ="The MIT License (MIT)",
classifiers =[
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Development Status :: 4 - Beta',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
+1 -1
View File
@@ -34,7 +34,7 @@ class TestOverlap(TestCase):
def setUp(self): pass
def tearDown(self): pass
def test_dema(self):
result = pandas_ta.dema(self.close)
+5
View File
@@ -81,6 +81,11 @@ class TestTrend(TestCase):
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'CHOP_14_1_100')
def test_cksp(self):
result = pandas_ta.cksp(self.high, self.low, self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'CKSP_10_1_9')
def test_decreasing(self):
result = pandas_ta.decreasing(self.close)
self.assertIsInstance(result, Series)
+5
View File
@@ -43,6 +43,11 @@ class TestTrendExtension(TestCase):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CHOP_14_1_100')
def test_cksp_ext(self):
self.data.ta.cksp(append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CKSPs_10_1_9')
def test_decreasing_ext(self):
self.data.ta.decreasing(append=True)
self.assertIsInstance(self.data, DataFrame)