Reputation: 541
Here's how Yahoo Finance apparently calculates Adjusted Close stock prices:
https://help.yahoo.com/kb/adjusted-close-sln28256.html
From this, I understand that a constant factor is applied to the unadjusted price and that said factor changes with each dividend or split event, which should happen not too often. And that I should be able to infer that factor by dividing the unadjusted by the adjusted price.
However, if I verify this with AAPL data (using Python), I get confusing results:
import yfinance
df = yfinance.download("AAPL", start="2010-01-01", end="2019-12-31")
df["Factor"] = df["Close"] / df["Adj Close"]
print(df["Factor"].nunique(), df["Factor"].count())
Which produces: 2442 2516
So the factor is different in by far most of the cases. But AAPL usually has 4 dividend events per year and had a stock split during that period, so I would expect roughly 40 different factors rather than 2442.
Is the formula Yahoo Finance provides under the link above overly simplified or am I missing something here?
Upvotes: 7
Views: 11810
Reputation: 31
The problem is that Yahoo Finance doesn't provide BOTH raw and adjusted prices for you to work with. If you check the footnote of a sample historical price page (e.g., MSFT), you will see a text that says "Close price adjusted for splits; Adjusted close price adjusted for both dividends and splits."
In order to derive clean adjusted ratios, both raw (unadjusted) and adjusted prices are needed. Then you can apply an adjustment method such as CRSP to derive the correct values. In summary, you didn't do anything wrong! It's the intrinsic limitation of Yahoo's output.
References: [1] https://medium.com/@patrick.collins_58673/stock-api-landscape-5c6e054ee631 [2] http://www.crsp.org/products/documentation/crsp-calculations
Upvotes: 3
Reputation: 24940
I'm not sure this is a complete answer, but it's too long for a comment:
First, there is definitely an issue with rounding. If you modify your third line to
df["Factor"] = df["Close"] / df["Adj Close"].round(12)
you get 2441 unique factors. If, however, you use, for example round(6)
, you only get 46 unique factors.
Second, according to the adjustment rules in the Yahoo help page in your question, each dividend results in an adjustment for the 5 trading dates immediately prior to the ex-divined date. During the 10 year period in your question, there were no stock splits and approximately 40 quarterly dividends. These should have resulted in 200 dates with adjusted closing prices. All the other 2300 or so dates should have no closing adjustments, ie., a Factor of 1
. Yet when you run:
df[df.Factor == 1].shape
you get only 37
dates (regardless of the rounding used) with no adjustments.
Obviously, that doesn't make sense and - unless I'm missing something basic - there is some error either in the implementation of the adjustment methodology or in the Yahoo code.
Upvotes: 1