Friday, March 11, 2016

Quantopian Tutorials: Linear Regression

This, like all of the tutorials I am creating, comes from the Quantopian website. I am simply rehashing them for people and trying to make them more simplified with more detailed explanations of the "why" and "when".

Here we are going to discuss linear regression, followed by the actual application of regression in our analysis through Python code via Quantopian. The goal of this tutorial is not necessarily to rehash everything talked about by the folks at Quantopian already, but to help give you a better and more detailed explanation of everything. Everything in this tutorial is aimed at folks who are new to Python. So let's begin!

Link to the Quantopian notebook which is what this tutorial is based upon.

Let's look at some code:

# Import libraries
import numpy as np
from statsmodels import regression
import statsmodels.api as sm
import matplotlib.pyplot as plt
import math

Ok, so here we see the word "import" a lot, what is going on? It means we are importing something into our coding session, in this instance, import is used to import a set of commands and libraries into our IDLE. You can think of Python as a car frame where the axels, engine, seats, and actual body will connect to. The actual engine, seats, axels, and body are represented by what we are importing into it. Think of numpy as the engine, numpy is a library of functions and commands used to crunch numbers, we want this so of course to add it we tell Python to import it into our session and we will call it np rather than numpy because it's shorter and easier to input. The same goes for statsmodels, matplotlib. Math is short enough, we don't need to abbreviate it really so we just leave it as math. The from statsmodels import regression command is telling Python to import the regression function from the statsmodels database. The statsmodels.api is an api function used with Python to help utilize it's functions. It is a module that provides classes and functions for the estimation of many different statistical models. The same style of explanation can be used for the import of most everything.

Ok, we now know what each function does and why we have them (need them for calculations!), now we need to define them and plot the results.

def linreg(X,Y):
    # Running the linear regression
    X = sm.add_constant(X)
    model = regression.linear_model.OLS(Y, X).fit()
    a = model.params[0]
    b = model.params[1]
    X = X[:, 1]

Looking at this one at a time: X = sm.add_constant(X) , this means we are adding a constant to our graph along the X-axis, that constant is denoted within the parenthesis, so our constant is X. The sm.add part of our module comes from our previously imported statsmodels.api where we defined it as sm. Remember? So we are simply adding an X constant to our previously imported module. Next we have model = regression.linear_model.OLS(Y, X).fit() which is a simple ordinary least squares model. The OLS part stands for 'ordinary least squares', followed by both axis, constrained to fit() within our defined parameters which are denoted by a (alpha) and b (beta) below. The X = X(:, 1) means we are slicing the array and taking all the rows (:), but keeping the second column (1)

    # Return summary of the regression and plot results
    X2 = np.linspace(X.min(), X.max(), 100)
    Y_hat = X2 * b + a
    plt.scatter(X, Y, alpha=0.3) # Plot the raw data
    plt.plot(X2, Y_hat, 'r', alpha=0.9);  # Add the regression line, colored in red
    plt.xlabel('X Value')
    plt.ylabel('Y Value')
    return model.summary()

 X2 = np.linspace(X.min(), X.max(), 100), returns evenly spaced numbers over a specified interval. The X.min() is the starting point and the X.max() is the ending point, both constrained by our 100 limit. Y_hat (denoted  in statistics) represents the predicted equation for a line of best fit in linear regression. Within that best fit we have X2 * b + a. The plt.scatter plots the parameters you have input on a scatter plot.The rest of the code are customizations to the plot you can modify as you would like, described by the #.

start = '2014-01-01'
end = '2015-01-01'
asset = get_pricing('TSLA', fields='price', start_date=start, end_date=end)
benchmark = get_pricing('SPY', fields='price', start_date=start, end_date=end)

# We have to take the percent changes to get to returns
# Get rid of the first (0th) element because it is NAN
r_a = asset.pct_change()[1:]
r_b = benchmark.pct_change()[1:]

linreg(r_b.values, r_a.values)

Here, we have our start and end dates, which represent the time-line for which we want to obtain our stock data, defined by our asset function where we are going to get the price via the get_pricing function, which is defined by parameters such as the name of the stock, in this case it is 'TSLA' which is Tesla's stock, followed by our fields inputs where we will have 'price', start_date=start, end_date=end). Now we are setting this against a benchmark, as any security should be, and in this case we are setting it against the 'SPY' with the same fields of entry now input.

r_a = asset.pct_change()[1:] and r_b = benchmark.pct_change()[1:] both of these are the percentage change which is the daily returns because we are getting it at a daily frequency by default and the same thing goes for the benchmark. We want to consider the daily returns as our time-series.

The linreg(r_b.values, r_a.values)  is our command to begin our linear regression of our asset and benchmark daily returns.

Now, from our code you will a table that spits out, most of the statistics you needn't worry about, but you should pay attention to the F-statistic which is telling us how predictive our model actually is, you want this value to be less than 0.5 (X<0.5). If you F-statistic is any higher than 0.5 than it is pretty much useless.

The rest of the code and their descriptions is available through the link . If you have any questions or concerns let me know!

The last part to making our graph is the following code:
# Generate ys correlated with xs by adding normally-destributed errors
Y = X + 0.2*np.random.randn(100)
linreg(X,Y)

This "makes Y dependent on X plus some random noise".

And to help with interpreting your data, you can use the following code below to help identify your 95% confidence interval for the regression line:

import seaborn

start = '2014-01-01'
end = '2015-01-01'
asset = get_pricing('TSLA', fields='price', start_date=start, end_date=end)
benchmark = get_pricing('SPY', fields='price', start_date=start, end_date=end)

# We have to take the percent changes to get to returns
# Get rid of the first (0th) element because it is NAN
r_a = asset.pct_change()[1:]
r_b = benchmark.pct_change()[1:]

seaborn.regplot(r_b.values, r_a.values);

I like their clear explanation here:
The regression model relies on several assumptions:
  • The independent variable is not random.
  • The variance of the error term is constant across observations. This is important for evaluating the goodness of the fit.
  • The errors are not autocorrelated. The Durbin-Watson statistic detects this; if it is close to 2, there is no autocorrelation.
  • The errors are normally distributed. If this does not hold, we cannot use some of the statistics, such as the F-test.

Thursday, March 10, 2016

Quantopian Tutorial 6

So here we will talk about order management. By default on Quantopian there is no limit as to how much money you can borrow and invest in your algorithm, but in reality this isn't realistic. So here we will take a look at how to control the amount of money you invest.

def initialize(context)
     context.stock = sid(xtl) <---- now here, when you type in 'xtl' it will appear as '40768'.

def before_trading_start(context, data):
     pass

# Called every minute
def handle_data(context, data):
     open_orders = get_open_orders()
     if context.stock not in open _orders: 
          order_target_percent(context.stock, 1.00)
     record(cash = context.portfolio.cash)

What you see here in the 'order_target_percent(context.stock, 1.00) is the order we are placing for 100% (1.00) of the stock. Then we use the record function to plot the cash in my portfolio at the end of each day (even though we are in minute mode).

After you have written the code above, go ahead and hit the 'build' button.

When the build is finished, you will notice that the cash dips below zero, this is because we are investing borrowed money.

For this example, let's say we don't want to borrow any money, we just want to invest what is in our capital base.
Now, you might be wondering 'I already ordered 100% of my portfolio value so why is it ordering more?" The answer is because sometimes an order takes more than a bar to fill. Like with what is happening in our order. Remember, we are ordering more than a million dollars of XTL shares, and in every bar after that we are making similar-sized orders because our original order has not yet filled. Each of these order are going to stack up on each other to the point where, at the end, when all the orders are resolved, you will end up in a much bigger position in XTL than you had originally planned. To prevent this, we can use the function get_open_orders to see which securities we have placed orders for that have not yet been filled. The get_open_orders is going to give us a dictionary keyed by security ID of our open orders. So, if we hit the 'build' button again after inserting this function, we will notice that we are no longer borrowing a lot of money. The number we get is not zero (what we want) and this is due to slippage which we will discuss later.

So let's look at ticker XTL, using an algorithm that uses order-target percent to order 100% of our portfolio in XTL in a minute!

I hope you enjoyed this lesson about managing orders in Quantopian, as always, if you have any questions or comments please feel free to leave feedback!


Sunday, January 31, 2016

Quantopian Tutorial, part 5

This part of the tutorial will cover more advanced topics that build upon our previous knowledge of constructing Python algorithms for trading.

First, let's go over the 'set)universe function.

def initialize(context)
     set_universe(universe.DollarVolumeUniverse(99.0, 100.0))

def handle_data(context, data):
     symbol('GOOG')
     for stock in data:
          print len(data)

So from this point on, any stocks or securities that you inquiry about using functions will be automatically included into our stocks universe.

Now, let's go over the 'fetch_csv()' function. This function allows us to import an external dataset in the CSV format.

fetch_csv("location of your csv file"
     pre_func=preview,
     date_column='data,
     universe_func=(my_universe))

context.target_weight = 0.01

def handle_data(context, data)

the fetch_csv("location of your csv file" will import your csv file full of securities, ticker symbols, dates, etc, into our algorithm. date_column='data' will locate and import the date column of your securities. And finally it will use the my_universe function to define our universe of securities.

What our algorithm is going to do is take our csv file and convert all of our securities into SID objects sids = set(financials['sid']) and then pass it through to our my_universe function defined as def my_universe(context, fetcher_data): and then that is going to grab all financial securities in our financials fetcher data financials = fetcher_data[fetcher_data['GICS Sector'] === 'Financials'], so it will grab all of the unique symbols of those securities, and then finally we are going to get the universe size so that we know how much weight to put into each security context.target_weight = 1.0/context.count and then we will return the set we got previously sids = set(financials['sid'] and return it via return sids.

So, the function financials = fetcher_data[fetcher_data['GICS Sector'] === 'Financials'] is describing all the securities listed in the S&P 500, which we will then grab their unique SIDs via the sids = set(financials['sid'] function, and then it will return that list return sids, and then we will use that as our daily universe for the stock. The pre_func=preview is a function that will allow us to preview the outcome of algorithm. The df['data'] = '11/1/15' function will allow us to pull those dates directly from our csv file or we can view them manually in Excel. The point of using the function is to tell our algorithm how to associate the SID object to the date that it belongs to.

We are then ordering that security with the context.target_weight which we found by calculating the number of securities in our universe and dividing that by 1 context.target_weight = 1.0/context.count .

**NOTE: this is all in daily mode, if you want it in minutely mode use the  schedule_function(func=rebalance, day_rule=day_rules.every_day(), time_rule=time_rules.market_open()) def rebalance(context, data): **

**NOTE: the maximum number of securities that you can import from a csv file into your universe is going to be around 200! 82 is the typical number of stocks in a 1% range of the dollar volume universe. You can also define your universe with a mix of fundamental factors.
Here is what our code will look like:

import datetime
import pandas as pd
import numpy as np

def preview(df):    
    log.info(' \n %s ' % df.head()) 
    df['data'] = '11/1/15'
    return df

# Function for returning a set of SIDs from fetcher_data
def my_universe(context, fetcher_data):
   
    # Grab just the SIDs for the Financials sector w/in the SP500:
    financials = fetcher_data[fetcher_data['GICS Sector'] == 'Financials']
     sids = set(financials['sid'])
   symbols = [s.symbol for s in sids if s != 0]
    context.count = len(symbols)
    print "total universe size: {c}".format(c=context.count)
   
    # Compute target equal-weight for each stock in the SP500 Financials 
universe
    context.target_weight = 1.0/context.count
    return sids

def initialize(context):
   
    # Fetch the SP500 constituents -- sourced from Quandl
    # https://s3.amazonaws.com/quandl-static-content/Ticker+CSV
%27s/Indicies/SP500.csv
    # static snapshot of the SP500 constituents as of 10/2013, along with 
GICS sectors
    # I'm grabbing the data from a file on my dropbox folder which I 
modified by adding
    # a date column, alternatively you could add the date inside of a 
more complicated
    # pre_func and use the csv file as is.
   
    fetch_csv(
       "https://dl.dropboxusercontent.com/u/169032081/SP500.csv",
        pre_func=preview,
        date_column='date',
        universe_func=(my_universe))

    context.target_weight = 0.01
    
    schedule_function(func=rebalance,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_open())
    
def rebalance(context, data):
    # Loop over every stock in the Financials sector and make sure we have an equal-weight
    # exposure using the order_target_percent() method.
    for stock in data:
        # Guard for missing stock data
        if 'price' in data[stock]:
            order_target_percent(stock,context.target_weight)
        else:
            log.warn("No price for {s}".format(s=stock))
    
def handle_data(context,data):
    pass

Saturday, January 30, 2016

Quantopian Introduction, part 4

Welcome to part 4 of my Quantopian tutorial! In this tutorial we will go over how to use fundamentals data!

This tutorial is going to cover how to select a dynamic portfolio from fundamentals data. This means that we will be selecting securities based upon a property like market cap rather than just hardcoding a list at the beginning of the algorithm. Dynamic portfolio selection leads to more robust algorithms as it reduces the chances of over-fitting your strategy to a particular backtest period. We can use the get_fundamentals function to access the skeleton of a fundamentals query featured below.

import numpy as np

# This function is run once at the beginning of the algorithm, REQUIRED
def initialize(context):
    # AAPL stock
    # context.stock = sid(24)
    # SPY stock
    # context.market = sid(8554)
   
    schedule_function(check_mean, date_rules.every_day(), time_rules.market_close(minutes=30))

# This function is run once per day before any calls to handle_data, OPTIONAL
def before_trading_start(context, data):
     get_fundamentals(
    #Fundamentals Reference Page: https://www.quantopian.com/help/fundamentals
    context.fundamental_df = get_fundamentals(
        query(
            fundamentals.income_statement.total_revenue
        )
        .filter(
            fundamentals.valuation.market_cap > 30000000000
        )
        .order_by(
            fundamentals.valuation.market_cap.desc()
        )
        .limit(10)
    )
   
    update_universe(context.fundamental_df.columns.values)






Ok, so let's explain what all this code is above us. First we have context.fundamental_df = fundamentals(query(, what this does is open up the fundamentals skeleton that will allow us to choose our criteria and values per category. An example of this would be the .fundamentals.valuation.market_cap > 3000000000 which tells the algorithm "hey look, I only want to include companies with a market cap of greater than 300 billion dollars!"



The query( section at the beginning of our algorithm on the second line above, tells the algorithm what data we actually want to access. As you can see, we are telling our algorithm to look at the income statement of the company to determine whether or not it is a 300 billion dollar company!


The .order_by( section will allow us to sort the results of our query, and in this situation we are going to sort them by market-cap in descending order.


And finally, our .limit(10) will limit the number of securities returned, in this case we are limiting the securities to 10.

Also, we are going to store our results (information) in a dataframe denoted by the df listed above and we are giving it the name context.fundamental. The results will be a pandas dataframe where the columns are securities and the rows are the fundamental values that we queried for.

update_universe(context.fundamental_df.columns.values) , this will update our securities universe by adding in our information that we queried above, notice how the context.fundamental_df is the name we gave to our query for market cap info? It is indeed the same!

# This function is run once per bar, REQUIRED
def handle_data(context, data):
    pass

       
def check_mean(context, data):  
   
    print get_datetime('US/Eastern')
   
    # Get the close price of each of the last 10 minutes for all stocks
    # in our universe.

    hist = history(10, '1m', 'close_price')
   
    # Print the 10-minute mean close price for each stock in our universe.
    for stock in data:
        print '%s - mean price: %.2f, total revenue: %.2f' % (stock.symbol, np.mean(hist[stock]), context.fundamental_df[stock][0])
    print '-------------------------------'
    print ''


The print '%s - mean price: %.2f, total revenue: %.2f' % (stock.symbol, np.mean(hist[stock]) function will go through and check the mean of the information we have gathered, and then it will print it for us so we can look through it. Additionally, it will print our total revenue through the use of the context.fundamental_df[stock][0] function.

And that's it! You have now mastered the ability to build your own algorithm! Next lesson, we will move into more complex and powerful functions that will allow us to check a greater amount of information using mathematical tools! 

Friday, January 29, 2016

Quantopian Introduction, part 3

This is the third part of our Quantopian tutorial! Let's dive in!

Data variable and trading universe will be the topic we will start with.

A trading universe is any stock that we might be interested in trading in a given bar in our algorithm. 
The trading universe is represented by the data variable, which is a dictionary key'd by securities.

#this function is run once per bar, REQUIRED
def handle_data(context, data);
     log.info(get_datetime())
     for stock in data;

          log.info('Close price for %s: .2f' % (stock.symbol, data[stock].close_price))
     log.info('/n')

So what we did here is logged all this so we can take a look at the minute/lead/close price of each our securities ('Close price for (stock.symbol, data[stock].close_price)), and then we added in some formatting so that it all prints out in a more readable form (%s: .2f' %). And then we added the print time so we can see which minute we are on ( log.info(get_datetime()) ) And then we printed a new line for spacing ( log.info('/n') ).

Hit the 'Build Algorithm' key and what you will find is the pricing data for AAPL and SPY in each minute.

The 'stock universe' includes any stocks that we currently hold position in, as well as any stocks that we have explicitly referenced in the context variable. Another way to get a stock in our universe is to use the 'update universe function'.

Now let's turn our attention to the 'history()' function! The history function is used to us historical data for each stock in our stock universe.

#this function is run once per bar, REQUIRED
def handle_data(context, data);
    
    print history(5, '1m', 'close_price')

What this is doing is grabbing the history for our SPY and APPL data for the last 5 minute bars, and then we put '1m' for our frequency, and then we put close_price as the field that we are interested in. This returns as a pandas data frame with each column being a different stock and each row being a different date-time.

If we wanted a days frequency we would simply put '1d' instead of '1m'. Additionally, we can also change our field, so that we can find the volume traded rather than the closing price. We do this by placing 'volume' where our 'closing_price' is. 

If we want to find the ten day mean in the closing price of our stocks, we can change the number of bars to '11' and keep the frequency at '1d' and then I am actually going to save this function which, we can do through the following function: hist = history(11, '1d', 'close_price')
Now we want to make a 'for' loop going through each stock in data:

#this function is run once per bar, REQUIRED
def handle_data(context, data);
    
     hist = history(11, '1d', 'close_price')
     for stock in data:
          print '10-day mean close price for stock  %s: %2f' % (stock.symbol, np.mean(hist[stock][:-1]))

So, what we did here was print a line of text '10-day mean close price for stock' that references our stock %s: %2f' % and then we retrieve the stock symbol, and then we import the numpy library denoted as np (**NOTE: when importing a library you must also type a line of a code at the very beginning of your algorithm (above the def initialize(context) function); so above that function we would have the following line of code: import numpy as np. )
followed by the use of the statistical .mean variable of the (hist <--- our historical data for our stock. And then we type [stock] for the column that corresponds to the specific stock in our loop.
The [:-1] portion of our code excludes the last row of our column.

And the result will give us our ten day mean for AAPL and SPY.

We can change the our days to minutes like this: '10-minute mean...'

Thank you for reading part 3 of our tutorial, and as always if you have any questions or comments please send me an e-mail or comment!

Thursday, January 28, 2016

Quantopian Introduction, part 2

This is part 2 in our tutorial demonstrating how to use the online interactive investment trading tool known as Quantopian, using Python. These are the most basic code inputs that are either REQUIRED or they are OPTIONAL; the optional ones are encouraged if you have information to query before running the actual trading algorithm.

#this function is run once at the beginning of the algorithm REQUIRED
def initialize(context)
context.stock = sid(24)
     pass


#this function is run once per day before any calls to handle_data OPTIONAL
def before_trading_start(context, data)
     pass

^**This is typically where we will run calculations necessary for pre-computations that will be used for the rest of the day.


#this function is run once per bar, REQUIRED
def handle_data(context, data);
     pass

^**Ok, so this bit of code right here is retrieves data either by the minute or by the day, depending on the variable you set. Speaking of variables, the command 'handle_data' requires two inputs: context, and data.

Now let's go over securities referencing, SID, or "Security Identifier". The SID function takes care of the issues that might arise when backtesting an algorithm over an extended period of time, including if the stock ticker symbol changes. That's right, the SID function will keep the correct stock that you're using.

An example would be our previous function that we used above:
context.stock = sid(24)
..... sid(24) means that the function is calling upon the Apple stock symbol (AAPL). the (24) is the ID number given to the AAPL stock, so rather than having AAPL as the stock symbol, Quantopian identifies it by the (24) integers.

The context.stock, is a function used to store the stock data.
Next, we can 'print' out the function using the following:
     #this function is run once per bar, REQUIRED
def handle_data(context, data);
     print context.stock

Notice how this is mostly the same list of functions we used previously? The only difference is that we removed the 'pass' function and replaced it with the 'print context.stock'

A really cool feature of Quantopian with Python in this instance is that we don't have to use the ID number (SID) if we don't want to. We can simply use the following bit of code to locate the stock by it's ticker symbol:

symbol('AAPL')
**NOTE: the ticker symbol is not robust to ticker changes; in other words, if the ticker symbol changes the function will not change with it, rendering it useless. This is not a dynamic function so it is best to use the SID function instead!


Now we are going to go over how to order securities!
The portfolio value in some contexts, including this one, is calculated as the sum value of all open positions plus the cash balance.
Let's say we want half our portfolio value to be long Apple stock

     #this function is run once per bar, REQUIRED
def handle_data(context, data);
     order_target_percent(context.stock, 0.5)
This takes two parameters, the first being the stock that we want to order and the second being the target percent. The 0.5 dictates that it will take half of our available funds (0.5) and order Apple stock. So if we have $100,000 available and no open positions, this function will go through and order $50,000 of Apple stock.

Now, let's say we want to hedge our investment, we can go short in SPY, a stock that mirrors the performance of the S&P 500 index, for the other half of our portfolio.

 #this function is run once at the beginning of the algorithm REQUIRED
def initialize(context)
context.stock = sid(24)
context.market = sid(8554)
The (8554) is a reference to the SPY security.
Notice that we added the 'context.market = sid(8554)' to our previous function.

#this function is run once per bar, REQUIRED
def handle_data(context, data);
     order_target_percent(context.stock, 0.5)
     order_target_percent(context.market, -0.5)

Notice how we added 'order_target_percent(context.market, -0.5)' to our previous function? This algorithm is saying 'I want to short the SPY using half of my portfolio (-0.5). The short position is denoted by the negative ("-") symbol before the (0.5) number.

I hope you enjoyed this brief tutorial! Part 3 will be added shortly!

Let me know if you have any questions or comments!

Quantopian Introduction

Quantopian.com is pretty neat. You have access to a lot of data, can build your own algorithms, backtest them, and even have the support of the Quantopian community who will share their algorithms with you! Let's get into it here!

This introductory lesson is based upon the Quantopian tutorial, as we advance and move into more sophisticated techniques we will move away from their tutorial however I see fit. My goal is to make this simple and informative so that anyone can learn algorithmic trading without too much of a headache!

Here we go:

_________________________________________________________________________________

This is the default "Sample Mean Reversion" tutorial that I am regurgitating from Quantopian.com and in addition I will provide the reader with a deeper understanding of what's going on and why.

Background: Mean Reversion is a statistical method used in finance: Mean Reversion "is the assumption that a stocks price will tend to move to the average price over time"
"When the current market price is less than the average price, the stock is considered attractive for purchase, with the expectation that the price will rise. When the current market price is above the average price, the market price is expected to fall. In other words, deviations from the average price are expected to revert to the average"-https://en.wikipedia.org/wiki/Mean_reversion_(finance)

In other words, a stock that deviates either above or below it's market price will eventually revert back to it's historical mean. We can visualize this using continuous time-series analysis otherwise known as Orstein-Uhlenbeck process. We don't need to go into depth on the Orstein-Uhlenbeck process, but if you would like to know more see Wikipedia, and basic stochastic processes!

Ok, so now we know what a mean reversion is and why we are doing it. It helps us to understand if a stock is a buy or sell value based upon its current market price compared to its historical mean.

Now for the code: (mind you, this is in Python since we are using Quantopian.com).
**Any line that is preceded with a hashtag (#) and is underlined means that it is a 'comment'-comments are used within lines of code by the creator to define a process, or explain why he/she has done something. You do not need to include it in your code!

# Import the libraries we will use here
import numpy as np

**Ok, so import numpy as np is the coding package we are using in our Python module. This allows us to use certain commands as tools and helps us build the algorithm we intend to build!**

# The initialize function is the place to set your tradable universe and define any parameters. 
def initialize(context):
    # Use the top 1% of stocks defined by average daily trading volume.
    set_universe(universe.DollarVolumeUniverse(99, 100))

  # Set execution cost assumptions. For live trading with Interactive Brokers 
    # we will assume a $1.00 minimum per trade fee, with a per share cost of $0.0075. 
    set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1.00))
   
    # Set market impact assumptions. We limit the simulation to 
    # trade up to 2.5% of the traded volume for any one minute,
    # and  our price impact constant is 0.1. 
    set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.10))
**NOTE: slippage defines how your algorithm will impact the price of the security. As a participant in the market, you will have a small impact on prices depending on how you buy or sell.

    # Define the other variables
    context.long_leverage = 0.5
    context.short_leverage = -0.5
    context.lower_percentile = 20
    context.upper_percentile = 80
    context.returns_lookback = 5

  # Rebalance every Monday (or the first trading day if it's a holiday).
    # At 11AM ET, which is 1 hour and 30 minutes after market open.
    schedule_function(rebalance,
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open(hours = 1, minutes = 30))

# The handle_data function is run every bar.  
def handle_data(context,data):  
    # Record and plot the leverage of our portfolio over time. 
    record(leverage = context.account.leverage)

    # We also want to monitor the number of long and short positions 
    # in our portfolio over time. This loop will check our positition sizes 
    # and add the count of longs and shorts to our plot.
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)

# This rebalancing is called according to our schedule_function settings.    
def rebalance(context,data):
    # Get the last N days of prices for every stock in our universe.
    prices = history(context.returns_lookback, '1d', 'price')
   
    # Calculate the past 5 days' returns for each security.
    returns = (prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
   
    # Remove stocks with missing prices.
    # Remove any stocks we ordered last time that still have open orders.
    # Get the cutoff return percentiles for the long and short portfolios.
    returns = returns.dropna()
    open_orders = get_open_orders()
    if open_orders:
        eligible_secs = [sec for sec in data if sec not in open_orders]
        returns = returns[eligible_secs]

    # Lower percentile is the threshhold for the bottom 20%, upper percentile is for the top 20%.
    lower, upper = np.percentile(returns, [context.lower_percentile,
                                           context.upper_percentile])
   
    # Select the X% worst performing securities to go long.
    long_secs = returns[returns <= lower]
   
    # Select the Y% best performing securities to short.
    short_secs = returns[returns >= upper]
   
    # Set the allocations to even weights in each portfolio.
    long_weight = context.long_leverage / len(long_secs)
    short_weight = context.short_leverage / len(short_secs)
   
    for security in data:
       
        # Buy/rebalance securities in the long leg of our portfolio.
        if security in long_secs:
            order_target_percent(security, long_weight)
           
        # Sell/rebalance securities in the short leg of our portfolio.
        elif security in short_secs:
            order_target_percent(security, short_weight)
           
        # Close any positions that fell out of the list of securities to long or short.
        else:
            order_target(security, 0)
           
    log.info("This week's longs: "+", ".join([long_.symbol for long_ in long_secs.index]))
    log.info("This week's shorts: "  +", ".join([short_.symbol for short_ in short_secs.index]))



Ok, so run the code over at Quantopian.com or go ahead and run it through your own local Python IDLE and have a look at the results. 

If you're running it over at Quantopian.com and want to know the meaning of your results read here:

First, in the right hand side, you have your return; that is pretty self-explanatory, it is telling you how much you have made or lost given percentage of movement in the value of the stock.

Next we have alpha; alpha means 'a measure of performance on a risk adjusted basis' and additionally 'The abnormal rate of return on a security or portfolio in excess of what would be predicted by an equilibrium model like the capital asset pricing model (CAPM).' -http://www.investopedia.com/terms/a/alpha.asp

After alpha, we have beta which measures the volatility or risk.

After beta, we have 'Sharpe', which is the 'Sharpe ratio": it measures the risk-adjusted return. The Sharpe ratio is the average return earned in excess of the risk-free rate per unit of volatility or total risk.

Lastly, we have the drawdown: The peak-to-trough decline during a specific record period of an investment, fund or commodity. A drawdown is usually quoted as the percentage between the peak and the trough.

If you have any questions or concerns please send me an e-mail or post a comment!