added trend_return function and tests

This commit is contained in:
Kevin Johnson
2019-04-11 13:53:00 -07:00
parent 3f9c7f4035
commit dc82732301
6 changed files with 158 additions and 11 deletions
+2 -1
View File
@@ -136,12 +136,13 @@ help(pd.DataFrame().ta.log_return)
|:--------:|
| ![Example Chart](/images/TA_Chart.png) |
## _Performance_ (2)
## _Performance_ (3)
Use parameter: cumulative=**True** for cumulative results.
* _Log Return_: **log_return**
* _Percent Return_: **percent_return**
* _Trend Return_: **trend_return**
| _Percent Return_ (Cumulative) with _Simple Moving Average_ (SMA) |
|:--------:|
+6
View File
@@ -516,6 +516,12 @@ class AnalysisIndicators(BasePandasObject):
self._append(result, **kwargs)
return result
def trend_return(self, close=None, trend=None, log=True, cumulative=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
trend = self._get_column(trend, f"{trend}")
result = trend_return(close=close, trend=trend, log=log, cumulative=cumulative, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
# Statistics Indicators
+97 -7
View File
@@ -2,7 +2,7 @@
import numpy as np
import pandas as pd
from .utils import get_offset, verify_series
from .utils import get_offset, verify_series, zero
@@ -54,6 +54,49 @@ def percent_return(close, length=None, cumulative=False, offset=None, **kwargs):
return pct_return
def trend_return(close, trend, trend_reset=0, log=True, cumulative=False, offset=None, **kwargs):
"""Indicator: Trend Return"""
# Validate Arguments
close = verify_series(close)
trend = verify_series(trend)
offset = get_offset(offset)
variable = kwargs.pop('variable', False)
# Calculate Result
returns = log_return(close, cumulative=False) if log else percent_return(close, cumulative=False)
m = trend.size
tsum = 0
result = []
returns = (trend * returns).apply(zero)
# trend = trend.astype(int)
for i in range(0, m):
if trend[i] == trend_reset:
tsum = 0
else:
return_ = returns[i]
if cumulative:
tsum += return_
else:
tsum = return_
result.append(tsum)
trend_return = pd.Series(result)
# Experimental: Add the individual return flucuations to the cumulative returns
if variable and cumulative:
trend_return += returns
# Offset
if offset != 0:
trend_return = trend_return.shift(offset)
# Name & Category
trend_return.name = f"{'C' if cumulative else ''}{'L' if log else 'P'}TR"
trend_return.category = 'performance'
return trend_return
log_return.__doc__ = \
"""Log Return
@@ -66,14 +109,14 @@ Sources:
Calculation:
Default Inputs:
length=1, cummulative=False
length=1, cumulative=False
LOGRET = log( close.diff(periods=length) )
CUMLOGRET = LOGRET.cumsum() if cummulative
CUMLOGRET = LOGRET.cumsum() if cumulative
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 20
cummulative (bool): If True, returns the cummulative returns. Default: False
cumulative (bool): If True, returns the cumulative returns. Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
@@ -96,20 +139,67 @@ Sources:
Calculation:
Default Inputs:
length=1, cummulative=False
length=1, cumulative=False
PCTRET = close.pct_change(length)
CUMPCTRET = PCTRET.cumsum() if cummulative
CUMPCTRET = PCTRET.cumsum() if cumulative
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 20
cummulative (bool): If True, returns the cummulative returns. Default: False
cumulative (bool): If True, returns the cumulative returns. Default: False
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.
"""
trend_return.__doc__ = \
"""Trend Return
Calculates the (Cumulative) Returns of a Trend as defined by some conditional.
By default it calculates log returns but can also use percent change.
Sources: Kevin Johnson
Calculation:
Default Inputs:
trend_reset=0, log=True, cumulative=False
sum = 0
returns = log_return if log else percent_return # These are not cumulative
returns = (trend * returns).apply(zero)
for i, in range(0, trend.size):
if item == trend_reset:
sum = 0
else:
return_ = returns.iloc[i]
if cumulative:
sum += return_
else:
sum = return_
trend_return.append(sum)
if cumulative and variable:
trend_return += returns
Args:
close (pd.Series): Series of 'close's
trend (pd.Series): Series of 'trend's. Preferably 0's and 1's.
trend_reset (value): Value used to identify if a trend has ended. Default: 0
log (bool): Calculate logarithmic returns. Default: True
cumulative (bool): If True, returns the cumulative returns. Default: False
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
variable (bool, optional): Whether to include if return fluxuations in the cumulative returns.
Returns:
pd.Series: New feature generated.
"""
+1 -1
View File
@@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension of Technical Analys
setup(
name = "pandas_ta",
packages = ["pandas_ta"],
version = "0.1.12a",
version = "0.1.13a",
description=long_description,
long_description=long_description,
author = "Kevin Johnson",
+27 -1
View File
@@ -11,11 +11,13 @@ class TestPerformace(TestCase):
def setUpClass(cls):
cls.data = sample_data
cls.close = cls.data['close']
cls.islong = cls.close > pandas_ta.sma(cls.close, length=50)
@classmethod
def tearDownClass(cls):
del cls.data
del cls.close
del cls.islong
def setUp(self):
@@ -41,4 +43,28 @@ class TestPerformace(TestCase):
def test_cum_percent_return(self):
result = self.performance.percent_return(self.close, cumulative=True)
self.assertEqual(result.name, 'CUMPCTRET_1')
self.assertEqual(result.name, 'CUMPCTRET_1')
def test_log_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=True, cumulative=False)
self.assertEqual(result.name, 'LTR')
def test_cum_log_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=True, cumulative=True)
self.assertEqual(result.name, 'CLTR')
def test_variable_cum_log_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=True, cumulative=True, variable=True)
self.assertEqual(result.name, 'CLTR')
def test_pct_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=False, cumulative=False)
self.assertEqual(result.name, 'PTR')
def test_cum_pct_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=False, cumulative=True)
self.assertEqual(result.name, 'CPTR')
def test_variable_pct_log_trend_return(self):
result = self.performance.trend_return(self.close, self.islong, log=False, cumulative=True, variable=True)
self.assertEqual(result.name, 'CPTR')
+25 -1
View File
@@ -12,10 +12,12 @@ class TestPerformaceExtension(TestCase):
@classmethod
def setUpClass(cls):
cls.data = sample_data
cls.islong = cls.data['close'] > pandas_ta.sma(cls.data['close'], length=50)
@classmethod
def tearDownClass(cls):
del cls.data
del cls.islong
def setUp(self):
@@ -30,6 +32,7 @@ class TestPerformaceExtension(TestCase):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'LOGRET_1')
def test_cum_log_return_ext(self):
self.data.ta.log_return(append=True, cumulative=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CUMLOGRET_1')
@@ -39,6 +42,27 @@ class TestPerformaceExtension(TestCase):
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'PCTRET_1')
def test_cum_percent_return_ext(self):
self.data.ta.percent_return(append=True, cumulative=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CUMPCTRET_1')
self.assertEqual(self.data.columns[-1], 'CUMPCTRET_1')
def test_log_trend_return_ext(self):
self.data.ta.trend_return(trend=self.islong, log=True, cumulative=False, append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'LTR')
def test_cum_log_trend_return_ext(self):
self.data.ta.trend_return(trend=self.islong, log=True, cumulative=True, append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CLTR')
def test_pct_trend_return_ext(self):
self.data.ta.trend_return(trend=self.islong, log=False, cumulative=False, append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'PTR')
def test_cum_pct_trend_return_ext(self):
self.data.ta.trend_return(trend=self.islong, log=False, cumulative=True, append=True)
self.assertIsInstance(self.data, DataFrame)
self.assertEqual(self.data.columns[-1], 'CPTR')