Analyze Amazon Stocks also see github repo

Obtain the log returns of Amazon’s stock beginning Jan 1, 2020 to Jan 25, 2021

getSymbols("AMZN",from="2020-01-020",to="2021-01-25")
## 'getSymbols' currently uses auto.assign=TRUE by default, but will
## use auto.assign=FALSE in 0.5-0. You will still be able to use
## 'loadSymbols' to automatically load data. getOption("getSymbols.env")
## and getOption("getSymbols.auto.assign") will still be checked for
## alternate defaults.
## 
## This message is shown once per session and may be disabled by setting 
## options("getSymbols.warning4.0"=FALSE). See ?getSymbols for details.
## [1] "AMZN"
AMZN_log_returns<-AMZN%>%Ad()%>%dailyReturn(type='log')
tail(AMZN_log_returns, 10)
##            daily.returns
## 2021-01-08   0.006474567
## 2021-01-11  -0.021754382
## 2021-01-12   0.002123521
## 2021-01-13   0.014335166
## 2021-01-14  -0.012209821
## 2021-01-15  -0.007452221
## 2021-01-19   0.005304425
## 2021-01-20   0.044686867
## 2021-01-21   0.013274975
## 2021-01-22  -0.004473266

Technical Analysis

# The first chart series graph is straightforward as it shows Amazon’s price chart.
AMZN%>%Ad()%>%chartSeries()

# The second chart series show the Bollinger Band chart, % Bollinger change, Volume Traded and Moving Average Convergence Diverence in 2020 alone.
AMZN%>%chartSeries(TA='addBBands();addVo();addMACD()',subset='2020')

Comparisons

I implemented the underlying principle of public comparisons. I wanted to see how Amazon (AMZN) was doing in comparison to other popular technology stocks such as Facebook (FB), Google (GOOGL) and Apple (AAPL).

I first compared the risk/return rate of each stock. I took the mean of log return and standard deviation of log return. The mean is assumed as the consistent rate of return while standard deviation is the risk that comes with purchasing the stock. I used plotly, an interactive visualization tool, to illustrate my findings.

getSymbols("GOOGL",from="2020-01-020",to="2021-01-25")
## [1] "GOOGL"
GOOGL_log_returns<-GOOGL%>%Ad()%>%dailyReturn(type='log')

getSymbols("FB",from="2020-01-020",to="2021-01-25")
## [1] "FB"
FB_log_returns<-FB%>%Ad()%>%dailyReturn(type='log')

getSymbols("AAPL",from="2020-01-020",to="2021-01-25")
## [1] "AAPL"
AAPL_log_returns<-AAPL%>%Ad()%>%dailyReturn(type='log')

getSymbols("TSLA",from="2020-01-020",to="2021-01-25")
## [1] "TSLA"
TSLA_log_returns<-TSLA%>%Ad()%>%dailyReturn(type='log')

data<-cbind(diff(log(Cl(AMZN))),diff(log(Cl(GOOGL))),diff(log(Cl(AAPL))),diff(log(Cl(FB))))
chart.Correlation(data)

A popular investing principle is to diversify your investments: do not put all your eggs in one basket. When purchasing stocks you should try to purchase stocks that share a small correlation because you want to maximize the total rate of return.

These high tech companies are highly correlated

Price Prediction

I went on to predict the prices for Amazon (AMZN)’s stock. I achieved this by the random walk theory and monte carlo method. The random walk theory is suited for a stock’s price prediction because it is rooted in the believe that past performance is not an indicator of future results and price fluctuations can not be predicted with accuracy. I simulated the prices Amazon (AMZN)’s stock for 252*4 trading days (Since a year has ~252 trading days). That is 4 years worth of trading! I generated the prices using the data I have earlier from log returns and used exponential growth rate to predict how much the stock will grow per day. The growth rate is randomly generated and dependent on the input values of mu and sigma.

# random walk: Rooted in past performance is not an indicator of future results. Price fluctuations can not be predicted with accuracy
AMZN_mean_log <- mean(AMZN_log_returns$daily.returns)
AMZN_sd_log <- sd(AMZN_log_returns$daily.returns)
mu<-AMZN_mean_log
sig<-AMZN_sd_log
testsim<-rep(NA,1000)

#generate random daily exponent increase rate using AMZN's mean and sd log returns

#one year 252 trading days, simulate for 4 years 
# 4*252 trading days

price<-rep(NA,252*4)

#most recent price
price[1]<-as.numeric(AMZN$AMZN.Adjusted[length(AMZN$AMZN.Adjusted),])

#start simulating prices

for(i in 2:length(testsim)){
  price[i] <- price[i-1]*exp(rnorm(1,mu,sig))
}

random_data<-cbind(price,1:(252*4))
colnames(random_data)<-c("Price","Day")
random_data<-as.data.frame(random_data)

random_data%>%ggplot(aes(Day,Price))+geom_line()+labs(title="Amazon (AMZN) price simulation for 4 years")+theme_bw()
## Warning: Removed 8 row(s) containing missing values (geom_path).

The chart above shows the simulated prices for ~1000 trading days. If you pay attention to my code I did not include a set.seed(). The simulated prices will change and is dependent on my seed. In order to come up with a stable prediction, the price simulation needs to use the monte carlo method, where the prices are simulated repeatedly for accuracy.

N<-500
mc_matrix<-matrix(nrow=252*4,ncol=N)
mc_matrix[1,1]<-as.numeric(AMZN$AMZN.Adjusted[length(AMZN$AMZN.Adjusted),])
for(j in 1:ncol(mc_matrix)){
  mc_matrix[1,j]<-as.numeric(AMZN$AMZN.Adjusted[length(AMZN$AMZN.Adjusted),])
for(i in 2:nrow(mc_matrix)){
  mc_matrix[i,j]<-mc_matrix[i-1,j]*exp(rnorm(1,mu,sig))
}
}
name<-str_c("Sim ",seq(1,500))
name<-c("Day",name)
final_mat<-cbind(1:(252*4),mc_matrix)
final_mat<-as_tibble(final_mat)
## Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if `.name_repair` is omitted as of tibble 2.0.0.
## Using compatibility `.name_repair`.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
colnames(final_mat)<-name
dim(final_mat) #1008 501
## [1] 1008  501
final_mat%>%gather("Simulation","Price",2:501)%>%ggplot(aes(x=Day,y=Price,Group=Simulation))+geom_line(alpha=0.2)+labs(title="Amazon Stock (AMZN): 500 Monte Carlo Simulations for 4 Years")+theme_bw()

The graph above isn’t intuitive so I finalized my findings using percentile check the Amazon (AMZN)’s price after four years.

probs<-c(0.005,0.025,0.25,0.5,0.75,0.975,0.995)
final_mat[500,-1]%>%as.numeric()%>%quantile(probs=probs)
##      0.5%      2.5%       25%       50%       75%     97.5%     99.5% 
##  2453.181  3370.014  6338.647  8836.380 12872.103 27899.649 33801.413