From 5888cf1657275b9001beabe93da00257eafbee12 Mon Sep 17 00:00:00 2001 From: ChrisPappalardo Date: Thu, 2 Jun 2016 18:12:36 -0700 Subject: [PATCH] ENH: add true range technical factor --- tests/pipeline/test_technical.py | 18 ++++++++++++++++++ zipline/pipeline/factors/__init__.py | 2 ++ zipline/pipeline/factors/technical.py | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/tests/pipeline/test_technical.py b/tests/pipeline/test_technical.py index f63d9b8c..4b910a81 100644 --- a/tests/pipeline/test_technical.py +++ b/tests/pipeline/test_technical.py @@ -18,6 +18,7 @@ from zipline.pipeline.factors import ( IchimokuKinkoHyo, LinearWeightedMovingAverage, RateOfChangePercentage, + TrueRange, ) from zipline.testing import ExplodingObject, parameter_space from zipline.testing.fixtures import WithAssetFinder, ZiplineTestCase @@ -413,3 +414,20 @@ class TestLinearWeightedMovingAverage(ZiplineTestCase): wma2.compute(today, assets, out, data) assert_equal(out, np.array([30., 31., 32., 33., 34.])) + + +class TestTrueRange(WithTechnicalFactor, ZiplineTestCase): + + def test_tr_basic(self): + tr = TrueRange() + + today = pd.Timestamp('2014') + assets = np.arange(3, dtype=np.int64) + out = np.empty(3, dtype=np.float64) + + highs = np.full((2, 3), 3) + lows = np.full((2, 3), 2) + closes = np.full((2, 3), 1) + + tr.compute(today, assets, out, highs, lows, closes) + assert_equal(out, np.full((3,), 2)) diff --git a/zipline/pipeline/factors/__init__.py b/zipline/pipeline/factors/__init__.py index 0b505813..0155cab6 100644 --- a/zipline/pipeline/factors/__init__.py +++ b/zipline/pipeline/factors/__init__.py @@ -29,6 +29,7 @@ from .technical import ( Returns, RSI, SimpleMovingAverage, + TrueRange, VWAP, WeightedAverageValue, ) @@ -58,6 +59,7 @@ __all__ = [ 'RollingSpearmanOfReturns', 'RSI', 'SimpleMovingAverage', + 'TrueRange', 'VWAP', 'WeightedAverageValue', ] diff --git a/zipline/pipeline/factors/technical.py b/zipline/pipeline/factors/technical.py index 42e1736d..b6e10d24 100644 --- a/zipline/pipeline/factors/technical.py +++ b/zipline/pipeline/factors/technical.py @@ -11,6 +11,7 @@ from numpy import ( average, clip, diff, + dstack, exp, fmax, full, @@ -642,3 +643,28 @@ class RateOfChangePercentage(CustomFactor): global_dict={}, out=out, ) + + +class TrueRange(CustomFactor): + """ + True Range + + A technical indicator originally developed by J. Welles Wilder, Jr. + Indicates the true degree of daily price change in an underlying. + """ + + inputs = (USEquityPricing.high, USEquityPricing.low, USEquityPricing.close, ) + window_length = 2 + + def compute(self, today, assets, out, highs, lows, closes): + high_to_low = highs[1:] - lows[1:] + high_to_prev_close = abs(highs[1:] - closes[:-1]) + low_to_prev_close = abs(lows[1:] - closes[:-1]) + out[:] = nanmax( + dstack(( + high_to_low, + high_to_prev_close, + low_to_prev_close, + )), + 2 + )