Back to Community
Sentdex's Quantopian Tutorial Updated (by me) for Quantopian 2: Algorithm 1 Videos 1-3

Since people seem to like Sentdex's tutorial for Quantopian, and they have not been updated for Quantopian 2- I thought updating them would be valuable to people here and a good way to finally learn Quantopian!

This first algorithm is a simple long-only trend following strategy. It highlights two of the major changes between Quantopian 1 and Quantopian 2 First, data[asset].mavg(days) has been replaced with data.history(asset, 'price', days, '1d').mean(). Second, his handle_data function should be replaced with a scheduled rebalance function.

Potential "Gotchya": When called before trading, like in before_trading_start, data.history(asset,'price', 10,'1d') does exactly what you expect: return the closing price for the previous 10 days. However, if it is called during trading, i.e. in either a handle_data call or scheduled rebalancd call, then it returns the most recent price observed in trading today and the closing price for the previous 9 days. (If you ever have questions about what's being returned, I found setting a debug-point and using get_datetime() to be useful to make sure I was working with the correct data.)

OH, and I much prefer my order entry logic and design pattern over his, but let me know if you feel otherwise.

Clone Algorithm
Backtest from to with initial capital
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
This is the long-only trend following strategy developed in the first 3 videos
of Sentdex's tutorial.

This algorithm has been updated for Quantopian 2.

Original tutorial found here:

def initialize(context):
    Called once at the start of the algorithm.
    context.security_list = [symbol('SPY')]
    # Rebalance every day, 1 hour after market open.
    schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open())
    # Record tracking variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())
def before_trading_start(context, data):
    Called every day before market open.
    prices200 = data.history(context.security_list, 'price', 200, '1d')
    prices50 = prices200[-50:]
    context.ma50 = ma50 = prices50.mean()
    context.ma200 = ma200 = prices200.mean()
    context.signal = (ma50 > ma200).to_dict()
    # These are the securities that we are interested in trading each day.
def my_rebalance(context,data):
    Execute orders according to our schedule_function() timing. 
    target_securities = sum( i for i in context.signal.values())
    for security, signal in context.signal.items():
        if signal and (security not in context.portfolio.positions):
            order_target_percent(security, 1./target_securities)
  'Buying Shares')
        if (not signal) and (security in context.portfolio.positions):
            order_target_percent(security, 0)
  'Selling Shares')
def my_record_vars(context, data):
    Plot variables at the end of each day.
    NOTE: Recording moving averages really will not make sense if 
          you use more than one security in context.security_list.
          Recording leverage will still make sense.
    record(MA1 = context.ma50, MA2 = context.ma200, leverage=context.account.leverage)

There was a runtime error.
5 responses

This is great. Cleared up my confusion. Thanks!

Great job. Thanks.

Thanks a lot!

Getting an AttributeError: ' bool' object has no attribute 'to_dict' in the before_trading_start method. Does anyone know why?

Awesome job, thanks for updating it and sharing with people. Just so you know, I'm currently re-doing the Quantopian series in the new finance series. We've not gotten to Quantopian yet, but it's coming, so I am not sure you'll want to keep updating it.

edit: I am seeing now that actually this was posted a long time ago, just happened to see it since it got a recent post, whoops.