-
Notifications
You must be signed in to change notification settings - Fork 0
/
quantmod.Rmd
181 lines (167 loc) · 8.94 KB
/
quantmod.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
---
title: 'Financial Simulation: `quantmod` R package'
author: 'Majeed Simaan'
date: 'March 27th, 2018'
# output:
# pdf_document: default
# html_notebook: default
#
output: rmarkdown::github_document
fig_width: 20
---
## Introduction
In this vignette, I provide a brief introduction to the `quantmod` package to download stock prices, option prices, and different indices data.
## Downloading Stock Prices from Yahoo Finance
#### Loading the library
To get started, make sure you have installed the `quantmod` in R - you can do so using the following command:
```{r message=FALSE, warning=FALSE, eval=FALSE}
install.packages("quantmod")
```
After successfully installing the package, you can load the package
```{r message=FALSE, warning=FALSE}
library(quantmod)
```
#### Single stock example
To get started, assume that you are interested in downloading the stock prices for Apple ("AAPL"). To do so, you can easily get the data using the following command
```{r message=FALSE, warning=FALSE}
getSymbols("AAPL",from = "1990-01-01")
```
Note that getSymbols takes two inputs above. The first one is the ticker of the stock, whereas the second is the start date. In case there is no data prior to the inputted date, the function will return the maximum date. Also, note that R stores the stock data in a new item named `AAPL`. For instance,
```{r message=FALSE, warning=FALSE}
head(AAPL)
```
If one wishes to focus on the adjusted prices, which I will do in this article, one can do so by referring to the corresponding column number, i.e. `AAPL[,6]`. For instance, the following command plots the adjusted prices over time
```{r fig1, fig.width = 4, fig.height = 4, fig.align = "center"}
plot(AAPL[,6])
```
#### Multiple Stocks
Now, let's assume we are interested in downloading data for multiple tickers stacked in vector `tics`, where
```{r message=FALSE, warning=FALSE}
tics <- c("AAPL","GE","TWTR","BAC","RAD","PFE")
```
One approach is to run a loop and get the data for each ticker, and then try to figure out a way to merge the prices altogether. Instead, I would like to show you the following trick using Functional Programming:
```{r message=FALSE, warning=FALSE}
P.list <- lapply(tics, function(tic) get(getSymbols(tic, from = "1980-01-01")) )
```
Note that the `P.list` is a list object containing the data for each ticker. In total, it contains 6 elements (corresponding to the number of tickers), while the each element has the following length
```{r message=FALSE, warning=FALSE}
sapply(P.list, nrow)
```
Obviously, `TWTR` has the least number of dates in the time series. Merging the adjusted prices altogether is straightforward
```{r message=FALSE, warning=FALSE}
P.adj <- lapply(P.list, function(p) p[,6] ) # pulls the sixth column of each ticker
P <- Reduce(merge,P.adj) # merge altogether
names(P) <- tics # adjust the names with respect to the tickers
head(P,2) # returns the oldest two observations
tail(P,2) # returns the most recent two observations
```
Finally, to get the returns, I use the `lag` operator, such that
```{r message=FALSE, warning=FALSE}
R <- P/lag(P) - 1 # or log(P/lag(P))
```
Note that since each ticker has a different length, the combined returns have a lot of missing values. One can either drop the missing values using the `na.omit` function or utilize all data to derive the relevant estimates. In the latter case, one can compute the mean vector and the covariance matrix using all available information as follows
```{r message=FALSE, warning=FALSE}
M <- apply(R,2,function(x) mean(x,na.rm = T) )
S <- var(R,use = "pairwise")
```
Finally, you can save the data into a csv file. **But**, make sure that data is saved as a `data.frame` rather than an `xts` object, i.e.
```{r message=FALSE, warning=FALSE}
write.csv(data.frame(R),file = "R.csv")
```
## Downloading Options Data from Yahoo Finance
The `quantmod` package also allows users to download options data from Yahoo, however, this is more tricky. The main function I will use is the `getOptionChain` from the `quantmod` package. Like `getSymbols`, `getOptionChain` requires ticker as the main input. However, the function does not return any historical options data. The second argument one can add is the expiration date. If one knows the exact expiration date, then it is straightforward to implement. If not, one can either search for the expiration dates from Yahoo Finance or explore expiration as I will illustrate below.
#### Let's get started
To get started, let's pull some options data for Apple:
```{r message=FALSE, warning=FALSE}
opt <- getOptionChain("AAPL",Exp = "2018")
class(opt)
names(opt)
```
As you can see, the names of the lists are assigned with respect to the expiration date for the year 2018. Let's assume that we are interested in options expiring in six months ahead. In this case, "Sep.21.2018" is the most relevant one.
```{r message=FALSE, warning=FALSE}
opt6 <- opt[["Sep.21.2018"]]
class(opt6)
names(opt6)
```
Note that the `opt6` is also a list, where each item in the list corresponds to the call and put options data, such that
```{r message=FALSE, warning=FALSE}
sapply(opt6, class)
```
To put altogether, I perform the following commands
```{r message=FALSE, warning=FALSE}
opt6 <- lapply(1:length(opt6), function(i) data.frame(opt6[[i]],Type = names(opt6)[i], Expiration = "Sep.21.2018" , stringsAsFactors = F) )
opt6 <- Reduce(rbind,opt6)
```
The first line adds one column corresponding to the type of the option and another for the expiration date. The second line combines the two lists altogether by rows as one `data.frame`, i.e.
```{r message=FALSE, warning=FALSE}
class(opt6)
```
Finally, I would like to adjust the expiration date format and add today's date to the data:
```{r message=FALSE, warning=FALSE}
opt6$Expiration <- as.Date(opt6$Expiration,format='%B.%d.%Y')
opt6$Date <- Sys.Date()
head(opt6)
```
#### Generalization
The above illustration focuses on one stock and one expiration date. To generalize, let's consider a function that takes one ticker as the main input and returns a `data.frame` object that covers all options data today for all expiration dates.
```{r message=FALSE, warning=FALSE}
get_opt <- function(tic) {
OPT <- numeric()
opt.i <- try(getOptionChain(tic,Exp = NULL), silent = T )
if(inherits(opt.i, "try-error"))
return(NULL)
else {
# drop any missing
opt.i <- opt.i[!sapply(opt.i, function(x) any(sapply(x, is.null )) )]
exp.time <- names(opt.i)
opt.iy <- numeric()
for(exp_t in exp.time) {
opt.it <- opt.i[[exp_t]]
opt.it <- lapply(1:length(opt.it), function(i)
data.frame(opt.it[[i]],Type = names(opt.it)[i],
Expiration = exp_t , stringsAsFactors = F) )
opt.it <- Reduce(rbind,opt.it)
opt.it$Expiration <- as.Date(opt.it$Expiration,format='%B.%d.%Y')
opt.it$Date <- Sys.Date()
opt.iy <- rbind(opt.iy,opt.it)
}
OPT <- rbind(OPT,opt.iy)
OPT$Ticker <- tic
rownames(OPT) <- NULL
}
return(OPT)
}
```
Let's run the `get_opt` function on all tickers we have in `tics`:
```{r message=FALSE, warning=FALSE}
opt.list <- numeric()
for(i in 1:length(tics)) {
get.i <- try(get_opt(tics[i]),silent = T)
if(inherits(get.i, "try-error"))
opt.list[i] <- list(NULL)
else
opt.list[i] <- list(get.i)
}
names(opt.list) <- tics
sapply(opt.list,nrow) # number of observations in each data
```
The above tries to extract all options data for a set of tickers. In case there is a failure, the list assigns an empty object. As a final step, we can combine all items in the `opt.list` by rows as we did earlier
```{r message=FALSE, warning=FALSE}
opt.ds <- Reduce(rbind,opt.list)
write.csv(opt.ds,file = "OPT.csv",row.names = FALSE)
```
## Downloading Indices and Economic Indicators from FRED
To download other indices outside Yahoo Finance, especially economic indicators, I recommend the Federal Reserve Economic Data [FRED](https://fred.stlouisfed.org/) as the best open source to establish so. Let's say that you already know the tickers (codes) names you interested in, then getting these indices is as simple as getting stock data from Yahoo Finance. Nonetheless, I recommend browsing through the FRED website to figure out which code you are looking for. For instance, the corresponding codes for the LIBOR and 3-months Treasury maturity rates are given by `"USD1MTD156N"` and `"DGS3MO"`, respectively.
```{r message=FALSE, warning=FALSE}
indices <- c("USD1MTD156N","DGS3MO")
ind.list <- lapply(indices, function(tic) get(getSymbols(tic, from = "1980-01-01", src = "FRED")) )
IND <- Reduce(merge,ind.list)
```
Different from the stock returns, I changed the `src` to `FRED`, whereas the default is set to `src = "yahoo"`.
```{r fig2, fig.width = 4, fig.height = 4, fig.align = "center"}
plot(IND)
```
Finally, don't forget to save the `IND` into a csv by transforming into a `data.frame`:
```{r message=FALSE, warning=FALSE}
write.csv(data.frame(IND),file = "IND.csv")
```