# Python vs R #3: A simple moving average crossover backtest on SPY

This is the third in a series that is comparing Python and R for quantitative trading analysis. Using the zipline framework for Python and the work of Systematic Investor Toolbox for R, I implement the same moving average cross-over model in each language. Because of the OOP nature of Python there are many differences between the two languages, leading to about twice as much code. Presumably the added OO complexity is useful in much more complicated strategies.#### Python

```
#Load the required libraries
from zipline.algorithm import TradingAlgorithm
from zipline.transforms import MovingAverage
from zipline.utils.factory import load_from_yahoo
from zipline.finance.slippage import FixedSlippage
from zipline.finance.commission import PerShare
from datetime import datetime
import matplotlib.pyplot as plt
class DualMovingAverage(TradingAlgorithm):
def initialize(self, short_window = 50, long_window = 200):
# alculate the minimum window before a trade can be made
self.min_window = max(short_window,long_window)
#Calculate the long and short moving averages and
#add them to the data
self.add_transform(MovingAverage, 'short_mavg', ['price'],
window_length=short_window)
self.add_transform(MovingAverage, 'long_mavg', ['price'],
window_length=long_window)
#To keep track of whether we invested in the stock or not
self.invested = False
#To be used to determine what day in the backtest its in
self.days = 0
#To match the default settings on R, set slippage and
#comission to 0
self.set_slippage(FixedSlippage(spread=0.00))
self.set_commission(PerShare(cost=0.00))
def handle_data(self, data):
self.short_mavg = data['SPY'].short_mavg['price']
self.long_mavg = data['SPY'].long_mavg['price']
self.buy = False
self.sell = False
#If short MA is greater than long MA, we are past the
#minimum number of days and not currently invested then
#buy 100% of portfolio value to initiate position
if self.short_mavg > self.long_mavg and self.days >
self.min_window and not self.invested:
self.order_percent('SPY',1)
self.invested = True
self.buy = True
#If short MA is less than long MA, we are past the
#minimum number of days and its currently invested then
#sell 100% of portfolio to close position
elif self.short_mavg < self.long_mavg and self.days >
self.min_window and self.invested:
self.order_percent('SPY',-1)
self.invested = False
self.sell = True
#Increment the number of days in backtest
self.days = self.days + 1
#Record custom values to the results
self.record(short_mavg=self.short_mavg,
long_mavg=self.long_mavg,
buy=self.buy,
sell=self.sell,
days=self.days)
#Main program
if __name__ == '__main__':
#Get market data
start = datetime(2000, 1, 1)
end = datetime(2014, 3, 25)
data = load_from_yahoo(stocks=['SPY'], indexes={},
start=start, end=end,
adjusted=bool(1))
#Create the moving average strategy object and pass
#the market data
dma = DualMovingAverage()
results = dma.run(data)
#Plot the equity curve and export the trades to a csv
results.portfolio_value.plot(title="Equity Curve")
plt.show()
results.to_csv('/Users/jeickmeier/Desktop/python_results.csv',',')
```

#### R

```
#Load the required packages
load.packages('quantmod')
require(RCurl)
sit = getURLContent('https://github.com/systematicinvestor/SIT/raw/master/sit.gz', binary=TRUE, followlocation = TRUE, ssl.verifypeer = FALSE)
con = gzcon(rawConnection(sit, 'rb'))
source(con)
close(con)
data <- new.env()
# Load historical data and adjusts for splits and dividends
tickers = spl('SPY')
getSymbols(tickers, src = 'yahoo', from = '2000-01-01', env = data, auto.assign = T)
for(i in ls(data)) data[[i]] = adjustOHLC(data[[i]], use.Adjusted=T)
#Calculate the moving averages and lag them one day to prevent lookback bias
PreviousSMA_50 <- lag(SMA(Cl(data[['SPY']]),50))
PreviousSMA_200 <- lag(SMA(Cl(data[['SPY']]),200))
#Sets backtesting environment
bt.prep(data, align='remove.na')
prices = data$prices
#Create a empty list for attaching the models to at a later stage
models = list()
#Specify the weights to be used in the backtest
data$weight[] = NA #Zero out any weights from previous
data$weight[] = ifelse(as.integer(PreviousSMA_50>PreviousSMA_200)==1,1,0) #If price of SPY is above the SMA then buy
#Call the function to run the backtest given the data, which contains the prices and weights.
models$technical_model = bt.run.share(data, trade.summary=T)
#Plot equity curve and export the trades list to csv
plot(models$technical_model$equity, main="Equity Curve")
write.csv(models$technical_model$trade.summary$trades, "/Users/jeickmeier/Desktop/R_results.csv")
```