Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Calculating Values from Trailing Window of Data

Hello Everyone,
I have been working on creating an algorithm that trades stocks based on momentum. Originally I tested the algorithm with one stock and the calculation worked fine. However, when I started implementing pipeline I started having trouble achieving the value I wanted. I am trying to subtract the twelve minute price from the current price in order to achieve a minutely momentum value. Please Help.

8 responses

Here are some things to try.

Instead of getting the current price AND the history prices, just get the history prices. The latest history price will be the current price. Therefore to get a 12 minute momentum you can do something like this:

    twelve_min_prices = data.history(context.assets, 'price', 12, '1m')  
    twelve_price = twelve_min_prices.ix[0]  
    current_price = twelve_min_prices.ix[-1]  
    momentum = (current_price / twelve_price) - 1

I noticed in your code that 'momentum' was simply the difference in prices. You may want to express it as a percentage (as above).

Note that 'twelve_price', 'current_price', and 'momentum' are all Pandas series objects. What this means is that they are 1D arrays of values and have the security object as the index. In your code you are trying to 'print momentum' for example. This works, but remember you are printing an array (which may be quite long) with indexes of each object (so it will look funny).

So, if you want to do something for each stock with momentum greater than x you could do something like this

    for stock, my_momentum in momentum.iteritems():  
        if my_momentum > .001:  
            # do whatever logic when momentum is more than .1%  
            print "stock {0} has momentum greater than .1%".format(stock)  

Some words of caution... the 'data.history' function will fetch the previous n minutes (12 in your case) worth of data. If you check this at minute 1 of todays trading it will fetch todays current price along with the last 11 minutes of yesterdays trading. You may not want this behavior? Also, the 'price' field is forward filled. What this means is that if a security didn't trade in a particular minute the price will be reported as of the last time it did trade. Your '12 minute momentum' may not actually be the prices now or 12 minutes ago. If you want the true prices (not forward filled) then use 'open', 'high', 'low', or 'close' instead. However, you may find there are a lot of 'NaN' values especially with the low priced stocks you are filtering for. You will need to account for those.

Hope that helps. Attached is a cobbled up algo with these changes (or similar) and filtered down to just two stocks (AAPL and IBM) for clarity.

I'll see what I can do with it thanks for your help.

Perhaps, it would be easier if I posted my finished strategy. Ultimately, I am trying to buy and sell stocks based on momentum, high volume, percentage gain, and the total shares traded every five minutes. I have ran a few tests on single stocks,and they more or less produced the results I wanted. However, I started running into trouble when I implemented pipeline and multiple securities into my algorithm. I am not really sure if my algorithm is set up correctly, or if it is possible to execute trades since I have such a big list of securities, and multiple calculations to handle. Please help.

Here is the backtest. Also the reason I define momentum as just the current price minus the twelve minute price, as opposed to dividing the difference by the twelve minute price, is because its easier to compare with my trading software.

@Dan and @ Sam,

Been working on an algo very similar in strat to this (at least in the rebalance function at the end it is).

Stumbling upon this error:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Any idea what could be going on?

The error occurs in the if statement in the re balance function. Specifically, error happens on this line:

if time_momentum < .02: # end function if momentum for long index stocks is not above 2% for the day

This happens in the rebalance function towards the end.

Where this occurs, all I am attempting to do is create a time_momentum that screens for current price and compares it to price 30 minutes ago. If the price increase is more than 2% it gets long, and less than 2% it gets short. However, something may be off with my syntax and hoping you might catch it. I was thinking of posting to forum, but with the low hit ratio, thought it would be much smarter to connect with you first.

Please let me know what you think. Code is below:

def rebalance(context, data):

for security in context.longs.index:  

    thirty_min_prices = data.history(context.assets, 'price', 30, '1m')  # pull prices n minutes ago  
    thirty_price = thirty_min_prices.ix[0]  # prices n minute ago  
    current_price = thirty_min_prices.ix[-1] # current price  
    time_momentum = (current_price / thirty_price) - 1 # calculate % change in move for past n minutes  


    if time_momentum < .02: # end function if momentum for long index stocks is not above 2% for the day  
        return  
    if time_momentum > .02:    # do whatever logic when time momentum is more than 2%  
        order_target_percent(security, context.longs[security])  


for security in context.shorts.index:  

    thirty_min_prices = data.history(context.assets, 'price', 30, '1m')  # pull prices n minutes ago  
    thirty_price = thirty_min_prices.ix[0]  # prices n minute ago  
    current_price = thirty_min_prices.ix[-1] # current price  
    time_momentum = (current_price / thirty_price) - 1 # calculate % change in move for past n minutes  

    if time_momentum > .02: # end function if momentum for short index stocks is not below 2% for the day  
        return  
    if time_momentum < .02:    # do whatever logic when time momentum is less than n%  
        order_target_percent(security, -context.shorts[security])  

for security in context.portfolio.positions.iterkeys():  
    if security not in context.security_list:  
        order_target_percent(security, 0) 

The problem is that 'thirty_min_prices' is a data frame (rows are times and columns are the securities in context.assets. the values are the minute prices).
Then when you get 'thirty_price' that is a series (the indexes are the securities in context.assets. The values are the first data).
Then when you calculate 'time_momentum' that is also a series.

So, when you try to do


 if time_momentum < .02:

You are asking if a series is <.02. That is ambiguous and why you are getting the error.

I believe what you were attempting is

thirty_min_prices = data.history(security, 'price', 30, '1m')  

Note this is now getting the prices for a single security. This returns a series (not a dataframe) and the subsequent assignments return simple scalers. This way 'time_momentum' is a single value and can be compared.

This at least get's the code past the error.

Hi Dan,

thanks for the response. I made the change you talked about above, however now getting another error:

TypeError: Expected assets argument to be of type or iterable of type Asset, ContinuousFuture, basestring

the line where error is hitting is the line I changed the code to:

thirty_min_prices = data.history(security, 'price', 30, '1m') # pull prices n minutes ago

Fulle code adjusted with your change shown below in rebalance. Any idea what it could be?

def rebalance(context, data):

for security in context.longs.index:  

    thirty_min_prices = data.history(security, 'price', 30, '1m')  # pull prices n minutes ago  
    thirty_price = thirty_min_prices.ix[0]  # prices n minute ago  
    current_price = thirty_min_prices.ix[-1] # current price  
    time_momentum = (current_price / thirty_price) - 1 # calculate % change in move for past n minutes  


    if time_momentum < .02: # end function if momentum for long index stocks is not above 2% for the day  
        return  
    if time_momentum > .02:    # do whatever logic when time momentum is more than 2%  
        order_target_percent(security, context.longs[security])  


for security in context.shorts.index:  

    thirty_min_prices = data.history(security, 'price', 30, '1m')  # pull prices n minutes ago  
    thirty_price = thirty_min_prices.ix[0]  # prices n minute ago  
    current_price = thirty_min_prices.ix[-1] # current price  
    time_momentum = (current_price / thirty_price) - 1 # calculate % change in move for past n minutes  

    if time_momentum > .02: # end function if momentum for short index stocks is not below 2% for the day  
        return  
    if time_momentum < .02:    # do whatever logic when time momentum is less than n%  
        order_target_percent(security, -context.shorts[security])  

for security in context.portfolio.positions.iterkeys():  
    if security not in context.security_list:  
        order_target_percent(security, 0) 

Hi Dan,

I tried something else (shown below) to take the conditional statements out of the for loop, but only ended with another error saying:

TypeError: cannot do label indexing on with these indexers [1123.0] of
type 'numpy.float64'

Wondering if something may be wrong with my conditions in before trading starts. Both before trading starts and rebalance code shown below.....

def before_trading_start(context, data):

results = pipeline_output('my_pipeline').dropna()  
ranks = results.rank().mean(axis=1).sort_values(ascending=True)  
context.assets = results.index.tolist()  

# Narrow down the securities to only the top n to filter long and bottom n to filter short & update my universe  

context.shorts = ranks[results["combo_rank"]].head(200)  
context.shorts /= context.shorts.sum() #  This line of code is how we get the 'weights' for how many shorts. x /= y is equivalent to x =x/y; thus in this case  
context.shorts = context.shorts/(total number of shorts).  


context.longs = ranks[results["combo_rank"]].tail(200)  
context.longs /= context.longs.sum()  


context.security_list = (context.longs.index.union(context.shorts.index)).tolist() 

def rebalance(context, data):

thirty_min_prices = data.history(context.assets, 'price', 30, '1m').ffill().bfill()  # pull prices n minutes ago  
thirty_price      = thirty_min_prices.ix[0]            # prices n minute ago  
current_price     = thirty_min_prices.ix[-1]           # current price  
time_momentum     = (current_price / thirty_price) - 1 # calculate % change in move for past n minutes

for security in context.longs.index:  
    if time_momentum[security] < .02:   # end function if momentum for long index stocks is not above 2% for the day  
        return  
    if time_momentum[security] > .02:    # do whatever logic when time momentum is more than 2%  
        order_target_percent(security, context.longs[security])

for security in context.shorts.index:

    if time_momentum[security] > .02: # end function if momentum for short index stocks is not below 2% for the day  
        return  
    if time_momentum[security] < .02:    # do whatever logic when time momentum is less than n%  
        order_target_percent(security, -context.shorts[security])

for security in context.portfolio.positions:  
    if security not in context.security_list:  
        order_target_percent(security, 0)