From fedeeaad1894b97c1b496205b808aada328f08b8 Mon Sep 17 00:00:00 2001 From: kajdo Date: Mon, 12 Dec 2022 23:55:20 +0100 Subject: [PATCH] FEAT: EPS and Revenue Estimations from Seeking Alpha (#3402) * FEAT: EPS and Revenue Estimations from Seeking Alpha * initial pytest for seekingalpha model and view * added fa_controller tests for seekingalpha views * integration tests for epsfc and revfc * FIX: handling of "no data found" * merge * number format fix * format change according to black linter * fixed unit tests because prev. recordings didn't match anymore * change to match linter rules * fixes * delete website files" * update codespell * Flake Co-authored-by: kajdo Co-authored-by: James Maslek Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- .pre-commit-config.yaml | 2 +- .../miscellaneous/data_sources_default.json | 2 + openbb_terminal/miscellaneous/i18n/en.yml | 4 +- .../scripts/stocks/test_stocks_fa.openbb | 3 + .../stocks/test_stocks_fa_epsfc.openbb | 5 + .../stocks/test_stocks_fa_revfc.openbb | 5 + .../fundamental_analysis/fa_controller.py | 35 +- .../seeking_alpha_model.py | 334 ++++++++++++++++++ .../seeking_alpha_view.py | 61 ++++ .../test_print_help.txt | 4 +- .../test_check_get_estimates_eps.yaml | 185 ++++++++++ .../test_check_get_estimates_rev.yaml | 185 ++++++++++ .../test_get_seekingalpha_id.yaml | 89 +++++ .../test_display_eps_estimation.yaml | 189 ++++++++++ .../test_display_rev_estimation.yaml | 192 ++++++++++ .../test_check_get_estimates_eps.csv | 9 + .../test_check_get_estimates_rev.csv | 9 + .../test_fa_controller.py | 12 + .../test_seeking_alpha_model.py | 32 ++ .../test_seeking_alpha_view.py | 18 + .../test_fa_controller/test_print_help.txt | 2 + .../test_get_seekingalpha_id.txt | 1 + .../test_display_eps_estimation.txt | 0 24 files changed, 1372 insertions(+), 8 deletions(-) create mode 100644 openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_epsfc.openbb create mode 100644 openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_revfc.openbb create mode 100644 openbb_terminal/stocks/fundamental_analysis/seeking_alpha_model.py create mode 100644 openbb_terminal/stocks/fundamental_analysis/seeking_alpha_view.py create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_eps.yaml create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_rev.yaml create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_get_seekingalpha_id.yaml create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_eps_estimation.yaml create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_rev_estimation.yaml create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_eps.csv create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_rev.csv create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_model.py create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_view.py create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_model/test_get_seekingalpha_id.txt create mode 100644 tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_view/test_display_eps_estimation.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1290044b963..14b2e41fd62 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: - run: pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six - run: bandit -x ./tests -r . || true - run: black --diff --check . - - run: codespell --ignore-words-list=commun,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml + - run: codespell --ignore-words-list=commun,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot,te --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml - run: flake8 . --count --ignore=E203,W503 --max-line-length=122 --show-source --statistics --exclude ./build/pyinstaller,./website/content - run: mypy --ignore-missing-imports openbb_terminal - run: shopt -s globstar && pyupgrade --py38-plus **/*.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a0333e584d..eac709ae27a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: entry: codespell args: [ - "--ignore-words-list=commun,ro,zar,vie,hel,jewl,zlot,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,statics,ket,toke,certi,buidl", + "--ignore-words-list=te,commun,ro,zar,vie,hel,jewl,zlot,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,statics,ket,toke,certi,buidl", "--quiet-level=2", "--skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,build/pyinstaller/*,./website/config.toml", ] diff --git a/openbb_terminal/miscellaneous/data_sources_default.json b/openbb_terminal/miscellaneous/data_sources_default.json index 92787536ff6..03b940412d1 100644 --- a/openbb_terminal/miscellaneous/data_sources_default.json +++ b/openbb_terminal/miscellaneous/data_sources_default.json @@ -238,6 +238,8 @@ "metrics": ["FinancialModelingPrep"], "ratios": ["FinancialModelingPrep"], "growth": ["FinancialModelingPrep"], + "revfc": ["SeekingAlpha"], + "epsfc": ["SeekingAlpha"], "warnings": ["MarketWatch"], "dcf": ["StockAnalysis"], "dcfc": ["FinancialModelingPrep"], diff --git a/openbb_terminal/miscellaneous/i18n/en.yml b/openbb_terminal/miscellaneous/i18n/en.yml index 84e218a25a7..9e3d873f8c4 100644 --- a/openbb_terminal/miscellaneous/i18n/en.yml +++ b/openbb_terminal/miscellaneous/i18n/en.yml @@ -354,6 +354,8 @@ en: stocks/fa/metrics: key metrics over time stocks/fa/ratios: in-depth ratios over time stocks/fa/growth: growth of financial statement items and ratios + stocks/fa/epsfc: Earning Estimate by Analysts - EPS + stocks/fa/revfc: Earning Estimate by Analysts - Revenue stocks/fa/dcfc: determine the (historical) discounted cash flow stocks/res/_ticker: Ticker stocks/res/macroaxis: www.macroaxis.com @@ -497,10 +499,8 @@ en: crypto/ov/categories: crypto categories crypto/ov/hold: ethereum, bitcoin holdings overview statistics crypto/ov/hm: crypto heatmap - crypto/ov/global: global crypto market info crypto/ov/info: basic info about all coins available crypto/ov/markets: market related info about all coins available - crypto/ov/exchanges: list all exchanges crypto/ov/exmarkets: all available markets on given exchange crypto/ov/platforms: list blockchain platforms eg. ethereum, solana, kusama, terra crypto/ov/contracts: all smart contracts for given platform diff --git a/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa.openbb b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa.openbb index d44cbb8037f..e584f375124 100644 --- a/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa.openbb +++ b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa.openbb @@ -42,3 +42,6 @@ earnings --source YahooFinance earnings --source AlphaVantage fraud dupont +epsfc +revfc +exit diff --git a/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_epsfc.openbb b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_epsfc.openbb new file mode 100644 index 00000000000..d0ef5358bb5 --- /dev/null +++ b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_epsfc.openbb @@ -0,0 +1,5 @@ +stocks +load aapl +fa +epsfc +exit diff --git a/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_revfc.openbb b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_revfc.openbb new file mode 100644 index 00000000000..e941990c8dc --- /dev/null +++ b/openbb_terminal/miscellaneous/scripts/stocks/test_stocks_fa_revfc.openbb @@ -0,0 +1,5 @@ +stocks +load aapl +fa +revfc +exit diff --git a/openbb_terminal/stocks/fundamental_analysis/fa_controller.py b/openbb_terminal/stocks/fundamental_analysis/fa_controller.py index 17e0144247d..9638c594b87 100644 --- a/openbb_terminal/stocks/fundamental_analysis/fa_controller.py +++ b/openbb_terminal/stocks/fundamental_analysis/fa_controller.py @@ -1,6 +1,5 @@ """Fundamental Analysis Controller.""" __docformat__ = "numpy" - import argparse import logging from datetime import datetime, timedelta @@ -32,6 +31,7 @@ from openbb_terminal.stocks.fundamental_analysis import ( polygon_view, fmp_view, eodhd_view, + seeking_alpha_view, ) # pylint: disable=inconsistent-return-statements,C0302,R0904 @@ -53,6 +53,8 @@ class FundamentalAnalysisController(StockBaseController): "metrics", "ratios", "growth", + "revfc", + "epsfc", "warnings", "data", "income", @@ -107,7 +109,6 @@ class FundamentalAnalysisController(StockBaseController): if session and obbff.USE_PROMPT_TOOLKIT: choices: dict = self.choices_default - self.completer = NestedCompleter.from_nested_dict(choices) def print_help(self): @@ -130,6 +131,8 @@ class FundamentalAnalysisController(StockBaseController): mt.add_cmd("metrics") mt.add_cmd("ratios") mt.add_cmd("growth") + mt.add_cmd("revfc") + mt.add_cmd("epsfc") mt.add_cmd("warnings") mt.add_cmd("dcf") mt.add_cmd("dcfc") @@ -543,6 +546,34 @@ class FundamentalAnalysisController(StockBaseController): self.ticker, start_date=ns_parser.start, export=ns_parser.export ) + @log_start_end(log=logger) + def call_epsfc(self, other_args: List[str]): + """Process eps forecast command.""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="epsfc", + description="""Estimated EPS [Source: Seeking Alpha]""", + ) + ns_parser = self.parse_known_args_and_warn(parser, other_args) + + if ns_parser: + seeking_alpha_view.display_eps_estimates(self.ticker) + + @log_start_end(log=logger) + def call_revfc(self, other_args: List[str]): + """Process revenue forecast command.""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="revfc", + description="""Estimated revenue [Source: Seeking Alpha]""", + ) + ns_parser = self.parse_known_args_and_warn(parser, other_args) + + if ns_parser: + seeking_alpha_view.display_rev_estimates(self.ticker) + @log_start_end(log=logger) def call_splits(self, other_args: List[str]): """Process splits command.""" diff --git a/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_model.py b/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_model.py new file mode 100644 index 00000000000..a686fe034ad --- /dev/null +++ b/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_model.py @@ -0,0 +1,334 @@ +""" Seeking Alpha Model """ +__docformat__ = "numpy" + +import logging +import requests +import pandas as pd + +from openbb_terminal.decorators import log_start_end +from openbb_terminal.helper_funcs import lambda_long_number_format + +logger = logging.getLogger(__name__) + + +@log_start_end(log=logger) +def get_estimates_eps(ticker: str) -> pd.DataFrame: + """Takes the ticker, asks for seekingalphaID and gets eps estimates + + Parameters + ---------- + ticker: str + ticker of company + Returns + ------- + pd.DataFrame + eps estimates for the next 10yrs + """ + + url = "https://seekingalpha.com/api/v3/symbol_data/estimates" + + querystring = { + "estimates_data_items": "eps_normalized_actual,eps_normalized_consensus_low,eps_normalized_consensus_mean," + "eps_normalized_consensus_high,eps_normalized_num_of_estimates", + "period_type": "annual", + "relative_periods": "-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11", + } + + # add ticker_ids for the ticker + seek_id = get_seekingalpha_id(ticker) + querystring["ticker_ids"] = seek_id + + payload = "" + headers = { + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0", + "Accept": "*/*", + "Accept-Language": "de,en-US;q=0.7,en;q=0.3", + "Accept-Encoding": "gzip, deflate, br", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-origin", + "Connection": "keep-alive", + } + + # semi random user agent -- disabled and static user agent because it might be the reason for 403 + # headers["User-Agent"] = get_user_agent() + + response = requests.request( + "GET", url, data=payload, headers=headers, params=querystring + ) + + # init + output = pd.DataFrame( + columns=[ + "fiscalyear", + "consensus_mean", + "change %", + "analysts", + "actual", + "consensus_low", + "consensus_high", + ] + ) + + # if no estimations exist, response is empty "reviews" and "reviews" + # {"revisions":{},"estimates":{}} + try: + seek_object = response.json()["estimates"][str(seek_id)] + + items = len(seek_object["eps_normalized_num_of_estimates"].keys()) + + for i in range(0, items - 3): + # python_dict + eps_estimates = {} + eps_estimates["fiscalyear"] = seek_object[ + "eps_normalized_num_of_estimates" + ][str(i)][0]["period"]["fiscalyear"] + eps_estimates["analysts"] = seek_object["eps_normalized_num_of_estimates"][ + str(i) + ][0]["dataitemvalue"] + try: + eps_estimates["actual"] = seek_object["eps_normalized_actual"][str(i)][ + 0 + ]["dataitemvalue"] + except Exception: + eps_estimates["actual"] = 0 + eps_estimates["consensus_low"] = seek_object[ + "eps_normalized_consensus_low" + ][str(i)][0]["dataitemvalue"] + eps_estimates["consensus_high"] = seek_object[ + "eps_normalized_consensus_high" + ][str(i)][0]["dataitemvalue"] + eps_estimates["consensus_mean"] = seek_object[ + "eps_normalized_consensus_mean" + ][str(i)][0]["dataitemvalue"] + + try: + this = float(eps_estimates["consensus_mean"]) + try: + prev = float( + seek_object["eps_normalized_actual"][str(i - 1)][0][ + "dataitemvalue" + ] + ) + except Exception: + prev = float( + seek_object["eps_normalized_consensus_mean"][str(i - 1)][0][ + "dataitemvalue" + ] + ) + + percent = ((this / prev) - 1) * 100 + except Exception: + percent = 0 + + eps_estimates["change %"] = percent + + # format correction (before return, so calculation still works) + eps_estimates["consensus_mean"] = lambda_long_number_format( + float(eps_estimates["consensus_mean"]) + ) + eps_estimates["consensus_low"] = lambda_long_number_format( + float(eps_estimates["consensus_low"]) + ) + eps_estimates["consensus_high"] = lambda_long_number_format( + float(eps_estimates["consensus_high"]) + ) + eps_estimates["actual"] = lambda_long_number_format( + float(eps_estimates["actual"]) + ) + + # df append replacement + new_row = pd.DataFrame(eps_estimates, index=[0]) + output = pd.concat([output, new_row]) + except Exception: + return pd.DataFrame() + + return output + + +@log_start_end(log=logger) +def get_estimates_rev(ticker: str) -> pd.DataFrame: + """Takes the ticker, asks for seekingalphaID and gets rev estimates + + Parameters + ---------- + ticker: str + ticker of company + Returns + ------- + pd.DataFrame + rev estimates for the next 10yrs + """ + + url = "https://seekingalpha.com/api/v3/symbol_data/estimates" + + querystring = { + "estimates_data_items": "revenue_actual,revenue_consensus_low,revenue_consensus_mean," + "revenue_consensus_high,revenue_num_of_estimates", + "period_type": "annual", + "relative_periods": "-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11", + } + + # add ticker_ids for the ticker + seek_id = get_seekingalpha_id(ticker) + querystring["ticker_ids"] = seek_id + + payload = "" + headers = { + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0", + "Accept": "*/*", + "Accept-Language": "de,en-US;q=0.7,en;q=0.3", + "Accept-Encoding": "gzip, deflate, br", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-origin", + "Connection": "keep-alive", + "TE": "trailers", + } + + # semi random user agent -- disabled and static user agent because it might be the reason for 403 + # headers["User-Agent"] = get_user_agent() + + response = requests.request( + "GET", url, data=payload, headers=headers, params=querystring + ) + + # init + # pd.empty should deliver true if no data-rows are added + output = pd.DataFrame( + columns=[ + "fiscalyear", + "consensus_mean", + "change %", + "analysts", + "actual", + "consensus_low", + "consensus_high", + ] + ) + + # if no estimations exist, response is empty "reviews" and "reviews" + # {"revisions":{},"estimates":{}} + try: + seek_object = response.json()["estimates"][seek_id] + + items = len(seek_object["revenue_num_of_estimates"].keys()) + + for i in range(0, items - 3): + # python_dict + revenue_estimates = {} + revenue_estimates["fiscalyear"] = seek_object["revenue_num_of_estimates"][ + str(i) + ][0]["period"]["fiscalyear"] + revenue_estimates["consensus_mean"] = seek_object["revenue_consensus_mean"][ + str(i) + ][0]["dataitemvalue"] + + revenue_estimates["analysts"] = seek_object["revenue_num_of_estimates"][ + str(i) + ][0]["dataitemvalue"] + if i < 1: + revenue_estimates["actual"] = seek_object["revenue_actual"][str(i)][0][ + "dataitemvalue" + ] + else: + revenue_estimates["actual"] = 0 + revenue_estimates["consensus_low"] = seek_object["revenue_consensus_low"][ + str(i) + ][0]["dataitemvalue"] + revenue_estimates["consensus_high"] = seek_object["revenue_consensus_high"][ + str(i) + ][0]["dataitemvalue"] + + try: + this = float(revenue_estimates["consensus_mean"]) + # if actual revenue is available, take it for the calc + try: + prev = float( + seek_object["revenue_actual"][str(i - 1)][0]["dataitemvalue"] + ) + except Exception: + prev = float( + seek_object["revenue_consensus_mean"][str(i - 1)][0][ + "dataitemvalue" + ] + ) + + percent = ((this / prev) - 1) * 100 + except Exception: + percent = float(0) + + revenue_estimates["change %"] = percent + + # format correction (before return, so calculation still works) + revenue_estimates["consensus_mean"] = lambda_long_number_format( + float(revenue_estimates["consensus_mean"]) + ) + revenue_estimates["consensus_low"] = lambda_long_number_format( + float(revenue_estimates["consensus_low"]) + ) + revenue_estimates["consensus_high"] = lambda_long_number_format( + float(revenue_estimates["consensus_high"]) + ) + revenue_estimates["actual"] = lambda_long_number_format( + float(revenue_estimates["actual"]) + ) + + # df append replacement + new_row = pd.DataFrame(revenue_estimates, index=[0]) + output = pd.concat([output, new_row]) + except Exception: + return pd.DataFrame() + + return output + + +@log_start_end(log=logger) +def get_seekingalpha_id(ticker: str) -> str: + """Takes the ticker, asks for seekingalphaID and returns it + + Parameters + ---------- + ticker: str + ticker of company + Returns + ------- + str: + seekingalphaID - to be used for further API calls + """ + + url = "https://seekingalpha.com/api/v3/searches" + + querystring = { + "filter[type]": "symbols", + "filter[list]": "all", + "page[size]": "1", + } + + querystring["filter[query]"] = ticker + payload = "" + + headers = { + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0", + "Accept": "*/*", + "Accept-Language": "de,en-US;q=0.7,en;q=0.3", + "Accept-Encoding": "gzip, deflate, br", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-origin", + "Referer": "https://seekingalpha.com/", + "Connection": "keep-alive", + # "TE": "trailers", + } + + response = requests.request( + "GET", url, data=payload, headers=headers, params=querystring + ) + + try: + seekingalphaID = str(response.json()["symbols"][0]["id"]) + except Exception: + # for some reason no mapping possible + seekingalphaID = "0" + + return seekingalphaID diff --git a/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_view.py b/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_view.py new file mode 100644 index 00000000000..2c2ba5dc075 --- /dev/null +++ b/openbb_terminal/stocks/fundamental_analysis/seeking_alpha_view.py @@ -0,0 +1,61 @@ +""" Seeking Alpha View """ +__docformat__ = "numpy" + +import logging + + +from openbb_terminal.decorators import log_start_end +from openbb_terminal.rich_config import console +from openbb_terminal.stocks.fundamental_analysis import seeking_alpha_model +from openbb_terminal.helper_funcs import ( + print_rich_table, +) + +logger = logging.getLogger(__name__) + + +@log_start_end(log=logger) +def display_eps_estimates(symbol: str): + """Display eps Estimates + + Parameters + ---------- + symbol: str + ticker of company + """ + eps_estimates = seeking_alpha_model.get_estimates_eps(symbol) + + if not eps_estimates.empty: + print_rich_table( + eps_estimates, + headers=list(eps_estimates.columns), + show_index=False, + title=f"{symbol.upper()} EPS History and Estimations", + ) + else: + console.print("No data found.") + return + + +@log_start_end(log=logger) +def display_rev_estimates(symbol: str): + """Display rev Estimates + + Parameters + ---------- + symbol: str + ticker of company + """ + + rev_estimates = seeking_alpha_model.get_estimates_rev(symbol) + + if not rev_estimates.empty: + print_rich_table( + rev_estimates, + headers=list(rev_estimates.columns), + show_index=False, + title=f"{symbol.upper()} Revenue History and Estimations", + ) + else: + console.print("No data found.") + return diff --git a/tests/openbb_terminal/cryptocurrency/overview/txt/test_overview_controller/test_print_help.txt b/tests/openbb_terminal/cryptocurrency/overview/txt/test_overview_controller/test_print_help.txt index 45e4effe298..772a8ce908a 100644 --- a/tests/openbb_terminal/cryptocurrency/overview/txt/test_overview_controller/test_print_help.txt +++ b/tests/openbb_terminal/cryptocurrency/overview/txt/test_overview_controller/test_print_help.txt @@ -1,7 +1,7 @@ - global global crypto market info [CoinGecko, CoinPaprika] + global crypto/ov/global [CoinGecko, CoinPaprika] defi global DeFi market info [CoinGecko] stables stablecoins [CoinGecko] - exchanges list all exchanges [CoinGecko, CoinPaprika] + exchanges crypto/ov/exchanges [CoinGecko, CoinPaprika] exrates coin exchange rates [CoinGecko] indexes crypto indexes [CoinGecko] derivatives crypto derivatives [CoinGecko] diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_eps.yaml b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_eps.yaml new file mode 100644 index 00000000000..a0026a490ed --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_eps.yaml @@ -0,0 +1,185 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Referer: + - https://seekingalpha.com/ + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + method: GET + uri: https://seekingalpha.com/api/v3/searches?filter%5Btype%5D=symbols&filter%5Blist%5D=all&page%5Bsize%5D=1&filter%5Bquery%5D=JNJ + response: + body: + string: !!binary | + H4sIAAAAAAAAA6tWKq7MTcrPKVayiq5WykxRsjI0NDbVUcpLzE1VslLy8vNS0lEqzilNB3Ky8rKA + nOT8vJLUvBKQZH5GXnF+noKaApQFlE2tSM5IzEsH6fWLDHYFqS8tKkrNS64EioQGuwAFMovjC0sT + 80riixJLUkEW1sbWAgDS1n6yhwAAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '85' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=3600, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '136' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:12:41 GMT + ETag: + - W/"cc200d9e38b2d26b2fffbef87ce15226" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 56yPeC8_nt_3HfZ8 + X-Runtime: + - '0.006611' + X-Served-By: + - cache-bfi-krnt7300038-BFI, cache-vie6365-VIE + X-Timer: + - S1668366761.419626,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=9737974274275; expires=Sat, 13 Nov 2027 19:12:41 GMT; path=/; + - machine_cookie_ts=1668366761; expires=Sat, 13 Nov 2027 19:12:41 GMT; path=/; + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + method: GET + uri: https://seekingalpha.com/api/v3/symbol_data/estimates?estimates_data_items=eps_normalized_actual%2Ceps_normalized_consensus_low%2Ceps_normalized_consensus_mean%2Ceps_normalized_consensus_high%2Ceps_normalized_num_of_estimates&period_type=annual&relative_periods=-3%2C-2%2C-1%2C0%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11&ticker_ids=1135 + response: + body: + string: !!binary | + H4sIAAAAAAAAA+2a4W6bMBCA34XfwfLZYLCfg3/TFKHEWZEI6QLJ1FV5951Lu7WNkxrpVtUoUqUW + dCrcx3H3xfFjsrfHpm92XZ+Yx9Misf3QbOvBusMEQObut73vl91uv63b5rddL7vDdrnbLN+EqsR8 + w8DNxq6G5mjX+C8SkwguRAqQcqhAmkwYmTHOecozw3mySDCsbga7PdbtwcUDc2fv7b7Zrd2Fx7+G + h3vb4HFSd92hbjFi0/Sruv15qPeD3ScmeznzYGs8xKsWiwQDbLeu96+jXs69jhuvgaH/7rlIQaQS + Ks7xNvFnvOd8vOd6fay71XOG3aFtT6fvi6T4WvmXgfljnCf/cnr+WCcfPH9l8sJkxdXnr6ievwrM + H+M8+avp+cvr+YuKa8MLA/pq/iCoAOArEfQCYJwHQDYdQHYdADaATy2APDB/jPPkn0/PXwTkD7kR + 8noBYH3QdEAZCADjPADkdADwxQCIQAAY5wGAY2vqCOCXAXBIRVYBNwDvx8nZCMQOSVMBEAgA4zwA + IBjAOOVdinmF+Qk3J19NzKfxmF6sDicHqeAVL41EPs/z4XnWnsEpqeDwQDgY54HDJ8EZU1QODiqQ + B87F3oGmhHCwd2qD/vRORP4bHNBhcFzcORzQk+CMKQoHB5+/B86lyYrXQThQVjhW0dIEuqMzy0uV + Q9VYIVCtXJwHTrha4Ws1piie4GTncJyuvzXzFXq87fpDv2x3v5xAE2k5ZyXQNKVYxRyYLGgIBNaP + 8NaPCK+fvx9NaNQcOJOahkCkcq6ZzmgARCrnWAIgaQhEqueaZUTvQKx6jmYnaEogUj/XTBGVwAz9 + vGAqp6mOGfp5yRTNqzNHPy9xtJQ5jWRGouh3zY+7m6MTLp7fHB2Xj0ua/hupowMwmh4rYnV0YErR + lECkjo4lQDNGRLyOTgQgWkUviZrADBUdV9CJ+sMsFb2g+fwyU0WnkYtI/Hxr6+7m5zc/dwSI1tCB + 5SAl0RpqrIrOWaFVTjSE4tV0IHKUWDUdv09SqiAy1XhVnWdZSTNWRbS6XpS6pPEuMUNjL5guJNX3 + 77OUdqU00LxDM/V2RbR54Uube70a3O5w3PXywU487za1883omtHUVFQ9ybtL7ZwNriIQWWxMDcm7 + S80HR9FUTkzdyL9LzQeHqlUHbqT6jI14p9PpD2wJzVtKMwAA + headers: + Accept-Ranges: + - bytes + Age: + - '0' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=60, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '891' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:12:42 GMT + ETag: + - W/"fa3611a593042edf6a005a94c3df2e84" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, MISS + X-Cache-Hits: + - 0, 0 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - DHRGVFfYyLSA9Aph + X-Runtime: + - '0.563933' + X-Served-By: + - cache-bfi-krnt7300119-BFI, cache-vie6330-VIE + X-Timer: + - S1668366761.491722,VS0,VE793 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=5477104746998; expires=Sat, 13 Nov 2027 19:12:42 GMT; path=/; + - machine_cookie_ts=1668366762; expires=Sat, 13 Nov 2027 19:12:42 GMT; path=/; + status: + code: 200 + message: OK +version: 1 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_rev.yaml b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_rev.yaml new file mode 100644 index 00000000000..ea72a8a4201 --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_check_get_estimates_rev.yaml @@ -0,0 +1,185 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Referer: + - https://seekingalpha.com/ + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + method: GET + uri: https://seekingalpha.com/api/v3/searches?filter%5Btype%5D=symbols&filter%5Blist%5D=all&page%5Bsize%5D=1&filter%5Bquery%5D=JNJ + response: + body: + string: !!binary | + H4sIAAAAAAAAA6tWKq7MTcrPKVayiq5WykxRsjI0NDbVUcpLzE1VslLy8vNS0lEqzilNB3Ky8rKA + nOT8vJLUvBKQZH5GXnF+noKaApQFlE2tSM5IzEsH6fWLDHYFqS8tKkrNS64EioQGuwAFMovjC0sT + 80riixJLUkEW1sbWAgDS1n6yhwAAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '465' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=3600, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '136' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:19:01 GMT + ETag: + - W/"cc200d9e38b2d26b2fffbef87ce15226" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 56yPeC8_nt_3HfZ8 + X-Runtime: + - '0.006611' + X-Served-By: + - cache-bfi-krnt7300038-BFI, cache-vie6331-VIE + X-Timer: + - S1668367141.204535,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=9924157037916; expires=Sat, 13 Nov 2027 19:19:01 GMT; path=/; + - machine_cookie_ts=1668367141; expires=Sat, 13 Nov 2027 19:19:01 GMT; path=/; + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + method: GET + uri: https://seekingalpha.com/api/v3/symbol_data/estimates?estimates_data_items=eps_normalized_actual%2Ceps_normalized_consensus_low%2Ceps_normalized_consensus_mean%2Ceps_normalized_consensus_high%2Ceps_normalized_num_of_estimates&period_type=annual&relative_periods=-3%2C-2%2C-1%2C0%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11&ticker_ids=1135 + response: + body: + string: !!binary | + H4sIAAAAAAAAA+2a4W6bMBCA34XfwfLZYLCfg3/TFKHEWZEI6QLJ1FV5951Lu7WNkxrpVtUoUqUW + dCrcx3H3xfFjsrfHpm92XZ+Yx9Misf3QbOvBusMEQObut73vl91uv63b5rddL7vDdrnbLN+EqsR8 + w8DNxq6G5mjX+C8SkwguRAqQcqhAmkwYmTHOecozw3mySDCsbga7PdbtwcUDc2fv7b7Zrd2Fx7+G + h3vb4HFSd92hbjFi0/Sruv15qPeD3ScmeznzYGs8xKsWiwQDbLeu96+jXs69jhuvgaH/7rlIQaQS + Ks7xNvFnvOd8vOd6fay71XOG3aFtT6fvi6T4WvmXgfljnCf/cnr+WCcfPH9l8sJkxdXnr6ievwrM + H+M8+avp+cvr+YuKa8MLA/pq/iCoAOArEfQCYJwHQDYdQHYdADaATy2APDB/jPPkn0/PXwTkD7kR + 8noBYH3QdEAZCADjPADkdADwxQCIQAAY5wGAY2vqCOCXAXBIRVYBNwDvx8nZCMQOSVMBEAgA4zwA + IBjAOOVdinmF+Qk3J19NzKfxmF6sDicHqeAVL41EPs/z4XnWnsEpqeDwQDgY54HDJ8EZU1QODiqQ + B87F3oGmhHCwd2qD/vRORP4bHNBhcFzcORzQk+CMKQoHB5+/B86lyYrXQThQVjhW0dIEuqMzy0uV + Q9VYIVCtXJwHTrha4Ws1piie4GTncJyuvzXzFXq87fpDv2x3v5xAE2k5ZyXQNKVYxRyYLGgIBNaP + 8NaPCK+fvx9NaNQcOJOahkCkcq6ZzmgARCrnWAIgaQhEqueaZUTvQKx6jmYnaEogUj/XTBGVwAz9 + vGAqp6mOGfp5yRTNqzNHPy9xtJQ5jWRGouh3zY+7m6MTLp7fHB2Xj0ua/hupowMwmh4rYnV0YErR + lECkjo4lQDNGRLyOTgQgWkUviZrADBUdV9CJ+sMsFb2g+fwyU0WnkYtI/Hxr6+7m5zc/dwSI1tCB + 5SAl0RpqrIrOWaFVTjSE4tV0IHKUWDUdv09SqiAy1XhVnWdZSTNWRbS6XpS6pPEuMUNjL5guJNX3 + 77OUdqU00LxDM/V2RbR54Uube70a3O5w3PXywU487za1883omtHUVFQ9ybtL7ZwNriIQWWxMDcm7 + S80HR9FUTkzdyL9LzQeHqlUHbqT6jI14p9PpD2wJzVtKMwAA + headers: + Accept-Ranges: + - bytes + Age: + - '379' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=60, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '891' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:19:01 GMT + ETag: + - W/"fa3611a593042edf6a005a94c3df2e84" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - DHRGVFfYyLSA9Aph + X-Runtime: + - '0.563933' + X-Served-By: + - cache-bfi-krnt7300119-BFI, cache-vie6321-VIE + X-Timer: + - S1668367141.269184,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=1882774375016; expires=Sat, 13 Nov 2027 19:19:01 GMT; path=/; + - machine_cookie_ts=1668367141; expires=Sat, 13 Nov 2027 19:19:01 GMT; path=/; + status: + code: 200 + message: OK +version: 1 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_get_seekingalpha_id.yaml b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_get_seekingalpha_id.yaml new file mode 100644 index 00000000000..20f3ab410fd --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_model/test_get_seekingalpha_id.yaml @@ -0,0 +1,89 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Referer: + - https://seekingalpha.com/ + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + method: GET + uri: https://seekingalpha.com/api/v3/searches?filter%5Btype%5D=symbols&filter%5Blist%5D=all&page%5Bsize%5D=1&filter%5Bquery%5D=JNJ + response: + body: + string: !!binary | + H4sIAAAAAAAAA6tWKq7MTcrPKVayiq5WykxRsjI0NDbVUcpLzE1VslLy8vNS0lEqzilNB3Ky8rKA + nOT8vJLUvBKQZH5GXnF+noKaApQFlE2tSM5IzEsH6fWLDHYFqS8tKkrNS64EioQGuwAFMovjC0sT + 80riixJLUkEW1sbWAgDS1n6yhwAAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '0' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=3600, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '136' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:11:16 GMT + ETag: + - W/"cc200d9e38b2d26b2fffbef87ce15226" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 56yPeC8_nt_3HfZ8 + X-Runtime: + - '0.006611' + X-Served-By: + - cache-bfi-krnt7300038-BFI, cache-vie6371-VIE + X-Timer: + - S1668366676.346920,VS0,VE228 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=2621104791757; expires=Sat, 13 Nov 2027 19:11:16 GMT; path=/; + - machine_cookie_ts=1668366676; expires=Sat, 13 Nov 2027 19:11:16 GMT; path=/; + status: + code: 200 + message: OK +version: 1 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_eps_estimation.yaml b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_eps_estimation.yaml new file mode 100644 index 00000000000..39cc55f7187 --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_eps_estimation.yaml @@ -0,0 +1,189 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Referer: + - https://seekingalpha.com/ + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + User-Agent: + - Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0 + method: GET + uri: https://seekingalpha.com/api/v3/searches?filter%5Btype%5D=symbols&filter%5Blist%5D=all&page%5Bsize%5D=1&filter%5Bquery%5D=JNJ + response: + body: + string: !!binary | + H4sIAAAAAAAAA6tWKq7MTcrPKVayiq5WykxRsjI0NDbVUcpLzE1VslLy8vNS0lEqzilNB3Ky8rKA + nOT8vJLUvBKQZH5GXnF+noKaApQFlE2tSM5IzEsH6fWLDHYFqS8tKkrNS64EioQGuwAFMovjC0sT + 80riixJLUkEW1sbWAgDS1n6yhwAAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '2042' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=3600, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '136' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:45:18 GMT + ETag: + - W/"cc200d9e38b2d26b2fffbef87ce15226" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 56yPeC8_nt_3HfZ8 + X-Runtime: + - '0.006611' + X-Served-By: + - cache-bfi-krnt7300038-BFI, cache-vie6328-VIE + X-Timer: + - S1668368719.580650,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=9030003503847; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + - machine_cookie_ts=1668368718; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + User-Agent: + - Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0 + method: GET + uri: https://seekingalpha.com/api/v3/symbol_data/estimates?estimates_data_items=eps_normalized_actual%2Ceps_normalized_consensus_low%2Ceps_normalized_consensus_mean%2Ceps_normalized_consensus_high%2Ceps_normalized_num_of_estimates&period_type=annual&relative_periods=-3%2C-2%2C-1%2C0%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11&ticker_ids=1135 + response: + body: + string: !!binary | + H4sIAAAAAAAAA+2a4W6bMBCA34XfwfLZYLCfg3/TFKHEWZEI6QLJ1FV5951Lu7WNkxrpVtUoUqUW + dCrcx3H3xfFjsrfHpm92XZ+Yx9Misf3QbOvBusMEQObut73vl91uv63b5rddL7vDdrnbLN+EqsR8 + w8DNxq6G5mjX+C8SkwguRAqQcqhAmkwYmTHOecozw3mySDCsbga7PdbtwcUDc2fv7b7Zrd2Fx7+G + h3vb4HFSd92hbjFi0/Sruv15qPeD3ScmeznzYGs8xKsWiwQDbLeu96+jXs69jhuvgaH/7rlIQaQS + Ks7xNvFnvOd8vOd6fay71XOG3aFtT6fvi6T4WvmXgfljnCf/cnr+WCcfPH9l8sJkxdXnr6ievwrM + H+M8+avp+cvr+YuKa8MLA/pq/iCoAOArEfQCYJwHQDYdQHYdADaATy2APDB/jPPkn0/PXwTkD7kR + 8noBYH3QdEAZCADjPADkdADwxQCIQAAY5wGAY2vqCOCXAXBIRVYBNwDvx8nZCMQOSVMBEAgA4zwA + IBjAOOVdinmF+Qk3J19NzKfxmF6sDicHqeAVL41EPs/z4XnWnsEpqeDwQDgY54HDJ8EZU1QODiqQ + B87F3oGmhHCwd2qD/vRORP4bHNBhcFzcORzQk+CMKQoHB5+/B86lyYrXQThQVjhW0dIEuqMzy0uV + Q9VYIVCtXJwHTrha4Ws1piie4GTncJyuvzXzFXq87fpDv2x3v5xAE2k5ZyXQNKVYxRyYLGgIBNaP + 8NaPCK+fvx9NaNQcOJOahkCkcq6ZzmgARCrnWAIgaQhEqueaZUTvQKx6jmYnaEogUj/XTBGVwAz9 + vGAqp6mOGfp5yRTNqzNHPy9xtJQ5jWRGouh3zY+7m6MTLp7fHB2Xj0ua/hupowMwmh4rYnV0YErR + lECkjo4lQDNGRLyOTgQgWkUviZrADBUdV9CJ+sMsFb2g+fwyU0WnkYtI/Hxr6+7m5zc/dwSI1tCB + 5SAl0RpqrIrOWaFVTjSE4tV0IHKUWDUdv09SqiAy1XhVnWdZSTNWRbS6XpS6pPEuMUNjL5guJNX3 + 77OUdqU00LxDM/V2RbR54Uube70a3O5w3PXywU487za1883omtHUVFQ9ybtL7ZwNriIQWWxMDcm7 + S80HR9FUTkzdyL9LzQeHqlUHbqT6jI14p9PpD2wJzVtKMwAA + headers: + Accept-Ranges: + - bytes + Age: + - '1956' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=60, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '891' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:45:18 GMT + ETag: + - W/"fa3611a593042edf6a005a94c3df2e84" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - DHRGVFfYyLSA9Aph + X-Runtime: + - '0.563933' + X-Served-By: + - cache-bfi-krnt7300119-BFI, cache-vie6383-VIE + X-Timer: + - S1668368719.647015,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=2152441849684; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + - machine_cookie_ts=1668368718; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + status: + code: 200 + message: OK +version: 1 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_rev_estimation.yaml b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_rev_estimation.yaml new file mode 100644 index 00000000000..22176afd7e7 --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/cassettes/test_seeking_alpha_view/test_display_rev_estimation.yaml @@ -0,0 +1,192 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Referer: + - https://seekingalpha.com/ + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + User-Agent: + - Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0 + method: GET + uri: https://seekingalpha.com/api/v3/searches?filter%5Btype%5D=symbols&filter%5Blist%5D=all&page%5Bsize%5D=1&filter%5Bquery%5D=JNJ + response: + body: + string: !!binary | + H4sIAAAAAAAAA6tWKq7MTcrPKVayiq5WykxRsjI0NDbVUcpLzE1VslLy8vNS0lEqzilNB3Ky8rKA + nOT8vJLUvBKQZH5GXnF+noKaApQFlE2tSM5IzEsH6fWLDHYFqS8tKkrNS64EioQGuwAFMovjC0sT + 80riixJLUkEW1sbWAgDS1n6yhwAAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '2042' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=3600, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '136' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:45:18 GMT + ETag: + - W/"cc200d9e38b2d26b2fffbef87ce15226" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 56yPeC8_nt_3HfZ8 + X-Runtime: + - '0.006611' + X-Served-By: + - cache-bfi-krnt7300038-BFI, cache-vie6369-VIE + X-Timer: + - S1668368719.768704,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=2620385759373; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + - machine_cookie_ts=1668368718; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Accept-Language: + - de,en-US;q=0.7,en;q=0.3 + Connection: + - keep-alive + Sec-Fetch-Dest: + - empty + Sec-Fetch-Mode: + - cors + Sec-Fetch-Site: + - same-origin + TE: + - trailers + User-Agent: + - Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0 + method: GET + uri: https://seekingalpha.com/api/v3/symbol_data/estimates?estimates_data_items=revenue_actual%2Crevenue_consensus_low%2Crevenue_consensus_mean%2Crevenue_consensus_high%2Crevenue_num_of_estimates&period_type=annual&relative_periods=-3%2C-2%2C-1%2C0%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11&ticker_ids=1135 + response: + body: + string: !!binary | + H4sIAAAAAAAAA+2abW/aMBCA/0s+k+rOL7Gd38G3aUIRmDUShA4CU1Xx33duoGuHWRPpNOGUCqmF + Hkruydn3JPZLtvWHeldvml1Wvhwnmd+19bpqfXibIUodflOMb/Z+1uzXs81y9iGmyMpvL5lfLv28 + rQ9+Qd/NykyAEDliDjhFWSpRSvUAADmoEiCbZBRW1a1fH6rVPsTjQ/j0yW/rzSIcsfurfX7yNb3P + qqbZVyuKWNa7ebX6ua+2rd9mpTp/8uwrektHNZOMAnyzqLbvo86fvY/rjkGhf87Z5ChyiVMAOk16 + deesu3OuFoeqmZ8ybPar1fH4fZKZ28rf9syf4iL52+H5U4F8cv2LUptSmX9e/4Lr+hc986e4SP7F + 8PzVbeWve+ZPcZH89fD85b/zl1N0JZpSn8bStfGvuQqApoReEwDFRQCo4QAEDwDHBUD2BEBxEQBy + OAC8MQCiJwCKiwCgtjW0BcB1AIC5UFOEEvHvdnLRAi1XBWBPABQXAYC9AXRdPqSop5SfCH3yXcd8 + bY/51eoIcpALmIItJfE59YdTr72AQ//mEQToCYfiInBgEJwuxSLAIQWKwLk6d5ApERySJ5o85aeV + wwUHXT84Ie4SDrpBcLoURYBD1z8C51pnoeMQHLTB0iSWWn6wtIvK4eos2FOtQlwETn+1omHVpShe + 4ahLOOTpZyWfk7n7ZrffzVabX8GcmXwcNEoS9vDDNfJSVXNwEF6cKHqWkoiWkuhfSm93KTyWjoDa + CF4UiQq7c0IjL4lE1d0ZsIaXRKIO7zQ6UyjOiSJRmXdSWewmTa7ukajVO+mQeXSMUO8tnuZSPtsY + oedblIZXRMYo/FRL+nUOZqulWzf/x/rH4139w7oD91P5u/q/LdCAKWzBOqxEouqPoKQ63Rxz2U2i + 7o8gJDDfBqUq/864QltHUwZXUaQq/9pSWbgwWXCRSFX+NQg0yElijPIvwOhCaMZ6GaP8y/PzWK5R + NU75L76Y/K991dzl/y7/8d1JXM/9lTUmTNB8LT1Z+RfSAi+KROXf0RoIWV6oCy7PS9X9jdaIoqAW + zUUiWfcHaYUwNEK4SKTq/vSIQClFY4SNxBjdH2k9WRutFBulMbq/QCes1Wi5KI3T/RXdalu0fJR6 + 7tP4v1t+qnkbNsPTXp9PNh5Gd+Vd7r138ux2XNUlUpqpotvzLilZoS3vspJIaaaK7tOLUQL9dZco + 4xv2IpRQ0/YIztupW1qiPB6PvwFwj6HQVzQAAA== + headers: + Accept-Ranges: + - bytes + Age: + - '45' + Allow: + - GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS + Cache-Control: + - max-age=60, public + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '940' + Content-Security-Policy: + - 'default-src https: wss: data: blob: ''unsafe-inline'' ''unsafe-eval''; report-uri + https://seekingalpha.com/report/csp' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sun, 13 Nov 2022 19:45:18 GMT + ETag: + - W/"cf0af100271bfcd8c54302c681602ea9" + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + Vary: + - User-Agent, Accept-Encoding + X-Cache: + - MISS, HIT + X-Cache-Hits: + - 0, 1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - WD7Kw0ltfAdqpIZG + X-Runtime: + - '0.625983' + X-Served-By: + - cache-bfi-kbfi7400089-BFI, cache-vie6380-VIE + X-Timer: + - S1668368719.841743,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + set-cookie: + - machine_cookie=5570966595206; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + - machine_cookie_ts=1668368718; expires=Sat, 13 Nov 2027 19:45:18 GMT; path=/; + status: + code: 200 + message: OK +version: 1 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_eps.csv b/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_eps.csv new file mode 100644 index 00000000000..04e1a6de8cb --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_eps.csv @@ -0,0 +1,9 @@ +,fiscalyear,consensus_mean,change %,analysts,actual,consensus_low,consensus_high +0,2021,9.790,21.915940224159414,17.0,9.800,9.690,9.820 +0,2022,10.045,2.4987755102040765,19.0,0,10.020,10.100 +0,2023,10.367,3.2039208034341904,19.0,0,9.490,11.100 +0,2024,10.797,4.14644569009841,12.0,0,9.940,11.200 +0,2025,11.120,2.9957690227257583,6.0,0,10.130,11.660 +0,2026,11.513,3.537140287769791,6.0,0,10.390,12.080 +0,2027,10.810,-6.108832110258278,1.0,0,10.810,10.810 +0,2028,11.370,5.180388529139668,1.0,0,11.370,11.370 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_rev.csv b/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_rev.csv new file mode 100644 index 00000000000..04e1a6de8cb --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/csv/test_seeking_alpha_model/test_check_get_estimates_rev.csv @@ -0,0 +1,9 @@ +,fiscalyear,consensus_mean,change %,analysts,actual,consensus_low,consensus_high +0,2021,9.790,21.915940224159414,17.0,9.800,9.690,9.820 +0,2022,10.045,2.4987755102040765,19.0,0,10.020,10.100 +0,2023,10.367,3.2039208034341904,19.0,0,9.490,11.100 +0,2024,10.797,4.14644569009841,12.0,0,9.940,11.200 +0,2025,11.120,2.9957690227257583,6.0,0,10.130,11.660 +0,2026,11.513,3.537140287769791,6.0,0,10.390,12.080 +0,2027,10.810,-6.108832110258278,1.0,0,10.810,10.810 +0,2028,11.370,5.180388529139668,1.0,0,11.370,11.370 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py b/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py index 961b2882ac9..b97fdc3cadf 100644 --- a/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py +++ b/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py @@ -270,6 +270,18 @@ def test_call_func_expect_queue(expected_queue, queue, func): [], {"TSLA"}, ), + ( + "call_epsfc", + "seeking_alpha_view.display_eps_estimates", + [], + {"TSLA"}, + ), + ( + "call_revfc", + "seeking_alpha_view.display_rev_estimates", + [], + {"TSLA"}, + ), ( "call_cal", "yahoo_finance_view.display_calendar_earnings", diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_model.py b/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_model.py new file mode 100644 index 00000000000..36c4bb1c54c --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_model.py @@ -0,0 +1,32 @@ +# IMPORTATION THIRDPARTY +import pytest + +# IMPORTATION INTERNAL +from openbb_terminal.stocks.fundamental_analysis import seeking_alpha_model + + +@pytest.fixture(scope="module") +# might not be necessary +def vcr_config(): + return { + "filter_headers": [("User-Agent", None)], + } + + +@pytest.mark.vcr +def test_get_seekingalpha_id(recorder): + seeking_id = seeking_alpha_model.get_seekingalpha_id(ticker="JNJ") + + recorder.capture(seeking_id) + + +@pytest.mark.vcr +def test_check_get_estimates_eps(recorder): + df = seeking_alpha_model.get_estimates_eps(ticker="JNJ") + recorder.capture(df) + + +@pytest.mark.vcr +def test_check_get_estimates_rev(recorder): + df = seeking_alpha_model.get_estimates_eps(ticker="JNJ") + recorder.capture(df) diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_view.py b/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_view.py new file mode 100644 index 00000000000..6d408e67c02 --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/test_seeking_alpha_view.py @@ -0,0 +1,18 @@ +# IMPORTATION STANDARD + +# IMPORTATION THIRDPARTY +import pytest + +# IMPORTATION INTERNAL +from openbb_terminal.stocks.fundamental_analysis import seeking_alpha_view + + +@pytest.mark.vcr +# @pytest.mark.record_stdout # deactivated, because assertion doesn't make sense if data changes +def test_display_eps_estimation(): + seeking_alpha_view.display_eps_estimates(symbol="JNJ") + + +@pytest.mark.vcr +def test_display_rev_estimation(): + seeking_alpha_view.display_rev_estimates(symbol="JNJ") diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_fa_controller/test_print_help.txt b/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_fa_controller/test_print_help.txt index 64320b6c9d2..ca66d384329 100644 --- a/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_fa_controller/test_print_help.txt +++ b/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_fa_controller/test_print_help.txt @@ -15,6 +15,8 @@ Ticker: TSLA metrics key metrics over time [FinancialModelingPrep] ratios in-depth ratios over time [FinancialModelingPrep] growth growth of financial statement items and ratios [FinancialModelingPrep] + revfc Earning Estimate by Analysts - Revenue [SeekingAlpha] + epsfc Earning Estimate by Analysts - EPS [SeekingAlpha] warnings company warnings according to Sean Seah book [MarketWatch] dcf advanced Excel customizable discounted cash flow [StockAnalysis] dcfc determine the (historical) discounted cash flow [FinancialModelingPrep] diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_model/test_get_seekingalpha_id.txt b/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_model/test_get_seekingalpha_id.txt new file mode 100644 index 00000000000..163dda977a2 --- /dev/null +++ b/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_model/test_get_seekingalpha_id.txt @@ -0,0 +1 @@ +1135 \ No newline at end of file diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_view/test_display_eps_estimation.txt b/tests/openbb_terminal/stocks/fundamental_analysis/txt/test_seeking_alpha_view/test_display_eps_estimation.txt new file mode 100644 index 00000000000..e69de29bb2d