The idea for doing this project comes from the book Doing Data Science by Cathy O'Neil and Rachel Schutt.
Gather financial data and create and investigate potential features for modeling use cases. Compute daily log returns and log Volume data. Generate a volatility index that looks at an exponentially weighted window function of the variance. Generate simple linear forecasting models based on these features. Compare a strategy using these models with a random model and a buy and hold model.
The goal of this project was to code simple predictive models and compare returns over some time period with using "naive models", e.g. buy and hold. In this notebook I use data for AAPL stock from 1995 to 2018. I generate a model trained from data between 1995 and 2015 and apply this model to the years 2015, 2016 and 2017. It is not surprising to me that I did not find any significant correlation with the model and next day stock returns. The models do not show any predictive tendencies relative to a stochastic model that randomly chose to buy and sell on any given day or just buying and holding.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import pandas_datareader
## Get some financial data
## Quandl - is a private a financial data provider.
start_date = '1990-01-01'
end_date = '2018-11-12'
# Quandl Key, add here:
key="YOURKEYHERE"
# this is the sp500 - just the daily value
sp_code="MULTPL/SP500_REAL_PRICE_MONTH"
## To start = let's use an index
#q1 = pandas_datareader.quandl.QuandlReader("AMZN", start_date, end_date, api_key=key)
#q2 = pandas_datareader.quandl.QuandlReader("GOOGL", start_date, end_date, api_key=key)
q3 = pandas_datareader.quandl.QuandlReader("AAPL", start_date, end_date, api_key=key)
#q4 = pandas_datareader.quandl.QuandlReader("FB", start_date, end_date, api_key=key)
#q = pandas_datareader.quandl.QuandlReader(sp_code, start_date, end_date, api_key=key)
#amzn=q1.read()
#goog=q2.read()
aapl=q3.read()
# Note - data stops around 3/27/2018
# In previous notebooks I've looked at this data in more depth, here we'll take a peak,
# and then do a series of transformations before we look at modeling results
#print(amzn.shape, amzn.index.min(),amzn.index.max())
#print(goog.shape, goog.index.min(),goog.index.max())
print(aapl.shape, aapl.index.min(),aapl.index.max())
# Aapl
aapl.head()
## Ok - a while ago the adjusted close values are pretty low!
aapl[(aapl.index>'1997') & (aapl.index<'1999') ].AdjClose.plot()
# Oh right - there was a bit split a few years back
aapl[['AdjClose','Close']].plot()
First transform the data so that it is feasible to generate linear models with y = Bx + C and find B and C that are the best fit to the data
# Transformations we'll do:
#
aapl=aapl.reindex(index=aapl.index[::-1])
aapl['LR']=aapl[['AdjClose']].apply(lambda x: np.log(x) - np.log(x.shift(1)))
aapl['NLR']=(aapl.LR - aapl.LR.mean())/aapl.LR.std()
aapl['vol']=aapl.LR.ewm(halflife=0.97).std()
aapl['LV']=aapl[['AdjVolume']].apply(lambda x: np.log(x) - np.log(x.shift(1)))
aapl['IV']=(aapl.AdjHigh - aapl.AdjLow)/aapl.AdjClose
aapl['IC']=(aapl.AdjClose - aapl.AdjLow)/(aapl.AdjHigh - aapl.AdjLow)
aapl[['LR','NLR','vol','LV','IV','IC']].head()
# Look at the log return and Inter Close
aapl[(aapl.index > '2002') & (aapl.index < '2003')][['NLR','IC']].plot(figsize=(12,6))
# Are there any interesting correlations?
aapl[(aapl.index > '2002') & (aapl.index < '2003')][['NLR','IC']].corr()
## Look at the volatility and the Interday Volatility
aapl[(aapl.index > '2004') & (aapl.index < '2005')][['vol','IV']].plot(figsize=(12,6))
## are the vols correlated?
aapl[(aapl.index > '2004') & (aapl.index < '2005')][['vol','IV']].corr()
# Ok, now add previous days data:
# This will add the LR-1 as previous NormedLR, making it available for a y = Ax + B type linear problem.
# Since data is ordered old => new, a positive shift, shifts the index "upwards" and gets older data
aapl['NLR-1']=aapl[['NLR']].apply(lambda x: x.shift(1))
aapl['NLR-2']=aapl[['NLR']].apply(lambda x: x.shift(2))
aapl['NLR-3']=aapl[['NLR']].apply(lambda x: x.shift(3))
aapl['NLR-4']=aapl[['NLR']].apply(lambda x: x.shift(4))
# And the future value - what the model is to predict, y = NLR+1
aapl['NLR+1']=aapl[['NLR']].apply(lambda x: x.shift(-1))
# Peak at this:
aapl[['LR', 'AdjClose','NLR+1','NLR','NLR-1','NLR-2','NLR-3','NLR-4','vol','LV','AdjVolume','IV','IC']].head(6)
aapl[['LR', 'AdjClose','NLR+1','NLR','NLR-1','NLR-2','NLR-3','NLR-4','vol','LV','IV','IC']].describe().transpose()
## The modeling process could be as simple as seeing if there's any correlation with NLR+1 with any variable?
aapl[(aapl.index > '2002') & (aapl.index < '2003')][['NLR+1', 'AdjClose','NLR+1','NLR','NLR-1','NLR-2','NLR-3','NLR-4','vol','LV','IV','IC']].corr()
Now that we've prepared historic data we'd like to test and apply a predictive model and strategy for trading securities. Here is my initial work that explores the code used to create the different model returns.
## How do I see how much just holding AAPL would do?
# Let's say I make a bet of 1000 shares. What would happen?
hold = aapl[(aapl.index > '2002') & (aapl.index < '2003')][['AdjClose','LR']]
# Calculate the daily change by looking at the Return from the previous day, and multiplying by previous days price
hold['daily_change']=1000*(np.exp(hold['LR'])-1)*hold['AdjClose'].shift(1)
hold['investment_value']=1000*hold.AdjClose
initial_investment=1000*hold[hold.index==hold.index.min()].AdjClose[0]
# This works - but is hella ugly
#hold['overall_return']=np.ones(hold.count()[0])*initial_investment[0]*hold.AdjClose
hold['overall_return']=1000*hold.AdjClose - initial_investment
# calculate daily change, by looking at overall_return_1 - overall_return_0
hold['daily_change2']=hold[['overall_return']].apply(lambda x: x - x.shift(1))
hold['overall_return2']=hold.daily_change2.cumsum()
# checksum:
hold['chksm1']=hold['overall_return2']-hold['overall_return']
hold.chksm1.sum()
del hold['chksm1']
hold.head()
hold.tail()
# Using the plt.figure()
hold['investment_value'].plot(grid=True, legend=True)
hold['daily_change'].plot(grid=True, legend=True, secondary_y=True)
## Ok, now lets make a stochastic model, (perhaps a few.. ) and see how how it does..
# Let's say bet on 1000 shares. And always sell on the next day after a bet. What would happen?
# Also - what would the range of outcomes be, etc..
# first, what is the approx number of days that returns are positive in the data? close to 50% over all..
print(aapl[aapl.index<'2002'].count()[0])
print(aapl[(aapl.index<'2002') & (aapl.LR > 0)].count()[0])
print(np.float(aapl[(aapl.index<'2002') & (aapl.LR > 0)].count()[0]) / aapl[aapl.index<'2002'].count()[0])
# First cut a simple stochastic model
rand = aapl[(aapl.index > '2002') & (aapl.index < '2003')][['AdjClose','LR']]
rand['make_bet']=np.random.randint(0,2, rand.shape[0])
print("number of days: ",rand.shape[0]," bets: ",rand.make_bet.sum())
# Calculate the daily change by looking at the Return from the previous day, and multiplying by previous days price
#rand['daily_change']=1000*(np.exp(hold['LR'])-1)*hold['AdjClose'].shift(1)
rand['daily_change']=1000*rand[['AdjClose']].apply(lambda x: x - x.shift(1))
rand['investment_change']=rand['daily_change']*rand['make_bet']
rand['investment_return']=rand['investment_change'].cumsum()
rand.head(10)
hold.head()
# Compare the holding vs random buying and selling
ax = hold['overall_return'].plot(grid=True, legend=True)
rand['investment_return'].plot(grid=True, legend=True)
hold['daily_change'].plot(grid=True, legend=True, secondary_y=True)
ax.set_ylabel('Cumulative Return [$]')
ax.right_ax.set_ylabel('Daily Price Change [$]')
ax.set_xlabel('Year')
Here I train a simple linear model apply it to future data. I also compare to the "buy and hold" and "stochastic" models and generate explanatory statistics and plots.
Note that the since the stochastic model chooses to bet ~ half the time, the return is roughly half of the buy and hold strategy.
# Simple model -
# Train a simple model with AAPL on say 1998 to 2012, then test the model for each year post 2012
X_train = aapl[(aapl.index>'1996') & (aapl.index<'2015')][['NLR','NLR-1','NLR-2','NLR-3','vol','LV','IV','IC']]
Y_train = aapl[(aapl.index>'1996') & (aapl.index<'2015')][['NLR+1']]
# Lets test the model on various years: (Select out 15, 16, 17 for plots later)
X = aapl[(aapl.index>'2015') & (aapl.index<'2018')][['NLR','NLR-1','NLR-2','NLR-3','vol','LV','IV','IC']]
Y = aapl[(aapl.index>'2015') & (aapl.index<'2018')][['NLR+1']]
X15 = aapl[(aapl.index>'2015') & (aapl.index<'2016')][['NLR','NLR-1','NLR-2','NLR-3','vol','LV','IV','IC']]
Y15 = aapl[(aapl.index>'2015') & (aapl.index<'2016')][['NLR+1']]
X16 = aapl[(aapl.index>'2016') & (aapl.index<'2017')][['NLR','NLR-1','NLR-2','NLR-3','vol','LV','IV','IC']]
Y16 = aapl[(aapl.index>'2016') & (aapl.index<'2017')][['NLR+1']]
X17 = aapl[(aapl.index>'2017') & (aapl.index<'2018')][['NLR','NLR-1','NLR-2','NLR-3','vol','LV','IV','IC']]
Y17 = aapl[(aapl.index>'2017') & (aapl.index<'2018')][['NLR+1']]
X_train.describe().transpose()
# Creat the model
X_train.head()
Y_train.describe().transpose()
Y_train.head()
from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso
from sklearn.metrics import mean_squared_error
# Actual model - lasso model
regressor = Ridge(alpha=0.5)
regressor.fit(X_train, Y_train)
r2 = Lasso(alpha=0.0001)
r2.fit(X_train, Y_train)
# Predictions for each of 2015, 2016, 2017
Y_predict = regressor.predict(X)
Y15_predict = regressor.predict(X15)
Y16_predict = regressor.predict(X16)
Y17_predict = regressor.predict(X17)
# Predictions for each of 2015, 2016, 2017 using the Lasso model
Y_predict2 = r2.predict(X)
Y15_predict2 = r2.predict(X15)
Y16_predict2 = r2.predict(X16)
Y17_predict2 = r2.predict(X17)
mean_squared_error(Y_predict, Y)
mean_squared_error(Y_predict2, Y)
regressor.coef_
r2.coef_
Column Name | Model | Details |
---|---|---|
daily_change | None | Difference in stock price between today and yesterday |
hold_current_value | Hold | Today's AdjClose * Number of shares purchased, Hold investment value |
hold_current_return | Hold | Current Return, today's investment - initial investment |
rand_make_bet | Random | boolean on whether to buy on that day |
rand_daily_change | Random | If a bet is made today, tomorrow will reflect that bet as (amount * daily_change) |
predict | Predictive | Output of predictive model (Real number) |
predict_make_bet | Predictive | Boolean output of predictive model (1 if predict > 0) |
predict_daily_change | Predictive | If a bet is made today, tomorrow will reflect that bet as (amount * daily_change) |
## Ok - gather the data for 2015
data_15 = aapl[(aapl.index > '2015') & (aapl.index < '2016')][['AdjClose','LR']]
## Random model - randomly buy and sell stock, if this is a 1, buy (and sell the next day)
data_15['rand_make_bet']=np.random.randint(0,2, data_15.shape[0])
print("Number of days: {0}".format(data_15.shape[0]))
print("Number of random bets: {0}".format(data_15.rand_make_bet.sum()))
## Recall - LR = Log(C_t/C_(t-1)))
data_15['daily_change']=(np.exp(data_15['LR'])-1)*data_15['AdjClose'].shift(1)
## Static model - buy and hold
data_15['hold_current_value']=1000*data_15.AdjClose
initial_investment15=1000*data_15[data_15.index==data_15.index.min()].AdjClose[0]
print("initial investment: {0:8.2f}".format(initial_investment15))
# This is the current Investment amount
data_15['hold_current_return']=1000*data_15.AdjClose - initial_investment15
roi_hold_net15=data_15.hold_current_return[-1:][0]
print("Final hold net return: {0:8.2f}".format(roi_hold_net15))
#rand['daily_change']=1000*(np.exp(hold['LR'])-1)*hold['AdjClose'].shift(1)
#data_15['rand_daily_change']=1000*data_15[['AdjClose']].apply(lambda x: x - x.shift(1))
data_15['rand_daily_change']=1000*data_15['daily_change']*data_15['rand_make_bet'].shift(1)
#data_15['rand_current_return']=data_15['rand_daily_change'].cumsum()
data_15['predict']=Y15_predict
data_15['predict_make_bet']=np.where(data_15['predict']>0, 1, 0)
print("Number of model bets: {0}".format(data_15.predict_make_bet.sum()))
data_15['predict_daily_change']=1000*data_15['daily_change']*data_15['predict_make_bet'].shift(1)
#data_15['predict_current_return']=data_15['predict_daily_change'].cumsum()
data_15['predict2']=Y15_predict2
data_15['predict_make_bet2']=np.where(data_15['predict2']>0, 1, 0)
print("Number of model bets: {0}".format(data_15.predict_make_bet2.sum()))
data_15['predict_daily_change2']=1000*data_15['daily_change']*data_15['predict_make_bet2'].shift(1)
#data_15['predict_current_return']=data_15['predict_daily_change'].cumsum()
# Calculate my return:
print("\nBuy and Hold Results")
print("Net gain: {0:8.2f}".format(roi_hold_net15))
prct_roi_hold15= 100*roi_hold_net15/initial_investment15
print("Percent gain: {0:2.2f} %".format(prct_roi_hold15))
print("Random Results:")
roi_rand15=data_15['rand_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_rand15))
prct_roi_rand15=100*(roi_rand15 ) / initial_investment15
print("Percent gain: {0:2.2f} %".format(prct_roi_rand15))
print("Model Results:")
roi_model15=data_15['predict_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model15))
prct_roi_model15=100*(roi_model15 ) / initial_investment15
print("Percent gain: {0:2.2f} %".format(prct_roi_model15))
print("Model Results (Lasso, alpha=.001):")
roi_model15_2=data_15['predict_daily_change2'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model15_2))
prct_roi_model15_2=100*(roi_model15_2 ) / initial_investment15
print("Percent gain: {0:2.2f} %".format(prct_roi_model15_2))
# Ok - gather the data for 2016
data_16 = aapl[(aapl.index > '2016') & (aapl.index < '2017')][['AdjClose','LR']]
## Random model - randomly buy and sell stock
data_16['rand_make_bet']=np.random.randint(0,2, data_16.shape[0])
print("Number of days: {0}".format(data_16.shape[0]))
print("Number of random bets: {0}".format(data_16.rand_make_bet.sum()))
## Recall - LR = Log(C_t/C_(t-1)))
data_16['daily_change']=(np.exp(data_16['LR'])-1)*data_16['AdjClose'].shift(1)
## Static model - buy and hgold
data_16['hold_current_value']=1000*data_16.AdjClose
initial_investment16=1000*data_16[data_16.index==data_16.index.min()].AdjClose[0]
print("initial investment: {0:8.2f}".format(initial_investment16))
data_16['hold_current_return']=1000*data_16.AdjClose - initial_investment16
roi_hold_net16=data_16.hold_current_return[-1:][0]
print("Final hold net return: {0:8.2f}".format(roi_hold_net16))
data_16['rand_daily_change']=1000*data_16['daily_change']*data_16['rand_make_bet'].shift(1)
data_16['predict']=Y16_predict
data_16['predict_make_bet']=np.where(data_16['predict']>0, 1, 0)
print("Number of model bets: {0}".format(data_16.predict_make_bet.sum()))
data_16['predict_daily_change']=1000*data_16['daily_change']*data_16['predict_make_bet'].shift(1)
data_16['predict2']=Y16_predict2
data_16['predict_make_bet2']=np.where(data_16['predict2']>0, 1, 0)
print("Number of model bets: {0}".format(data_16.predict_make_bet2.sum()))
data_16['predict_daily_change2']=1000*data_16['daily_change']*data_16['predict_make_bet2'].shift(1)
#data_15['predict_current_return']=data_15['predict_daily_change'].cumsum()
# Calculate my return:
print("Buy and Hold Results")
print("Net gain: {0:8.2f}".format(roi_hold_net16))
prct_roi_hold16= 100*roi_hold_net16/initial_investment16
print("Percent gain: {0:2.2f} %".format(prct_roi_hold16))
print("Random Results:")
roi_rand16=data_16['rand_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_rand16))
prct_roi_rand16=100*(roi_rand16 ) / initial_investment16
print("Percent gain: {0:2.2f} %".format(prct_roi_rand16))
print("Model Results:")
roi_model16=data_16['predict_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model16))
prct_roi_model16=100*(roi_model16 ) / initial_investment16
print("Percent gain: {0:2.2f} %".format(prct_roi_model16))
print("Model Results (Lasso, alpha=.001):")
roi_model16_2=data_16['predict_daily_change2'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model16_2))
prct_roi_model16_2=100*(roi_model16_2 ) / initial_investment16
print("Percent gain: {0:2.2f} %".format(prct_roi_model16_2))
# Ok - gather the data for 2017
data_17 = aapl[(aapl.index > '2017') & (aapl.index < '2018')][['AdjClose','LR']]
## Random model - randomly buy and sell stock
data_17['rand_make_bet']=np.random.randint(0,2, data_17.shape[0])
print("Number of days: {0}".format(data_17.shape[0]))
print("Number of random bets: {0}".format(data_17.rand_make_bet.sum()))
## Recall - LR = Log(C_t/C_(t-1)))
data_17['daily_change']=(np.exp(data_17['LR'])-1)*data_17['AdjClose'].shift(1)
## Static model - buy and hgold
data_17['hold_current_value']=1000*data_17.AdjClose
initial_investment17=1000*data_17[data_17.index==data_17.index.min()].AdjClose[0]
print("initial investment: {0:8.2f}".format(initial_investment17))
data_17['hold_current_return']=1000*data_17.AdjClose - initial_investment17
roi_hold_net17=data_17.hold_current_return[-1:][0]
print("Final hold net return: {0:8.2f}".format(roi_hold_net17))
data_17['rand_daily_change']=1000*data_17['daily_change']*data_17['rand_make_bet'].shift(1)
data_17['predict']=Y17_predict
data_17['predict_make_bet']=np.where(data_17['predict']>0, 1, 0)
print("Number of model bets: {0}".format(data_17.predict_make_bet.sum()))
data_17['predict_daily_change']=1000*data_17['daily_change']*data_17['predict_make_bet'].shift(1)
data_17['predict2']=Y17_predict2
data_17['predict_make_bet2']=np.where(data_17['predict2']>0, 1, 0)
print("Number of model bets: {0}".format(data_17.predict_make_bet2.sum()))
data_17['predict_daily_change2']=1000*data_17['daily_change']*data_17['predict_make_bet2'].shift(1)
# Calculate my return:
print("Buy and Hold Results 2017")
print("Net gain: {0:8.2f}".format(roi_hold_net17))
prct_roi_hold17= 100*roi_hold_net17/initial_investment17
print("Percent gain: {0:2.2f} %".format(prct_roi_hold17))
print("Random Results:")
roi_rand17=data_17['rand_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_rand17))
prct_roi_rand17=100*(roi_rand17 ) / initial_investment17
print("Percent gain: {0:2.2f} %".format(prct_roi_rand17))
print("Model Results:")
roi_model17=data_17['predict_daily_change'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model17))
prct_roi_model17=100*(roi_model17 ) / initial_investment17
print("Percent gain: {0:2.2f} %".format(prct_roi_model17))
print("Model Results (Lasso, alpha=.001):")
roi_model17_2=data_17['predict_daily_change2'].cumsum()[-1:][0]
print("Net gain: {0:8.2f}".format(roi_model17_2))
prct_roi_model17_2=100*(roi_model17_2 ) / initial_investment17
print("Percent gain: {0:2.2f} %".format(prct_roi_model17_2))
year=2015
"Investment Return on {0} in {1}".format(initial_investment, year)
# 2015 just loses, based on the last day, -2%
data_15.AdjClose.plot(legend=True,grid=True,title="AAPL Adjusted Close, 2015",figsize=(10,5))
# 2016 is a big win, 12%
data_16.AdjClose.plot(legend=True,grid=True,title="AAPL Adjusted Close, 2016",figsize=(10,5))
# 2017 is a huge win, 46%
data_17.AdjClose.plot(legend=True,grid=True,title="AAPL Adjusted Close, 2017",figsize=(10,5))
## Plot the various returns - first 2015:
# Hold
# Random
# Applying the model
year=2015
ax = data_15['hold_current_return'].plot(grid=True, legend=True, figsize=(8,6),
title="Investment Return on {0:9.2f}$ in {1}".format(initial_investment15, year))
data_15['rand_daily_change'].cumsum().plot(grid=True, legend=True)
data_15['predict_daily_change'].cumsum().plot(grid=True, legend=True)
data_15['predict_daily_change2'].cumsum().plot(grid=True, legend=True)
# data_15['daily_change'].plot(grid=True, legend=True, secondary_y=True)
ax.set_ylabel('Cumulative Return [$]')
# ax.right_ax.set_ylabel('Daily Investment Flu [$]')
ax.set_xlabel('Year')
## Plot the various returns:
# Hold
# Random
# Applying the model
year = 2016
ax = data_16['hold_current_return'].plot(grid=True, legend=True, figsize=(8,6),
title="Investment Return on {0:9.2f}$ in {1}".format(initial_investment16, year))
data_16['rand_daily_change'].cumsum().plot(grid=True, legend=True)
data_16['predict_daily_change'].cumsum().plot(grid=True, legend=True)
data_16['predict_daily_change2'].cumsum().plot(grid=True, legend=True)
# data_15['daily_change'].plot(grid=True, legend=True, secondary_y=True)
ax.set_ylabel('Cumulative Return [$]')
# ax.right_ax.set_ylabel('Daily Investment Flu [$]')
ax.set_xlabel('Year')
## Plot the various returns:
# Hold
# Random
# Applying the model
year=2017
ax = data_17['hold_current_return'].plot(grid=True, legend=True, figsize=(8,6),
title="Investment Return on {0:9.2f}$ in {1}".format(initial_investment17, year))
data_17['rand_daily_change'].cumsum().plot(grid=True, legend=True)
data_17['predict_daily_change'].cumsum().plot(grid=True, legend=True)
data_17['predict_daily_change2'].cumsum().plot(grid=True, legend=True)
# data_15['daily_change'].plot(grid=True, legend=True, secondary_y=True)
ax.set_ylabel('Cumulative Return [$]')
# ax.right_ax.set_ylabel('Daily Investment Flu [$]')
ax.set_xlabel('Year')
## Ok - so these models are pretty crappy.
# what is the range of outcomes for the random models? And what does the distribution look like?
# 1. Simulate returns on (say 1000) random models
# 2. What's the mean and std of these outcomes?
# The static data
data_test15 = aapl[(aapl.index > '2015') & (aapl.index < '2016')][['AdjClose','LR']]
data_test15['daily_change']=(np.exp(data_test15['LR'])-1)*data_test15['AdjClose'].shift(1)
results15 = np.zeros(1000)
# The stochastic model
for i in range(1000):
data_test15['rand_make_bet']=np.random.randint(0,2, data_test15.shape[0])
data_test15['rand_daily_change']=1000*data_test15['daily_change']*data_test15['rand_make_bet'].shift(1)
results15[i]=data_test15['rand_daily_change'].cumsum()[-1:][0]
print("2015 Model Results: {0:8.2f}".format(results15.mean()))
print("2015 Model Results: {0:8.2f}%".format(100*(results15.mean()/initial_investment15)))
print("2015 Model Std: {0:8.2f}".format(results15.std()))
# Look at 2016
# The static data
data_test16 = aapl[(aapl.index > '2016') & (aapl.index < '2017')][['AdjClose','LR']]
data_test16['daily_change']=(np.exp(data_test16['LR'])-1)*data_test16['AdjClose'].shift(1)
results16 = np.zeros(1000)
# The stochastic model
for i in range(1000):
data_test16['rand_make_bet']=np.random.randint(0,2, data_test16.shape[0])
data_test16['rand_daily_change']=1000*data_test16['daily_change']*data_test16['rand_make_bet'].shift(1)
results16[i]=data_test16['rand_daily_change'].cumsum()[-1:][0]
print("2016 Model Results: {0:8.2f}".format(results16.mean()))
print("2016 Model Results: {0:8.2f}%".format(100*(results16.mean()/initial_investment16)))
print("2016 Model Std: {0:8.2f}".format(results16.std()))
# Look at 2017
# The static data
data_test17 = aapl[(aapl.index > '2017') & (aapl.index < '2018')][['AdjClose','LR']]
data_test17['daily_change']=(np.exp(data_test17['LR'])-1)*data_test17['AdjClose'].shift(1)
results17 = np.zeros(1000)
# The stochastic model
for i in range(1000):
data_test17['rand_make_bet']=np.random.randint(0,2, data_test17.shape[0])
data_test17['rand_daily_change']=1000*data_test17['daily_change']*data_test17['rand_make_bet'].shift(1)
results17[i]=data_test17['rand_daily_change'].cumsum()[-1:][0]
print("2017 Model Results: {0:8.2f}".format(results17.mean()))
print("2017 Model Results: {0:8.2f}%".format(100*(results17.mean()/initial_investment17)))
print("2017 Model Std: {0:8.2f}".format(results17.std()))
If you look closer at my model results from 2015. There was a net gain of -14723.44 and a percent gain of -14.18. These results are near the left side of the distribution of normal results from the stochastic model.
# Quick and dirty histogram of the model outcomes
plt.hist(results15, color = 'blue', edgecolor = 'black', bins=25)
# Quick and dirty density plot of the model outcomes
pd.DataFrame(results15).plot.density()
ax = pd.DataFrame({'2015' : results15, '2016' : results16, '2017' : results17}).plot.hist(
title='Density plot of Stochastic Model Returns', bins=30, alpha=0.5)
ax.set_xlabel('Return on Investment [$]')