Skip to content

Commit

Permalink
Fix Chande-Kroll stop twopirllc#256, and twopirllc#257
Browse files Browse the repository at this point in the history
Add an optional "tvmode" parameter that controls the behaviour of the
Chande-Kroll volatility stop. The default, True, retains the used
behaviour, compatibility with Trading View. When False however, the
moving average mode used is now a simple moving average instead of the
Welles Wilder moving average and the periods used are different as well,
(10/1/9 vs 10/3/20).

Update the unit tests to account for the optional parameter, though
sadly we have no TA-lib implementation to compare with, and the Japanese
Yen Futures 09/93 contract used in figure 7.4 page 95 of the book, has
no freely available OHLC data i could find.
  • Loading branch information
luisbarrancos committed Mar 30, 2021
1 parent 360a26d commit 4865399
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
40 changes: 26 additions & 14 deletions pandas_ta/trend/cksp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,32 @@
from pandas_ta.utils import get_offset, verify_series


def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
def cksp(high, low, close, p=None, x=None, q=None, offset=None, tvmode=None, **kwargs):
"""Indicator: Chande Kroll Stop (CKSP)"""
# Validate Arguments
# TV defaults=(10,1,9), book defaults = (10,3,20)
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
x = float(x) if x and x > 0 else 1 if tvmode is True else 3
q = int(q) if q and q > 0 else 9 if tvmode is True else 20

_length = max(p, q, x)

high = verify_series(high, _length)
low = verify_series(low, _length)
close = verify_series(close, _length)
offset = get_offset(offset)

if high is None or low is None or close is None: return

# Calculate Result
atr_ = atr(high=high, low=low, close=close, length=p)
offset = get_offset(offset)
tvmode = tvmode if isinstance(tvmode, bool) else True

mamode = "rma" if tvmode is True else "sma"
atr_ = atr(high=high, low=low, close=close, length=p, mamode = mamode)

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_ = low.rolling(p).min() + x * atr_
short_stop = short_stop_.rolling(q).min()

# Offset
Expand Down Expand Up @@ -57,16 +62,22 @@ def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
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.
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. The indicator defaults to the implementation
found on tradingview but it provides the original book implementation as well,
which differs by the default periods and moving average mode. While the trading
view implementation uses the Welles Wilder moving average, the book uses a
simple moving average.
Sources:
https://www.multicharts.com/discussion/viewtopic.php?t=48914
"The New Technical Trader", Wikey 1st ed. ISBN 9780471597803, page 95
Calculation:
Default Inputs:
p=10, x=1, q=9
p=10, x=1, q=9, tvmode=True
ATR = Average True Range
LS0 = high.rolling(p).max() - x * ATR(length=p)
Expand All @@ -77,10 +88,11 @@ def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
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
p (int): ATR and first stop period. Default: 10 in both modes
x (float): ATR scalar. Default: 1 in TV mode, 3 otherwise
q (int): Second stop period. Default: 9 in TV mode, 20 otherwise
offset (int): How many periods to offset the result. Default: 0
tvmode (bool): Trading View or book implementation mode. Default: True
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
Expand Down
1 change: 1 addition & 0 deletions tests/test_ext_indicator_trend.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def test_chop_ext(self):

def test_cksp_ext(self):
self.data.ta.cksp(append=True)
self.data.ta.cksp(tv=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "CKSPs_10_1_9")

Expand Down

0 comments on commit 4865399

Please sign in to comment.