Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Average Volume and Floating Indicators

2 things I'm having trouble with in this alg and 1 question::
1) Average Volume, is this the right way to do it.
2) I'm getting an error on the boolean indicators, open_long_position and open_short_position. Im trying to avoid taking another position if I have one already.
3) For set_universe, is it possible to filter the stock selection based on prices, i.e., stocks between 1 and 10 dollars for instance, or does that have to be done as in if statement in the handle_data loop?

# Put any initialization logic here.  The context object will be passed to  
# the other methods in your algorithm.  
def initialize(context):  
    set_universe(universe.DollarVolumeUniverse(98, 100))

# Will be called on every trade event for the securities you specify.  
def handle_data(context, data):  
    #track the volume history for 3 days  
    volume_history = history(bar_count=50, frequency='1d', field='volume')  
    # average_volume = sum(volume_history)/50 (getting an error here)  
    #track the price history for 3 days  
    price_history = history(bar_count=4, frequency='1d', field='price')  
    # get close price history  
    for stock in data:  
        # Moving Averages - http://www.forexonlinetradingsystems.info/simple-systems/triple-moving-averages-crossover  
        slow_ma = data[stock].mavg(50)  
        medium_ma = data[stock].mavg(25)  
        fast_ma = data[stock].mavg(10)  
        # volume_1 = volume_history[-1]  
        if open_long_position is None:  
            open_long_position = False  
        if open_short_position is None:  
            open_short_position = False

        # Open Long Position  
        if fast_ma>medium_ma and fast_ma>slow_ma and context.portfolio.positions[stock]==0:  
            order_target(stock, 100)  
            open_long_position = true  
            log.info("Open Long Position: " + str(stock))  
        # Close Long Position  
        if fast_ma<=medium_ma and context.portfolio.positions[stock]>0 and open_long_position==True and open_short_position==False:  
            order_target(stock, 0)  
            open_long_position = false  
            log.info("Close Long Position: " + str(stock))  
        # Open Short Position  
        if fast_ma<medium_ma and fast_moving_average<slow_moving_average and context.portfolio.positions[stock]==0:  
            order_target(stock, -100)  
            open_short_position = true  
            log.info("Open Short Position: " + str(stock))  
        # Cover Short Position  
        if fast_ma>=medium_ma and context.portfolio.positions[stock]>0 and open_short_position==True and open_long_position==False:  
            order_target(stock, 0)  
            open_short_position = false  
            log.info("Cover Short Position: " + str(stock))

        record(SMA=slow_ma,MMA=medium_ma,FMA=fast_ma)  
2 responses

Hi Don,

This backtest is a step in the right direction. It's not quite there yet, but we're making progress!

To answer your questions and describe some of the changes I made,

  1. Average Volume - The history call returns a pandas dataframe where the rows are the date and the columns are labeled by security. The cells are the volumes per security on each date. As a result, this piece of code was throwing an error: sum(volume_history). Instead, you need to index into the stock to select the appropriate column. I fixed this in your code by moving this call to handle_data on line 31, average_volume = sum(volume_history[stock])/50. Do you know you're not using this variable? Was this intentional?
  2. open long and short positions - The open_long_position and open_short_positions needs to be created as a context variable in initialize, to save state between bars of the backtest. I also updated this section to make the backtest compile.
  3. Filter stocks based on price - Within your 'for stock in data' loop in handle_data you can query for the stock price to create your stock selection
  4. calculating moving average - Since you're already using history, I changed the syntax to use panda's mean function to calculate the moving average. This is a faster function and improves performance instead of using the built-in Quantopian .mavg() call.
  5. open_long_position - The open long position on line 42 was not getting triggered. To access the number of shares owned of a stock, you need to use 'context.portfolio.positions[stock].amount'
  6. Closing positions - This is perhaps the most important one. When do you want to close your long and short positions? If you enter a long position on line 42, then open_long_position = True. In that same bar it will hit line 47 and submit a second, asynchronous order to close the position. It also looks like the short position was not getting closed. In the interim, I added a section on line 37 to close all positions at the end of day.

For testing purposes, I narrowed down the set_universe size from 2% to 0.1%. Let me know how you'd like to close the positions for #6 and we'll continue developing the strategy.

Cheers,
Alisa

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

This is great, thanks for the reply! I wanted to close a long position when fast_ma=medium_ma instead of closing at the end of the day. I used the booleans so that an Open Long would not be closed for an Open Short and vice versa. The context setup makes sense, I will use this. As far as #3, I figured that was the answer, to do it in the loop and filter by price.