Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Simple MA Crossover Strategy in Python

Hi all,

Can anyone help provide with a potential cleaner/simpler MA crossover strategy code with Python? I'm also trying to figure out how to get the stock performance to plot along with the equity curve in one. Thank you for your help.

import pandas_datareader as pdr
import pandas as pd
import datetime
import numpy as np
import matplotlib.pyplot as plt

def get(tickers, startdate, enddate):
def data(ticker):
return (pdr.get_data_yahoo(ticker, start=startdate, end=enddate))
datas = map (data, tickers)
return(pd.concat(datas, keys=tickers, names=['Ticker', 'Date']))

tickers = ['XIV', 'MSFT', 'IBM', 'GOOG']
all_data = get(tickers, datetime.datetime(2006, 10, 1), datetime.datetime(2017, 10, 27))

aapl = pdr.get_data_yahoo('XIV',
start=datetime.datetime(2006, 10, 1),
end=datetime.datetime(2017, 10, 27))

Initialize the short and long windows

short_window = 50
long_window = 100

Initialize the signals DataFrame with the signal column

signals = pd.DataFrame(index=aapl.index)
signals['signal'] = 0.0

Create short simple moving average over the short window

signals['short_mavg'] = aapl['Close'].rolling(window=short_window, min_periods=1, center=False).mean()

Create long simple moving average over the long window

signals['long_mavg'] = aapl['Close'].rolling(window=long_window, min_periods=1, center=False).mean()

Create signals

signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:]
> signals['long_mavg'][short_window:], 1.0, 0.0)

Generate trading orders

signals['positions'] = signals['signal'].diff()

Initialize the plot figure

fig = plt.figure()

Add a subplot and label for y-axis

ax1 = fig.add_subplot(111, ylabel='Price in $')

Plot the closing price

aapl['Close'].plot(ax=ax1, color='r', lw=2.)

Plot the short and long moving averages

signals[['short_mavg', 'long_mavg']].plot(ax=ax1, lw=2.)

Plot the buy signals

ax1.plot(signals.loc[signals.positions == 1.0].index,
signals.short_mavg[signals.positions == 1.0],
'^', markersize=10, color='m')

Plot the sell signals

ax1.plot(signals.loc[signals.positions == -1.0].index,
signals.short_mavg[signals.positions == -1.0],
'v', markersize=10, color='k')

Set the initial capital

initial_capital= float(100000.0)

Create a DataFrame positions

positions = pd.DataFrame(index=signals.index).fillna(0.0)

Buy a 1000 shares

positions['AAPL'] = 1000*signals['signal']

Initialize the portfolio with value owned

portfolio = positions.multiply(aapl['Adj Close'], axis=0)

Store the difference in shares owned

pos_diff = positions.diff()

Add holdings to portfolio

portfolio['holdings'] = (positions.multiply(aapl['Adj Close'], axis=0)).sum(axis=1)

Add cash to portfolio

portfolio['cash'] = initial_capital - (pos_diff.multiply(aapl['Adj Close'], axis=0)).sum(axis=1).cumsum()

Add total to portfolio

portfolio['total'] = portfolio['cash'] + portfolio['holdings']

Add returns to portfolio

portfolio['returns'] = portfolio['total'].pct_change()

Create a figure

fig = plt.figure()

ax1 = fig.add_subplot(111, ylabel='Portfolio value in $')

Plot the equity curve in dollars

portfolio['total'].plot(ax=ax1, lw=2.)

ax1.plot(portfolio.loc[signals.positions == 1.0].index,
portfolio.total[signals.positions == 1.0],
'^', markersize=10, color='m')
ax1.plot(portfolio.loc[signals.positions == -1.0].index,
portfolio.total[signals.positions == -1.0],
'v', markersize=10, color='k')

Show the plot

plt.tight_layout()
plt.show()

Isolate the returns of your strategy

returns = portfolio['returns']

annualized Sharpe ratio

sharpe_ratio = np.sqrt(252) * (returns.mean() / returns.std())

Print the Sharpe ratio

print(sharpe_ratio)

Define a trailing 252 trading day window

window = 252

Calculate the max drawdown in the past window days for each day

rolling_max = aapl['Adj Close'].rolling(window, min_periods=1).max()
daily_drawdown = aapl['Adj Close']/rolling_max - 1.0

Calculate the minimum (negative) daily drawdown

max_daily_drawdown = daily_drawdown.rolling(window, min_periods=1).min()

Plot the results

daily_drawdown.plot()
max_daily_drawdown.plot()

Show the plot

plt.show()