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