Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Seeking Help Complete First Algorithm

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  
9 responses

@Laurent, What kind of errors are you getting when you run the backtests? You may want to start with a working backtest, rip out the parts you don't want, insert your own code for the parts that have to be different. Of course do that one step at a time making sure that each change doesn't break it.

I get this:
KeyError: 'longs'
There was a runtime error on line 32.

Not related to this specific error. But you should probably change the line about long_weight to:
long_weight = 1.0/len(context.longs)

Take a look at https://www.quantopian.com/posts/new-and-need-help-with-something-basic-i-hope
It appears to have already been working except for the above fix. It may provide some clues as to what you are missing in regards to 'longs'.

Still need help on this, can't seem to know how to fix it.

That KeyError for longs means it does not exist yet. So, either:

Add this to initialize section:
context.longs = {}

or

Add something similar to this to
def before_trading_start(context, data):

# Gets our pipeline output every day.  
context.output = pipeline_output('value_momo_pipeline')

# The low p/e stocks that we want to long.  
context.longs = context.output[context.output['longs']].index.tolist()  

Here is the correct algo that I have. Looking at transactions it seems like the only problem I have is selling the stock if it goes up by 1% during the day.

The algorithm seems to sell at the end of the day. It also buys evenly the 5 stocks afterwards. All I am missing is to trigger a sell of a position if the stock rises up 1% the next day.

Easiest would be limit orders at start of day like stp_lmt() here, although they aren't allowed in the contest or with Optimize.
You can see the ordering in the logging window. Or particular stocks can be set, in 'symbols' list.

You've added a lot to my already existing algo. This is a lot to try and absorb but I really like the result. This will be a great learning experience!