## Monday, 6 April 2015

### Quantopian Algorithmic Trading Strategy: Basic, Daily

We have been recently been using Quantopian, a crowd-sourced hedge fund which allows individuals access to a browser-based algorithmic trading platform. Below is a basic investment strategy. Algorithms are coded in Python, and backtested against US stock price and fundamental data.

def initialize(context):
context.security = symbol('K')

def handle_data(context, data):

average_price = data[context.security].mavg(5)
current_price = data[context.security].price
cash = context.portfolio.cash

if current_price > 1.01*average_price and cash > current_price:
number_of_shares = int(cash/current_price)
order(context.security, +number_of_shares)

elif current_price < average_price:
order_target(context.security, 0)
log.info("Selling %s" % (context.security.symbol))

record(stock_price=data[context.security].price)

Function meanings:

• To start an algorithm, we need to use the initialise function. This will set any data or variables that are used in the algorithm, such as the security, or parameters
• data is a dictionary that represents a snapshot of the algorithm's universe including market information about the security and transforms
• context stores any state defined by us and stores portfolio object
• In the first example, we are using Kellogg (K)
• The handle_data function is run based on user specified frequency- either every minute (live trading and minute backtesting) or daily i.e. handle_data is called whenever a market event occurs for Kellogg
• We calculate the average price of Kellogg stock based on the moving average for the last 5 days
• The portfolio object tracks our position, cash, cost basis of holdings, etc. In our basic strategy, we are interested in the current amount of cash in our portfolio
• We have programmed the algorithm to BUY if current price is 1% above Kellogg's 5 day average price and there is enough cash in the portfolio
• This is why we also need to calculate how many shares to buy
• We have programmed the algorithm to SELL if current price is below Kellogg's 5 day average price, that is, close position to holding zero shares
• The record function can track signals, up to five different variables. In our case, we are recording Kellogg's stock price.
The screenshot demonstrates this strategy generates 8.3% return from the start of 2014 to April 2015.

However, we identified a potential problem which played a role in lowering returns. We replaced the code to sell with a code instructing sell only if the current price is higher than purchase price/cost basis. Firstly we define cost basis as the volume weighted average price paid (including commission) per share in this position.

costBasis = context.portfolio.positions[context.security].cost_basis
elif current_price > costBasis:
order_target(context.security, 0)
log.info("Selling %s" % (context.security.symbol))

This gave us a higher return of 19%, outperforming the benchmark.

Update (7/4/15): I updated the buying strategy to

if current_price > 1.005*average_price and cash > current_price:
number_of_shares = int(cash/current_price)
order(context.security, +number_of_shares)

All else remains unchanged. I believe that buying the stock when it increases its price by 0.5% as opposed to 1% would improve chances of making the most of the upswing in price before it fell again. This was confirmed by the 28.59% returns.

If the same buy strategy (buy if 0.5% increase) had used a sell strategy where we sell if current price is below average price, ignoring the fact the current price could be below purchase price,

elif current_price < average_price:
order_target(context.security, 0)
log.info("Selling %s" % (context.security.symbol)) The returns are 13.1%. This is higher than our original strategy (which generated 8.3% return)- the 0.5% buy strategy boosted returns by approximately 5%. Adding in the improved sell strategy where sell only if current price is above purchase price more than doubles this return.

Using the same strategy on Facebook stock though with a moving average of 7 days, we generate a 22.4% return. We have added the function set_symbol_lookup_date, which globally sets the date to help disambiguate cases where a symbol historically referred to different securities (FB used to refer to FBR Asset Investment Corp, last traded in 2003).