Back to Community
Dual Moving Averages version 0.3

This is a version cloned from Thomas's Dual Moving Averages .2. It's also inspired by John's Moving Average Crossover.

This version is heavily commented so you can click the "Clone Algorithm" button and make some changes yourself. You can try different stocks. You can vary the moving average windows. Depending on the details you choose, you will get very different outcomes.

Clone Algorithm
Total Returns
Max Drawdown
Benchmark Returns
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
def initialize(context):
    # Define which stocks we want to work with. I'm starting with just one, but you can add up to 10.
    context.sids = [sid(24)]
    context.N = len(context.sids)

    # This section initializes a dictionary that will later track whether we invested in a particular stock
    context.invested = {}
    for cur_sid in context.sids:
        context.invested[cur_sid] = False
def handle_data(context, data):
    # Uncomment the line below if you want to log the sids that you're testing. Be careful, it's a lot of
    # log lines if you're doing a full backtest!
    # allocate part of our portfolio for each sid in our list    
    cash_per_sid = context.portfolio.starting_cash / context.N
    # This loop goes over the specified sids
    for cur_sid in context.sids:
        # skip sids that have no data (like Facebook pre-IPO)
        if not (cur_sid) in data:
        # buy if short moving average crossed long moving average going up       
        if (data[cur_sid].mavg(10) > data[cur_sid].mavg(50)) and not context.invested[cur_sid]:
            order_in_cash(data, cur_sid, cash_per_sid)
            context.invested[cur_sid] = True
        # sell if short moving average crossed long moving average going down  
        elif (data[cur_sid].mavg(10) < data[cur_sid].mavg(50)) and context.invested[cur_sid]:
            # log the fact that we're closing our position, and the conditions that triggered it
  'Selling SID %i by %i shares. mavg(10) is %i, mavg(50) is %i' %(cur_sid, context.portfolio.positions[cur_sid].amount, data[cur_sid].mavg(10), data[cur_sid].mavg(50)))
            # sell the amount we invested
            order(cur_sid, -context.portfolio.positions[cur_sid].amount)
            context.invested[cur_sid] = False
def order_in_cash(data, security, cash):
    # This function calculates how many shares to buy given the price and cash available
    shares = cash // data[security].price
    # log.debug("security: %i, cash: %f, shares: %i"% (security, cash, shares))
    if shares < 0: 
        shares += 1 
    # to fix python's flooring of negative integer division. 
    # log the fact that we're going long, and the conditions that triggered it'Ordering %i shares of sid %i. mavg(10) is %i, mavg(50) is %i' %(shares, security, data[security].mavg(10), data[security].mavg(50)))
    order(security, shares)    
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

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.

9 responses

Dan, I am curious what happened after July 2012. Is it because the data for August, September, October and part of November are not available? Thanks.

I'm curious too ;)

Correct, we don't yet have that data available. Getting that corrected, and getting regular data updates, is one of our highest priorities right now. I expect that sometime in December we will have all of the old data loaded, and we'll be loading "yesterday's data" every night. You'll be able to log in and check every day how your algorithms are doing.

Thanks, Dan.

Thanks Dan. I'm going to clone it and try it out now.

Awesome! If you run into problems, let us know so we can track it down and/or help!

I do have one question in general, is there a way to optimize over a variable? By that I mean, you second moving average is 50. Is there a way to replace 50 by some variable X that can be optimized over to find the optimal moving average? (I know this is data fitting but still it might be educational)

We don't have that yet, but we're working on it. Resident researcher Thomas is the expert. Blog post

Awesome! Just discovered this site yesterday and cloned and played with my first algo today. Looking forward to learning with you guys.

Thanks! Glad you like it. Let us know what you think we need to do to make it better.