ranaroussi / yfinance

Download market data from Yahoo! Finance's API
https://aroussi.com/post/python-yahoo-finance
Apache License 2.0
14.89k stars 2.44k forks source link

Fix prices 30m resampling #2027

Closed aleksfasting closed 3 months ago

aleksfasting commented 3 months ago

Solves #2026 to fix interval offset of the indian stock exchange

Solution that checks the offset of the opening time of the stock exchange (mod 30 minutes) and adds it to the quotes

That issue addresses #1436 and #1447.


Solution

The only change lies in yfinance/scrapers/history.py.

If ìnterval='30m', we find the time that the stock exchange opens. If it opens at a timet.minutes % 30 != 0` we add that offset to the quote.

ValueRaider commented 3 months ago

Hypothetical - can self._history_metadata["tradingPeriods"][0][0]["start"] throw a KeyError or IndexError?

aleksfasting commented 3 months ago

The 'tradingPeriods' key

The data from Yahoo Finance will always come with metadata, and it will include the 'tradingPeriods' key as long as there was a ticker to be found. If the ticker wasn't found, that would have been handled before the call to this line.

The first 0 index

The entries of self._histoy_metadata['tradingPeriods'] will be a list of all the opening-times, end-times, etc. of each day succeding the start date.

If the start date is after the current date there will not have been generated any price data, and the code has handled this before this line of code. The same goes for any scenario where no price data has been generated, like weekends, holidays or such.

The second 0 index

I have no idea why Yahoo Finance supply their metadata with this wrapper list. The list always contains a single dict. Artistic choice by Yahoo finance. I could not find a counter example.

The 'start' index

This is a key in the standard dict in self._history_metadata["tradingPeriods][0][0]. I have not found a dict that does not contain this key.


So i think the keys and indexes will always exist if this line is being executed. No exceptions will be thrown

ValueRaider commented 3 months ago

KeyError was possible, I encountered it:

    exchangeStartTime = pd.Timestamp(self._history_metadata["tradingPeriods"][0][0]["start"], unit='s')
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^

KeyError: 0

I'll try to provide arguments to reproduce, but this is rare so could take a long time to repeat.

ValueRaider commented 3 months ago

Reproduce:

dat = yf.Ticker('0001.HK')
df = dat.history(start=1719763200, end=1720540800, interval='30m', prepost=True)