Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
volume spike purchasing formula

I had to copy and paste my code because it can't yet run a backtest...I've tried to manipulate the basic momentum backtest from quantopian

Starting at the bottom of my code: if the most recent 1m volume is > any previous minute during the current trading day * 500% I want to open up a position of 100 shares. -- How do I get the most recent minute's volume to compare to every respective minutes' trading volume or, more simply, initiate a position if the most recent 1m volume is 500% greater than the highest 1m volume of the current day.

I would love to use the schedule_position function and restrict this to placing trades only between 12pm-1pm, but I want it to look at the volume history of each minute since 9:30 -- I didn't even know where to begin to put this in.

Thanks for the help.

def initialize(context):
context.aapl = sid(24)

def handle_data(context, data):

volume = history(60, '1m', 'volume')  
volume = data[context.aapl].volume


if 1m volume > any previous 1m volume histroy of current day * 5.0:  
    order(context.aapl,+100)  
    log.info("Buying %s" % (context.aapl))  
17 responses

This is awesome, and so much help. Thank you! But now I have even more questions :)

1) If I wanted the purchase to be on 500% spike in volume would this be the code: if (volume >= maxVolume * 5.0):
2) Is there an easy way to disregard the volume for the first minute of the trading day?..wanting to dodge all the market open orders.

3) Instead of an end of day exit - say I want to sell the position on the first of two occurences: a) a decrease in price of 0.25% from the inital trade or b) the current price is above the initial purchase price by 0.25% AND the most recent 1m volume is < 25% of the largest 1m volume in the past 15 minutes.

@Michael,

1) yes, but you can just use the global variable I provided: VolumeMultiplier = 1.0

2) to avoid the first minute you could try this statement:

maxVolume = volumeDeck[stock][1 :-2].max()  

which should select from the second minute of the day to the next to last minute of the day to measure the max().

3) this gets into complexities that compound both the entry and the exit. Sure you can add exit conditions and if you take a look at this post: framework for code blocks you can see that this mechanism represents a simple means of adding exits into strategies.

However, you must now start to manage your positions more accurately else you'll get into leveraged positions when you thought you'd never do so. Buying 100 X every time volume spikes is an incomplete mechanism for managing your money. If you restate your full intent with regards to entry and exit, numbers of instruments, percents of account, etc. then perhaps we can rework the above strategy to suit your needs.

MT

So much help again. You rock.

A quick fix to 3) above,

Blockquote 3) this gets into complexities that compound both the entry and the exit. Sure you can add exit conditions and if you take a look at this post: framework for code blocks you can see that this mechanism represents a simple means of adding exits into strategies.

Blockquote However, you must now start to manage your positions more accurately else you'll get into leveraged positions when you thought you'd never do so. Buying 100 X every time volume spikes is an incomplete mechanism for managing your money. If you restate your full intent with regards to entry and exit, numbers of instruments, percents of account, etc. then perhaps we can rework the above strategy to suit your needs.

What's the quick way to only buy when I don't have any positions open and to only sell when I have securities? i.e. only have one trade of 100 shares, or a certain $ amount, open at any time on a particular security?

A simple test to determine whether you're in any trade would be easy to add. I think "if (context.portfolio.positions_value):" might actually do it. So if that test is true, then don't buy anything more. Or invert the test "if (not context.portfolio.positions_value):" -- buy now. Or, if you want to cancel the old trade and always enter on a new one, you could just perform the entry test and if positive, close all positions first, then enter the new one.

Cool. Is there any way you can tell a noobie like me where to enter that code? I'm guessing at the top, after "ExitVolumeThresholdPctThreshold = 25.0"? Also, will that hold for, let's use a random number, 10 stocks? i.e. if my constraint is to buy or sell 100 shares of 10 different stocks I would like to be able to purchase shares of each stock if I don't have any. Thus my maximum position size would be 1000 shares (100 from each stock).

This continues to get so much better. Again, you rock. The last filter I need to add now (after some more tinkering) is a simple price entry point. I want to limit this to purchasing at the low price, or near low, of the day. Can I setup a purchase filter to only buy if the current price is within the respective day's low price by < 15 minutes? i.e. if low price of stock for a given day was at 12:10pm I could only place a buy order from 12:11 - 12:26? Thanks for the help.

The key here is to divide and conquer.

So many algorithms here pack all the logic into one or two gnarly routines where the whole intent gets lost in the nitty gritty details.

Cut your strategy into segments of logical compartments. Even this strategy could do with some additional division. But in general, perform work to calculate each logically separate metric in an isolated routine. Then, when all metrics are calculated, perform your binary logic for entry (If Not A remove, If Not B remove, if Not C remove...). You'll be able to understand your strategy and more importantly be able to reuse modules of it in your next trading idea.

Great tip on dividing logics....I was able to trade this for a few days on my IB paper trade account and found two more edits I need some help with:

1) No short selling
2) I need to clarify my exit/selling strategy: I want to keep my volume exit logic, but also add a, what I think would be a highdeck, exit only if the current price is within 5 minutes of a 30 minute high i.e. must be within 5 minutes of the high looking 30 minutes back.

Also, where's the best place to go for researching code? I notice the quantopian overview page has a lot of good info, but there's a lot of stuff not on there such as lowdeck. As always, thanks for the help!

Thanks for all the help on this...I used to have some code in here that I could select which stocks to trade. How is my universe of eligible stocks selected? What's the easy way for me to select what stocks I want?

• Get rid of "before_trading_start" -- all of it.
• Inside def initialize(context): add
symbols("ABC", "DEF", "GHI"..)
Then your data object will have those symbols you specified as the only symbols you trade with.

This wasn't happening at first, but now if you run a backtest on the above you get this error:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
There was a runtime error on line 52.

I can't figure out why??

yes, I get that error too.

3/21/15 e: Updated per the new deployment by Quantopian of the various software packages.

3/17/15 d: Updated with specific securities, removed update_universe method
3/12/15 c: Updated with high must be high of last 30 min exit filter
3/7/15 b: Updated with entry filter to only enter if low is within 15 minutes of volume spike

We can use the same logic as was used on the volume:
• grab the lows,
• look for the min for the day,
• look for the min for the last 15 minutes and then
• remove from eligible if the low did not happen within the last 15 minutes.

    lowDeck = history(EntryTestStart + context.MinuteCounter, '1m', 'low').dropna(axis=1)  
    lowDeck = lowDeck[[sid for sid in lowDeck if sid in data]]  
    for stock in eligible:  
        lowOfDay = lowDeck[stock].min()  
        lowOfLastXMinutes = lowDeck[stock].tail(EntryLowWithinMinutes).min()  
        # If the low occured outside of the last n minutes - NO TRADE  
        if (lowOfDay < lowOfLastXMinutes):  
            eligible.remove(stock)  
3/7/15: Updated with simple test for position for each leg before entry
3/2/15: Updated algorithm, includes two new exits PercentLossStop and PercentGainStopWithVolumeTest

You can start with this. A few tricks (if you can call them that) were to schedule n number of entry tests for the times you want check the volume.

EntryTestStart    = 150 # Noon == 150 minutes after open  
EntryTestDuration = 55  # Start at noon and progress until 12:55 

    for i in xrange(0, EntryTestDuration):  
        schedule_function(HandleEntry, date_rules.every_day(),  
                          time_rules.market_open(minutes = EntryTestStart + i))  

Next was to use the .tail(1) to pick the last volume from each series. This would be the most recent volume for the security under examination:

volume = volumeDeck[stock].tail(1)  

Then to use the array offset and max to get the max volume for the prior n periods:

maxVolume = volumeDeck[stock][:-2].max()  

The specific number of periods was managed by the start minute + an increment for each new minute test between 12:00 and 12:55

volumeDeck = history(EntryTestStart + context.MinuteCounter, '1m', 'volume').dropna(axis=1)  

Is the max securities to trade at 200 limiting how many stocks I can buy at a certain time? Today (3/24) my formula should have bought 100 shares of QCOM but it never did. I'm wondering if it's because I had 100 shares of KO and 100 shares of TWTR??

@Michael M., MaxSecuritiesToTrade = 200 is a remnant from when the strategy loaded new securities from fundamentals. Delete it. It has nothing to do with your logic.

Tomorrow when minutely data is available, you should test to see if the logic still skips or buys QCOM. Do you have any of the log statements from that time? Or around that time?

You might want to add more logging anywhere the strategy makes inclusion or exclusion decisions. For instance:

        # If the low occured outside of the last n minutes - NO TRADE  
        if (lowOfDay < lowOfLastXMinutes):  
            eligible.remove(stock)  

You'd want to add a print statement below that line:

        # If the low occured outside of the last n minutes - NO TRADE  
        if (lowOfDay < lowOfLastXMinutes):  
            eligible.remove(stock)  
            print("   Removing {0} on low of day filter ...".format(stock.symbol))  

Trace through the code and see if there are not other locations where decisions are made which you'd want to know about in the logs. The logs are your ONLY way of knowing what has occurred in your strategy.

So I'm back at it with this algo... I still can't figure out why it makes so few trades. It should trade more because i purposely entered wide criteria with multiple securities. Anyone have any idea how I can clean this up a bit and get it to do all the trades that it should? Thanks.

Just wondering @Michael Mcgill were you ever able to figure the issues out with this algo?