Hi Quantopians,
I am new to this platform and so far I am loving it. I am currently an intern and one of my bosses has asked me to make a model on Excel for a certain stock behavior. It's pretty simple.
1. At the end of the day, I look at the top 5 gainers of the top 500 stocks and buy them all at 20% of the portfolio.
2. Following day, if the stock goes up 1% then sell it off, if it doesn't reach 1% then sell 5minutes before closing bell.
3. Buy top 5 stocks of the day and repeat.
I've been doing it manually for a couple of weeks but after having worked on my python whole summer I thought it would be neat if I could build an algorithm that would do the work for me. I have gotten to a certain extent but I can't seem to be able to complete it.
I've attached the notebook with pipeline that gets's me the top 5 equity of the day.
I couldn't attach the backtests since no backtests are working but here what I currently have has my code. I would like the code to work if I decide to change the top 5 to the top 10 or the top 20 and this is why I defined a weight function to work in any cases.
Thanks for you time and your help!
import quantopian.algorithm as algo
from quantopian.algorithm import attach_pipeline,pipeline_output
from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.filters import Q500US
def initialize(context):
schedule_function(my_rebalance,date_rules.every_day(),time_rules.market_close(minutes=1))
schedule_function(sell_off,date_rules.every_day(),time_rules.market_close(minutes=5))
schedule_function(sell,date_rules.every_day())
my_pipe = make_pipeline()
attach_pipeline(my_pipe,'my_pipeline')
def my_compute_weights(context):
if len(context.longs)==0:
long_weight = 0
else:
long_weight = 1 / len(context.longs)
return long_weight
def end_trading(context,data):
context.output = pipeline_output('my_pipeline')
# LONG
context.longs = context.output['close_minus_open'].index.tolist()
context.long_weight = my_compute_weights(context)
def my_rebalance(context,data):
for security in context.longs:
if data.can_trade(security):
order_target_percent(security,context.long_weight)
def sell_off(context,data):
for security in context.portfolio.positions:
if data.can_trade(security):
order_target_percent(security,0)
def sell(context,data):
for security in context.portfolio.positions:
entry_price = context.portfolio.positions[security].cost_basis
pct = 1.01
exit_price = pct*entry_price
price_history = data.history(security, 'price', 2, '1m')
current_price = price_history[-1]
if current_price >= exit_price:
if get_open_orders(security):
continue
if data.can_trade(security):
order_target_percent(security, 0)
class Close_Open_Delta(CustomFactor):
# Define inputs
inputs = [USEquityPricing.open, USEquityPricing.close]
window_length = 1
def compute(self, today, assets, out, open, close):
out[:] = (close - open)/open
def make_pipeline():
"""
Function to create a pipeline with high, low, open,and the Close_Open_Delta custom factors
"""
# Factors for the latest pricing data can be easily created using the "latest" method
# from the desired dataset
open = USEquityPricing.open.latest
high = USEquityPricing.high.latest
low = USEquityPricing.low.latest
close = USEquityPricing.close.latest
# Custom factors need to be instantiated explicitly
close_minus_open = Close_Open_Delta()
# Create a pipeline and add the factors to it
p = Pipeline()
p.add(open, 'open')
p.add(high, 'high')
p.add(low, 'low')
p.add(close, 'close')
p.add(close_minus_open, 'close_minus_open')
# Create filters to select and sort securities based upon factors
# Always good to use an initial "universe" filter to start with a realistic set of tradable securities
my_universe = Q500US() # built in universe of 500 larger stocks
# Create a "top gainers" filter. Use a mask to ensure only qualified securities get counted.
# Set the number to however many "off the top" one wishes to purchase (in this case 5)
top_gainers = close_minus_open.top(5, mask = (my_universe))
# Set a screen for our pipeline. Don't really need the my_universe and other filters because they were
# included in the top_gainers mask
p.set_screen(top_gainers)
return p