From c3db565d0954ab6508a9103b5ba7644ea794dea6 Mon Sep 17 00:00:00 2001 From: Alessandro Colace Date: Mon, 25 May 2026 21:46:38 +0200 Subject: [PATCH] Preserve Date/Datetime index name in yf.download() output reindex_dfs() rebuilt the combined index via sorted(set(...)) + pd.to_datetime, dropping the index name set by history.py ('Date' for daily, 'Datetime' for intraday). After concat, data.index.name was None, so users doing data.stack().reset_index() got a 'level_0' column instead of 'Date' / 'Datetime'. Use Index.union, which preserves the name natively when sources agree. Drive-by: narrow data.columns to MultiIndex before swaplevel to silence a pyright attribute warning. --- tests/test_ticker.py | 2 ++ yfinance/multi.py | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/test_ticker.py b/tests/test_ticker.py index 6d0d5be..048bdf6 100644 --- a/tests/test_ticker.py +++ b/tests/test_ticker.py @@ -324,6 +324,8 @@ class TestTickerHistory(unittest.TestCase): interval=interval, progress=False) self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + expected_name = 'Datetime' if interval[-1] in ('m', 'h') else 'Date' + self.assertEqual(data.index.name, expected_name) if ignore_tz: self.assertIsNone(data.index.tz) else: diff --git a/yfinance/multi.py b/yfinance/multi.py index ca3158d..265127a 100644 --- a/yfinance/multi.py +++ b/yfinance/multi.py @@ -214,7 +214,7 @@ def _download_impl(ctx, tickers, start=None, end=None, actions=False, threads=Tr keys=ctx.dfs.keys(), names=['Ticker', 'Price']) data.rename(columns=ctx.isins, inplace=True) - if group_by == 'column': + if group_by == 'column' and isinstance(data.columns, _pd.MultiIndex): data.columns = data.columns.swaplevel(0, 1) data.sort_index(level=0, axis=1, inplace=True) @@ -240,11 +240,12 @@ def reindex_dfs(dfs, ignore_tz): if (dfs[tkr] is not None) and (not dfs[tkr].empty): dfs[tkr].index = dfs[tkr].index.tz_convert(tz_mode) - all_indices = set() + idx = None for df in dfs.values(): - all_indices.update(df.index) - idx = sorted(all_indices) - idx = _pd.to_datetime(idx) + if df is not None and not df.empty: + idx = df.index if idx is None else idx.union(df.index) + if idx is None: + idx = _pd.DatetimeIndex([]) for key, df in dfs.items(): dfs[key] = df.reindex(idx)