Yahoo Finance API reports incorrect quotes (so it seems) - yql

I was retrieving some quotes from Yahoo finance today, and I received some very strange values. Consider the following query:
http://query.yahooapis.com/v1/public/yql?q=select%20Date%2C%20Open%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22JAH%22%20and%20startDate%20%3D%20%222013-03-1%22%20and%20endDate%20%3D%20%222013-04-10%22&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys
which retrieves the quotes for the Jarden corporation, starting at 2013/03/01, up to 2013/04/01. Now at the dates 2013/03/18 and 2013/03/19, there is a sudden price drop of about 20 dollars. This price drop is not visible on the Yahoo finance website (http://finance.yahoo.com/echarts?s=JAH+Interactive#symbol=JAH;range=1y), or any other financial source for that matter.
Therefore, I think the quote data has to be wrong. Another fun fact if you were to take the price retrieved from the API at 2013-03-18 (the last incorrect price), multiply it with 2/3, you arrive at the price displayed on the website (64.24 * 0.6666666667 = 42.16).
Does anyone have even the slightest idea of what is going on here?

On Mar 19, 2013 there was a 3: 2 Stock Split
http://finance.yahoo.com/q/hp?s=JAH&a=2&b=29&c=1993&d=2&e=26&f=2014&g=d&z=66&y=198
The historical opening price are not adjusted for dividends and splits

Related

Google Finance does not show last closing price after market hours. It just shows last *traded* price instead of *closing*

My query is on stock market of India where I fetch the quotes from =googlefinance function in my google sheet. I was very disappointed to know that the function does not show last closing price. Instead, it shows the last traded price.
Lets take an example of a stock RELIANCE:
=GoogleFinance("NSE:reliance", "price") result is 2498.00 which is incorrect.
Actual closing on Friday, 16 Sep 2022 was 2499.20 as per official National Stock Exchange of India. You may refer to this link for the Close price and the screenshot below
The incorrect quote 2498.00 is the last traded price before market closing
The correct quote is 2499.20 when the markets were closed.
This behavior is common across all stocks of Indian stock market. I have used almost all the parameters those are available in the =googlefinance function but I could not find a way to get the correct stock quote.
Then I decided to scrape the value from the official website using the following without success
<div id="closePrice">2,499.20</div>
//*[#id="closePrice"]
/html/body/div[2]/div[4]/div[2]/div[1]/div[4]/ul/li[6]/div[1]
document.querySelector("#closePrice")
I searched a lot of valuable articles on this site and also on google but could not find a solution which would fetch the desired result. Can someone help me with a way to get 2499.20 as a result for RELIANCE stock either using =googlefinance function or by scraping the value from office website?
Thank you.
Solution suggested by #TheMaster (Thank you so much!)
=LAMBDA(gf,INDEX(gf,ROWS(gf),2))(GOOGLEFINANCE("NSE:RELIANCE", "close",TODAY()-5,15))
Two other ways
=index(GOOGLEFINANCE("NSE:reliance","Close",today()-5,15),4,2)
=query(GOOGLEFINANCE("NSE:reliance","Close",today()-5,15),"select Col2 where Col1 < date '"&TEXT(today()+1, "YYYY-MM-DD")&"' order by Col1 desc limit 1",False)
I am also keen to know which one of these or other methods (if any) will get the results faster without crashes or any other processing issues as my googlesheet is loaded with thousands of stock quotes which will be refreshed every 1 minute.
Only historical prices support close attribute. Use the start date argument to get historical prices and get the last close:
=LAMBDA(gf,INDEX(gf,ROWS(gf),2))(GOOGLEFINANCE("NSE:RELIANCE", "close",TODAY()-5,15))
This is another way of achieving the result.
=query(GOOGLEFINANCE("NSE:reliance","Close",today()-5,15),"select Col2 where Col1 < date '"&TEXT(today()+1, "YYYY-MM-DD")&"' order by Col1 desc limit 1",False)
When I compared performance of both the solutions =LAMBDA and =QUERY on 2500+ stocks, I found query to be more faster than lambda.
Cheers!
However, my main query remains unresolved as no formula of google finance gives today's close until the actual day is over.

Googlesheet formulas for Crypto Coins

I am trying to create a google sheet showing various crypto prices for a few set times (but lets just use BTC-USD for the moment).
The sheet would show
BTCUSD Current Price, Previous Close, Close 5 days ago and Close 31 days ago
I have tried the following but running into the problems described which appear to be reserved for crypto.
There are various ways one can get the current price:
=GOOGLEFINANCE("BTCUSD") will work - so we are ok for current price
=GOOGLEFINANCE("BTCUSD","change") will not work, however it will work for an equity
=GOOGLEFINANCE("AAPL","change") will work
Similarly
=index(IMPORTHTML(CONCATENATE("https://finance.yahoo.com/quote/","AAPL"),"table",1),1,2) will return from table 1 row 1, column 2 from the yahoo finance page for Apple (an equity)
However
=index(IMPORTHTML(CONCATENATE("https://finance.yahoo.com/quote/","BTC-USD"),"table",1),1,2)
does not work even though the page and table layout appear to be the same
I also notice that
=GOOGLEFINANCE("BTCUSD", "price", DATE(2022,1,1), DATE(2022,8,15), "DAILY") will return the price of bitcoin for the date range,
However
=GOOGLEFINANCE("BTCUSD", "price", DATE(a1), DATE(a2), "DAILY")
will not work even if cell a1 and a2 have a copy and paste of the 2022,1,1 and 2022,8,15 in them.
I suspect the second question relates to the fact that the dates in the formula are not in quotes, however if you reference them from a cell excel may inadvertently put them into a quote causing a problem.
This last problem makes it difficult to solve the problem from a different angle ie by referencing cells as the day changes and we refresh the sheet ie we cannot reference a cell which would always be 5 days ago or 31 days ago.
Answer to your first question
With the first formula, =index(IMPORTHTML(CONCATENATE("https://finance.yahoo.com/quote/","AAPL"),"table",1),1,2) it worked for a moment and then stopped working. Then I tested =index(IMPORTHTML(CONCATENATE("https://finance.yahoo.com/quote/","BTC-USD"),"table",1),1,2) and did not work, I even tried =IMPORTHTML("https://finance.yahoo.com/quote/BTC-USD","table") to see if it was importing the table but you get the same error "Resource at url not found".
I did some research and it seems that Yahoo made some changes to their website and this affected some of their web-pages. It's suggested to use another website that is scrape-able by IMPORT functions. This is just an example of what is mentioned about Yahoo Finance and IMPORT functions, there are other communities that are also mentioning issues with doing web scraping to Yahoo Finance.
Answer to your second question
Issue with this formula =GOOGLEFINANCE("BTCUSD", "price", DATE(a1), DATE(a2), "DAILY"), according to documentation:
Inputs to DATE must be numbers - if a string or a reference to a cell containing a string is provided, the #VALUE! error will be returned.
The correct way would be: DATE(2022,1,1) and if you want to refer to a cell you will have to split 2022,1,1 in three different cells and make the reference this way DATE(A2,B2,C2).

Google sheets beginners question to average unit price formula

I am doing a test for a data analytics bootcamp. i have to use google sheets and i am an absolute beginner.
We have a dataset called products that we have to extract on a google spreadsheet first. I will upload the link to my google spreadsheet here:
https://docs.google.com/spreadsheets/d/1m67VmLZispyTwFTmPdppsdJNtbvnZsZK2LBCSchUWmU/edit?usp=sharing
the question is to use a formula to say what the average unit price of all products listed is.
My formula was to write under colum F(unit price) the formula: =AVERAGE(F2:F78). but the number i get is 44702 which cant be correct, if you look at the table.
also i dont know if i have to consider Column E, where the quantityperunit is stated to answer the question.
Could someone please help me?
I feel like I answered this for you in another post recently. But I can add more details.
You are working with a spreadsheet that seems to have been created in the United States, yet you've set the locale to Germany. This is creating a conflict, because the decimal separator in Germany is a comma while the decimal separator in the US is a period.
In addition, your Col-F values are all strings, not numbers — except for the one entry in F66. So you have mixed data types, and math functions can't act on that mix.
This leaves the only valid number being 21.05. However, as I said, in Germany, this is not a valid number. It's a date: May 21. And the data of May 21 (2022) is 44702 days since the Google Sheets origin date of December 30, 1899 (which is how Sheets stores all dates). So that is why you are getting that result.
If you change your locale to "United States," this will solve some of your issues. But no matter what your locale, it won't change those strings in Col F to real numbers. So you'll need to convert them in place, or your formula is going to need to account for them.
Seeing as this is an assignment, it's unclear whether the instructor intended for you to have to address these problems, or whether the additional problems are an unintentional result of spreadsheet conversions that happened somewhere.
In addition to all of that, you interpreted the original question in your post rather than sharing the actual exact wording of the question; and wording matters.
First, I would ask the instructor if the numbers in Col F were all supposed to be real numbers, or if most of them being strings is part of the assignment.
In any case, given exactly what you have right now, this should produce the average unit price (regardless of quantity in stock, as we don't know the actual wording of that question):
=ArrayFormula(ROUND(AVERAGE(VALUE(SUBSTITUTE(F2:F78&"",".",","))),2))
It's a lot longer than it would have needed to be if not for the multiple factors I described above. That is, given the locale setting of Germany and the fact that you have mixed data types, all of the Col-F values had to be converted to strings, then all of the periods had to be SUBSTITUTEd with commas, then they all had to be converted to numbers with VALUE before AVERAGE could be applied.

Change the delay from 20 to 1 minutes

Quotes are not sourced from all markets and may be delayed up to 20
minutes. Information is provided 'as is' and solely for informational
purposes, not for trading purposes or advice.
This advice appears when I use GOOGLEFINANCE() function in my spreadsheet. It is unfortunate that the data is delayed up to 20 minutes.
What is the best way to get real-time stock prices? Suppose my budget is around $50 per month.
Be aware that I trade only US equities, i.e. no bonds, no cryptocurrencies, and so on.
UPDATE
Here is a sample version of my portfolio spreadsheet : https://docs.google.com/spreadsheets/d/1hIfCuupmc_OZ6514DXFe_NrDCX1Ix6tcvySP_VolppI/edit#gid=42667785. It would be important for me to get the price in real-time, and not delayed by maximum 20 minutes.
Is there a way to fix that?
The GOOGLEFINANCE formula is not consistent with the delays. Different stocks can be delayed by different times. You can get an estimate of the delay by using GOOGLEFINANCE("TICKER","DATADELAY").
This is at least somewhat helpful, but not ideal, because you'll have a price on your sheet and you don't know exactly when the price was from, just an estimate of how old the price might be. And forget about pre-market or after-hours. Once the market closes, all bets are off you'll have no idea when the price is from (i.e. after hours quote or regular session close).
If you want accurate real-time quotes, you're going to need an add-on. You said your budget is $50. That doesn't leave you a lot of options. For $9 per month you can use the Market Data Add-on and get real-time stock prices along with historical intraday prices. There is also a free tier that gives you 100 free daily prices.
Market Data's STOCKDATA formula is a drop-in replacement for GOOGLEFINANCE, so it follows the same syntax. It will accomplish what you need. For example, STOCKDATA("SPY","ALL") will produce an output like this:
Date
Bid
Bid Size
Mid
Ask
Ask Size
Last
Volume
5/19/2022 9:09:48
388.36
1400
388.38
388.41
1400
388.37
2715229
Note that the date and time of the quote is included in the output, so you know exactly when the quote was fetched. There is no doubt as to whether the quote is coming from the previous day or whether it is a quote from the pre-market session (which is the case of this example). If you compare to the current time using NOW(), you'll find the Market Data quotes are delayed by about 1-2 seconds, which is due to network latency from your Google Sheet to the servers.
it's important to notice the word "may" in the first sentence:
...and may be delayed up to 20 minutes...
usually, it's way under 20 minutes (around 1 - 1:30 minutes), but there could be times when some delay may occur.
and to answer your question: no, it's not possible to force it under 1 minute
if you want to go full pro mode with Google Sheets then try: =CRYPTOFINANCE()
The documentation links from player0 indicate that ONLY crypto exchanges are supported. Data is NOT available from stock exchanges (NASDAQ, NYSE, etc).

Getting adjusted price information from Yahoo! Finance API for multiple symbols in one call

I would like to get the adjusted price (adjusting for splits and dividends) for a group of stock symbols using Yahoo! Finance. It looks like the historical prices call is limited to one symbol at a time. Could please let me know if there is a way to get multiple symbols in one call?
I would like to get this data so I can do some back testing on that data. Since I may require quite a few symbols (say 500-1000), it will be easier if I can make just a few batch calls to Yahoo!'s servers instead of making one call per symbol everyday.
Another way of getting the adjusted price is to use their daily stock price api and adjust it manually using dividend and splits information (they allow multiple symbols for their daily stock quotes). Unfortunately I cannot find any way to get splits information from the http call (guessing based on 50% or 200% is one option but if you deal with penny stocks, this can be dangerous and cannot figure out uneven splits). Also, the dividend information returned by it is not easy to decode. They seem to be returning the total over 4 quarters and the dividend date doesn't really correspond with the actual dividend date based on the historical price. The various options for the call can be found here: http://www.gummy-stuff.org/Yahoo-data.htm
Any suggestions on getting adjusted price for multiple symbols? Or Am I unnecessarily worrying about making 100s of calls to Yahoo! everyday? Ideally I would like to download all the required data within a couple of hours each day - that would be 10-20 calls per minute. Is that too much? I couldn't find any documentation on the permissible number of requests per second.
I am open to other places where I can get similar data. However, since I am just trying to learn the basics of quant trading and not trade, I would prefer free downloads.
Thanks
-e
This is an old question, but I did find a source where split data is available. Not sure how comprehensive these announcements are though:
http://biz.yahoo.com/c/09/s1.html
In the url, the "09" part is the year (2009), and the "s1" part is the month (s1 = Jan, s2 = Feb., s3 = Mar., etc.)
It isn't a nice clean CSV, but the format of the page is consistent and should be parseable. Just make a query each day for the current month, parse the page, and process any splits that you didn't see the day before.
ETA: And another source (probably less reliable than Yahoo, but can be queried by ticker):
http://getsplithistory.com/
I am not sure which language you are using but I have a sample in C#. I think it will give you the idea at least or may be help some one else
private string BASE_URL = "http://query.yahooapis.com/v1/public/yql?q=" + "select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20({0})" + "&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
Collection<Quote> quotes;
string symbolList = String.Join("%2C", quotes.Select(w => "%22" + w.Symbol + "%22").ToArray());
string url = string.Format(BASE_URL,symbolList);
XDocument doc = XDocument.Load(url);
Parse(quotes,doc);
What we are doing here is appending "," to each array item then passing that symbol list to yahoo. I have successfully fetched prices for 700 symbols in each call. Hitting yahoo servers for each ticker is a pain. I fetch stock prices for all of 6500+ tickers everyday. Earlier it use to take 3 hours now it is less than 2 mins.....sweet
Source link for that code is here - http://www.jarloo.com/get-yahoo-finance-api-data-via-yql/
P.S. Please get a api key to work smoothly. The above url is a public link where tables are timed out most of the time. Once you get an api key then your url will be (minus "public")
http://query.yahooapis.com/v1/yql

Resources