from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.research import run_pipeline
from quantopian.pipeline.filters import StaticAssets
from quantopian.pipeline.factors import EWMA
from quantopian.pipeline.data.builtin import USEquityPricing
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#from numpy import average, full, arange, nan, isnan
def exponential_weights(length, decay_rate):
return full(length, decay_rate) ** arange(length + 1, 1, -1)
class EWMAWeekly(CustomFactor):
"""
Exponentially Weighted Moving Average
**Default Inputs:** None
**Default Window Length:** None
Parameters
----------
inputs : length-1 list/tuple of BoundColumn
The expression over which to compute the average.
window_length : int > 0
Length of the lookback window over which to compute the average.
ema_lookback : int > 0. This should be the
number of days back to calculate ema.
decay_rate : float, 0 < decay_rate <= 1
Weighting factor by which to discount past observations.
When calculating historical averages, rows are multiplied by the
sequence::
decay_rate, decay_rate ** 2, decay_rate ** 3, ...
Notes
-----
- This class can also be imported under the name ``EWMA``.
See Also
--------
:func:`pandas.ewma`
"""
params = ('decay_rate',)
def compute(self, today, assets, out, data, decay_rate):
out[:] = average(
data[::5],
axis=0,
weights=exponential_weights(len(data[::5]), decay_rate),
)
class PreviousEWMAWeekly(CustomFactor):
"""
Exponentially Weighted Moving Average
**Default Inputs:** None
**Default Window Length:** None
Parameters
----------
inputs : length-1 list/tuple of BoundColumn
The expression over which to compute the average.
window_length : int > 0
Length of the lookback window over which to compute the average.
ema_lookback : int > 0. This should be the
number of days back to calculate ema.
decay_rate : float, 0 < decay_rate <= 1
Weighting factor by which to discount past observations.
When calculating historical averages, rows are multiplied by the
sequence::
decay_rate, decay_rate ** 2, decay_rate ** 3, ...
Notes
-----
- This class can also be imported under the name ``EWMA``.
See Also
--------
:func:`pandas.ewma`
"""
params = ('decay_rate',)
def compute(self, today, assets, out, data, decay_rate):
out[:] = average(
data[:-5:5],
axis=0,
weights=exponential_weights(len(data[:-5:5]), decay_rate),
)
my_asset = symbols('SPY')
my_filter = StaticAssets([my_asset])
# MACD Calculations
# CURRENT
ewma_12wk = EWMAWeekly(inputs=[USEquityPricing.close], window_length=60, decay_rate=0.94, mask=my_filter)
ewma_26wk = EWMAWeekly(inputs=[USEquityPricing.close], window_length=130, decay_rate=0.94, mask=my_filter)
macd_fast = ewma_26wk - ewma_12wk
# ??? SIGNAL LINE ???
# PREVIOUS WEEK
prev_ewma_12wk = PreviousEWMAWeekly(inputs=[USEquityPricing.close], window_length=65, decay_rate=0.94, mask=my_filter)
prev_ewma_26wk = PreviousEWMAWeekly(inputs=[USEquityPricing.close], window_length=135, decay_rate=0.94, mask=my_filter)
prev_macd_fast = prev_ewma_26wk - prev_ewma_12wk
# ??? PREVIOUS SIGNAL LINE ???
# Current and Previous MACD-H
macd = myMACD()
my_pipe = Pipeline(
screen = my_filter,
columns = {
'macd_fast': macd_fast,
'prev_macd_fast': prev_macd_fast
}
)
start_date = '2-5-2009'
end_date = '3-5-2009'
results = run_pipeline(my_pipe, start_date, end_date)
results