Simple Quantopian Pipeline Strategy




Welcome to another Quantopian tutorial, where we're learning about utilizing the Pipeline API. In the previous tutorial, we covered how to grab data from the pipeline and how to manipulate that data a bit. We'll continue building on that here, mainly by adding an actual trading strategy around the data we have. The code up to this point:

from quantopian.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage


def initialize(context):
    pipe = Pipeline()
    attach_pipeline(pipe, 'pipeline_tutorial')
    _50ma = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50)
    _200ma = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    pipe.add(_50ma, '_50ma')
    pipe.add(_200ma, '_200ma')
    pipe.add(_50ma/_200ma, 'ma_ratio')
    pipe.set_screen(_50ma/_200ma > 1.0)
    

def before_trading_start(context, data):
    output = pipeline_output('pipeline_tutorial')
    context.my_universe = output.sort('ma_ratio', ascending=False).iloc[:100]
    update_universe(context.my_universe.index)


def handle_data(context, data):
    log.info("\n" + str(context.my_universe.head()))
    log.info("\n" + str(len(context.my_universe)))

Now we need to do a couple things. First, we want to buy all of the companies we can that are in our universe, and then we also want to sell off the companies that are no longer in our universe. If the company isn't in our universe, then it means it does not meet our parameters. To do all of this, we can use the handle_data function:

def handle_data(context, data):
    cash = context.portfolio.cash
    purchase_value = 1500
    for stock in context.my_universe.index:
        if stock not in context.portfolio.positions:
            if purchase_value < cash:
                try:
                    order_target_value(stock, purchase_value)
                    cash -= purchase_value
                except:
                    pass

First, we're accounting for how much money we have, an amount of money we want to invest per company, and then we begin iterating through the companies in our universe. If the company is not already in our portfolio, and if we have the cash to invest, then we're going to make the order. We encase this in a try/except simply due to issues with some tickers, despite the lookup date. So this our way of acquiring positions in companies, now we need to exit companies we aren't interested in:

    for stock in context.portfolio.positions:
        if stock not in context.my_universe.index and stock not in context.stocks_sold:
            order_target_value(stock, 0)

    record('Leverage',context.account.leverage)

Here, we're looking for companies that are in our portfolio, but not in our universe. If this is the case, we make the target value of our ownership in the companies zero.

Logically, this makes total sense to me, but leverage gets out of hand due to this second for loop.

finance tutorials

Logically, it really shouldn't have any issues, since the target value is zero, but it does. Thus, we're going to add in one final check, just to make sure we don't do any double sells, which is what appears to be happening. First, within our initialize function:

def initialize(context):
    set_symbol_lookup_date('2007-01-04')
    pipe = Pipeline()
    attach_pipeline(pipe, 'pipeline_tutorial')
    _50ma = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50)
    _200ma = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    pipe.add(_50ma, '_50ma')
    pipe.add(_200ma, '_200ma')
    pipe.add(_50ma/_200ma, 'ma_ratio')
    pipe.set_screen(_50ma/_200ma > 1)
    context.stocks_sold = []

The only change here is the last line, with the context.stocks_sold list definition. The idea here is to actually track every stock sale. If we have sold the stock, we don't want to sell it again, so we'll add the stock to the list if we sell it. Any time we buy a stock, we'll also check to see if that stock is currently in the stocks_sold list. If it is, we'll remove it, since we're re-buying it and may want to sell it later.

def handle_data(context, data):
    cash = context.portfolio.cash
    purchase_value = 1500
    for stock in context.my_universe.index:
        if stock not in context.portfolio.positions:
            if purchase_value < cash:
                try:
                    order_target_value(stock, purchase_value)
                    cash -= purchase_value
                    ####################################
                    if stock in context.stocks_sold:
                        context.stocks_sold.remove(stock)
                except:
                    pass

    for stock in context.portfolio.positions:
        if stock not in context.my_universe.index and stock not in context.stocks_sold:
            order_target_value(stock, 0)
            #################################
            context.stocks_sold.append(stock)

    record('Leverage',context.account.leverage)

Additions to the script are noted with the # sign.

finance tutorials

That's all for now. For more tutorials, head:





  • Programming for Finance with Python, Zipline and Quantopian
  • Programming for Finance Part 2 - Creating an automated trading strategy
  • Programming for Finance Part 3 - Back Testing Strategy
  • Accessing Fundamental company Data - Programming for Finance with Python - Part 4
  • Back-testing our strategy - Programming for Finance with Python - part 5
  • Strategy Sell Logic with Schedule Function with Quantopian - Python for Finance 6
  • Stop-Loss in our trading strategy - Python for Finance with Quantopian and Zipline 7
  • Achieving Targets - Python for Finance with Zipline and Quantopian 8
  • Quantopian Fetcher - Python for Finance with Zipline and Quantopian 9
  • Trading Logic with Sentiment Analysis Signals - Python for Finance 10
  • Shorting based on Sentiment Analysis signals - Python for Finance 11
  • Paper Trading a Strategy on Quantopian - Python for Finance 12
  • Understanding Hedgefund and other financial Objectives - Python for Finance 13
  • Building Machine Learning Framework - Python for Finance 14
  • Creating Machine Learning Classifier Feature Sets - Python for Finance 15
  • Creating our Machine Learning Classifiers - Python for Finance 16
  • Testing our Machine Learning Strategy - Python for Finance 17
  • Understanding Leverage - Python for Finance 18
  • Quantopian Pipeline Tutorial Introduction
  • Simple Quantopian Pipeline Strategy