From 82181b0d6f80e4b5079b413e59e7100c27d5636e Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 20 Aug 2021 16:11:56 +0100 Subject: [PATCH] add hot penny stocks to discovery menu (#683) --- .../stocks/discovery/disc_controller.py | 51 +++++++++++++++- .../stocks/discovery/shortinterest_model.py | 58 +++++++++++++++++++ .../stocks/discovery/shortinterest_view.py | 30 +++++++++- 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/stocks/discovery/disc_controller.py b/gamestonk_terminal/stocks/discovery/disc_controller.py index 8585cd9726f..394cab3b2a3 100644 --- a/gamestonk_terminal/stocks/discovery/disc_controller.py +++ b/gamestonk_terminal/stocks/discovery/disc_controller.py @@ -50,6 +50,7 @@ class DiscoveryController: "latest", "trending", "lowfloat", + "hotpenny", ] CHOICES += CHOICES_COMMANDS @@ -87,7 +88,9 @@ Seeking Alpha: latest latest news trending trending news shortinterest.com - lowfloat show low float stocks under 10M shares float + lowfloat low float stocks under 10M shares float +pennystockflow.com + hotpenny today's hot penny stocks """ print(help_text) @@ -619,6 +622,52 @@ shortinterest.com except Exception as e: print(e, "\n") + def call_hotpenny(self, other_args: List[str]): + """Process hotpenny command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="hotpenny", + description=""" + This site provides a list of todays most active and hottest penny stocks. While not for everyone, penny + stocks can be exciting and rewarding investments in many ways. With penny stocks, you can get more bang + for the buck. You can turn a few hundred dollars into thousands, just by getting in on the right penny + stock at the right time. Penny stocks are increasing in popularity. More and more investors of all age + groups and skill levels are getting involved, and the dollar amounts they are putting into these + speculative investments are representing a bigger portion of their portfolios. + [Source: www.pennystockflow.com] + """, + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="n_num", + type=check_positive, + default=10, + help="Number of top stocks to print.", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + shortinterest_view.hot_penny_stocks( + num=ns_parser.n_num, + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + def menu(): """Discovery Menu""" diff --git a/gamestonk_terminal/stocks/discovery/shortinterest_model.py b/gamestonk_terminal/stocks/discovery/shortinterest_model.py index 42306c417e5..6133e86e49b 100644 --- a/gamestonk_terminal/stocks/discovery/shortinterest_model.py +++ b/gamestonk_terminal/stocks/discovery/shortinterest_model.py @@ -52,3 +52,61 @@ def get_low_float() -> DataFrame: low_float_data = list() return df_low_float + + +def get_today_hot_penny_stocks() -> DataFrame: + """Returns today hot penny stocks + + Returns + ------- + DataFrame + Today hot penny stocks DataFrame with the following columns: + Ticker, Price, Change, $ Volume, Volume, # Trades + """ + url_penny_stock_stocks = "https://www.pennystockflow.com" + + text_soup_penny_stock_stocks = BeautifulSoup( + requests.get( + url_penny_stock_stocks, headers={"User-Agent": get_user_agent()} + ).text, + "lxml", + ) + + a_penny_stock_header = list() + for penny_stock_header in text_soup_penny_stock_stocks.findAll( + "td", {"class": "tblhdr"} + ): + a_penny_stock_header.append(penny_stock_header.text) + + df_penny = pd.DataFrame(columns=a_penny_stock_header) + + first_penny = list() + for idx, penny_stock_header in enumerate(text_soup_penny_stock_stocks.findAll("a")): + if idx == 0: + continue + if idx > 1: + break + first_penny.append(penny_stock_header.text) + + for idx, first_penny_stock in enumerate( + text_soup_penny_stock_stocks.findAll("td", {"align": "right"}) + ): + first_penny.append(first_penny_stock.text) + if idx > 3: + break + + df_penny.loc[0] = first_penny + + a_penny_stock = list() + penny_idx = 1 + for idx, penny_stock in enumerate( + text_soup_penny_stock_stocks.findAll("td", {"class": "tdi"}) + ): + a_penny_stock.append(penny_stock.text) + + if (idx + 1) % 6 == 0: + df_penny.loc[penny_idx] = a_penny_stock + penny_idx += 1 + a_penny_stock = list() + + return df_penny diff --git a/gamestonk_terminal/stocks/discovery/shortinterest_view.py b/gamestonk_terminal/stocks/discovery/shortinterest_view.py index b4b2bcc3d30..c5f94022604 100644 --- a/gamestonk_terminal/stocks/discovery/shortinterest_view.py +++ b/gamestonk_terminal/stocks/discovery/shortinterest_view.py @@ -40,4 +40,32 @@ def low_float(num: int, export: str): ) -# TODO: Add https://www.pennystockflow.com +def hot_penny_stocks(num: int, export: str): + """Prints top N hot penny stocks from https://www.pennystockflow.com + + Parameters + ---------- + num: int + Number of stocks to display + export : str + Export dataframe data to csv,json,xlsx file + """ + df_penny_stocks = shortinterest_model.get_today_hot_penny_stocks() + + print( + tabulate( + df_penny_stocks.head(num), + headers=df_penny_stocks.columns, + floatfmt=".2f", + showindex=False, + tablefmt="fancy_grid", + ), + "\n", + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "hotpenny", + df_penny_stocks, + )