Replace prints with logging module
parent
a0046439d1
commit
972547ca8c
|
@ -15,6 +15,9 @@ Sanity check for most common library uses all working
|
||||||
|
|
||||||
import yfinance as yf
|
import yfinance as yf
|
||||||
import unittest
|
import unittest
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
symbols = ['MSFT', 'IWO', 'VFINX', '^GSPC', 'BTC-USD']
|
symbols = ['MSFT', 'IWO', 'VFINX', '^GSPC', 'BTC-USD']
|
||||||
tickers = [yf.Ticker(symbol) for symbol in symbols]
|
tickers = [yf.Ticker(symbol) for symbol in symbols]
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import logging
|
||||||
import time as _time
|
import time as _time
|
||||||
import datetime as _datetime
|
import datetime as _datetime
|
||||||
import dateutil as _dateutil
|
import dateutil as _dateutil
|
||||||
|
@ -47,6 +48,7 @@ _BASE_URL_ = 'https://query2.finance.yahoo.com'
|
||||||
_SCRAPE_URL_ = 'https://finance.yahoo.com/quote'
|
_SCRAPE_URL_ = 'https://finance.yahoo.com/quote'
|
||||||
_ROOT_URL_ = 'https://finance.yahoo.com'
|
_ROOT_URL_ = 'https://finance.yahoo.com'
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class FastInfo:
|
class FastInfo:
|
||||||
# Contain small subset of info[] items that can be fetched faster elsewhere.
|
# Contain small subset of info[] items that can be fetched faster elsewhere.
|
||||||
|
@ -899,7 +901,7 @@ class TickerBase:
|
||||||
sub_interval = nexts[interval]
|
sub_interval = nexts[interval]
|
||||||
td_range = itds[interval]
|
td_range = itds[interval]
|
||||||
else:
|
else:
|
||||||
print("WARNING: Have not implemented repair for '{}' interval. Contact developers".format(interval))
|
logger.critical("Have not implemented repair for '%s' interval. Contact developers", interval)
|
||||||
raise Exception("why here")
|
raise Exception("why here")
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
@ -1035,7 +1037,7 @@ class TickerBase:
|
||||||
df_fine = self.history(start=fetch_start, end=fetch_end, interval=sub_interval, auto_adjust=False, actions=False, prepost=prepost, repair=r, keepna=True)
|
df_fine = self.history(start=fetch_start, end=fetch_end, interval=sub_interval, auto_adjust=False, actions=False, prepost=prepost, repair=r, keepna=True)
|
||||||
if df_fine is None or df_fine.empty:
|
if df_fine is None or df_fine.empty:
|
||||||
if not silent:
|
if not silent:
|
||||||
print("YF: WARNING: Cannot reconstruct because Yahoo not returning data in interval")
|
logger.warning("Cannot reconstruct because Yahoo not returning data in interval")
|
||||||
continue
|
continue
|
||||||
# Discard the buffer
|
# Discard the buffer
|
||||||
df_fine = df_fine.loc[g[0] : g[-1]+itds[sub_interval]-_datetime.timedelta(milliseconds=1)]
|
df_fine = df_fine.loc[g[0] : g[-1]+itds[sub_interval]-_datetime.timedelta(milliseconds=1)]
|
||||||
|
@ -1273,7 +1275,7 @@ class TickerBase:
|
||||||
if n_fixed_crudely > 0:
|
if n_fixed_crudely > 0:
|
||||||
report_msg += f"({n_fixed_crudely} crudely) "
|
report_msg += f"({n_fixed_crudely} crudely) "
|
||||||
report_msg += f"in {interval} price data"
|
report_msg += f"in {interval} price data"
|
||||||
print(report_msg)
|
logger.info('%s', report_msg)
|
||||||
|
|
||||||
# Restore original values where repair failed
|
# Restore original values where repair failed
|
||||||
f = df2_tagged
|
f = df2_tagged
|
||||||
|
@ -1366,7 +1368,7 @@ class TickerBase:
|
||||||
if n_fixed < 4:
|
if n_fixed < 4:
|
||||||
dts_repaired = sorted(list(set(dts_tagged).difference(dts_not_repaired)))
|
dts_repaired = sorted(list(set(dts_tagged).difference(dts_not_repaired)))
|
||||||
msg += f": {dts_repaired}"
|
msg += f": {dts_repaired}"
|
||||||
print(msg)
|
logger.info('%s', msg)
|
||||||
|
|
||||||
if df2_reserve is not None:
|
if df2_reserve is not None:
|
||||||
df3 = _pd.concat([df3, df2_reserve]).sort_index()
|
df3 = _pd.concat([df3, df2_reserve]).sort_index()
|
||||||
|
@ -1729,7 +1731,7 @@ class TickerBase:
|
||||||
if start is None:
|
if start is None:
|
||||||
start = end - _pd.Timedelta(days=548) # 18 months
|
start = end - _pd.Timedelta(days=548) # 18 months
|
||||||
if start >= end:
|
if start >= end:
|
||||||
print("ERROR: start date must be before end")
|
logger.error("Start date must be before end")
|
||||||
return None
|
return None
|
||||||
start = start.floor("D")
|
start = start.floor("D")
|
||||||
end = end.ceil("D")
|
end = end.ceil("D")
|
||||||
|
@ -1741,14 +1743,14 @@ class TickerBase:
|
||||||
json_str = self._data.cache_get(shares_url).text
|
json_str = self._data.cache_get(shares_url).text
|
||||||
json_data = _json.loads(json_str)
|
json_data = _json.loads(json_str)
|
||||||
except:
|
except:
|
||||||
print(f"{self.ticker}: Yahoo web request for share count failed")
|
logger.error("%s: Yahoo web request for share count failed", self.ticker)
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
fail = json_data["finance"]["error"]["code"] == "Bad Request"
|
fail = json_data["finance"]["error"]["code"] == "Bad Request"
|
||||||
except:
|
except:
|
||||||
fail = False
|
fail = False
|
||||||
if fail:
|
if fail:
|
||||||
print(f"{self.ticker}: Yahoo web request for share count failed")
|
logger.error(f"%s: Yahoo web request for share count failed", self.ticker)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
shares_data = json_data["timeseries"]["result"]
|
shares_data = json_data["timeseries"]["result"]
|
||||||
|
@ -1757,7 +1759,7 @@ class TickerBase:
|
||||||
try:
|
try:
|
||||||
df = _pd.Series(shares_data[0]["shares_out"], index=_pd.to_datetime(shares_data[0]["timestamp"], unit="s"))
|
df = _pd.Series(shares_data[0]["shares_out"], index=_pd.to_datetime(shares_data[0]["timestamp"], unit="s"))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{self.ticker}: Failed to parse shares count data: "+str(e))
|
logger.error(f"%s: Failed to parse shares count data: %s", self.ticker, e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
df.index = df.index.tz_localize(tz)
|
df.index = df.index.tz_localize(tz)
|
||||||
|
@ -1872,7 +1874,7 @@ class TickerBase:
|
||||||
|
|
||||||
if dates is None or dates.shape[0] == 0:
|
if dates is None or dates.shape[0] == 0:
|
||||||
err_msg = "No earnings dates found, symbol may be delisted"
|
err_msg = "No earnings dates found, symbol may be delisted"
|
||||||
print('- %s: %s' % (self.ticker, err_msg))
|
logger.error('%s: %s', self.ticker, err_msg)
|
||||||
return None
|
return None
|
||||||
dates = dates.reset_index(drop=True)
|
dates = dates.reset_index(drop=True)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import functools
|
import functools
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
usePycryptodome = False # slightly faster
|
usePycryptodome = False # slightly faster
|
||||||
|
@ -25,6 +26,8 @@ except ImportError:
|
||||||
|
|
||||||
cache_maxsize = 64
|
cache_maxsize = 64
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def lru_cache_freezeargs(func):
|
def lru_cache_freezeargs(func):
|
||||||
"""
|
"""
|
||||||
|
@ -294,7 +297,7 @@ class TickerData:
|
||||||
msg = "No decryption keys could be extracted from JS file."
|
msg = "No decryption keys could be extracted from JS file."
|
||||||
if "requests_cache" in str(type(response)):
|
if "requests_cache" in str(type(response)):
|
||||||
msg += " Try flushing your 'requests_cache', probably parsing old JS."
|
msg += " Try flushing your 'requests_cache', probably parsing old JS."
|
||||||
print("WARNING: " + msg + " Falling back to backup decrypt methods.")
|
logger.warning("WARNING: %s Falling back to backup decrypt methods.", msg)
|
||||||
if len(keys) == 0:
|
if len(keys) == 0:
|
||||||
keys = []
|
keys = []
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import logging
|
||||||
import time as _time
|
import time as _time
|
||||||
import multitasking as _multitasking
|
import multitasking as _multitasking
|
||||||
import pandas as _pd
|
import pandas as _pd
|
||||||
|
@ -28,6 +29,7 @@ import pandas as _pd
|
||||||
from . import Ticker, utils
|
from . import Ticker, utils
|
||||||
from . import shared
|
from . import shared
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def download(tickers, start=None, end=None, actions=False, threads=True, ignore_tz=None,
|
def download(tickers, start=None, end=None, actions=False, threads=True, ignore_tz=None,
|
||||||
group_by='column', auto_adjust=False, back_adjust=False, repair=False, keepna=False,
|
group_by='column', auto_adjust=False, back_adjust=False, repair=False, keepna=False,
|
||||||
|
@ -144,12 +146,16 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_
|
||||||
if progress:
|
if progress:
|
||||||
shared._PROGRESS_BAR.completed()
|
shared._PROGRESS_BAR.completed()
|
||||||
|
|
||||||
if shared._ERRORS and show_errors:
|
if shared._ERRORS:
|
||||||
print('\n%.f Failed download%s:' % (
|
if show_errors:
|
||||||
len(shared._ERRORS), 's' if len(shared._ERRORS) > 1 else ''))
|
print('\n%.f Failed download%s:' % (
|
||||||
# print(shared._ERRORS)
|
len(shared._ERRORS), 's' if len(shared._ERRORS) > 1 else ''))
|
||||||
print("\n".join(['- %s: %s' %
|
# print(shared._ERRORS)
|
||||||
v for v in list(shared._ERRORS.items())]))
|
print("\n".join(['- %s: %s' %
|
||||||
|
v for v in list(shared._ERRORS.items())]))
|
||||||
|
else:
|
||||||
|
logger.error('%d failed downloads: %s',
|
||||||
|
len(shared._ERRORS), shared._ERRORS)
|
||||||
|
|
||||||
if ignore_tz:
|
if ignore_tz:
|
||||||
for tkr in shared._DFS.keys():
|
for tkr in shared._DFS.keys():
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Analysis:
|
||||||
analysis_data = analysis_data['QuoteSummaryStore']
|
analysis_data = analysis_data['QuoteSummaryStore']
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
err_msg = "No analysis data found, symbol may be delisted"
|
err_msg = "No analysis data found, symbol may be delisted"
|
||||||
print('- %s: %s' % (self._data.ticker, err_msg))
|
logger.error('%s: %s', self._data.ticker, err_msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(analysis_data.get('earningsTrend'), dict):
|
if isinstance(analysis_data.get('earningsTrend'), dict):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -8,6 +9,7 @@ from yfinance import utils
|
||||||
from yfinance.data import TickerData
|
from yfinance.data import TickerData
|
||||||
from yfinance.exceptions import YFinanceDataException, YFinanceException
|
from yfinance.exceptions import YFinanceDataException, YFinanceException
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Fundamentals:
|
class Fundamentals:
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ class Fundamentals:
|
||||||
self._fin_data_quote = self._financials_data['QuoteSummaryStore']
|
self._fin_data_quote = self._financials_data['QuoteSummaryStore']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
err_msg = "No financials data found, symbol may be delisted"
|
err_msg = "No financials data found, symbol may be delisted"
|
||||||
print('- %s: %s' % (self._data.ticker, err_msg))
|
logger.error('%s: %s', self._data.ticker, err_msg)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _scrape_earnings(self, proxy):
|
def _scrape_earnings(self, proxy):
|
||||||
|
@ -144,7 +146,7 @@ class Financials:
|
||||||
if statement is not None:
|
if statement is not None:
|
||||||
return statement
|
return statement
|
||||||
except YFinanceException as e:
|
except YFinanceException as e:
|
||||||
print(f"- {self._data.ticker}: Failed to create {name} financials table for reason: {repr(e)}")
|
logger.error("%s: Failed to create %s financials table for reason: %r", self._data.ticker, name, e)
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
|
|
||||||
def _create_financials_table(self, name, timescale, proxy):
|
def _create_financials_table(self, name, timescale, proxy):
|
||||||
|
@ -267,7 +269,7 @@ class Financials:
|
||||||
if statement is not None:
|
if statement is not None:
|
||||||
return statement
|
return statement
|
||||||
except YFinanceException as e:
|
except YFinanceException as e:
|
||||||
print(f"- {self._data.ticker}: Failed to create financials table for {name} reason: {repr(e)}")
|
logger.error("%s: Failed to create financials table for %s reason: %r", self._data.ticker, name, e)
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
|
|
||||||
def _create_financials_table_old(self, name, timescale, proxy):
|
def _create_financials_table_old(self, name, timescale, proxy):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -6,6 +7,7 @@ import pandas as pd
|
||||||
from yfinance import utils
|
from yfinance import utils
|
||||||
from yfinance.data import TickerData
|
from yfinance.data import TickerData
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
info_retired_keys_price = {"currentPrice", "dayHigh", "dayLow", "open", "previousClose", "volume", "volume24Hr"}
|
info_retired_keys_price = {"currentPrice", "dayHigh", "dayLow", "open", "previousClose", "volume", "volume24Hr"}
|
||||||
info_retired_keys_price.update({"regularMarket"+s for s in ["DayHigh", "DayLow", "Open", "PreviousClose", "Price", "Volume"]})
|
info_retired_keys_price.update({"regularMarket"+s for s in ["DayHigh", "DayLow", "Open", "PreviousClose", "Price", "Volume"]})
|
||||||
|
@ -126,7 +128,7 @@ class Quote:
|
||||||
quote_summary_store = json_data['QuoteSummaryStore']
|
quote_summary_store = json_data['QuoteSummaryStore']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
err_msg = "No summary info found, symbol may be delisted"
|
err_msg = "No summary info found, symbol may be delisted"
|
||||||
print('- %s: %s' % (self._data.ticker, err_msg))
|
logger.error('%s: %s', self._data.ticker, err_msg)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# sustainability
|
# sustainability
|
||||||
|
|
|
@ -936,9 +936,10 @@ def get_tz_cache():
|
||||||
try:
|
try:
|
||||||
_tz_cache = _TzCache()
|
_tz_cache = _TzCache()
|
||||||
except _TzCacheException as err:
|
except _TzCacheException as err:
|
||||||
print("Failed to create TzCache, reason: {}".format(err))
|
logger.error("Failed to create TzCache, reason: %s. "
|
||||||
print("TzCache will not be used.")
|
"TzCache will not be used. "
|
||||||
print("Tip: You can direct cache to use a different location with 'set_tz_cache_location(mylocation)'")
|
"Tip: You can direct cache to use a different location with 'set_tz_cache_location(mylocation)'",
|
||||||
|
err)
|
||||||
_tz_cache = _TzCacheDummy()
|
_tz_cache = _TzCacheDummy()
|
||||||
|
|
||||||
return _tz_cache
|
return _tz_cache
|
||||||
|
|
Loading…
Reference in New Issue