Merge pull request #293 from DidierRLopes/disco-refactor

Discovery menu refactor
This commit is contained in:
Artem Veremey
2021-03-29 08:22:30 -07:00
committed by GitHub
22 changed files with 906 additions and 442 deletions

View File

@@ -1 +1 @@
from . import disc_menu # noqa: F401
from . import disc_controller # noqa: F401

View File

@@ -1,19 +1,34 @@
""" Alpha Vantage View """
__docformat__ = "numpy"
import argparse
from typing import List
import matplotlib.pyplot as plt
from alpha_vantage.sectorperformance import SectorPerformances
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
from gamestonk_terminal import feature_flags as gtff
def sectors(l_args):
def sectors_view(other_args: List[str]):
"""Opens a bar chart with sector performance
Parameters
----------
other_args : List[str]
argparse other args
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="sectors",
description="""Real-time and historical sector performances calculated from
S&P500 incumbents. Pops plot in terminal. [Source: Alpha Vantage]""",
description="""
Real-time and historical sector performances calculated from
S&P500 incumbents. Pops plot in terminal. [Source: Alpha Vantage]
""",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
@@ -27,5 +42,9 @@ def sectors(l_args):
plt.title("Real Time Performance (%) per Sector")
plt.tight_layout()
plt.grid()
if gtff.USE_ION:
plt.ion()
plt.show()
print("")

View File

@@ -1,35 +1,28 @@
import argparse
""" ARK Model """
__docformat__ = "numpy"
from datetime import timedelta
import json
import requests
from colorama import Fore, Style
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
from pandas.core.frame import DataFrame
import yfinance as yf
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
patch_pandas_text_adjustment,
parse_known_args_and_warn,
)
from gamestonk_terminal import feature_flags as gtff
def direction_color_red_green(val: str) -> str:
if val == "Buy":
ret = Fore.GREEN + val + Style.RESET_ALL
elif val == "Sell":
ret = Fore.RED + val + Style.RESET_ALL
else:
ret = val
return ret
from gamestonk_terminal.helper_funcs import get_user_agent
def get_ark_orders() -> DataFrame:
"""Returns ARK orders in a Dataframe
Returns
-------
DataFrame
ARK orders data frame with the following columns:
ticker, date, shares, weight, fund, direction
"""
url_orders = "https://cathiesark.com/ark-funds-combined/trades"
raw_page = requests.get(url_orders, headers={"User-Agent": get_user_agent()}).text
@@ -62,6 +55,21 @@ def get_ark_orders() -> DataFrame:
def add_order_total(df_orders: DataFrame) -> DataFrame:
"""Takes an ARK orders dataframe and pulls data from Yahoo Finance to add
volume, open, close, high, low, and total columns
Parameters
----------
df_orders : DataFrame
ARK orders data frame with the following columns:
ticker, date, shares, weight, fund, direction
Returns
-------
DataFrame
ARK orders data frame with the following columns:
ticker, date, shares, volume, open, close, high, low, total, weight, fund, direction
"""
start_date = df_orders["date"].iloc[-1] - timedelta(days=1)
tickers = " ".join(df_orders["ticker"].unique())
@@ -93,52 +101,3 @@ def add_order_total(df_orders: DataFrame) -> DataFrame:
)
return df_orders
def ark_orders(l_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="ARK Orders",
description="""
Orders by ARK Investment Management LLC - https://ark-funds.com/. [Source: https://cathiesark.com]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=20,
help="Last N orders.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
if not ns_parser:
return
df_orders = get_ark_orders()
if df_orders.empty:
print("The ARK orders aren't anavilable at the moment.\n")
return
pd.set_option("mode.chained_assignment", None)
df_orders = add_order_total(df_orders.head(ns_parser.n_num))
if gtff.USE_COLOR:
df_orders["direction"] = df_orders["direction"].apply(direction_color_red_green)
patch_pandas_text_adjustment()
df_orders["link"] = "https://finviz.com/quote.ashx?t=" + df_orders["ticker"]
pd.set_option("display.max_colwidth", None)
pd.set_option("display.max_rows", None)
pd.set_option("display.float_format", "{:,.2f}".format)
print("")
print("Orders by ARK Investment Management LLC")
print("")
print(df_orders.to_string(index=False))
print("")

View File

@@ -0,0 +1,96 @@
""" ARK View """
__docformat__ = "numpy"
import argparse
from typing import List
from colorama import Fore, Style
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
patch_pandas_text_adjustment,
parse_known_args_and_warn,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.discovery import ark_model
def direction_color_red_green(val: str) -> str:
"""Adds color tags to the Direction information: Buy -> Green, Sell -> Red
Parameters
----------
val : str
Direction string - either Buy or Sell
Returns
-------
str
Direction string with color tags added
"""
if val == "Buy":
ret = Fore.GREEN + val + Style.RESET_ALL
elif val == "Sell":
ret = Fore.RED + val + Style.RESET_ALL
else:
ret = val
return ret
def ark_orders_view(other_args: List[str]):
"""Prints a table of the last N ARK Orders
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="ARK Orders",
description="""
Orders by ARK Investment Management LLC - https://ark-funds.com/. [Source: https://cathiesark.com]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=20,
help="Last N orders.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_orders = ark_model.get_ark_orders()
if df_orders.empty:
print("The ARK orders aren't anavilable at the moment.\n")
return
pd.set_option("mode.chained_assignment", None)
df_orders = ark_model.add_order_total(df_orders.head(ns_parser.n_num))
if gtff.USE_COLOR:
df_orders["direction"] = df_orders["direction"].apply(direction_color_red_green)
patch_pandas_text_adjustment()
df_orders["link"] = "https://finviz.com/quote.ashx?t=" + df_orders["ticker"]
pd.set_option("display.max_colwidth", None)
pd.set_option("display.max_rows", None)
pd.set_option("display.float_format", "{:,.2f}".format)
print("")
print("Orders by ARK Investment Management LLC")
print("")
print(df_orders.to_string(index=False))
print("")

View File

@@ -0,0 +1,188 @@
""" Disc Controller """
__docformat__ = "numpy"
import argparse
from typing import List
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal.menu import session
from gamestonk_terminal.discovery import (
alpha_vantage_view,
ark_view,
fidelity_view,
finviz_view,
seeking_alpha_view,
short_interest_view,
simply_wallst_view,
spachero_view,
unusual_whales_view,
yahoo_finance_view,
)
class DiscoveryController:
""" Discovery Controller """
# Command choices
CHOICES = [
"help",
"q",
"quit",
"map",
"sectors",
"gainers",
"losers",
"orders",
"ark_orders",
"up_earnings",
"high_short",
"low_float",
"simply_wallst",
"spachero",
"uwhales",
]
def __init__(self):
"""Constructor"""
self.disc_parser = argparse.ArgumentParser(add_help=False, prog="disc")
self.disc_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
@staticmethod
def print_help():
""" Print help """
print("\nDiscovery Mode:")
print(" help show this discovery menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" map S&P500 index stocks map [Finviz]")
print(" sectors show sectors performance [Alpha Vantage]")
print(" gainers show latest top gainers [Yahoo Finance]")
print(" losers show latest top losers [Yahoo Finance]")
print(" orders orders by Fidelity Customers [Fidelity]")
print(" ark_orders orders by ARK Investment Management LLC")
print(" up_earnings upcoming earnings release dates [Seeking Alpha]")
print(
" high_short show top high short interest stocks of over 20% ratio [www.highshortinterest.com]"
)
print(
" low_float show low float stocks under 10M shares float [www.lowfloat.com]"
)
print(" simply_wallst Simply Wall St. research data [Simply Wall St.]")
print(" spachero great website for SPACs research [SpacHero]")
print(" uwhales good website for SPACs research [UnusualWhales]")
print("")
def switch(self, an_input: str):
"""Process and dispatch input
Returns
-------
True, False or None
False - quit the menu
True - quit the program
None - continue in the menu
"""
(known_args, other_args) = self.disc_parser.parse_known_args(an_input.split())
return getattr(
self, "call_" + known_args.cmd, lambda: "Command not recognized!"
)(other_args)
def call_help(self, _):
"""Process Help command"""
self.print_help()
def call_q(self, _):
"""Process Q command - quit the menu"""
return False
def call_quit(self, _):
"""Process Quit command - quit the program"""
return True
def call_map(self, other_args: List[str]):
"""Process map command"""
finviz_view.map_sp500_view(other_args)
def call_sectors(self, other_args: List[str]):
"""Process sectors command"""
alpha_vantage_view.sectors_view(other_args)
def call_gainers(self, other_args: List[str]):
"""Process gainers command"""
yahoo_finance_view.gainers_view(other_args)
def call_losers(self, other_args: List[str]):
"""Process losers command"""
yahoo_finance_view.losers_view(other_args)
def call_orders(self, other_args: List[str]):
"""Process orders command"""
fidelity_view.orders_view(other_args)
def call_ark_orders(self, other_args: List[str]):
"""Process ark_orders command"""
ark_view.ark_orders_view(other_args)
def call_up_earnings(self, other_args: List[str]):
"""Process up_earnings command"""
seeking_alpha_view.earnings_release_dates_view(other_args)
def call_high_short(self, other_args: List[str]):
"""Process high_short command"""
short_interest_view.high_short_interest_view(other_args)
def call_low_float(self, other_args: List[str]):
"""Process low_float command"""
short_interest_view.low_float_view(other_args)
def call_simply_wallst(self, other_args: List[str]):
"""Process simply_wallst command"""
simply_wallst_view.simply_wallst_view(other_args)
def call_spachero(self, other_args: List[str]):
"""Process spachero command"""
spachero_view.spachero_view(other_args)
def call_uwhales(self, other_args: List[str]):
"""Process uwhales command"""
unusual_whales_view.unusual_whales_view(other_args)
def menu():
"""Discovery Menu"""
disc_controller = DiscoveryController()
disc_controller.call_help(None)
# Loop forever and ever
while True:
# Get input command from user
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in disc_controller.CHOICES}
)
an_input = session.prompt(
f"{get_flair()} (disc)> ",
completer=completer,
)
else:
an_input = input(f"{get_flair()} (disc)> ")
try:
process_input = disc_controller.switch(an_input)
if process_input is not None:
return process_input
except SystemExit:
print("The command selected doesn't exist\n")
continue

View File

@@ -1,144 +0,0 @@
import argparse
from gamestonk_terminal.discovery import (
alpha_vantage_api,
ark_api,
fidelity_api,
finviz_api,
seeking_alpha_api,
short_interest_api,
simply_wallst_api,
spachero_api,
unusual_whales_api,
yahoo_finance_api,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal.menu import session
from prompt_toolkit.completion import NestedCompleter
def print_discovery():
""" Print help """
print("\nDiscovery Mode:")
print(" help show this discovery menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" map S&P500 index stocks map [Finviz]")
print(" sectors show sectors performance [Alpha Vantage]")
print(" gainers show latest top gainers [Yahoo Finance]")
print(" losers show latest top losers [Yahoo Finance]")
print(" orders orders by Fidelity Customers [Fidelity]")
print(" ark_orders orders by ARK Investment Management LLC")
print(" up_earnings upcoming earnings release dates [Seeking Alpha]")
print(
" high_short show top high short interest stocks of over 20% ratio [www.highshortinterest.com]"
)
print(
" low_float show low float stocks under 10M shares float [www.lowfloat.com]"
)
print(" simply_wallst Simply Wall St. research data [Simply Wall St.]")
print(" spachero great website for SPACs research [SpacHero]")
print(" uwhales good website for SPACs research [UnusualWhales]")
print("")
return
def disc_menu():
# Add list of arguments that the discovery parser accepts
disc_parser = argparse.ArgumentParser(add_help=False, prog="discovery")
choices = [
"help",
"q",
"quit",
"map",
"sectors",
"gainers",
"losers",
"spacs",
"orders",
"ark_orders",
"spachero",
"high_short",
"low_float",
"up_earnings",
"simply_wallst",
"uwhales",
"mill",
]
disc_parser.add_argument("cmd", choices=choices)
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
print_discovery()
# Loop forever and ever
while True:
# Get input command from user
if session and gtff.USE_PROMPT_TOOLKIT:
as_input = session.prompt(
f"{get_flair()} (disc)> ",
completer=completer,
)
else:
as_input = input(f"{get_flair()} (disc)> ")
# Parse fundamental analysis command of the list of possible commands
try:
(ns_known_args, l_args) = disc_parser.parse_known_args(as_input.split())
except SystemExit:
print("The command selected doesn't exist\n")
continue
if ns_known_args.cmd == "help":
print_discovery()
elif ns_known_args.cmd == "q":
# Just leave the DISC menu
return False
elif ns_known_args.cmd == "quit":
# Abandon the program
return True
elif ns_known_args.cmd == "map":
finviz_api.map_sp500(l_args)
elif ns_known_args.cmd == "sectors":
alpha_vantage_api.sectors(l_args)
elif ns_known_args.cmd == "gainers":
yahoo_finance_api.gainers(l_args)
elif ns_known_args.cmd == "losers":
yahoo_finance_api.losers(l_args)
elif ns_known_args.cmd == "spachero":
spachero_api.spachero(l_args)
elif ns_known_args.cmd == "uwhales":
unusual_whales_api.unusual_whales(l_args)
elif ns_known_args.cmd == "orders":
fidelity_api.orders(l_args)
elif ns_known_args.cmd == "ark_orders":
ark_api.ark_orders(l_args)
elif ns_known_args.cmd == "simply_wallst":
simply_wallst_api.simply_wallst(l_args)
elif ns_known_args.cmd == "up_earnings":
seeking_alpha_api.earnings_release_dates(l_args)
elif ns_known_args.cmd == "high_short":
short_interest_api.high_short_interest(l_args)
elif ns_known_args.cmd == "low_float":
short_interest_api.low_float(l_args)
else:
print("Command not recognized!")

View File

@@ -0,0 +1,93 @@
""" Fidelity Model """
__docformat__ = "numpy"
from typing import Tuple
import requests
from bs4 import BeautifulSoup
import pandas as pd
from pandas.core.frame import DataFrame
from gamestonk_terminal.helper_funcs import get_user_agent
def get_orders() -> Tuple[str, DataFrame]:
"""Returns Fidelity orders in a Dataframe
Returns
-------
Tuple[str, DataFrame]
First value in the tuple is a Fidelity orders header
Fidelity orders Dataframe with the following columns:
Symbol, Buy / Sell Ratio, Price Change, Company, # Buy Orders, # Sell Orders
"""
url_orders = (
"https://eresearch.fidelity.com/eresearch/gotoBL/fidelityTopOrders.jhtml"
)
text_soup_url_orders = BeautifulSoup(
requests.get(url_orders, headers={"User-Agent": get_user_agent()}).text, "lxml"
)
l_orders = list()
l_orders_vals = list()
idx = 0
order_list = text_soup_url_orders.findAll(
"td",
{"class": ["second", "third", "fourth", "fifth", "sixth", "seventh", "eight"]},
)
for an_order in order_list:
if ((idx + 1) % 3 == 0) or ((idx + 1) % 4 == 0) or ((idx + 1) % 6 == 0):
if not an_order:
l_orders_vals.append("")
else:
l_orders_vals.append(an_order.contents[1])
elif (idx + 1) % 5 == 0:
s_orders = str(an_order)
l_orders_vals.append(
s_orders[
s_orders.find('title="') + len('title="') : s_orders.find('"/>')
]
)
else:
l_orders_vals.append(an_order.text.strip())
idx += 1
# Add value to dictionary
if (idx + 1) % 8 == 0:
l_orders.append(l_orders_vals)
l_orders_vals = list()
idx = 0
df_orders = pd.DataFrame(
l_orders,
columns=[
"Symbol",
"Company",
"Price Change",
"# Buy Orders",
"Buy / Sell Ratio",
"# Sell Orders",
"Latest News",
],
)
df_orders = df_orders[
[
"Symbol",
"Buy / Sell Ratio",
"Price Change",
"Company",
"# Buy Orders",
"# Sell Orders",
"Latest News",
]
]
order_header = text_soup_url_orders.findAll("span", {"class": "source"})[
0
].text.capitalize()
return order_header, df_orders

View File

@@ -1,20 +1,36 @@
""" Fidelity View """
__docformat__ = "numpy"
import argparse
from typing import List
import re
import requests
from colorama import Fore, Style
from bs4 import BeautifulSoup
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
patch_pandas_text_adjustment,
parse_known_args_and_warn,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.discovery import fidelity_model
def buy_sell_ratio_color_red_green(val: str) -> str:
"""Add color tags to the Buys/Sells ratio cell
Parameters
----------
val : str
Buys/Sells ratio cell
Returns
-------
str
Buys/Sells ratio cell with color tags
"""
buy_sell_match = re.match(r"(\d+)% Buys, (\d+)% Sells", val, re.M | re.I)
if not buy_sell_match:
@@ -32,6 +48,19 @@ def buy_sell_ratio_color_red_green(val: str) -> str:
def price_change_color_red_green(val: str) -> str:
"""Add color tags to the price change cell
Parameters
----------
val : str
Price change cell
Returns
-------
str
Price change cell with color tags
"""
val_float = float(val.split(" ")[0])
if val_float > 0:
color = Fore.GREEN
@@ -40,7 +69,15 @@ def price_change_color_red_green(val: str) -> str:
return color + val + Style.RESET_ALL
def orders(l_args):
def orders_view(other_args: List[str]):
"""Prints a table with the last N orders by Fidelity customers
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="orders",
@@ -62,78 +99,13 @@ def orders(l_args):
help="Number of top ordered stocks to be printed.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
url_orders = (
"https://eresearch.fidelity.com/eresearch/gotoBL/fidelityTopOrders.jhtml"
)
order_header, df_orders = fidelity_model.get_orders()
text_soup_url_orders = BeautifulSoup(
requests.get(url_orders, headers={"User-Agent": get_user_agent()}).text, "lxml"
)
l_orders = list()
l_orders_vals = list()
idx = 0
order_list = text_soup_url_orders.findAll(
"td",
{"class": ["second", "third", "fourth", "fifth", "sixth", "seventh", "eight"]},
)
for an_order in order_list:
if ((idx + 1) % 3 == 0) or ((idx + 1) % 4 == 0) or ((idx + 1) % 6 == 0):
if not an_order:
l_orders_vals.append("")
else:
l_orders_vals.append(an_order.contents[1])
elif (idx + 1) % 5 == 0:
s_orders = str(an_order)
l_orders_vals.append(
s_orders[
s_orders.find('title="') + len('title="') : s_orders.find('"/>')
]
)
else:
l_orders_vals.append(an_order.text.strip())
idx += 1
# Add value to dictionary
if (idx + 1) % 8 == 0:
l_orders.append(l_orders_vals)
l_orders_vals = list()
idx = 0
df_orders = pd.DataFrame(
l_orders,
columns=[
"Symbol",
"Company",
"Price Change",
"# Buy Orders",
"Buy / Sell Ratio",
"# Sell Orders",
"Latest News",
],
)
df_orders = df_orders[
[
"Symbol",
"Buy / Sell Ratio",
"Price Change",
"Company",
"# Buy Orders",
"# Sell Orders",
"Latest News",
]
]
print(
text_soup_url_orders.findAll("span", {"class": "source"})[0].text.capitalize()
+ ":"
)
print(order_header, ":")
pd.set_option("display.max_colwidth", None)

View File

@@ -1,9 +1,21 @@
""" Finviz View """
__docformat__ = "numpy"
import argparse
from typing import List
import webbrowser
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def map_sp500(l_args):
def map_sp500_view(other_args: List[str]):
"""Opens Finviz website in a browser
Parameters
----------
other_args : List[str]
argparse other args - ["-p", "6m", "-t", "sp500"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="map",
@@ -38,7 +50,7 @@ def map_sp500(l_args):
d_period = {"1d": "", "1w": "w1", "1m": "w4", "3m": "w13", "6m": "w26", "1y": "w52"}
d_type = {"sp500": "sec", "world": "geo", "full": "sec_all", "etf": "etf"}
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return

View File

@@ -0,0 +1,51 @@
""" Seeking Alpha Model """
__docformat__ = "numpy"
import requests
from bs4 import BeautifulSoup
import pandas as pd
from pandas.core.frame import DataFrame
from gamestonk_terminal.helper_funcs import get_user_agent
def get_next_earnings(pages: int) -> DataFrame:
"""Returns a DataFrame with upcoming earnings
Parameters
----------
pages : int
Number of pages
Returns
-------
DataFrame
Upcoming earnings DataFrame
"""
earnings = list()
for idx in range(0, pages):
if idx == 0:
url_next_earnings = "https://seekingalpha.com/earnings/earnings-calendar"
else:
url_next_earnings = (
f"https://seekingalpha.com/earnings/earnings-calendar/{idx+1}"
)
text_soup_earnings = BeautifulSoup(
requests.get(
url_next_earnings, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
)
for stock_rows in text_soup_earnings.findAll("tr", {"data-exchange": "NASDAQ"}):
stocks = list()
for a_stock in stock_rows.contents[:3]:
stocks.append(a_stock.text)
earnings.append(stocks)
df_earnings = pd.DataFrame(earnings, columns=["Ticker", "Name", "Date"])
df_earnings["Date"] = pd.to_datetime(df_earnings["Date"])
df_earnings = df_earnings.set_index("Date")
return df_earnings

View File

@@ -1,15 +1,26 @@
""" Seeking Alpha View """
__docformat__ = "numpy"
import argparse
import requests
from bs4 import BeautifulSoup
from typing import List
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
parse_known_args_and_warn,
)
from gamestonk_terminal.discovery import seeking_alpha_model
def earnings_release_dates_view(other_args: List[str]):
"""Prints a data frame with earnings release dates
Parameters
----------
other_args : List[str]
argparse other args - ["-p", "20", "-n", "5"]
"""
def earnings_release_dates(l_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="up_earnings",
@@ -35,34 +46,11 @@ def earnings_release_dates(l_args):
help="Number of upcoming earnings release dates to print",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
l_earnings = list()
for idx in range(0, ns_parser.n_pages):
if idx == 0:
url_next_earnings = "https://seekingalpha.com/earnings/earnings-calendar"
else:
url_next_earnings = (
f"https://seekingalpha.com/earnings/earnings-calendar/{idx+1}"
)
text_soup_earnings = BeautifulSoup(
requests.get(
url_next_earnings, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
)
for bs_stock in text_soup_earnings.findAll("tr", {"data-exchange": "NASDAQ"}):
l_stock = list()
for stock in bs_stock.contents[:3]:
l_stock.append(stock.text)
l_earnings.append(l_stock)
df_earnings = pd.DataFrame(l_earnings, columns=["Ticker", "Name", "Date"])
df_earnings["Date"] = pd.to_datetime(df_earnings["Date"])
df_earnings = df_earnings.set_index("Date")
df_earnings = seeking_alpha_model.get_next_earnings(ns_parser.n_pages)
pd.set_option("display.max_colwidth", None)
for n_days, earning_date in enumerate(df_earnings.index.unique()):

View File

@@ -1,42 +1,26 @@
import argparse
""" Short Interest View """
__docformat__ = "numpy"
import requests
from bs4 import BeautifulSoup
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
parse_known_args_and_warn,
)
from pandas.core.frame import DataFrame
from gamestonk_terminal.helper_funcs import get_user_agent
def high_short_interest(l_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="high_short",
description="""
Print top stocks being more heavily shorted. HighShortInterest.com provides
a convenient sorted database of stocks which have a short interest of over
20 percent. Additional key data such as the float, number of outstanding shares,
and company industry is displayed. Data is presented for the Nasdaq Stock Market,
the New York Stock Exchange, and the American Stock Exchange. [Source: www.highshortinterest.com]
""",
)
def get_high_short_interest() -> DataFrame:
"""Returns a high short interest DataFrame
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top stocks to print.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
if not ns_parser:
return
Returns
-------
DataFrame
High short interest Dataframe with the following columns:
Ticker, Company, Exchange, ShortInt, Float, Outstd, Industry
"""
url_high_short_interested_stocks = "https://www.highshortinterest.com"
text_soup_high_short_interested_stocks = BeautifulSoup(
requests.get(
url_high_short_interested_stocks, headers={"User-Agent": get_user_agent()}
@@ -72,39 +56,21 @@ def high_short_interest(l_args):
shorted_stock_data = list()
pd.set_option("display.max_colwidth", None)
print(df_high_short_interest.head(n=ns_parser.n_num).to_string(index=False))
print("")
return df_high_short_interest
def low_float(l_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="low_float",
description="""
Print top stocks with lowest float. LowFloat.com provides a convenient
sorted database of stocks which have a float of under 10 million shares. Additional key
data such as the number of outstanding shares, short interest, and company industry is
displayed. Data is presented for the Nasdaq Stock Market, the New York Stock Exchange,
the American Stock Exchange, and the Over the Counter Bulletin Board. [Source: www.lowfloat.com]
""",
)
def get_low_float() -> DataFrame:
"""Returns low float DataFrame
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top stocks to print.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
if not ns_parser:
return
Returns
-------
DataFrame
Low float DataFrame with the following columns:
Ticker, Company, Exchange, ShortInt, Float, Outstd, Industry
"""
url_high_short_interested_stocks = "https://www.lowfloat.com"
text_soup_low_float_stocks = BeautifulSoup(
requests.get(
url_high_short_interested_stocks, headers={"User-Agent": get_user_agent()}
@@ -136,6 +102,4 @@ def low_float(l_args):
low_float_data = list()
pd.set_option("display.max_colwidth", None)
print(df_low_float.head(n=ns_parser.n_num).to_string(index=False))
print("")
return df_low_float

View File

@@ -0,0 +1,95 @@
""" Short Interest View """
__docformat__ = "numpy"
import argparse
from typing import List
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
parse_known_args_and_warn,
)
from gamestonk_terminal.discovery import short_interest_model
def high_short_interest_view(other_args: List[str]):
"""Prints top N shorted stocks
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "20"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="high_short",
description="""
Print top stocks being more heavily shorted. HighShortInterest.com provides
a convenient sorted database of stocks which have a short interest of over
20 percent. Additional key data such as the float, number of outstanding shares,
and company industry is displayed. Data is presented for the Nasdaq Stock Market,
the New York Stock Exchange, and the American Stock Exchange. [Source: www.highshortinterest.com]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top stocks to print.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_high_short_interest = short_interest_model.get_high_short_interest()
pd.set_option("display.max_colwidth", None)
print(df_high_short_interest.head(n=ns_parser.n_num).to_string(index=False))
print("")
def low_float_view(other_args: List[str]):
"""Prints top N low float stocks
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "20"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="low_float",
description="""
Print top stocks with lowest float. LowFloat.com provides a convenient
sorted database of stocks which have a float of under 10 million shares. Additional key
data such as the number of outstanding shares, short interest, and company industry is
displayed. Data is presented for the Nasdaq Stock Market, the New York Stock Exchange,
the American Stock Exchange, and the Over the Counter Bulletin Board. [Source: www.lowfloat.com]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top stocks to print.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_low_float = short_interest_model.get_low_float()
pd.set_option("display.max_colwidth", None)
print(df_low_float.head(n=ns_parser.n_num).to_string(index=False))
print("")

View File

@@ -1,9 +1,21 @@
""" Simply Wallst View """
__docformat__ = "numpy"
import argparse
from typing import List
import webbrowser
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def simply_wallst(l_args):
def simply_wallst_view(other_args: List[str]):
"""Opens simplywall.st for a specific industry in a browser
Parameters
----------
other_args : List[str]
argparse other args - ["-i", "banks"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="simply_wallst",
@@ -51,7 +63,7 @@ def simply_wallst(l_args):
],
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return

View File

@@ -1,16 +1,28 @@
""" Spachero View """
__docformat__ = "numpy"
import argparse
from typing import List
import webbrowser
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def spachero(l_args):
def spachero_view(other_args: List[str]):
"""Opens www.spachero.com website in a browser
Parameters
----------
other_args : List[str]
argparse other args
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="spachero",
description="""Great website for SPACs research. [Source: www.spachero.com]""",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return

View File

@@ -1,16 +1,25 @@
import argparse
from typing import List
import webbrowser
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def unusual_whales(l_args):
def unusual_whales_view(other_args: List[str]):
"""Opens unusualwhales.com in a browser
Parameters
----------
other_args : List[str]
argparse other args
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="uwhales",
description="""Good website for SPACs research. [Source: www.unusualwhales.com]""",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return

View File

@@ -1,9 +1,21 @@
""" Yahoo Finance View """
__docformat__ = "numpy"
import argparse
from typing import List
import pandas as pd
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def gainers(l_args):
def gainers_view(other_args: List[str]):
"""Prints top N gainers
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "20"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="gainers",
@@ -21,7 +33,7 @@ def gainers(l_args):
help="Number of the top gainers stocks to retrieve.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
@@ -32,7 +44,15 @@ def gainers(l_args):
print("")
def losers(l_args):
def losers_view(other_args: List[str]):
"""Prints top N loosers
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "20"]
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="losers",
@@ -50,7 +70,7 @@ def losers(l_args):
help="Number of the top losers stocks to retrieve.",
)
ns_parser = parse_known_args_and_warn(parser, l_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return

View File

@@ -14,7 +14,7 @@ from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal import thought_of_the_day as thought
from gamestonk_terminal import res_menu as rm
from gamestonk_terminal.discovery import disc_menu as dm
from gamestonk_terminal.discovery import disc_controller
from gamestonk_terminal.due_diligence import dd_menu as ddm
from gamestonk_terminal.fundamental_analysis import fa_menu as fam
from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair
@@ -184,7 +184,7 @@ def main():
main_cmd = True
elif ns_known_args.opt == "disc":
b_quit = dm.disc_menu()
b_quit = disc_controller.menu()
elif ns_known_args.opt == "mill":
b_quit = mill.papermill_menu()

View File

@@ -1,4 +1,4 @@
test_high_short_interest:
test_get_high_short_interest:
base_high_short:
mock_high_short: |
<html>
@@ -628,8 +628,60 @@ test_high_short_interest:
</body>
</html>
expected_result: "banana"
test_low_float:
expected_result: |
,Ticker,Company,Exchange,ShortInt,Float,Outstd,Industry
0,,,,,,,
1,OTRK,"Ontrak, Inc.",Nasdaq,43.33%,7.53M,17.69M,Healthcare Facilities
2,BLNK,Blink Charging Co,Nasdaq,41.94%,31.69M,38.95M,Utilities - Electric
3,ROOT,Root Inc,Nasdaq,41.66%,26.62M,59.66M,Insurance - Multiline & Brokers
4,GOGO,Gogo Inc,Nasdaq,40.74%,38.90M,86.40M,Communications Services
5,GTT,GTT Communications Inc,NYSE,40.29%,25.15M,58.82M,IT Services & Consulting
6,ASO,Academy Sports & Outdoors Inc,Nasdaq,39.91%,31.34M,89.91M,Retailers - Apparel & Accessories
7,TRIT,Triterras Inc,Nasdaq,35.34%,23.25M,83.20M,Fintech
8,CLVS,Clovis Oncology Inc,Nasdaq,33.85%,101.89M,104.53M,Biotechnology & Drugs
9,HPR,HighPoint Resources Corp,NYSE,32.78%,2.21M,4.31M,Oil & Gas - Exploration and Production
10,GSX,GSX Techedu Inc,NYSE,32.65%,128.57M,254.69M,Personal Services
11,SENS,Senseonics Holdings Inc,AMEX,31.40%,219.11M,377.88M,Medical Equipment & Supplies
12,MDGL,Madrigal Pharmaceuticals Inc,Nasdaq,30.69%,8.03M,15.44M,Biotechnology & Medical Research
13,SDC,SmileDirectClub Inc,Nasdaq,30.55%,101.05M,117.37M,"Medical Equipment, Supplies & Distribution"
14,AXDX,Accelerate Diagnostics Inc,Nasdaq,28.49%,31.17M,59.33M,Scientific & Technical Instruments
15,REV,Revlon Inc,NYSE,28.17%,6.74M,53.34M,Personal & Household Products
16,ICPT,Intercept Pharmaceuticals Inc,Nasdaq,26.59%,27.24M,33.02M,Biotechnology & Medical Research
17,RUBY,Rubius Therapeutics Inc,Nasdaq,26.40%,35.93M,88.08M,Biotechnology & Medical Research
18,SKT,Tanger Factory Outlet Centers,NYSE,26.37%,89.76M,93.57M,Real Estate Operations
19,FUBO,Fubotv Inc,NYSE,26.10%,69.50M,67.56M,Online Services
20,INO,Inovio Pharmaceuticals Inc,Nasdaq,26.01%,204.08M,207.63M,Biotechnology & Medical Research
21,PGEN,"Precigen, Inc",Nasdaq,25.88%,90.09M,178.60M,Biotechnology & Medical Research
22,TR,"Tootsie Roll Industries, Inc.",NYSE,25.67%,14.91M,40.52M,Food Processing
23,MSTR,MicroStrategy Inc,Nasdaq,25.59%,7.06M,7.62M,Software & Programming
24,BYND,Beyond Meat Inc,Nasdaq,25.52%,43.53M,62.94M,Food Processing
25,WKHS,Workhorse Group Inc,Nasdaq,25.49%,116.18M,123.51M,Auto & Truck Manufacturers
26,PRTS,Carparts.Com Inc,Nasdaq,25.22%,35.23M,48.09M,"Retailers - Auto Vehicles, Parts & Service"
27,CVNA,Carvana Co,NYSE,24.89%,67.53M,78.33M,Retail (Specialty Non-Apparel)
28,RVP,"Retractable Technologies, Inc.",AMEX,24.85%,14.71M,33.82M,"Medical Equipment, Supplies & Distribution"
29,MAC,Macerich Co,NYSE,24.37%,146.11M,149.47M,REITs - Commercial
30,LCI,"Lannett Company, Inc.",NYSE,24.31%,32.17M,41.40M,Biotechnology & Drugs
31,KPTI,Karyopharm Therapeutics Inc,Nasdaq,24.26%,63.06M,74.63M,Biotechnology & Medical Research
32,OPK,Opko Health Inc.,Nasdaq,24.14%,383.89M,670.04M,Biotechnology & Drugs
33,GME,GameStop Corp.,NYSE,24.10%,42.29M,69.75M,Retail (Technology)
34,EBIX,"Ebix, Inc.",Nasdaq,23.53%,25.32M,30.96M,Computer Networks
35,BFI,Burgerfi International Inc,Nasdaq,23.04%,4.02M,17.44M,Restaurants & Bars
36,HJLI,Hancock Jaffe Laboratories Inc,Nasdaq,22.84%,1.71M,7.73M,"Medical Equipment, Supplies & Distribution"
37,SRNE,Sorrento Therapeutics Inc,Nasdaq,22.76%,242.64M,280.86M,Biotechnology & Medical Research
38,SPWR,SunPower Corporation,Nasdaq,22.74%,81.43M,170.56M,Semiconductors
39,KOSS,Koss Corp,Nasdaq,22.33%,4.24M,8.62M,Audio & Video Equipment
40,OMER,Omeros Corporation,Nasdaq,22.30%,59.18M,61.93M,Biotechnology & Drugs
41,VXRT,Vaxart Inc,Nasdaq,22.04%,117.06M,117.77M,Biotechnology & Medical Research
42,BBBY,Bed Bath & Beyond Inc.,Nasdaq,21.97%,114.09M,126.01M,Retail (Specialty Non-Apparel)
43,DVAX,Dynavax Technologies Corporati,Nasdaq,21.63%,113.50M,113.26M,Biotechnology & Medical Research
44,KDMN,Kadmon Holdings Inc,NYSE,21.25%,165.35M,171.82M,Pharmaceuticals
45,DKS,Dicks Sporting Goods Inc,NYSE,21.16%,59.03M,65.73M,Retailers - Other Specialty
46,CVM,CEL-SCI Corporation,AMEX,21.10%,38.86M,40.53M,Biotechnology & Medical Research
47,CRTX,Cortexyme Inc,Nasdaq,20.98%,15.36M,29.50M,Biotechnology & Medical Research
48,FBRX,Forte Biosciences Inc,Nasdaq,20.90%,1.48M,13.51M,Biotechnology & Medical Research
49,PETS,Petmed Express Inc,Nasdaq,20.70%,19.59M,20.27M,Retail (Drugs)
50,IRBT,iRobot Corporation,Nasdaq,20.58%,27.51M,28.20M,Electronic Equipment & Parts
test_get_low_float:
base_low_float:
mock_low_float: |
<html>
@@ -1255,4 +1307,56 @@ test_low_float:
</body>
</html>
expected_result: "banana"
expected_result: |
,Ticker,Company,Exchange,Float,Outstd,ShortInt,Industry
0,,,,,,,
1,DIT,Amcon Distributing Co,AMEX,150K,550K,0.30%,Retail (Grocery)
2,SEB,Seaboard Corp,AMEX,240K,1.16M,0.71%,Fish/Livestock
3,HMG,HMG Courtland Properties,AMEX,280K,1.01M,0.01%,Real Estate Operations
4,BDL,Flanigan's Enterprises Inc,AMEX,380K,1.86M,0.11%,Restaurants
5,MAYS,JW Mays Inc,Nasdaq,390K,2.02M,0.80%,Real Estate Operations
6,SENEB,Seneca Foods Corp,Nasdaq,460K,1.72M,0.07%,Food Processing
7,PNRG,PrimeEnergy Corp,Nasdaq,490K,1.99M,1.90%,Oil & Gas Operations
8,COHN,Cohen & Company Inc,AMEX,500K,1.33M,1.23%,Diversified Investment Services
9,VBFC,Village Bank and Trust Financial Corp,Nasdaq,530K,1.47M,0.07%,Regional Banks
10,MDLY,Medley Management Inc,NYSE,620K,670K,13.84%,Investment Services
11,RAND,Rand Capital Corp,Nasdaq,640K,2.58M,0.01%,Misc. Financial Services
12,CVR,Chicago Rivet & Machine Co,AMEX,780K,970K,0.03%,Misc. Fabricated Products
13,INTG,Intergroup Corp,Nasdaq,780K,2.28M,0.30%,Real Estate Operations
14,QADB,"QAD, Inc.",Nasdaq,780K,3.33M,0.19%,Software & Programming
15,CARV,Carver Bancorp Inc,Nasdaq,790K,3.33M,12.71%,S&Ls/Savings Banks
16,ARL,"American Realty Investors, Inc",NYSE,800K,16.00M,7.45%,Real Estate Operations
17,IKNX,Ikonics Corp,Nasdaq,830K,1.98M,0.67%,Photography
18,AAMC,Altisource Asset Management Co,AMEX,910K,2.05M,0.10%,Investment Services
19,VALU,Value Line Inc,Nasdaq,950K,9.57M,1.36%,Investment Services
20,MXC,Mexco Energy Corp,AMEX,960K,2.05M,2.92%,Oil & Gas Operations
21,FFDF,FFD Financial Corp,Nasdaq,980K,990K,0.00%,S&Ls/Savings Banks
22,VRTA,Vestin Realty Mortgage I Inc,Nasdaq,1.01M,1.30M,0.00%,Real Estate Operations
23,SQBG,Sequential Brands Group Inc,Nasdaq,1.02M,1.65M,6.33%,Retailers - Apparel & Accessories
24,SVT,Servotronics Inc,NYSE,1.04M,2.49M,0.14%,Personal & Household Products
25,LINK,Interlink Electronics Inc,Nasdaq,1.06M,6.60M,0.00%,Electronic Instruments & Controls
26,DJCO,Daily Journal Corp,Nasdaq,1.08M,1.38M,1.06%,Printing & Publishing
27,NSEC,National Security Group Inc,Nasdaq,1.08M,2.53M,0.01%,Insurance (Life)
28,ISIG,"Insignia Systems, Inc.",Nasdaq,1.09M,1.75M,4.36%,Advertising & Marketing
29,EDRY,EuroDry Ltd,Nasdaq,1.09M,2.35M,1.27%,Water Transportation
30,TSRI,TSR Inc,Nasdaq,1.10M,1.96M,0.05%,Software & Programming
31,FFHL,Fuwei Films Holdings Co Ltd,Nasdaq,1.13M,3.27M,1.16%,Fabricated Plastic & Rubber
32,GTEC,Greenland Technologies Holding,Nasdaq,1.13M,10.16M,12.23%,"Auto, Truck & Motorcycle Parts"
33,HFBL,Home Federal Bancorp Inc of LA,Nasdaq,1.15M,1.69M,0.01%,S&Ls/Savings Banks
34,LBPS,4D Pharma PLC,Nasdaq,1.16M,2.63M,0.80%,Pharmaceuticals
35,ELTK,Eltek Ltd,Nasdaq,1.17M,4.38M,0.10%,Electronic Instruments & Controls
36,BNSO,Bonso Electronic International Inc,Nasdaq,1.17M,4.89M,0.09%,Misc. Capital Goods
37,NSYS,Nortech Systems Inc,Nasdaq,1.18M,2.66M,0.48%,Electronic Instruments & Controls
38,WAFU,Wah Fu Education Group Ltd,Nasdaq,1.18M,4.38M,1.30%,Personal Services
39,OFED,Oconee Federal Financial,Nasdaq,1.19M,5.60M,1.08%,S&Ls/Savings Banks
40,ACY,AeroCentury Corp,AMEX,1.20M,1.55M,3.09%,Rental & Leasing
41,AEI,Alset Ehome International Inc,Nasdaq,1.23M,8.57M,1.76%,Construction & Engineering
42,MTEX,"Mannatech,Inc.",Nasdaq,1.24M,2.07M,0.13%,Biotechnology & Drugs
43,KSPN,"Kaspien Holdings, Inc",Nasdaq,1.25M,2.43M,0.72%,Retailers - Other Specialty
44,QBAK,Qualstar Corp,Nasdaq,1.29M,1.93M,0.00%,Computer Storage Devices
45,LIVE,Live Ventures Inc,Nasdaq,1.32M,1.56M,0.55%,Computer Services
46,PNBK,Patriot National Bancorp Inc,Nasdaq,1.32M,3.94M,1.42%,Regional Banks
47,TCI,Transcontinental Realty Investors,NYSE,1.33M,8.72M,1.68%,Real Estate Operations
48,DXR,Daxor Corp,AMEX,1.35M,4.09M,1.45%,Healthcare Facilities
49,HIFS,Hingham Institution for Savings,Nasdaq,1.36M,2.14M,1.67%,S&Ls/Savings Banks
50,CKX,CKX Lands Inc,AMEX,1.38M,1.94M,0.20%,Oil & Gas Operations

View File

@@ -1,16 +1,16 @@
""" discovery/fidelity_api.py tests """
import unittest
from gamestonk_terminal.discovery.fidelity_api import (
from gamestonk_terminal.discovery.fidelity_view import (
buy_sell_ratio_color_red_green,
price_change_color_red_green,
orders,
orders_view,
)
class TestDiscoveryFidelityApi(unittest.TestCase):
def test_orders(self):
orders([])
orders_view([])
def test_buy_sell_ratio_color_red_green(self):
res = buy_sell_ratio_color_red_green("56% Buys, 44% Sells")

View File

@@ -1,40 +0,0 @@
""" discovery/short_interest_api.py tests """
import unittest
from unittest import mock
# pylint: disable=unused-import
from gamestonk_terminal.test_helper import ( # noqa: F401
parameterize_from_file,
pytest_generate_tests,
)
from gamestonk_terminal.discovery.short_interest_api import (
high_short_interest,
low_float,
)
assertions = unittest.TestCase("__init__")
class TestDiscoveryShortInterestApi:
@mock.patch("gamestonk_terminal.discovery.short_interest_api.requests")
@parameterize_from_file(
"test_high_short_interest",
"../tests/data/discovery_short_interest_api.yaml",
)
# pylint: disable=unused-argument
def test_high_short_interest(
self, mock_request_get, mock_high_short, expected_result
):
mock_request_get.get().text = mock_high_short
high_short_interest(["-n", "10"])
@mock.patch("gamestonk_terminal.discovery.short_interest_api.requests")
@parameterize_from_file(
"test_low_float",
"../tests/data/discovery_short_interest_api.yaml",
)
# pylint: disable=unused-argument
def test_low_float(self, mock_request_get, mock_low_float, expected_result):
mock_request_get.get().text = mock_low_float
low_float(["-n", "10"])

View File

@@ -0,0 +1,54 @@
""" discovery/short_interest_api.py tests """
import unittest
from unittest import mock
# pylint: disable=unused-import
from gamestonk_terminal.test_helper import ( # noqa: F401
parameterize_from_file,
pytest_generate_tests,
)
from gamestonk_terminal.discovery.short_interest_model import (
get_high_short_interest,
get_low_float,
)
assertions = unittest.TestCase("__init__")
class TestDiscoveryShortInterestApi:
@mock.patch("gamestonk_terminal.discovery.short_interest_model.requests")
@parameterize_from_file(
"test_get_high_short_interest",
"../tests/data/discovery_short_interest_model.yaml",
)
# pylint: disable=unused-argument
def test_get_high_short_interest(
self, mock_request_get, mock_high_short, expected_result
):
mock_request_get.get().text = mock_high_short
df_high_short = get_high_short_interest()
assertions.assertEqual.__self__.maxDiff = None
assertions.assertEqual(
df_high_short.to_csv().replace("\r\n", "\n"),
expected_result.replace("\r\n", "\n"),
)
@mock.patch("gamestonk_terminal.discovery.short_interest_model.requests")
@parameterize_from_file(
"test_get_low_float",
"../tests/data/discovery_short_interest_model.yaml",
)
# pylint: disable=unused-argument
def test_get_low_float(self, mock_request_get, mock_low_float, expected_result):
mock_request_get.get().text = mock_low_float
df_low_float = get_low_float()
assertions.assertEqual.__self__.maxDiff = None
assertions.assertEqual(
df_low_float.to_csv().replace("\r\n", "\n"),
expected_result.replace("\r\n", "\n"),
)