/
pricing.R
215 lines (176 loc) · 7.42 KB
/
pricing.R
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#' Get Quotes for specified tickers in List form
#'
#' Enter tickers for real time or delayed quotes returned as a list
#'
#' Quotes may be delayed depending on agreement with TD Ameritrade. If the
#' account is set up for real-time quotes then this will return real-time.
#' Otherwise the quotes will be delayed.
#'
#' @param tickers One or more tickers
#' @param output indication on whether the data should be returned as a list or
#' df. The default is 'df' for data frame, anything else would be a list.
#' @inheritParams td_accountData
#'
#' @return a list or data frame with quote details for each valid ticker
#' submitted
#' @export
#'
#' @examples
#' \dontrun{
#'
#' # Get stored refresh token
#' refreshToken = readRDS('/secure/location/')
#'
#' # generate a new access token
#' accessToken = td_auth_accessToken('consumerKey', refreshToken)
#'
#' # Pass one or more tickers as a vector
#' # accessToken is optional once it is set
#' quoteSPY = td_priceQuote('SPY')
#' quoteList = td_priceQuote(c('GOOG','TSLA'), output = 'list', accessToken)
#'
#' }
td_priceQuote = function(tickers = c('AAPL','MSFT'), output = 'df', accessToken=NULL) {
# Check output desired and pass to helper function
if (output != 'df') {
# If not data frame, assume list
quotes = ram_quote_list(tickers, accessToken)
} else {
# If df then return data frame
quotes = ram_quote_df(tickers, accessToken)
}
quotes
}
#' Get price history for a multiple securities
#'
#' Open, Close, High, Low, and Volume for one or more securities
#'
#' Pulls price history for a list of security based on the parameters that
#' include a date range and frequency of the interval. Depending on the
#' frequency interval, data can only be pulled back to a certain date. For
#' example, at a one minute interval, data can only be pulled for 30-35 days.
#' Prices are adjusted for splits but not dividends.
#'
#' PLEASE NOTE: Large data requests will take time to pull back because of the
#' looping nature. TD Does not allow bulk ticker request, so this is simply
#' running each ticker individually. For faster and better historical data
#' pulls, try Tiingo or FMP Cloud
#'
#' @param tickers a vector of tickers - no more than 15 will be pulled. for
#' bigger requests, split up the request or use Tiingo, FMP Cloud, or other
#' free data providers
#' @param startDate the Starting point of the data
#' @param endDate the Ending point of the data
#' @param freq the frequency of the interval. Can be daily, 1min, 5min, 10min,
#' 15min, or 30min
#' @inheritParams td_accountData
#'
#'
#' @return a tibble of historical price data
#' @export
#'
#' @examples
#' \dontrun{
#'
#' # Set the access token and a provide a vector of one or more tickers
#' refreshToken = readRDS('/secure/location/')
#' accessToken = td_auth_accessToken(refreshToken, 'consumerKey')
#' tickHist5min = td_priceHistory(c('TSLA','AAPL'), freq='5min')
#'
#' # The default is daily. Access token is optional once it's been set
#' tickHistDay = td_priceHistory(c('SPY','IWM'), startDate = '1990-01-01')
#'
#' }
td_priceHistory = function(tickers=c('AAPL','MSFT'),startDate=Sys.Date()-30,endDate=Sys.Date(),
freq=c('daily','1min','5min','10min','15min','30min'),
accessToken=NULL){
# Limit request to first 15 tickers
if (length(tickers)>15) {
tickers = tickers[1:15]
warning('More than 15 tickers submitted. Only the first 15 tickers were pulled from the list of tickers.')
}
if (missing(freq)) freq='daily'
# Loop through all tickers and collapse into a single data frame
allTickers = dplyr::bind_rows(lapply(tickers,function(x) ram_history_single(ticker = x,
startDate,
endDate,
freq,
accessToken=accessToken)))
# Return all tickers in a data frame
allTickers
}
############### =============================
############### =============================
############### =============================
# ----------- Helper function
# Get pricing data for a single ticker
ram_history_single = function(ticker='AAPL',startDate=Sys.Date()-30,endDate=Sys.Date(),
freq=c('daily','1min','5min','10min','15min','30min'),
accessToken=NULL){
# Get access token from options if one is not passed
accessToken = ram_accessToken(accessToken)
# Set Variable to NULL to pass check()
date_time <- volume <- NULL
# Adjust dates to support conversion to numeric time
startDate = as.Date(startDate)+lubridate::days(1)
endDate = as.Date(endDate)+lubridate::days(1)
# Set to non scientific notation and Reset options on exit
old <- options()
on.exit(options(old))
options(scipen=999)
# Set Variables for URL
if (missing(freq)) freq='daily'
startDateMS = as.character(as.numeric(lubridate::as_datetime(startDate, tz='America/New_York'))*1000)
endDateMS = as.character(as.numeric(lubridate::as_datetime(endDate, tz='America/New_York'))*1000)
# Set URL specific parameters
if (freq=='daily') {
# If daily, plug in ticker and date in numeric format
PriceURL = paste0('https://api.tdameritrade.com/v1/marketdata/',ticker,
'/pricehistory','?periodType=month&frequencyType=daily',
'&startDate=',startDateMS,'&endDate=',endDateMS)
} else {
# If not daiy, pass frequency and date in numeric format
PriceURL = paste0('https://api.tdameritrade.com/v1/marketdata/',ticker,
'/pricehistory','?periodType=day&frequency=',
gsub('min','',freq),'&startDate=',startDateMS,'&endDate=',endDateMS)
}
# Send request
tickRequest = httr::GET(PriceURL,ram_headers(accessToken))
# Confirm status code of 200
ram_status(tickRequest)
# Extract pricing data from request
tickHist <- httr::content(tickRequest, as = "text")
tickHist <- jsonlite::fromJSON(tickHist)
tickHist <- tickHist[["candles"]]
# If no data was pulled, exit the request
if (class(tickHist)=='list') return()
tickHist$ticker = ticker
tickHist$date_time = lubridate::as_datetime(tickHist$datetime/1000, tz='America/New_York')
tickHist$date = as.Date(tickHist$date_time)
tickHist = dplyr::select(tickHist,ticker,date,date_time,open:volume)
# Return pricing data as a tibble
dplyr::as_tibble(tickHist)
}
# ----------- Helper function
# Get quote as a list
ram_quote_list = function(tickers = c('AAPL','MSFT'), accessToken=NULL) {
# Get access token from options if one is not passed
accessToken = ram_accessToken(accessToken)
# Create URL for all the tickers
quoteURL = base::paste0('https://api.tdameritrade.com/v1/marketdata/quotes?symbol=',
paste0(tickers, collapse = '%2C'))
quotes = httr::GET(quoteURL,ram_headers(accessToken))
# Confirm status code of 200
ram_status(quotes)
# Return content of quotes
httr::content(quotes)
}
# ----------- Helper function
# get quotes as a tibble
ram_quote_df = function(tickers = c('AAPL','MSFT'),accessToken=NULL) {
# Get list of quotes
quoteList = ram_quote_list(tickers,accessToken)
# Return data frame from list
dplyr::bind_rows(lapply(quoteList,data.frame)) %>%
dplyr::as_tibble()
}