Skip to content

Commit b339c4e

Browse files
authored
Merge pull request #3028 from ryanduguid/ryan/fx-dividend-history-tz
Pass tz and session to FX PriceHistory in dividend conversion
2 parents eebc2ed + 2cf2220 commit b339c4e

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

‎tests/test_price_repair.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,24 @@ def fake_history(ph, *args, **kwargs):
823823
self.assertAlmostEqual(divs["Dividends"].iloc[0], expected_div)
824824
self.assertEqual(divs["currency"].iloc[0], price_ccy)
825825

826+
def test_dividends_convert_fx_passes_tz_and_session(self):
827+
# The FX PriceHistory needs a real timezone: with repair=True its
828+
# history() can call itself with start/end, which parses dates in self.tz.
829+
session = object()
830+
created = []
831+
832+
def fake_history(ph, *args, **kwargs):
833+
created.append((ph.ticker, ph.tz, ph.session))
834+
return _pd.DataFrame({"Close": [0.5]})
835+
836+
idx = _pd.DatetimeIndex([_pd.Timestamp("2025-01-10", tz="Europe/London")])
837+
ph = yf.scrapers.history.PriceHistory(None, "TEST", "Europe/London", session=session)
838+
# USD converts in one step; ZAR goes through USD in two.
839+
divs = _pd.DataFrame({"Dividends": [1.0, 1.0], "currency": ["USD", "ZAR"]}, index=idx.repeat(2))
840+
with mock.patch.object(yf.scrapers.history.PriceHistory, "history", fake_history):
841+
ph._dividends_convert_fx(divs, "GBP", repair=True)
842+
self.assertEqual(created, [(t, "Europe/London", session) for t in ("GBP=X", "ZAR=X", "GBP=X")])
843+
826844

827845
class TestPriceRepairLevelShift(unittest.TestCase):
828846
# Offline: the 1h data used for calibration is read from CSV, not fetched.

‎yfinance/scrapers/history.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,13 +1332,15 @@ def _dividends_convert_fx(self, dividends, fx, repair=False):
13321332
# - step 2: USD -> FX
13331333
fx2_tkr = f'{fx}=X'
13341334

1335-
fx_dat = PriceHistory(self._data, fx_tkr, self.session)
1335+
# The FX ticker takes this ticker's timezone. Only the last close of a
1336+
# 1-month fetch is used, so a day-boundary difference does not change the rate.
1337+
fx_dat = PriceHistory(self._data, fx_tkr, self.tz, self.session)
13361338
fx_rate = fx_dat.history(period='1mo', repair=repair)['Close'].iloc[-1]
13371339
if reverse:
13381340
fx_rate = 1/fx_rate
13391341
dividends.loc[dividends['currency']==c, 'Dividends'] *= fx_rate
13401342
if fx2_tkr is not None:
1341-
fx2_dat = PriceHistory(self._data, fx2_tkr, self.session)
1343+
fx2_dat = PriceHistory(self._data, fx2_tkr, self.tz, self.session)
13421344
fx2_rate = fx2_dat.history(period='1mo', repair=repair)['Close'].iloc[-1]
13431345
dividends.loc[dividends['currency']==c, 'Dividends'] *= fx2_rate
13441346

0 commit comments

Comments
 (0)