In [33]:
import datetime as dt
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
In [17]:
import quandl
aapl = quandl.get("WIKI/AAPL", start_date="2006-10-01",
end_date="2012-01-01")
aapl.to_csv('data/aapl_ohlc.csv')
df = pd.read_csv('data/aapl_ohlc.csv', header=0, index_col='Date',
parse_dates=True)
df.describe()
Out[17]:
In [ ]:
# Return last rows of `appl`
In [ ]:
# Return last rows of `appl`
In [18]:
df['Close'].plot(grid=True)
plt.show()
In [24]:
# Assign `Adj Close` to `daily_close`
daily_close = df[['Adj. Close']]
# Daily returns
daily_pct_change = daily_close.pct_change()
# Replace NA values with 0
daily_pct_change.fillna(0, inplace=True)
# Inspect daily returns
print(daily_pct_change)
# Daily log returns
daily_log_returns = np.log(daily_close.pct_change()+1)
# Print daily log returns
print(daily_log_returns)
In [25]:
# Resample `aapl` to business months, take last observation as value
monthly = df.resample('BM').apply(lambda x: x[-1])
# Calculate the monthly percentage change
monthly.pct_change()
# Resample `aapl` to quarters, take the mean as value per quarter
quarter = df.resample("4M").mean()
# Calculate the quarterly percentage change
quarter.pct_change()
Out[25]:
In [26]:
# Daily returns
daily_pct_change = daily_close / daily_close.shift(1) - 1
# Print `daily_pct_change`
print(daily_pct_change)
In [27]:
# Import matplotlib
import matplotlib.pyplot as plt
# Plot the distribution of `daily_pct_c`
daily_pct_change.hist(bins=50)
# Show the plot
plt.show()
# Pull up summary statistics
print(daily_pct_change.describe())
In [28]:
# Calculate the cumulative daily returns
cum_daily_return = (1 + daily_pct_change).cumprod()
# Print `cum_daily_return`
print(cum_daily_return)
In [29]:
# Import matplotlib
import matplotlib.pyplot as plt
# Plot the cumulative daily returns
cum_daily_return.plot(figsize=(12,8))
# Show the plot
plt.show()
In [30]:
# Resample the cumulative daily return to cumulative monthly return
cum_monthly_return = cum_daily_return.resample("M").mean()
# Print the `cum_monthly_return`
print(cum_monthly_return)
In [37]:
def get(tickers, startdate, enddate):
def data(ticker):
return (quandl.get('WIKI/{}'.format(ticker),
start_date=startdate.isoformat(),
end_date=enddate.isoformat()))
datas = map (data, tickers)
return(pd.concat(datas, keys=tickers, names=['Ticker', 'Date']))
tickers = ['AAPL', 'MSFT', 'IBM', 'GOOG']
all_data = get(tickers, dt.date(2006, 10, 1),
dt.date(2012, 1, 1))
In [41]:
# Import matplotlib
import matplotlib.pyplot as plt
# Isolate the `Adj Close` values and transform the DataFrame
daily_close_px = all_data[['Adj. Close']].reset_index().pivot('Date',
'Ticker',
'Adj. Close')
# Calculate the daily percentage change for `daily_close_px`
daily_pct_change = daily_close_px.pct_change()
# Plot the distributions
daily_pct_change.hist(bins=50, sharex=True, figsize=(12,8))
# Show the resulting plot
plt.show()
In [46]:
# Plot a scatter matrix with the `daily_pct_change` data
pd.plotting.scatter_matrix(daily_pct_change, diagonal='kde', alpha=0.1,figsize=(12,12))
# Show the plot
plt.show()
In [48]:
# Isolate the adjusted closing prices
adj_close_px = df['Adj. Close']
# Calculate the moving average
moving_avg = adj_close_px.rolling(window=40).mean()
# Inspect the result
print(moving_avg[-10:])
In [50]:
# Short moving window rolling mean
df['42'] = adj_close_px.rolling(window=40).mean()
# Long moving window rolling mean
df['252'] = adj_close_px.rolling(window=252).mean()
# Plot the adjusted closing price, the short and long windows of rolling means
df[['Adj. Close', '42', '252']].plot()
# Show plot
plt.show()
In [51]:
# Define the minumum of periods to consider
min_periods = 75
# Calculate the volatility
vol = daily_pct_change.rolling(min_periods).std() * np.sqrt(min_periods)
# Plot the volatility
vol.plot(figsize=(10, 8))
# Show the plot
plt.show()
In [54]:
# Import the `api` model of `statsmodels` under alias `sm`
import statsmodels.api as sm
# Import the `datetools` module from `pandas`
from pandas.core import datetools
# Isolate the adjusted closing price
all_adj_close = all_data[['Adj. Close']]
# Calculate the returns
all_returns = np.log(all_adj_close / all_adj_close.shift(1))
# Isolate the AAPL returns
aapl_returns = all_returns.iloc[all_returns.index.get_level_values('Ticker') == 'AAPL']
aapl_returns.index = aapl_returns.index.droplevel('Ticker')
# Isolate the MSFT returns
msft_returns = all_returns.iloc[all_returns.index.get_level_values('Ticker') == 'MSFT']
msft_returns.index = msft_returns.index.droplevel('Ticker')
# Build up a new DataFrame with AAPL and MSFT returns
return_data = pd.concat([aapl_returns, msft_returns], axis=1)[1:]
return_data.columns = ['AAPL', 'MSFT']
# Add a constant
X = sm.add_constant(return_data['AAPL'])
# Construct the model
model = sm.OLS(return_data['MSFT'],X).fit()
# Print the summary
print(model.summary())
In [55]:
# Plot returns of AAPL and MSFT
plt.plot(return_data['AAPL'], return_data['MSFT'], 'r.')
# Add an axis to the plot
ax = plt.axis()
# Initialize `x`
x = np.linspace(ax[0], ax[1] + 0.01)
# Plot the regression line
plt.plot(x, model.params[0] + model.params[1] * x, 'b', lw=2)
# Customize the plot
plt.grid(True)
plt.axis('tight')
plt.xlabel('Apple Returns')
plt.ylabel('Microsoft returns')
# Show the plot
plt.show()
In [56]:
# Plot the rolling correlation
return_data['MSFT'].rolling(window=252).corr(return_data['AAPL']).plot()
# Show the plot
plt.show()
In [57]:
# Initialize the short and long windows
short_window = 40
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()
# Print `signals`
print(signals)
In [58]:
# 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')
# Show the plot
plt.show()
In [62]:
# Set the initial capital
initial_capital= float(100000.0)
# Create a DataFrame `positions`
positions = pd.DataFrame(index=signals.index).fillna(0.0)
# Buy a 100 shares
positions['AAPL'] = 100*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()
# Print the first lines of `portfolio`
print(portfolio.head())
In [63]:
# 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.show()
In [64]:
def initialize(context):
context.sym = symbol('AAPL')
context.i = 0
def handle_data(context, data):
# Skip first 300 days to get full windows
context.i += 1
if context.i < 300:
return
# Compute averages
# history() has to be called with the same params
# from above and returns a pandas dataframe.
short_mavg = data.history(context.sym, 'price', 100, '1d').mean()
long_mavg = data.history(context.sym, 'price', 300, '1d').mean()
# Trading logic
if short_mavg > long_mavg:
# order_target orders as many shares as needed to
# achieve the desired number of shares.
order_target(context.sym, 100)
elif short_mavg < long_mavg:
order_target(context.sym, 0)
# Save values for later inspection
record(AAPL=data.current(context.sym, "price"),
short_mavg=short_mavg,
long_mavg=long_mavg)
In [65]:
# 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)
In [67]:
# 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()
In [69]:
# Get the number of days in `aapl`
days = (aapl.index[-1] - aapl.index[0]).days
# Calculate the CAGR
cagr = ((((aapl['Adj. Close'][-1]) / aapl['Adj. Close'][1])) ** (365.0/days)) - 1
# Print the CAGR
print(cagr)
In [ ]: