Stock data analysis with R an introduction


Stock data analysis with R: an introduction

Stock and investments analysis are themes that can be deeply explored in programming. Multiple programming languages and data science framework can be explored in this context. This includes R language, which already has a big literature, packages and functions developed in the domain of quantitative finance. In this post, we’ll do a brief introduction to the subject using the quantmod package. R is a programming language and integrated environment focused in statistics, but with a lot of applications in different areas for instance quantmod is a well known package used to quantitative financial modelling. The analyzed stock here will be SPY, an ETF following the U.S. S&P 500 index, with data extracted from Yahoo Finance using the package quantmod in R.

library(PerformanceAnalytics)
library(quantmod)
library(tidyverse)
spy <- getSymbols("SPY", src = "yahoo", from = "2013-01-01", to = "2019-06-01", auto.assign = FALSE)

The getSymbols function provides the open, close, high, and low prices for any given date range for an equity.

Op(spy)
Hi(spy)
Lo(spy)
Cl(spy)
Vo(spy)
Ad(spy)
chartSeries(spy, type="line", theme=chartTheme('white'))

chartSeries(spy,type="bar", theme=chartTheme('white'))

Another interesting possibility given by quantmod is the calculation of returns for different periods. For example, it’s possible to calculate the returns by day, week, month, quarter and year, just by using the following commands:

#dailyReturn(spy)
plot(dailyReturn(spy))

#weeklyReturn(spy)
plot(weeklyReturn(spy))

#monthlyReturn(spy)
plot(monthlyReturn(spy))

#quarterlyReturn(spy)
plot(quarterlyReturn(spy))

#yearlyReturn(spy)
plot(yearlyReturn(spy))

The quantmod package also provides graphing for the abovementioned modalities of pricing and volume. The package also provides Technical Analysis indicators such as Moving Averages of the prices for a given equity. A simple moving average is an arithmetic average from the last q days from a timeseries in the t time-period. This indicator is interesting because it helps to smooths noises from prices and identify trends. That is, the smaller the window for the MA calculation, the faster MA adapts itself to changes, and bigger the days window the smaller is the MA responsiveness to price variation. One strategy is to apply for trading is to use two moving averages one longer term and one shorter term.

#SMA(Ad(spy),n=20)
#EMA(Ad(spy),n=20)
chartSeries(spy,
            subset='2013::2016',
            theme=chartTheme('white'))

addSMA(n=20)

addEMA(n=20)

Also known as a “golden cross”, when the shorter-term MA crosses above the longer-term MA, it is a buy signal, which indicates that the trend is shifting up. Meanwhile, when the shorter-term MA crosses below the longer-term MA, it is a sell signal, as it indicates that the trend is shifting down. This is known as a “dead/death cross.”

signal1=1*(RSI(Ad(spy))< 30)
trade1 <- Lag(signal1)
trade1[is.na(trade1)]=0
ret1 <- dailyReturn(spy)*trade1
sum(ret1)
## [1] 0.09667714
charts.PerformanceSummary(ret1)

The relative strength index (RSI) is another technical which is intended to chart the current and historical weakness or strength of an equity based on the closing prices of a predetermined trading period. RSI is a momentum indicator that measures the magnitude of recent price changes to evaluate oversold or overbought conditions in the price of an equity or other asset. Traditional usage of the RSI dictates that values of 30 or below indicates an oversold or undervalued condition and values of 70 or above suggest that a security is becoming overbought or overvalued and may be primed for a trend reversal or corrective price pullback.

#RSI(Ad(spy),n=5)
chartSeries(spy,
            subset='2013::2016',
            theme=chartTheme('white'))

addRSI(n = 14, maType = "EMA", wilder = TRUE)

In the same vein as above RSI values of 30 and 70 can be used as signals to buy or sell in the context of technical analysis.

signal2=1*(EMA(Ad(spy),n=10)>EMA(Ad(spy),n=50))
trade2 <- Lag(signal2)
trade2[is.na(trade2)]=0
ret2 <- dailyReturn(spy)*trade2
sum(ret2)
## [1] 0.2946037
charts.PerformanceSummary(ret2)