diff --git a/gamestonk_terminal/stocks/dark_pool_shorts/dps_controller.py b/gamestonk_terminal/stocks/dark_pool_shorts/dps_controller.py index 779e5870252..cd007570bc0 100644 --- a/gamestonk_terminal/stocks/dark_pool_shorts/dps_controller.py +++ b/gamestonk_terminal/stocks/dark_pool_shorts/dps_controller.py @@ -16,9 +16,11 @@ from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, check_positive, valid_date, + check_int_range, ) from gamestonk_terminal.stocks.stocks_helper import load from gamestonk_terminal.stocks.dark_pool_shorts import ( + yahoofinance_view, stockgrid_view, shortinterest_view, quandl_view, @@ -41,6 +43,7 @@ class DarkPoolShortsController: ] CHOICES_COMMANDS = [ + "shorted", "hsi", "prom", "pos", @@ -80,7 +83,9 @@ Dark Pool Shorts: quit quit to abandon program load load a specific stock ticker for analysis -shortinterest.com +Yahoo Finance: + shorted show most shorted stocks +shortinterest.com: hsi show top high short interest stocks of over 20% ratio FINRA: prom promising tickers based on dark pool shares regression @@ -149,6 +154,48 @@ Quandl/Stockgrid: other_args, self.ticker, self.start, "1440min", self.stock ) + def call_shorted(self, other_args: List[str]): + """Process shorted command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="shorted", + description="Print up to 25 top ticker most shorted. [Source: Yahoo Finance]", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="num", + type=check_int_range(1, 25), + default=5, + help="Number of the most shorted stocks to retrieve.", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-n") + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + yahoofinance_view.display_most_shorted( + num_stocks=ns_parser.num, + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + def call_hsi(self, other_args: List[str]): """Process hsi command""" parser = argparse.ArgumentParser( diff --git a/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_model.py b/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_model.py new file mode 100644 index 00000000000..a5dfb0953c9 --- /dev/null +++ b/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_model.py @@ -0,0 +1,20 @@ +""" Yahoo Finance Model """ +__docformat__ = "numpy" + +import pandas as pd +import requests + + +def get_most_shorted() -> pd.DataFrame: + """Get most shorted stock screener [Source: Yahoo Finance] + + Returns + ------- + pd.DataFrame + Most Shorted Stocks + """ + url = "https://finance.yahoo.com/screener/predefined/most_shorted_stocks" + + data = pd.read_html(requests.get(url).text)[0] + data = data.iloc[:, :-1] + return data diff --git a/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_view.py b/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_view.py new file mode 100644 index 00000000000..fed383a8c70 --- /dev/null +++ b/gamestonk_terminal/stocks/dark_pool_shorts/yahoofinance_view.py @@ -0,0 +1,43 @@ +""" Yahoo Finance View """ +__docformat__ = "numpy" + +import os +from tabulate import tabulate +from gamestonk_terminal.helper_funcs import export_data +from gamestonk_terminal.stocks.dark_pool_shorts import yahoofinance_model + + +def display_most_shorted(num_stocks: int, export: str): + """Display most shorted stocks screener. [Source: Yahoo Finance] + + Parameters + ---------- + num_stocks: int + Number of stocks to display + export : str + Export dataframe data to csv,json,xlsx file + """ + df = yahoofinance_model.get_most_shorted().head(num_stocks) + df.dropna(how="all", axis=1, inplace=True) + df = df.replace(float("NaN"), "") + + if df.empty: + print("No data found.") + else: + print( + tabulate( + df, + headers=df.columns, + floatfmt=".2f", + showindex=False, + tablefmt="fancy_grid", + ) + ) + print("") + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "shorted", + df, + ) diff --git a/gamestonk_terminal/stocks/discovery/disc_controller.py b/gamestonk_terminal/stocks/discovery/disc_controller.py index 394cab3b2a3..4cea729fc30 100644 --- a/gamestonk_terminal/stocks/discovery/disc_controller.py +++ b/gamestonk_terminal/stocks/discovery/disc_controller.py @@ -44,6 +44,7 @@ class DiscoveryController: "fipo", "gainers", "losers", + "under", "ford", "arkord", "upcoming", @@ -79,6 +80,7 @@ Finnhub: Yahoo Finance: gainers show latest top gainers losers show latest top losers + under undervalued growth stocks Fidelity: ford orders by Fidelity Customers cathiesark.com: @@ -308,6 +310,48 @@ pennystockflow.com except Exception as e: print(e, "\n") + def call_under(self, other_args: List[str]): + """Process under command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="under", + description="Print up to 25 top ticker losers. [Source: Yahoo Finance]", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="num", + type=check_int_range(1, 25), + default=5, + help="Number of the undervalued stocks to retrieve.", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-n") + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + yahoofinance_view.display_undervalued( + num_stocks=ns_parser.num, + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + def call_ford(self, other_args: List[str]): """Process ford command""" parser = argparse.ArgumentParser( diff --git a/gamestonk_terminal/stocks/discovery/yahoofinance_model.py b/gamestonk_terminal/stocks/discovery/yahoofinance_model.py index 13a76f3cb6c..1ce8601572a 100644 --- a/gamestonk_terminal/stocks/discovery/yahoofinance_model.py +++ b/gamestonk_terminal/stocks/discovery/yahoofinance_model.py @@ -29,3 +29,18 @@ def get_losers() -> pd.DataFrame: url_losers = "https://finance.yahoo.com/screener/predefined/day_losers" return pd.read_html(requests.get(url_losers).text)[0] + + +def get_undervalued() -> pd.DataFrame: + """Get Yahoo Finance undervalued growth stocks + + Returns + ------- + pd.DataFrame + Undervalued stocks + """ + url = "https://finance.yahoo.com/screener/predefined/undervalued_growth_stocks" + + data = pd.read_html(requests.get(url).text)[0] + data = data.iloc[:, :-1] + return data diff --git a/gamestonk_terminal/stocks/discovery/yahoofinance_view.py b/gamestonk_terminal/stocks/discovery/yahoofinance_view.py index 5c400ea60e8..7999b224938 100644 --- a/gamestonk_terminal/stocks/discovery/yahoofinance_view.py +++ b/gamestonk_terminal/stocks/discovery/yahoofinance_view.py @@ -17,7 +17,7 @@ def display_gainers(num_stocks: int, export: str): export : str Export dataframe data to csv,json,xlsx file """ - df_gainers = yahoofinance_model.get_gainers().head(num_stocks) + df_gainers = yahoofinance_model.get_gainers() df_gainers.dropna(how="all", axis=1, inplace=True) df_gainers = df_gainers.replace(float("NaN"), "") @@ -26,7 +26,7 @@ def display_gainers(num_stocks: int, export: str): else: print( tabulate( - df_gainers, + df_gainers.head(num_stocks), headers=df_gainers.columns, floatfmt=".2f", showindex=False, @@ -53,7 +53,7 @@ def display_losers(num_stocks: int, export: str): export : str Export dataframe data to csv,json,xlsx file """ - df_losers = yahoofinance_model.get_losers().head(num_stocks) + df_losers = yahoofinance_model.get_losers() df_losers.dropna(how="all", axis=1, inplace=True) df_losers = df_losers.replace(float("NaN"), "") @@ -62,7 +62,7 @@ def display_losers(num_stocks: int, export: str): else: print( tabulate( - df_losers, + df_losers.head(num_stocks), headers=df_losers.columns, floatfmt=".2f", showindex=False, @@ -77,3 +77,39 @@ def display_losers(num_stocks: int, export: str): "losers", df_losers, ) + + +def display_undervalued(num_stocks: int, export: str): + """Display most undervalued growth stock. [Source: Yahoo Finance] + + Parameters + ---------- + num_stocks: int + Number of stocks to display + export : str + Export dataframe data to csv,json,xlsx file + """ + df = yahoofinance_model.get_undervalued() + df.dropna(how="all", axis=1, inplace=True) + df = df.replace(float("NaN"), "") + + if df.empty: + print("No data found.") + else: + print( + tabulate( + df.head(num_stocks), + headers=df.columns, + floatfmt=".2f", + showindex=False, + tablefmt="fancy_grid", + ) + ) + print("") + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "undervalued", + df, + ) diff --git a/gamestonk_terminal/stocks/screener/screener_controller.py b/gamestonk_terminal/stocks/screener/screener_controller.py index 1500d19d1db..26894dcb55b 100644 --- a/gamestonk_terminal/stocks/screener/screener_controller.py +++ b/gamestonk_terminal/stocks/screener/screener_controller.py @@ -1,21 +1,21 @@ """Screener Controller Module""" __docformat__ = "numpy" -import os import argparse import configparser +import os from typing import List + import matplotlib.pyplot as plt from prompt_toolkit.completion import NestedCompleter -from gamestonk_terminal.helper_funcs import get_flair -from gamestonk_terminal.menu import session from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import ( + get_flair, parse_known_args_and_warn, ) -from gamestonk_terminal.stocks.screener import finviz_view -from gamestonk_terminal.stocks.screener import yahoo_finance_view +from gamestonk_terminal.menu import session from gamestonk_terminal.portfolio.portfolio_optimization import po_controller +from gamestonk_terminal.stocks.screener import finviz_view, yahoofinance_view presets_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "presets/") @@ -253,7 +253,7 @@ class ScreenerController: def call_historical(self, other_args: List[str]): """Process historical command""" - self.screen_tickers = yahoo_finance_view.historical(other_args, self.preset) + self.screen_tickers = yahoofinance_view.historical(other_args, self.preset) def call_overview(self, other_args: List[str]): """Process overview command""" diff --git a/gamestonk_terminal/stocks/screener/yahoo_finance_view.py b/gamestonk_terminal/stocks/screener/yahoofinance_view.py similarity index 99% rename from gamestonk_terminal/stocks/screener/yahoo_finance_view.py rename to gamestonk_terminal/stocks/screener/yahoofinance_view.py index fbf7c064b0a..f2d71e1a97e 100644 --- a/gamestonk_terminal/stocks/screener/yahoo_finance_view.py +++ b/gamestonk_terminal/stocks/screener/yahoofinance_view.py @@ -1,21 +1,24 @@ -import os +"""Yahoo Finance View""" +__docformat__ = "numpy" import argparse -from typing import List -import random -import datetime import configparser +import datetime +import os +import random +from typing import List + from pandas.plotting import register_matplotlib_converters import matplotlib.pyplot as plt import yfinance as yf from finvizfinance.screener import ticker -from gamestonk_terminal.stocks.screener import finviz_view from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, plot_autoscale, valid_date, ) -from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal.stocks.screener import finviz_view register_matplotlib_converters()