Skip to content

Commit

Permalink
ENH tos_stdevall initial code in dev
Browse files Browse the repository at this point in the history
  • Loading branch information
twopirllc committed Jun 20, 2021
1 parent b6cbcef commit 3728266
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 9 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
* [Momentum](#momentum-40)
* [Overlap](#overlap-32)
* [Performance](#performance-3)
* [Statistics](#statistics-9)
* [Statistics](#statistics-10)
* [Trend](#trend-18)
* [Utility](#utility-5)
* [Volatility](#volatility-14)
Expand Down Expand Up @@ -110,7 +110,7 @@ $ pip install pandas_ta

Latest Version
--------------
Best choice! Version: *0.2.92b*
Best choice! Version: *0.2.93b*
```sh
$ pip install -U git+https://github.com/twopirllc/pandas-ta
```
Expand Down Expand Up @@ -774,7 +774,7 @@ Use parameter: cumulative=**True** for cumulative results.
| ![Example Cumulative Percent Return](/images/SPY_CumulativePercentReturn.png) |
<br/>

### **Statistics** (9)
### **Statistics** (10)

* _Entropy_: **entropy**
* _Kurtosis_: **kurtosis**
Expand Down
1 change: 1 addition & 0 deletions pandas_ta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
# Statistics
"statistics": [
"entropy", "kurtosis", "mad", "median", "quantile", "skew", "stdev",
# "tos_stdevall",
"variance", "zscore"
],
# Trend
Expand Down
5 changes: 5 additions & 0 deletions pandas_ta/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,11 @@ def stdev(self, length=None, offset=None, **kwargs):
result = stdev(close=close, length=length, offset=offset, **kwargs)
return self._post_process(result, **kwargs)

# def tos_stdevall(self, length=None, stds=None, offset=None, **kwargs):
# close = self._get_column(kwargs.pop("close", "close"))
# result = tos_stdevall(close=close, length=length, stds=stds, offset=offset, **kwargs)
# return self._post_process(result, **kwargs)

def variance(self, length=None, offset=None, **kwargs):
close = self._get_column(kwargs.pop("close", "close"))
result = variance(close=close, length=length, offset=offset, **kwargs)
Expand Down
1 change: 1 addition & 0 deletions pandas_ta/statistics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
from .quantile import quantile
from .skew import skew
from .stdev import stdev
from .tos_stdevall import tos_stdevall
from .variance import variance
from .zscore import zscore
104 changes: 104 additions & 0 deletions pandas_ta/statistics/tos_stdevall.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
from numpy import array as npArray
from numpy import arange as npArange
from numpy import polyfit as npPolyfit
from numpy import std as npStd
from pandas import DataFrame, DatetimeIndex, Series
# from pandas_ta import Imports
from .stdev import stdev as stdev
from pandas_ta.utils import get_offset, verify_series

def tos_stdevall(close, length=None, stds=None, ddof=None, offset=None, **kwargs):
"""Indicator: TD Ameritrade's Think or Swim Standard Deviation All"""
# Validate Arguments
stds = stds if isinstance(stds, list) and len(stds) > 0 else [1, 2, 3]
if min(stds) <= 0: return
if not all(i < j for i, j in zip(stds, stds[1:])):
stds = stds[::-1]
ddof = int(ddof) if ddof and ddof >= 0 and ddof < length else 1
offset = get_offset(offset)

if length is None:
length = close.size
_props = f"STDEVALL"
else:
length = int(length) if length and length > 2 else 30
close = close.iloc[-length:]
_props = f"STDEVALL_{length}"

close = verify_series(close, length)

if close is None: return

# Calculate Result
if isinstance(close.index, DatetimeIndex):
close_ = npArray(close)
np_index = npArange(length)
m, b = npPolyfit(np_index, close_, 1)
lr_ = m * np_index + b
else:
m, b = npPolyfit(close.index, close, 1)
lr_ = m * close.index + b

lr = Series(lr_, index=close.index)
stdevall = stdev(Series(close), length=length, ddof=ddof)
# std = npStd(close, ddof=ddof)

# Name and Categorize it
df = DataFrame({f"{_props}_LR": lr}, index=close.index)
for i in stds:
df[f"{_props}_L_{i}"] = lr - i * stdevall.iloc[-1]
df[f"{_props}_U_{i}"] = lr + i * stdevall.iloc[-1]
df[f"{_props}_L_{i}"].name = df[f"{_props}_U_{i}"].name = f"{_props}"
df[f"{_props}_L_{i}"].category = df[f"{_props}_U_{i}"].category = "statistics"

# Offset
if offset != 0:
df = df.shift(offset)

# Handle fills
if "fillna" in kwargs:
df.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
df.fillna(method=kwargs["fill_method"], inplace=True)

# Prepare DataFrame to return
df.name = f"{_props}"
df.category = "statistics"

return df


tos_stdevall.__doc__ = \
"""TD Ameritrade's Think or Swim Standard Deviation All (TOS_STDEV)
**UNDER DEVELOPMENT**
A port of TD Ameritrade's Think or Swim Standard Deviation All indicator which
returns the standard deviation of data for the entire plot or for the interval
of the last bars defined by the length parameter.
Sources:
https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/StDevAll
Calculation:
Default Inputs:
length=30
VAR = Variance
STDEV = variance(close, length).apply(np.sqrt)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 1
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.
"""
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"pandas_ta.volatility",
"pandas_ta.volume"
],
version=".".join(("0", "2", "92b")),
version=".".join(("0", "2", "93b")),
description=long_description,
long_description=long_description,
author="Kevin Johnson",
Expand Down
3 changes: 1 addition & 2 deletions tests/test_ext_indicator_momentum.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,7 @@ def test_squeeze_ext(self):

self.data.ta.squeeze(tr=False, append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(
list(self.data.columns[-4:]),
self.assertEqual(list(self.data.columns[-4:]),
["SQZ_ON", "SQZ_OFF", "SQZ_NO", "SQZhlr_20_2.0_20_1.5"]
)

Expand Down
13 changes: 12 additions & 1 deletion tests/test_ext_indicator_statistics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .config import sample_data
from .context import pandas_ta

from unittest import TestCase
from unittest import skip, TestCase
from pandas import DataFrame


Expand Down Expand Up @@ -53,6 +53,17 @@ def test_stdev_ext(self):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], "STDEV_30")

@skip
def test_tos_stdevall_ext(self):
self.data.ta.tos_stdevall(append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(list(self.data.columns[-7:]), [
"STDEVALL_LR",
"STDEVALL_L_1", "STDEVALL_U_1",
"STDEVALL_L_2", "STDEVALL_U_2",
"STDEVALL_L_3", "STDEVALL_U_3"
])

def test_variance_ext(self):
self.data.ta.variance(append=True)
self.assertIsInstance(self.data, DataFrame)
Expand Down
21 changes: 19 additions & 2 deletions tests/test_indicator_statistics.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .config import error_analysis, sample_data, CORRELATION, CORRELATION_THRESHOLD, VERBOSE
from .context import pandas_ta

from unittest import TestCase, skip
from unittest import skip, TestCase
import pandas.testing as pdt
from pandas import Series
from pandas import DataFrame, Series

import talib as tal

Expand Down Expand Up @@ -79,6 +79,23 @@ def test_stdev(self):
except Exception as ex:
error_analysis(result, CORRELATION, ex)

@skip
def test_tos_sdtevall(self):
result = pandas_ta.tos_stdevall(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, "STDEVALL")
self.assertEqual(len(result.columns), 7)

result = pandas_ta.tos_stdevall(self.close, length=30)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, "STDEVALL_30")
self.assertEqual(len(result.columns), 7)

result = pandas_ta.tos_stdevall(self.close, length=30, stds=[1, 2])
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, "STDEVALL_30")
self.assertEqual(len(result.columns), 5)

def test_variance(self):
result = pandas_ta.variance(self.close)
self.assertIsInstance(result, Series)
Expand Down

0 comments on commit 3728266

Please sign in to comment.