Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch keyError in #2027 #2029

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ body:
id: debug-log
attributes:
label: "Debug log"
description: "Run code with debug logging enabled and post the full output. IMPORTANT INSTRUCTIONS: https://github.com/ranaroussi/yfinance/tree/main#logging"
description: "Run code with debug logging enabled - `yf.enable_debug_mode()` - and post the full output. Context: https://github.com/ranaroussi/yfinance/tree/main#logging"
validations:
required: true

Expand Down
30 changes: 18 additions & 12 deletions tests/test_prices.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from .context import yfinance as yf
from .context import session_gbl

import datetime as _dt
import os
import unittest

import os
import datetime as _dt
import pytz as _tz
import numpy as _np
import pandas as _pd
import pytz as _tz

from .context import session_gbl
from .context import yfinance as yf


class TestPriceHistory(unittest.TestCase):
Expand All @@ -32,17 +32,23 @@ def test_daily_index(self):
f = df.index.time == _dt.time(0)
self.assertTrue(f.all())

def test_download(self):
def test_download_multi_large_interval(self):
tkrs = ["BHP.AX", "IMP.JO", "BP.L", "PNL.L", "INTC"]
intervals = ["1d", "1wk", "1mo"]
for interval in intervals:
df = yf.download(tkrs, period="5y", interval=interval)
with self.subTest(interval):
df = yf.download(tkrs, period="5y", interval=interval)

f = df.index.time == _dt.time(0)
self.assertTrue(f.all())

f = df.index.time == _dt.time(0)
self.assertTrue(f.all())
df_tkrs = df.columns.levels[1]
self.assertEqual(sorted(tkrs), sorted(df_tkrs))

df_tkrs = df.columns.levels[1]
self.assertEqual(sorted(tkrs), sorted(df_tkrs))
def test_download_multi_small_interval(self):
use_tkrs = ["AAPL", "0Q3.DE", "ATVI"]
df = yf.download(use_tkrs, period="1d", interval="5m")
self.assertEqual(df.index.tz, _dt.timezone.utc)

def test_download_with_invalid_ticker(self):
#Checks if using an invalid symbol gives the same output as not using an invalid symbol in combination with a valid symbol (AAPL)
Expand Down
20 changes: 20 additions & 0 deletions tests/test_ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,26 @@ def test_no_analysts(self):
except Exception as e:
self.fail(f"Excpetion raised for attribute '{attribute}': {e}")

class Test30MinResamplePreposts(unittest.TestCase):
session = None

@classmethod
def setUpClass(cls):
cls.session = session_gbl

@classmethod
def tearDownClass(cls):
if cls.session is not None:
cls.session.close()

def setUp(self):
self.ticker = yf.Ticker("0001.HK", session=self.session)

def test_resample_with_prepost(self):
self.ticker.history(period='1d', interval='30m', prepost=True)

def test_resample_without_prepost(self):
self.ticker.history(period='1d', interval='30m', prepost=False)


class TestTickerInfo(unittest.TestCase):
Expand Down
27 changes: 26 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
python -m unittest tests.utils.TestTicker

"""
from datetime import datetime
from unittest import TestSuite

# import pandas as pd
import pandas as pd
# import numpy as np

from .context import yfinance as yf
Expand Down Expand Up @@ -81,10 +82,34 @@ def test_tzCacheRootLookup(self):
cache.lookup(tkr)


class TestPandas(unittest.TestCase):
date_strings = ["2024-08-07 09:05:00+02:00", "2024-08-07 09:05:00-04:00"]

@unittest.expectedFailure
def test_mixed_timezones_to_datetime_fails(self):
series = pd.Series(self.date_strings)
series = series.map(pd.Timestamp)
converted = pd.to_datetime(series)
self.assertIsNotNone(converted[0].tz)

def test_mixed_timezones_to_datetime(self):
series = pd.Series(self.date_strings)
series = series.map(pd.Timestamp)
converted = pd.to_datetime(series, utc=True)
self.assertIsNotNone(converted[0].tz)
i = 0
for dt in converted:
dt: datetime
ts: pd.Timestamp = series[i]
self.assertEqual(dt.isoformat(), ts.tz_convert(tz="UTC").isoformat())
i += 1


def suite():
ts: TestSuite = unittest.TestSuite()
ts.addTest(TestCache('Test cache'))
ts.addTest(TestCacheNoPermission('Test cache no permission'))
ts.addTest(TestPandas("Test pandas"))
return ts


Expand Down
2 changes: 1 addition & 1 deletion yfinance/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_
_realign_dfs()
data = _pd.concat(shared._DFS.values(), axis=1, sort=True,
keys=shared._DFS.keys(), names=['Ticker', 'Price'])
data.index = _pd.to_datetime(data.index)
data.index = _pd.to_datetime(data.index, utc=True)
# switch names back to isins if applicable
data.rename(columns=shared._ISINS, inplace=True)

Expand Down
2 changes: 1 addition & 1 deletion yfinance/scrapers/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def history(self, period="1mo", interval="1d",
# 2) fix weired bug with Yahoo! - returning 60m for 30m bars
if interval.lower() == "30m":
logger.debug(f'{self.ticker}: resampling 30m OHLC from 15m')
exchangeStartTime = pd.Timestamp(self._history_metadata["tradingPeriods"][0][0]["start"], unit='s')
exchangeStartTime = pd.Timestamp(self._history_metadata["currentTradingPeriod"]['regular']["start"], unit='s')
offset = str(exchangeStartTime.minute % 30)+"min"
quotes2 = quotes.resample('30min', offset=offset)
quotes = pd.DataFrame(index=quotes2.last().index, data={
Expand Down