mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-05 08:51:20 +00:00
Merge pull request #293 from DidierRLopes/disco-refactor
Discovery menu refactor
This commit is contained in:
@@ -1 +1 @@
|
||||
from . import disc_menu # noqa: F401
|
||||
from . import disc_controller # noqa: F401
|
||||
|
||||
@@ -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("")
|
||||
@@ -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("")
|
||||
96
gamestonk_terminal/discovery/ark_view.py
Normal file
96
gamestonk_terminal/discovery/ark_view.py
Normal 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("")
|
||||
188
gamestonk_terminal/discovery/disc_controller.py
Normal file
188
gamestonk_terminal/discovery/disc_controller.py
Normal 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
|
||||
@@ -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!")
|
||||
93
gamestonk_terminal/discovery/fidelity_model.py
Normal file
93
gamestonk_terminal/discovery/fidelity_model.py
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
51
gamestonk_terminal/discovery/seeking_alpha_model.py
Executable file
51
gamestonk_terminal/discovery/seeking_alpha_model.py
Executable 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
|
||||
@@ -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()):
|
||||
@@ -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
|
||||
95
gamestonk_terminal/discovery/short_interest_view.py
Normal file
95
gamestonk_terminal/discovery/short_interest_view.py
Normal 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("")
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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"])
|
||||
54
tests/test_discovery_short_interest_model.py
Normal file
54
tests/test_discovery_short_interest_model.py
Normal 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"),
|
||||
)
|
||||
Reference in New Issue
Block a user