from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.research import run_pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import Latest
import numpy as np
class MaxHigh(CustomFactor):
# Define inputs
inputs = [USEquityPricing.high]
# Set window_length to whatever number of days to lookback as a default
# in the case where no window_length is given when instantiated.
# This can also be set/over-ridden as shown below:
# my_high_10 = MaxHigh(window_length = 10)
window_length = 2
def compute(self, today, assets, out, high):
# The input 'high' is a Numpy array with high prices as axis 0 (total rows = window length)
# and axis 1 are all the assets (ie stocks and securities).
# Here we use the built in Numpy method to return the high in each row.
# The nanmax method is used because it excludes nans unlike the standard max
out[:] = np.nanmax(high, axis=0)
def create_pipeline():
# Create the high factors.
high_250 = MaxHigh(window_length = 250)
high_5 = MaxHigh(window_length = 5)
# Create volume and close factors
# This is easier because they are just versions of the built in 'Latest' factor.
volume = Latest(inputs=[USEquityPricing.volume])
close = Latest(inputs=[USEquityPricing.close])
p = Pipeline()
p.add(high_250, 'high_250')
p.add(high_5, 'high_5')
p.add(volume, 'volume')
p.add(close, 'close')
# Below is what we would really like to do but can't currently compare factors
# pipe_screen = ((close > 1.0) & (close < 20.0) & (high_5 > high_250))
# so this step is done after the results of the pipe are retrieved
# lets just screen for price and volume now
p.set_screen((close > 1.0) & (close < 20.0))
return p
# Run the pipeline with desired date(s). close collumn will be close 5 trading days before that date
# In this case it will be the close on 6-30-2016 because of the July 4 holiday.
results = run_pipeline(create_pipeline(), '7-8-2016', '7-8-2016')
results
# Now just select the rows where the 5 day high is greater than or equal to the 250 day high
# Notice that all the high_250 are equal to the high_5 which makes sense since we include the
# most recent 5 days in our 250 days. This works, but if one would like to show "previous high"
# then the MaxHigh factor would need to be modified a bit. At that point it may be advantageous
# to make a single "ReachedNewHighestHigh" custom factor?
# We then select the top 50 securities with the highest volume that have a new high
highest_highs = results[results.high_5 >= results.high_250]
highest_highs.sort('volume', ascending=False).iloc[:50]