mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-03 01:07:15 +08:00
Merge pull request #1325 from quantopian/lwma
ENH: Adds LinearWeightedMovingAverage factor
This commit is contained in:
@@ -16,6 +16,7 @@ from zipline.pipeline.factors import (
|
||||
Aroon,
|
||||
FastStochasticOscillator,
|
||||
IchimokuKinkoHyo,
|
||||
LinearWeightedMovingAverage,
|
||||
RateOfChangePercentage,
|
||||
)
|
||||
from zipline.testing import ExplodingObject, parameter_space
|
||||
@@ -380,3 +381,35 @@ class TestRateOfChangePercentage(ZiplineTestCase):
|
||||
out = np.zeros(len(assets))
|
||||
rocp.compute(today, assets, out, data)
|
||||
assert_equal(out, np.full((len(assets),), expected))
|
||||
|
||||
|
||||
class TestLinearWeightedMovingAverage(ZiplineTestCase):
|
||||
def test_wma1(self):
|
||||
wma1 = LinearWeightedMovingAverage(
|
||||
inputs=(USEquityPricing.close,),
|
||||
window_length=10
|
||||
)
|
||||
|
||||
today = pd.Timestamp('2015')
|
||||
assets = np.arange(5, dtype=np.int64)
|
||||
|
||||
data = np.ones((10, 5))
|
||||
out = np.zeros(data.shape[1])
|
||||
|
||||
wma1.compute(today, assets, out, data)
|
||||
assert_equal(out, np.ones(5))
|
||||
|
||||
def test_wma2(self):
|
||||
wma2 = LinearWeightedMovingAverage(
|
||||
inputs=(USEquityPricing.close,),
|
||||
window_length=10
|
||||
)
|
||||
|
||||
today = pd.Timestamp('2015')
|
||||
assets = np.arange(5, dtype=np.int64)
|
||||
|
||||
data = np.arange(50, dtype=float).reshape((10, 5))
|
||||
out = np.zeros(data.shape[1])
|
||||
|
||||
wma2.compute(today, assets, out, data)
|
||||
assert_equal(out, np.array([30., 31., 32., 33., 34.]))
|
||||
|
||||
@@ -23,6 +23,7 @@ from .technical import (
|
||||
ExponentialWeightedMovingStdDev,
|
||||
FastStochasticOscillator,
|
||||
IchimokuKinkoHyo,
|
||||
LinearWeightedMovingAverage,
|
||||
MaxDrawdown,
|
||||
RateOfChangePercentage,
|
||||
Returns,
|
||||
@@ -47,6 +48,7 @@ __all__ = [
|
||||
'FastStochasticOscillator',
|
||||
'IchimokuKinkoHyo',
|
||||
'Latest',
|
||||
'LinearWeightedMovingAverage',
|
||||
'MaxDrawdown',
|
||||
'RateOfChangePercentage',
|
||||
'RecarrayField',
|
||||
|
||||
@@ -364,6 +364,35 @@ class ExponentialWeightedMovingAverage(_ExponentialWeightedFactor):
|
||||
)
|
||||
|
||||
|
||||
class LinearWeightedMovingAverage(CustomFactor, SingleInputMixin):
|
||||
"""
|
||||
Weighted Average Value of an arbitrary column
|
||||
|
||||
**Default Inputs**: None
|
||||
|
||||
**Default Window Length**: None
|
||||
"""
|
||||
# numpy's nan functions throw warnings when passed an array containing only
|
||||
# nans, but they still returns the desired value (nan), so we ignore the
|
||||
# warning.
|
||||
ctx = ignore_nanwarnings()
|
||||
|
||||
def compute(self, today, assets, out, data):
|
||||
num_days = data.shape[0]
|
||||
|
||||
# Initialize weights array
|
||||
weights = arange(1, num_days + 1, dtype=float).reshape(num_days, 1)
|
||||
|
||||
# Compute normalizer
|
||||
normalizer = (num_days * (num_days + 1)) / 2
|
||||
|
||||
# Weight the data
|
||||
weighted_data = data * weights
|
||||
|
||||
# Compute weighted averages
|
||||
out[:] = nansum(weighted_data, axis=0) / normalizer
|
||||
|
||||
|
||||
class ExponentialWeightedMovingStdDev(_ExponentialWeightedFactor):
|
||||
"""
|
||||
Exponentially Weighted Moving Standard Deviation
|
||||
|
||||
Reference in New Issue
Block a user