How to solve an "atomic vector" problem when getting data through an API ?

Hi there,

First I want to mention the fact that I'm totally new to Rstudio and R language and to this forum. And, as you might see, English isn't my main language. I'm sorry about that and I will try to do my best.

So here's my problem, I want to get financial data from Alphavantage, through their API, with the package called "alphavantager".

To do this I went on their API Documentation and I did everything as instructed. So when I request like for example "Stocks Time Series", everything goes nice and smooth, but when I try to get Forex Exchange Rates, I always do get an error about "argument is not an atomic vector", and I ain't got no clue on how to solve this, since the concept of atomic vector is a bit "dark" for me and I'm still learning.

Here's the code and the error ( I tried to do a reprex but I also have an error when I try to do it :sweat_smile:)

> library(alphavantager)
> av_get(av_fun = "CURRENCY_EXCHANGE_RATE",
+        from_currency = "EUR",
+        to_currency = "USD",
+        interval = "5min",
+        outputsize= "compact",
+        datatype="CSV")
Error: list(`1. From_Currency Code` = "EUR", `2. From_Currency Name` = "Euro", `3. To_Currency Code` = "USD", `4. To_Currency Name` = "United States Dollar", `5. Exchange Rate` = "1.11570000", `6. Last Refreshed` = "2020-01-15 16:30:00", `7. Time Zone` = "UTC", `8. Bid Price` = "1.11570000", `9. Ask Price` = "1.11570000"). API parameters used: symbol=NULL, function=CURRENCY_EXCHANGE_RATE, from_currency=EUR, to_currency=USD, interval=5min, outputsize=compact, apikey=HIDDEN_FOR_YOUR_SAFETY
In addition: Warning message:
In stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
  argument is not an atomic vector; coercing

The CSV file I would get should look like this

And here's the API Documentation from Alphavantage

I hope that I made it clear

Cheers

Hi, and welcome!

First off, English is a world language, which is wonderful because it enables many to communicate directly. But it's not one language, it's many, and there's no one, true way to use it. In my country, where most of English speakers are monolingual, there are regional differences in pronunciation and word usage that are sometimes difficult to overcome!

Second, it's not necessary for this problem, but keep in mind the benefits of a reproducible example, called a reprex to attract more and better answers.

An atomic vector is a vector with just one element. When a function is doing something like a binary operator, such as taking a difference, it complains about that.

Here, it looks like the Euro/US$ bid ask spread is zero, which might be the cause.

Can you try when the markets are more active to see if you get the same result? Just eyeballing your csv file, there's a spread always.

Hi @technocrat and thank you for you reply.

I tried with another pair, which actually has a spread, and I had almost the same error.
Here's the code:

> av_get(av_fun = "CURRENCY_EXCHANGE_RATE",
+        from_currency = "USD",
+        to_currency = "CHF",
+        interval = "5min",
+        outputsize= "compact",
+        datatype="CSV")
Error: list(`1. From_Currency Code` = "USD", `2. From_Currency Name` = "United States Dollar", `3. To_Currency Code` = "CHF", `4. To_Currency Name` = "Swiss Franc", `5. Exchange Rate` = "0.96350000", `6. Last Refreshed` = "2020-01-15 17:48:31", `7. Time Zone` = "UTC", `8. Bid Price` = "0.96340000", `9. Ask Price` = "0.96350000"). API parameters used: symbol=NULL, function=CURRENCY_EXCHANGE_RATE, from_currency=USD, to_currency=CHF, interval=5min, outputsize=compact, apikey=HIDDEN_FOR_YOUR_SAFETY
In addition: Warning message:
In stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
  argument is not an atomic vector; coercing

Do you see any other possibility ?

I'm speculating here, but is the spread too small for whatever the related function does with it?

The message about the atomic vector isn't from the error, it's from the warning. So that's not stopping your code. It's weird that your error message isn't being fully printed. Try this to capture it in an object:

error_message <- tryCatch(
  av_get(av_fun = "CURRENCY_EXCHANGE_RATE",
    from_currency = "EUR",
    to_currency = "USD",
    interval = "5min",
    outputsize= "compact",
    datatype="CSV"),
  error = function(err) {
    conditionMessage(err)
  }
)
print(error_message)

Hopefully that'll let you look at the entire thing. I don't want to speculate too much, but your error message being cut off after apikey=HIDDEN_FOR_YOUR_SAFETY might not be a coincidence.

Nobody likes the "But actually..." guy, but actually...

A vector is atomic when it's one of the basic classes in R. There's a help keyword for it: ?atomic. It goes to the help page for vector, which says this:

The atomic modes are "logical" , "integer" , "numeric" (synonym "double" ), "complex" , "character" and "raw".

3 Likes

From the error list perhaps you're calling the CURRENCY_EXCHANGE_RATE function with the wrong parameters?

Try calling it with just the parameters it calls for in the docs: av_fun, from_currency, to_currency, api_key and see if that works.

1 Like

Ah! I see: masked and anonymous, an object with no qualities apart from its unnamed contents.

Well @technocrat I don't think that the spread value might impact the result of the function, because the av_get() function just aim to get the data from the Alphavantage API

I add the package doc here in case someone want to have a look at it.

1 Like

@nwerth first thank you for your reply. I tried to capture it in an object, here is what I got:

> print(error_message)
[1] "list(`1. From_Currency Code` = \"EUR\",
`2. From_Currency Name` = \"Euro\", 
`3. To_Currency Code` = \"USD\", 
`4. To_Currency Name` = \"United States Dollar\", 
`5. Exchange Rate` = \"1.11510000\", 
`6. Last Refreshed` = \"2020-01-15 22:58:01\", 
`7. Time Zone` = \"UTC\", 
`8. Bid Price` = \"1.11500000\", 
`9. Ask Price` = \"1.11510000\"). 
API parameters used: symbol=NULL, 
function=CURRENCY_EXCHANGE_RATE, 
from_currency=EUR, 
to_currency=USD, interval=5min, 
outputsize=compact, apikey=HIDDEN_FOR_YOUR_SAFETY"

Do you think that this might come from the settings of the request ?

Here is the doc of alphavantager in case you want to take a look at it. From what I read on it & on the API doc my request seems to be correct

And thank you for the explanation about the "atomic vector" you made it pretty clear

EDIT : The warning message was not captured in the variable but appeared between the capture and the print function :
Warning message:

In stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
argument is not an atomic vector; coercing

1 Like

@grosscol Thank you for your reply.

I tried to call the function with the required parameters only, as described in the doc. I also reset my API key in the function despite the fact that I already set it in the "alphavantager" settings.

And unfortunately, I had the exact same result as I had before

Hit the API endpoint directly with curl.

So probably not the parameters. Do you get the expected result when you curl the endpoint?

From your terminal:

curl --get "https://www.alphavantage.co/query" -d "function=CURRENCY_EXCHANGE_RATE" -d "from_currency=USD" -d "to_currency=JPY" -d "apikey=YourAPIKeyHere"

or in R:

library(httr)
base_url <- "https://www.alphavantage.co"
myquery <- list("function"="CURRENCY_EXCHANGE_RATE",
                "from_currency"="USD",
                "to_currency=JPY",
                "apikey=YourAPIKeyHere") # Remember to fill in your key

GET(base_url, path = "query", query = myquery)

Does curling the endpoint give you the data? If so, it's likely an issue with the package you're using.

2 Likes

@grosscol, thank you for this.

It's look like there is an issue with the package because both Curl function and the R code gave me the data. So, starting from the point that there might be an issue with the package, should I report in on the alphavantager's GitHub repository ?

One more question, how can I get in Rstudio the result from this api stocked on like a CSV file or something like this so I can then work on it. I tried to store it in list using your code but it didn't ended well.

This is how i proceeded:

> base_url <- "https://www.alphavantage.co"
> myquery <- list("function"="CURRENCY_EXCHANGE_RATE",
+                 "from_currency"="USD",
+                 "to_currency"="JPY",
+                 "apikey"="") # Remember to fill in your key
> 
> test <- GET(base_url, path = "query", query = myquery)

But it didn't store the result of the request but a bunch of technical stuff about the request like for example the headers, cookies, or URL.

What function works best for this case ?

Thank you in advance.

Investigate the result

I usually start with the class and names of an object.

class(test)
names(test)

That should tell you it's a response object. You can look at the documentation of the httr package to find out about that. When I look at http response, I check out the headers first.

test$headers

In this case, you're looking for the content type. If you didn't send a header in your request asking for "text/csv" it's probably not going to be what you get, but could get lucky. Maybe the API is all about the csv responses. You'll probably get json or html.

Either way, you'll need to parse the $content of the response. Check the class or type of that and see what you're working with.

# if the content is csv
read.csv(text=test$content)
# if it's json
library(json)
fromJSON(test$content)

Borrowing your API Key

Just noticed you put your API key in your post. Please excuse my borrowing that for a single request. You should probably edit your post and remove that by the way.

raw data

The content is raw (byte data) and the response header tells you it should be json. We can handle that.

# Convert the response content to a list
content_string <- rawToChar(test$content)
json_list <- fromJSON(content_string)

# Interrogate the list
class(json_list)
names(json_list)
names(json_list[[1]]) # json is lists of lists in R.

# yak out the data you'd like into a more convenient vector
result <- sapply(result[[1]], `[`)

You should note that the result here is all characters, so some additional conversion may be required. Best of luck.

1 Like

Thank you so much for your help