Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

279_getquote resillient to invalid symbols #282

Merged
merged 14 commits into from
Nov 18, 2019
Merged

279_getquote resillient to invalid symbols #282

merged 14 commits into from
Nov 18, 2019

Conversation

ethanbsmith
Copy link
Contributor

getQuote would fail if the source did not recognize any of the supplied symbols. this was particularly problematic on large batches where a single failure would cause a stop and there was no way to diagnose which symbol had caused the problem

all getQuote paths now support ";" delimited inputs
All getQuote paths now return NA rows for missing quotes

all getquote paths now support ";" delimited inputs and return NA for missing quotes
@ethanbsmith ethanbsmith changed the title getquote resillient to invalid symbols 279_getquote resillient to invalid symbols Nov 3, 2019
@ethanbsmith ethanbsmith marked this pull request as ready for review November 3, 2019 17:15
@ethanbsmith
Copy link
Contributor Author

ready for review. could not add tests for tiingo and av as these require a key

Copy link
Owner

@joshuaulrich joshuaulrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed and left some comments. Let me know if you would like me to make the changes I suggested.

R/getQuote.R Outdated
@@ -369,11 +377,14 @@ getQuote.av <- function(Symbols, api.key, ...) {
}

colnames(r) <- gsub("(^[[:alpha:]])", "\\U\\1", colnames(r), perl = TRUE)
r[, "Trade Time"] <- r[, "LastSaleTimestamp"]
colnames(r)[which(colnames(r) == "LastsaleTimeStamp")] <- "Trade Time"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you're doing this so the "Trade Time" column appears first, instead of last.

This introduces a bug. The column returned by Tiingo is "LastSaleTimestamp" (note "Sale" is initial capitalized).

Also, the call to which() is unnecessary. It's okay to use the logical vector returned by ==.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more robust solution would be to leave L372 as-is, and follow it with r[, "LastSaleTimestamp"] <- NULL to remove the "LastSaleTimestamp" column.

R/getQuote.R Outdated
sq <- merge(list(symbol = Symbols), sq, by = "symbol", all = TRUE)
}

# Extract user-requested columns. Convert to list to avoid
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be careful of accidentally introducing white space changes like this.

R/getQuote.R Outdated
@@ -79,6 +83,7 @@ function(Symbols,what=standardQuote(),...) {

# Add the trade time and setNames() on other elements
qflist <- c(list(regularMarketTime = Qposix), setNames(qflist, QF))

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another white space change. This one clutters the diff a little bit.

@@ -280,6 +285,7 @@ getQuote.av <- function(Symbols, api.key, ...) {
"?function=BATCH_STOCK_QUOTES",
"&apikey=", api.key,
"&symbols=")
Symbols <- unlist(strsplit(Symbols,';'))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good practice to only have one functional change per commit, so this should be in another commit. I like that you made this change though! Can you think of a way to add a unit test?

@@ -326,6 +332,8 @@ getQuote.av <- function(Symbols, api.key, ...) {
"Registration at https://api.tiingo.com/.", call. = FALSE)
}

Symbols <- unlist(strsplit(Symbols,';'))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good practice to only have one functional change per commit, so this should be in another commit.

@ethanbsmith
Copy link
Contributor Author

ethanbsmith commented Nov 4, 2019 via email

@ethanbsmith
Copy link
Contributor Author

ok, i made some changes. i think the diffs should be much cleaner now. Also, i think it's set up to consolidate the strsplit and merge code into the master function

@joshuaulrich
Copy link
Owner

joshuaulrich commented Nov 4, 2019 via email

@ethanbsmith
Copy link
Contributor Author

i realized the merge call wasn't needed. you can just use the symbol names returned from the server. If we want to ensure that the output includes NA rows for input symbols, which isn't a bad idea, that can be centralized into the main function, after the getting the dispatched results. If you want that, I can do at the same time as the symbol splitting. I'll do that after this PR gets merged so the conflicts don't get complicated. I already opened an issue to track that

@joshuaulrich
Copy link
Owner

joshuaulrich commented Nov 6, 2019

If we want to ensure that the output includes NA rows for input symbols, which isn't a bad idea, that can be centralized into the main function, after the getting the dispatched results.

We do want that, because that's the existing behavior. Removing it would break backward compatibility. Moving that to the main function should be in a separate PR, so I'm going to revert a71e1e5 in this branch.

I'm going to leave the Symbols <- unlist(strsplit(Symbols,';')) because I'm not sure your updates will work without them.

And I'm not going to make any changes until I understand my confusion, described below.


I just noticed that the getQuote functions still error if all the symbols are not valid. Your initial description said:

getQuote would fail if the source did not recognize any of the supplied symbols.

(Emphasis mine). I expected these calls to return objects that only contained missing values, but they still error.

quantmod::getQuote(c("FOO", "WYSIWYG"), src = "av", api.key = keyAV)
quantmod::getQuote(c("FOO", "WYSIWYG"), src = "tiingo", api.key = keyTiingo)
quantmod::getQuote(c("FOO", "WYSIWYG"), src = "yahoo")

Am I missing something? Maybe I don't understand the initial problem as well as I thought...


And another thing...

ready for review. could not add tests for tiingo and av as these require a key

My keys for Alpha Vantage and Tiingo are on TravisCI. They are stored in environment variables QUANTMOD_AV_API_KEY and QUANTMOD_TIINGO_API_KEY, respectively. Here's an example of how to use them. Notice that the environment variables are spelled wrong though...

apikey <- Sys.getenv("AV_API_KEY")
if (apikey != "") {

So you can write tests and they will run on TravisCI when you push. But please don't use them just yet... as I was testing this morning, I noticed that error messages contain the key in plain text. The TravisCI logs are public, and I don't want my keys displayed.

@ethanbsmith
Copy link
Contributor Author

the centralized code is already in PR #285. it might simplify this PR if that one gets accepted first. not sure.

I just noticed that the getQuote functions still error if all the symbols are not valid.

(Emphasis mine). Interesting. I've never encountered that myself and didn't test for it. It's an odd scenario, but probably one we should account for as well. Are you ok if we handle that in this PR or do you want it broken out?

Thx for the info on the keys. i will add test for av and tiingo

@joshuaulrich
Copy link
Owner

Thx for the info on the keys. i will add test for av and tiingo

To reiterate, please don't push those tests until I'm convinced my keys won't be publicly visible in an error message.

I looked at the issue again, and I see that your example was for getQuote.yahoo(). I confirm that function throws an error if any symbol is not valid. getQuote.av() and getQuote.tiingo() add the rows for any missing symbols. That's why I was confused. It makes sense now.

I'll take a look at this again after market hours today.

@ethanbsmith
Copy link
Contributor Author

I just noticed that the getQuote functions still error if all the symbols are not valid.

been stewing on this in the background all day. not as straight forward as I originally thought. it's fairly innocuous in the simple case of 1 or 2 tickers, but what about 2000 or 10000? if every single ticker you passed in is rejected, something is probably wrong. Sort of seems like a different use case from a disagreement on a subset of tickers. Not sure I have a strong view on "correct" behavior either way on this aspect and would support whatever you decide on

@joshuaulrich joshuaulrich merged commit 4b93bb2 into joshuaulrich:master Nov 18, 2019
@joshuaulrich joshuaulrich added this to the Release 0.4-16 milestone Feb 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants