INVALID_REQUEST when I'm using page_token - r

I try to capture the info in a list on r when I'm using page_token in google_places
In general the short code is functional, but I can see in google.maps 65 results, and my code just return me 60 results.
key_word = 'McDonalds Bogota'
res <- google_places(search_string = key_word)
info <- list(res)
while (res$status == 'OK') {
Sys.sleep(1.5)
res <- google_places(search_string = '',
page_token = res$next_page_token)
info <- c(info,list(res))
}
I obtain a list with complete information in info[[1]], info[[2]] and info[[3]], but when I see info[[4]] I get status INVALID_REQUEST, so I want to see the final 5 observations in info[[4]] but I could not to do this

info[[3]] does not have a $next_page_token since the number of results caps at 60. So the following loop for info[[4]] will not have a valid token to request more results.
next_page_token contains a token that can be used to return up to 20
additional results. A next_page_token will not be returned if there
are no additional results to display. The maximum number of results
that can be returned is 60.
https://developers.google.com/places/web-service/search

Related

How to place a Binance order through R

I am trying to place a new order through R studio, package Binancer, I am correctly connected to Binance Api (I added the key and secret in Binancer::credentials) but when I type this:
binancer::binance_new_order(symbol="WAVESBTC",side="BUY",type="MARKET",quantity = 1)
I get this error: Error in binancer::binance_new_order(symbol = "WAVESBTC", side = "BUY", :
abs(quot - round(quot)) < 1e-10 is not TRUE
I have tried to change quantity and put number of waves i want to buy, or amount of BTC I want to spend, but I always get this error. I would like to spend 100% of my Bitcoin on Waves in this order, where am I wrong? Is there any other way to place an order in Binance through R?
There are a few issues with the way you are approaching placing an order using binanceR. Unlike Binance itself, you cannot specify what percentage of your wallet you want to spend on a crypto, rather you have to calculate the exact amount of the crypto. This is very simple and done as follows:
#Fetching the current price of crypto of interest
curr_price <- binance_ticker_price("WAVEBTC")
curr_price <- curr_price$price
#Fetch your wallet balances
avail_btc <- binance_balances()
avail_btc <- filter(avail_btc, asset == "BTC")
avail_btc <- as.numeric(avail_usdt$free)
#Calculate possible coin quantity
buy_quantity<- avail_btc/curr_price
In this case we used all our available wallet crypto (100%+/-) to calculate the amount of crypto we want to buy, i.e. the quantity. You can select less of your wallet by dividing what you need (i.e 50% of wallet avail_btc/2).
#Reduce quantity of coins by 0.5% to avoid insufficient balance error NBNB!!
calc_price <- function(price, growth) {
new_price <- (price*growth)+price
return(new_price)
}
buy_quantity <- calc_price(buy_quantity, -0.005)
There are ways to condense the process, but step-wise is better for troubleshooting in my opinion.
Now that we have established the correct quantity, we can place an order:
binance_new_order("WAVEBTC",
side = "BUY",
type = "LIMIT",
quantity = buy_quantity,
price = b_price,
time_in_force = "GTC",
test = FALSE)
But we get the very annoying error: Error in binance_new_order("WAVEBTC", side = "BUY", type = "LIMIT", quantity = buy_quant, : abs(quot - round(quot)) < 1e-10 is not TRUE
This happens because all coins have limits on the size of the quantity OR price that you want to pass to Binance. I am not sure, but Binance sorts this out for you, which is why you never encounter this there. For example: WAVEBTC will accept a quantity of 3.2234 but not 3.223456, you see the additional two decimals... You can manually try to guess the correct format of the quantity or price, but for automation is a pain.
The solution is simple but not obvious. I had to go to the source code for binanceR and find the sections where the errors are generated. Here they are for quantity and price respectively:
#Price
quot <- (price - filters[filterType == 'PRICE_FILTER', minPrice]) / filters[filterType == 'PRICE_FILTER', tickSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
#Quantity
quot <- (buy_quantity - filters[filterType == 'LOT_SIZE', minQty]) / filters[filterType == 'LOT_SIZE', stepSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
These pieces of code basically checks if there is any unwanted decimals to your quantity or price. If we run this on an example using "ONTUSDT" you will see that if we use a buy_quantity of 332.44543 and calculate quot, we get a value of 33243.54. If we run stopifnot(abs(quot - round(quot)) < 1e-10) we get the error. But why? What is the value of abs(quot - round(quot): 0.457 which does not meet the error code criteria and which is why we get an error. If we change the buy_quantity to 332.44 we do not get an error message because our abs(quot - round(quot) value is 0. This is the key to the solution!
What we need to do is determine what the "correct" number of decimals are for our coins in question. For this we are going to use a simple function to calculate decimal positions for numbers and/or characters (you will see why):
decimalplaces <- function(x) {
if (class(x)=="character") {
x<-gsub("(.*)(\\.)|([0]*$)","",x)
nchar(x)
} else if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}
Next we need to fetch the filters used by these pieces of code to determine if our quantities or prices are correct:
filters <- binance_filters("WAVEBTC")
Now we need to reformat the equation for quot so that we calculate the unknown quantity which will look like this (remember we want a quot of value 0):
quantity <- (quot*filters[filterType == 'LOT_SIZE', stepSize])+filters[filterType == 'LOT_SIZE', minQty])
#Remember to change quot to 0
quantity <- (0*filters[filterType == 'LOT_SIZE', stepSize])+filters[filterType == 'LOT_SIZE', minQty])
#Since anything * by 0 = 0, our final equation is:
quantity <- filters[filterType == 'LOT_SIZE', minQty]
Again using "ONTUSDT" as an example, the quantity value will be 0.01. This is the number of decimals your buy_quantity needs to be. So simply:
#Sometimes the value will be in scientific notation, so we convert it which creates a character string and this is why the decimalplaces function accommodates numbers and character strings.
t <- format(quantity, scientific = FALSE)
dec <- decimalplaces(t)
buy_quantity<- round(buy_quantity, digits = dec)
NB! Follow the same process for your price!
If we use buy_quantity in the error code, you will see that we do not get an error message and placing an order works!
binance_new_order("WAVEBTC",
side = "BUY",
type = "LIMIT",
quantity = buy_quantity,
price = b_price,
time_in_force = "GTC",
test = TRUE)
Good luck and trade safely!
In this case, i think that the problem is in the type="MARKET" filters, in most of the cases quot finally values Inf so it doesn't pass the binance_new_order condition for that type.

R - Waiting for a list of promises to resolve

I am receiving some values in my R process and I want to compute them asynchronously. I am using promises and future package.
This is how my current code looks like:
arr = list()
i=0
while(i < 10)
{
a = read messages from KAFKA topic
arr[[i]] = future(DoSomething(a))
i = i + 1
}
Now, arr contains a list of promises
How do I get value() of the promise that has resolved first (and so on)?
Something like promise.race in javascript.
Edit: I just re-read your question and saw that you were asking about getting the first result, not just all results. Below is the code for getting that. It's a while loop that waits for any result to be ready and then moves forward when there's a result ready.
There is also a function called promise_race in the promises package, but the issue with the promises package is that it can only output results. You can't get the value produced back into a variable for further computations in the main thread.
require(future)
plan(multiprocess)
longRunningFunction <- function(value) {
random1<- runif(min= 5 ,max = 30,n = 1)
Sys.sleep(random1)
return(value)
}
arr = list()
#changed starting number to 1 since R lists start at 1, not 0
i=1
#If the number of futures generated is more than the number of cores available, then the main thread will block until the first future completes and allows more futures to be started
while(i < 6)
{
arr[[i]] = future(longRunningFunction(i))
i = i + 1
}
while(all(!resolved(arr))){ }
raceresults_from_future<-lapply(arr[resolved(arr)], value)
print(paste("raceresults_from_future: ",raceresults_from_future) )

TwitteR searchTwitter() call not working when in for loop

I'm currently trying to loop through a searchTwitter() call for each of 21 players in the NBA to get the 100 most recent tweets about them. However, weirdly, the call was working within my for loop of lastMVPs (which is a list of the names), but then stopped after 10 loops through, which would have only been 1,000 API calls. Now the call only works when outside of the for loop. Does anyone have any idea why this is?
For example - this works:
searchTwitter("Lebron James", n = 2, lang = 'en')
But this does not:
for (name in lastMVPs) {
newitem = searchTwitter(name, n = 100, lang = 'en')
df = twListToDF(newitem)
name = df$text
tweetMatrix = cbind(tweetMatrix, name)
}
And I get the error
Error in twListToDF(newitem) : Empty list passed to twListToDF
In addition: Warning message:
In doRppAPICall("search/tweets", n, params = params, retryOnRateLimit = retryOnRateLimit, :
100 tweets were requested but the API can only return 0
Which doesn't make sense to me because how can the API be maxed out when it's already working for my call outside of the loop?

Progress bar for rforcecom.checkbatchstatus()

I am asking to write a text or graphical progress tracker while rforcecom's batch update function loads batches of up to 10,000.
To set up and complete a batch update, a few objects must be created--there is no avoiding it. I really do not like having to re-run code in order to check the status of rforcecom.checkBatchStatus(). This needs to be automated while a progress bar gives a visual of actual progress, since checking in the global environment isn't preferred and it will be a static "status" update until it's run again.
Here's how the code is set up:
require(Rforcecom)
## Login to Salesforce using your username and password token
## Once ready to update records, use the following:
job<- rforcecom.createBulkJob(session, operation = 'update',
object = 'custom_object__c')
info<- rforcecom.createBulkBatch(session, jobId = job$id, data = entry,
batchSize = 10000)
### Re-run this line if status(in global environment) is "In Progress" for
### updated status
status<- lapply(info, FUN = function(x) {
rforcecom.checkBatchStatus(session, jobId = x$jobId, batchId = x$id)})
###Once complete, check details
details<- lapply(status, FUN = function(x){
rforcecom.getBatchDetails(session, jobId = x$jobId, batchId = x$id)})
close<- rforcecom.closeBulkJob(session, jobId = job$id)
To automate re-running the status code, use the repeat loop:
repeat {
statements...
if (condition) {
break
}
}
Then, to get a visual for a progress update, use the txtProgressBar() in base R. For this particular function, I made my own progress bar function with two simple companion functions. As a note about progressValue(), the rforcecom.checkBatchStatus() outputs as a list of 1 and a sublist. The sublist name for checking the number of records processed is "numberRecordsProcessed".
progressBar<- function(x, start = 0, finish){
# x is your object that is performing a function over a varying time length
# finish is your number of rows of data your function is processing
pb <- txtProgressBar(min = start, max = finish, style = 3)
for (i in 1:finish){
i<- progressValue(x)
setTxtProgressBar(pb, i)
if (progressValue(x)/finish == 1) {
close(pb)
}
}
}
finish<- function(x){
return(as.numeric(nrow(x)))
}
progressValue<- function(x){
x=x[[1]][["numberRecordsProcessed"]]
return(as.numeric(x))
}
Now, bring it all together! Repeat loops can be trained to end as long as you know your conditions: "Completed" or "Failed". Repeat "status", which will update the number of records processed, and by doing so this will update your progress bar. When the number of records processed equals the number of rows in your data, the progress bar will quit and so will your repeat loop.
repeat {
status<- lapply(info, FUN = function(x){
rforcecom.checkBatchStatus(session, jobId = x$jobId, batchId = x$id)})
progressBar(status, finish = finish(entry))
if (status[[1]][["state"]]=="Completed") {
break
}
if (status[[1]][["state"]]=="Failed") {
break
}
}

Debugging user-defined function

For a dataset of "Baltimore homicides"
It is required to create a function that takes a string for example "shooting" and return an integer represents the count of victims of "shooting".
I wrote the following function but i receive errors
Error: unexpected '}' in " }"
Error: object 'counti' not found
I also cant figure out if the ==Null is correct
count <- function(cause = NULL) {
## Check that "cause" is non-NULL; else throw error
if cause==NULL
{
stop()
print("no cause provided")
}
## Read "homicides.txt" data file
homicides <- readLines("homicides.txt")
## Extract causes of death
i <- grep(cause, homicides) ##get indices of cause
counti <- lenghth(i) ##get count of indices
## Check that specific "cause" is allowed; else throw error
if counti=0
{
stop()
print("no such cause")
}
## Return integer containing count of homicides for that cause
return(counti)
}
this is my working function after edit, thanks guys
count <- function(cause = NULL) {
if(missing(cause) | is.null(cause)) stop("no cause provided")
homicides <- readLines("homicides.txt")
i=length(grep(cause, homicides))
if(i==0) stop("no cause found")
return(i)
}
You can simplify your function to 2 lines by doing this:
count <- function(cause = NULL, data) {
if(is.null(cause)) stop("no cause provided")
length(grep(cause, data))
}
data <- c("murder", "some other cause")
count("murder", data)
[1] 1
Note the following principles:
R has many features of a functional language. This means that each function should, as far as possible, depend only on the arguments you pass it.
When you have a bug in your code, simplify it to the shortest possible version, fix the bug, then build out from there.
Also, keep stop() for really fatal errors. Not finding a search string in your data isn't an error, it simply means the cause wasn't found. You don't want your code to stop. At most, issue a message() or a warning().

Resources