Attempting to create a gap up strategy that filters for stocks with at least a 5% gain from yesterday close to today's open.
Then once I have that filter set, I then want to long all the stocks that price closes above the 15 minute high and close.
When I build the algorithm it starts off well but ends up with a large negative return. Looking for any kind of guidance on the below code that I have so far
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume, SimpleMovingAverage
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.algorithm import order_optimal_portfolio
import quantopian.optimize as opt
import pandas as pd
import numpy as np
def logging(msgs):
dt = get_datetime('US/Eastern')
youbi = dt.strftime("%w")
youbidict = {0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat"}
msgs = '\t%s\t%s:\t%s'%(dt.strftime('%Y/%m/%d %H:%M (ET)'), youbidict[int(youbi)], msgs)
log.info(msgs)
class ValueDaybeforeYesterday(CustomFactor):
window_length = 2
def compute(self, today, assets, out, values):
out[:] = values[0]
class ChangeAverage(CustomFactor):
def compute(self, today, assets, out, values):
mean = pd.DataFrame(values).pct_change().mean()
out[:] = mean.values
class ChangeAverageLog(CustomFactor):
def compute(self, today, assets, out, values):
df = pd.DataFrame(values)
mean = (df.shift(1) / df).mean().apply(np.log)
out[:] = mean.values
def make_pipeline(context):
pipe = Pipeline()
base_universe = QTradableStocksUS()
dollar_volume = AverageDollarVolume(window_length=20)
high_dollar_volume = dollar_volume.percentile_between(95,100)
close_day_before_yeseterday = ValueDaybeforeYesterday(inputs = [USEquityPricing.close])
volume_day_before_yeseterday = ValueDaybeforeYesterday(inputs = [USEquityPricing.volume])
close_yesterday = USEquityPricing.close.latest
mean_5 = SimpleMovingAverage(
inputs=[USEquityPricing.close],
window_length=5,
mask=base_universe
)
pipe.add(close_day_before_yeseterday, "close_day_before_yeseterday")
pipe.add(close_yesterday, "close_yeseterday")
pipe.add(mean_5, "ave_close_L5")
return_change_mean = ChangeAverage(inputs = [USEquityPricing.close], window_length = 5)
volume_change_mean = ChangeAverage(inputs = [USEquityPricing.volume], window_length = 5)
my_screen = base_universe & high_dollar_volume #& (return_change_mean < 0)
#my_screen = base_universe
pipe.set_screen(my_screen)
return pipe
def initialize(context):
attach_pipeline(make_pipeline(context), 'pipe')
schedule_function(set_open, date_rules.every_day(), time_rules.market_open())
schedule_function(set_high_low, date_rules.every_day(), time_rules.market_open(minutes=15))
schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=30))
schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=45))
schedule_function(my_close, date_rules.every_day(), time_rules.market_close(minutes=60))
def before_trading_start(context, data):
context.output = pipeline_output('pipe')
def set_open(context, data):
context.output['open'] = data.current(context.output.index, 'open')
def set_high_low(context, data):
context.output['high'] = data.current(context.output.index, 'high')
context.output['low'] = data.current(context.output.index, 'low')
context.output['gap'] = (context.output['open'] - context.output['close_day_before_yeseterday'])/context.output['close_day_before_yeseterday']
#context.output = context.output[(context.output['gap'] > 0.05)]
def my_rebalance(context, data):
context.output['price'] = data.current(context.output.index, 'price')
context.output = context.output[(context.output['gap'] > 0.05)]
context.output = context.output[(context.output['price'] > context.output['high'])]
context.security_list = context.output.index
print(context.security_list)
context.longs = []
for sec in context.security_list:
if data.can_trade(sec):
context.longs.append(sec)
target_weights = compute_target_weights(context, data)
if target_weights:
order_optimal_portfolio(
objective=opt.TargetWeights(target_weights),
constraints=[],
)
def compute_target_weights(context, data):
"""
Compute ordering weights.
"""
# Initialize empty target weights dictionary.
# This will map securities to their target weight.
weights = {}
# If there are securities in our longs and shorts lists,
# compute even target weights for each security.
if context.longs:
long_weight = 1.0 / len(context.longs)
else:
return weights
# Exit positions in our portfolio if they are not
# in our longs or shorts lists.
#for security in context.portfolio.positions:
#if security not in context.longs and data.can_trade(security):
#weights[security] = 0
for security in context.longs:
weights[security] = long_weight
return weights
def my_close(context, data):
if len(context.portfolio.positions) > 0:
for sid in context.portfolio.positions:
order_target(sid, 0)