From bb983c19f481c0c38c28f0103060960374cca988 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Mon, 6 Feb 2023 14:48:38 +0000 Subject: [PATCH 1/3] fix ticker info keys --- .../portfolio_optimization/optimizer_model.py | 16 ++++++++++-- .../yahoo_finance_model.py | 25 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py index d75be71b8bf..3b0fdac3105 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py @@ -289,6 +289,7 @@ def get_property_weights( value = get_kwarg("value", kwargs) s_property = get_kwarg("s_property", kwargs, default="marketCap") + s_property = yahoo_finance_model.fast_info_map.get(s_property, s_property) stock_prices = yahoo_finance_model.process_stocks( symbols, interval, start_date, end_date @@ -305,14 +306,22 @@ def get_property_weights( prop = {} prop_sum = 0 for stock in symbols: - stock_prop = yf.Ticker(stock).info[s_property] + info = yf.Ticker(stock).info + fast_info = yf.Ticker(stock).fast_info + info_dict = {} + if info: + info_dict.update(dict(info)) + if fast_info: + info_dict.update(dict(fast_info)) + + stock_prop = info_dict.get(s_property, None) if stock_prop is None: stock_prop = 0 prop[stock] = stock_prop prop_sum += stock_prop if prop_sum == 0: - console.print(f"No {s_property} was found on list of tickers provided", "\n") + console.print(f"No '{s_property}' was found on list of tickers provided", "\n") return None, None weights = {k: value * v / prop_sum for k, v in prop.items()} @@ -1368,6 +1377,9 @@ def get_black_litterman_portfolio( value=value, ) + if benchmark is None: + return None, stock_returns + factor = time_factor[freq.upper()] risk_free_rate = risk_free_rate / factor diff --git a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py index e54fe7133f9..98603d592c5 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py @@ -19,6 +19,27 @@ logger = logging.getLogger(__name__) # pylint: disable=R0912, E1101 +fast_info_map = { + "previousClose": "previous_close", + "twoHundredDayAverage": "two_hundred_day_average", + "regularMarketDayHigh": "day_high", + "averageDailyVolume10Day": "ten_day_average_volume", + "regularMarketPreviousClose": "regular_market_previous_close", + "fiftyDayAverage": "fifty_day_average", + "open": "open", + "averageVolume10days": "ten_day_average_volume", + "regularMarketDayLow": "day_low", + "currency": "currency", + "marketCap": "market_cap", + "averageVolume": "three_month_average_volume", + "dayLow": "day_low", + "volume": "last_volume", + "fiftyTwoWeekHigh": "year_high", + "fiftyTwoWeekLow": "year_low", + "dayHigh": "day_high", + "regularMarketPrice": "last_price", +} + yf_info_choices = [ "previousClose", "regularMarketOpen", @@ -30,7 +51,7 @@ yf_info_choices = [ "navPrice", "averageDailyVolume10Day", "totalAssets", - "regularMarketPreviousClose", + "regular_market_previous_close", "fiftyDayAverage", "trailingAnnualDividendRate", "open", @@ -51,7 +72,7 @@ yf_info_choices = [ "lastMarket", "maxSupply", "openInterest", - "marketCap", + "market_cap", "volumeAllCurrencies", "strikePrice", "averageVolume", From 0b9182e4900d22736e8e7a9d2ce7e66576131941 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Mon, 6 Feb 2023 15:12:50 +0000 Subject: [PATCH 2/3] decouple yfinance --- .../portfolio_optimization/optimizer_model.py | 55 +++++++++++++++---- .../yahoo_finance_model.py | 4 -- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py index 3b0fdac3105..f98dbf73ba7 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py @@ -289,7 +289,6 @@ def get_property_weights( value = get_kwarg("value", kwargs) s_property = get_kwarg("s_property", kwargs, default="marketCap") - s_property = yahoo_finance_model.fast_info_map.get(s_property, s_property) stock_prices = yahoo_finance_model.process_stocks( symbols, interval, start_date, end_date @@ -306,17 +305,7 @@ def get_property_weights( prop = {} prop_sum = 0 for stock in symbols: - info = yf.Ticker(stock).info - fast_info = yf.Ticker(stock).fast_info - info_dict = {} - if info: - info_dict.update(dict(info)) - if fast_info: - info_dict.update(dict(fast_info)) - - stock_prop = info_dict.get(s_property, None) - if stock_prop is None: - stock_prop = 0 + stock_prop = get_prop(symbol=stock, prop=s_property) prop[stock] = stock_prop prop_sum += stock_prop @@ -329,6 +318,48 @@ def get_property_weights( return weights, stock_returns +@log_start_end(log=logger) +def get_prop(symbol, prop) -> float: + """Get property from yfinance + + Parameters + ---------- + symbol : str + Stock ticker + prop : str + Property to get + + Returns + ------- + dict + Ticker info + """ + prop = yahoo_finance_model.fast_info_map.get(prop, prop) + + try: + info = yf.Ticker(symbol).info + except Exception as _: # noqa + info = None + + try: + fast_info = yf.Ticker(symbol).fast_info + except Exception as _: # noqa + fast_info = None + + info_dict = {} + if info: + info_dict.update(dict(info)) + if fast_info: + info_dict.update(dict(fast_info)) + + if info_dict: + value = info_dict.get(prop, 0.0) + if not value: + return 0.0 + return value + return 0.0 + + @log_start_end(log=logger) def get_mean_risk_portfolio( symbols: List[str], diff --git a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py index 98603d592c5..b8eefb379ea 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py @@ -42,7 +42,6 @@ fast_info_map = { yf_info_choices = [ "previousClose", - "regularMarketOpen", "twoHundredDayAverage", "trailingAnnualDividendYield", "payoutRatio", @@ -51,7 +50,6 @@ yf_info_choices = [ "navPrice", "averageDailyVolume10Day", "totalAssets", - "regular_market_previous_close", "fiftyDayAverage", "trailingAnnualDividendRate", "open", @@ -68,11 +66,9 @@ yf_info_choices = [ "priceHint", "currency", "trailingPE", - "regularMarketVolume", "lastMarket", "maxSupply", "openInterest", - "market_cap", "volumeAllCurrencies", "strikePrice", "averageVolume", From 198d7998b28b0e26a5fe17eebc2bc1c533306820 Mon Sep 17 00:00:00 2001 From: Andy Huynh <8610246+andyhuynh3@users.noreply.github.com> Date: Mon, 6 Feb 2023 20:10:34 -0800 Subject: [PATCH 3/3] Remove duplicate ruff selection of pycodestyle warnings (W) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7c0edb1937e..5d0e21bb1a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,7 +160,7 @@ target-version = "py38" # This is an introductory addition of ruff. We should look to adding: # D: pydocstyle, PD: pandas-vet # All options here: https://github.com/charliermarsh/ruff#supported-rules -select = ["E", "W", "F", "Q", "W", "S", "UP", "I"] +select = ["E", "W", "F", "Q", "S", "UP", "I"] ignore = ["S105", "S106", "S107"] [tool.ruff.per-file-ignores]