Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Black Box Trading - sample algorithm explanation

Hello Quantopian,

I am currently a student at Baruch College studying Statistics and Quantitative Modeling. We have started an undergraduate algorithmic trading organization called Black Box Trading. As part of our effort to expose undergraduates to algorithmic trading we are teaching Python and algorithmic trading using Quantopian. David Paradis and I started learning python and quantopian syntax during the summer and I would like to personally
thank the team for bringing such a fantastic platform to the public.

This code is for explanation purposes and will not compile due the misspacing of the comments. I tried to be very detailed in my explanation. I believe this explanation can be used for new quantopian members as well. for some reason, the code editor miscolors certain things. My apologies.

Note for Black Box Trading members: please use this code as a reference of sorts when you are writing your algorithm for this weeks meeting. I already outlined trading strategies you can use in my email.

#importing a library called numpy which does statistical and mathmatical analysis  
import numpy as np

#your main function where you declare global variables and objects  
def initialize(context):  
  '''set universe takes the most liquid stocks in the S&P and stores them in DATA'''   

  set_universe(universe.DollarVolumeUniverse(floor_percentile=98.0,ceiling_percentile=100.0))  
  '''context.stocks in an empty array which will store our stocks'''

  context.stocks = []  
  '''setting order limits so that we wont buy a security above or below the treshhold'''

  context.max_notional = 1000.0  
  context.min_notional = -1000.0

  '''this function loops constantly'''

def handle_data(context, data):  
  '''transferring our stocks from DATA into context.stocks  
     context.stocks now holds all our securities in a list'''

  context.stocks = [stock for stock in data]  
  '''prices is a variable that holds a matrix of all the prices  
     more explanation will be provided in batch transform'''

  prices = get_price(data,context.stocks)  
  '''if there are not enough data points prices will return nothing'''  

  if prices == None:  
      return  


  '''here we are looping through all the securities to use trading rationale for  
  each security stock is a number starting at 0 going up by one each time until  
  it reached the number of stocks we are trading -1.  
  Remember: range(0,10) will go through 0,1,2,3,4,5,6,7,8,9'''  
  for stock in range(len(context.stocks)):  
      '''we define the price of the security we are currently trading'''  

      price = data[context.stocks[stock]].price  
      '''here we are define our notional value; current value of the position we have in our  
         portfolio. it is the amount of shares we have * the current price of the security''' 

      notional = context.portfolio.positions[context.stocks[stock]].amount * price  
      '''we define a moving average by using the price matrix.  
         we are using numpy defined as np and numpy has an average function  
         we take all the prices from our matrix matrix[start value:end value,index number]  
         and find the average'''         

      mvg20 = np.average(prices[:,stock])  
      ''' we are using numpy to find the standard deviation of all our prices''' 

      stdv = np.std(prices[:,stock])  
      '''we are defining the upper and lower bound of our bollinger bands the average of prices  
         plus 2 * the standard deviation of our prices for one security''' 

      UB = mvg20 + 2 * stdv  
      LB = mvg20 - 2 * stdv  
      '''here I tried to define equal allocation for our trades so that our algorithm  
         will not inflate and each position will be equally in proportion to our portfolio  
         we are taking how much cash we have on hand, dividng by the price of the security,  
         dividng by how many securities we have so each security will have equal allocation'''

      nshares = context.portfolio.cash/price/len(context.stocks)  
      '''our trading rational: if the price above the upper limit the stock should go  
         down so you should sell, if the price below the lower bound the stock is over sold  
         and the stock should go up. we are also checking if we can buy or sell a stock  
         based on the value of our current position and max,min position restrictions'''

      if price > UB and notional > context.min_notional:  
          order(cotext.stocks[stock],-nshares)  
      elif price > LB and notional < context.max_notional:  
          order(context.stocks[stock],nshares)  
""" batch transform allows us to work on a trailing data set for all our prices
every period (1) it stores all the prices for the past 20 days (window length)"""  
@batch_transform(refresh_period=1, window_length=20) 

''' we define get_price which we insert data into at as well as the securities we want data on
we defined our securities in context.stocks so we will have:  
prices = get_price(data, context.stocks). prices will return a matrix with all the prices  
from the past 20 days'''  
def get_price(datapanel,sids):  
    '''we search datapanel for the index named 'price' and store the prices of the securiteis  
    as a matrix in our variable price'''  
    price = datapanel['price'].as_matrix(sids)  
    '''our function returns price'''  
    return price  
4 responses

Hello Daniel,

The code has one typo i.e. 'cotext' so you've probably been looking at it too long! And I assume '@batch' needs a 'def' on the next line so I moved some comments. I haven't looked at what the algo does yet.

P.

Sorry if this is a silly question Daniel, but can you elaborate on the "price"? I'm a tad confused on its usage since price = data[context.stocks[stock]].price as defined, but it's also the variable/matrix returned by get_price in the batch_transform, not to mention that there's a datapanel index named 'price' and also the prices array. Much thanks!

Hello Billy,

This might be more meaningful:

def get_price_history(datapanel,sids):  
        price_history = datapanel['close_price'].as_matrix(sids)  
        return price_history  

which is a rolling window of closing prices. And:

price = data[context.stocks[stock]].close_price  

is the current closing price for the current SID. 'price' and 'close_price' refer to the same property of the data object.

P.

Thanks for the prompt reply and clarification!