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)
log.info("Buying %s" % (context.security.symbol))
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)
log.info("Buying %s" % (context.security.symbol))
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, if current_price > 1.005*average_price and cash > current_price:
number_of_shares = int(cash/current_price)
order(context.security, +number_of_shares)
log.info("Buying %s" % (context.security.symbol))
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.
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).
No comments:
Post a Comment