In this assignment, you will implement simple algorithmic trading policies and modify a very simple backtester.
In the following, you will find a Backtester1 function that gets as an input the historical price series of a single stock.
At each time interval, the backtester calls for a new order (by calling the placeOrder function), along with the current opening price. Depending upon the current position of the customer (number of owned stocks and current cash), the customer decides upon a new investment. This is currently a random decision, merely deciding the percentage of capital to leave on a stocks. Consequently, the PlaceOrder function will return one of the following orders, to realize the decided position:
PlaceOrder assumes that stocks can be traded only as integer multiples.
Modify the program to create plots of the total wealth over time, along with the value of the stocks and cash at each time point.
Add the following type of orders that a customer can issue
The backtester should always keep track of the position of the trader and make appropriate checks, such as only allowing buying stocks allowed by the current capital.
Add an interest_rate such that at the beginning of each trading day, the cash earns a fixed interest. Also, include transaction costs (a fixed percentage of the trade) to be deduced from each transaction.
Modify the system such that it allows for open selling, that is selling without actually owning any stock. At the end of the trading day, any open positions should be cleared by the closing price.
Think and implement a trading policy of your imagination, such as estimating the trend in the last few days, and coming up with a smarter decision than random. Compare your policy with the random policy in terms of earnings or losses.
Modify the program such that you allow for pairs trading. Modify the backtester such that you input a pair of stocks. Now the generated investment decisions must be portfolio. Repeat task 5 for the pairs case.
In [30]:
import pandas as pd
import pandas.io.data as web
import numpy as np
import datetime
msft = pd.read_csv("msft.csv", index_col=0, parse_dates=True)
aapl = pd.read_csv("aapl.csv", index_col=0, parse_dates=True)
In [25]:
msft['2012-01']
Out[25]:
In [55]:
InitialCash = 1000
Position = {'Cash': InitialCash, 'Stocks': 0.0}
def DecideTargetPosition():
## Randomly decide a portfolio output percentage of capital to put into stocks
return np.random.choice([0.0, 0.5, 1.0])
def Capital(price):
return Position['Cash'] + Position['Stocks']*price
def PlaceOrder(price):
p = DecideTargetPosition()
capital = Capital(price)
numLots = np.floor(capital*p/price)
TargetPosition = {'Cash': capital-numLots*price, 'Stocks': numLots}
if TargetPosition['Stocks'] > Position['Stocks']:
# Buy
order = ('Buy', TargetPosition['Stocks']-Position['Stocks'])
return order
elif TargetPosition['Stocks'] < Position['Stocks']:
# Sell
order = ('Sell', -TargetPosition['Stocks']+Position['Stocks'])
return order
else:
# Do nothing
None
def UpdatePosition(deltaCash, deltaStock):
Position['Cash'] += deltaCash
Position['Stocks'] += deltaStock
return
def BackTester1(series, interest_rate):
openPrice = series['Open']
closePrice = series['Close']
for k in openPrice.keys():
price = openPrice[k]
order = PlaceOrder(price)
if order is None:
continue
print order
if order[0]=='Buy':
deltaCash = -price*order[1]
deltaStock = order[1]
UpdatePosition(deltaCash, deltaStock)
elif order[0]=='Sell':
deltaCash = price*order[1]
deltaStock = -order[1]
UpdatePosition(deltaCash, deltaStock)
else:
None
price = closePrice[k]
print k, Capital(price)
InitialCash = 1000
Position = {'Cash': InitialCash, 'Stocks': 0.0}
BackTester1(msft['2012-01'], 0.05)
In [47]:
class Customer:
def __init__(self, cash=10000):
self.Position = {'Cash': cash, 'Stocks': 0.0}
def DecideTargetPosition(self):
## Randomly decide a portfolio output percentage of capital to put into stocks
return np.random.choice([0.0, 0.5, 1.0])
def Capital(self, price):
return self.Position['Cash'] + self.Position['Stocks']*price
def PlaceOrder(self, price):
p = self.DecideTargetPosition()
capital = self.Capital(price)
numLots = np.floor(capital*p/price)
TargetPosition = {'Cash': capital-numLots*price, 'Stocks': numLots}
if TargetPosition['Stocks']>self.Position['Stocks']:
# Buy
return ('Buy', TargetPosition['Stocks']-self.Position['Stocks'])
elif TargetPosition['Stocks']<self.Position['Stocks']:
# Sell
return ('Sell', -TargetPosition['Stocks']+self.Position['Stocks'])
else:
# Do nothing
None
def GetPosition(self):
return self.Position
def UpdatePosition(self, deltaCash, deltaStock):
self.Position['Cash'] += deltaCash
self.Position['Stocks'] += deltaStock
return
def BackTester(series, customer, interest_rate):
openPrice = series['Open']
closePrice = series['Close']
for k in openPrice.keys():
price = openPrice[k]
order = customer.PlaceOrder(price)
if order is None:
continue
print order
if order[0]=='Buy':
deltaCash = -price*order[1]
deltaStock = order[1]
customer.UpdatePosition(deltaCash, deltaStock)
elif order[0]=='Sell':
deltaCash = price*order[1]
deltaStock = -order[1]
customer.UpdatePosition(deltaCash, deltaStock)
else:
None
price = closePrice[k]
print k, customer.Capital(price)
Cash = 1000
cust = Customer(cash=Cash)
BackTester(msft['2012-01'], cust, 0.05)