Refactor discovery menu (#657)

* Remove disc open browser websites

* remove sentiment investor from discovery

* add popular,emerging SI cmds to ba

* fix typo

* refactor disc/finnhub commands

* refactor disc/yfinance commands

* refactor disc/ford command

* refactor disc/arkord command

* fix disc/upcoming refactoring

* fix disc/upcoming refactoring

* fix disc/latest-trending news refactoring

* refactor disc/shortinterest commands

* refactor disc/shortinterest commands

* fix tests

* Update test_coingecko_crypto.py

* improvement after review

* add todo

Co-authored-by: jmaslek <jmaslek11@gmail.com>
This commit is contained in:
DidierRLopes
2021-08-10 00:49:07 +01:00
committed by GitHub
parent dddc912c2d
commit 6a641f2a09
26 changed files with 1168 additions and 966 deletions

View File

View File

View File

@@ -7,7 +7,7 @@ import os
import statistics
import textwrap
import time
from typing import Union, Optional, List, Tuple
from typing import Union, Optional, List, Tuple, Any
import matplotlib.dates as mdates
import pandas as pd
@@ -35,6 +35,83 @@ pd.plotting.register_matplotlib_converters()
# suppress warning messages for a clean interface
logging.getLogger().setLevel(logging.CRITICAL)
__command_descriptions = {
"popular": f"""
The {Style.BRIGHT}popular{Style.RESET_ALL} command prints the stocks with highest Average Hype Index right now.
{Style.BRIGHT}AHI (Absolute Hype Index){Style.RESET_ALL}
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock
on a social network by the mean number of mentions any stock receives on that
social medium.
===
{Style.BRIGHT}Sentiment Investor{Style.RESET_ALL} analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
""",
"emerging": f"""
The {Style.BRIGHT}emerging{Style.RESET_ALL} command prints the stocks with highest Relative Hype Index right now.
{Style.BRIGHT}RHI (Relative Hype Index){Style.RESET_ALL}
---
RHI is a measure of whether people are talking about a stock more or less than
usual, calculated by dividing the mean AHI for the past day by the mean AHI for
for the past week for that stock.
===
{Style.BRIGHT}Sentiment Investor{Style.RESET_ALL} analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
""",
}
def sort_sentiment(metric: str, other_args: List[str], command_name: str) -> None:
parser = argparse.ArgumentParser(
add_help=False,
prog=command_name,
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent(__command_descriptions[command_name]),
)
parser.add_argument(
"-l",
"--limit",
action="store",
dest="limit",
type=int,
default=10,
help="the maximum number of stocks to retrieve",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = sentipy.sort(metric, ns_parser.limit)
table: List[List[Any]] = []
for index, stock in enumerate(data):
if not hasattr(stock, "symbol") or not hasattr(stock, metric):
logging.warning("data for stock %s is incomplete, ignoring", index + 1)
table.append([])
else:
table.append([index + 1, stock.symbol, stock.__getattribute__(metric)])
print(
tabulate.tabulate(table, headers=["Rank", "Ticker", metric], floatfmt=".3f")
)
print("")
except Exception as e:
logging.error(e)
print(e, "\n")
@dataclasses.dataclass
class _Boundary:

View File

@@ -50,6 +50,9 @@ class BehaviouralAnalysisController:
"metrics",
"social",
"historical",
"emerging",
"popular",
"popularsi",
]
def __init__(self, ticker: str, start: datetime):
@@ -104,6 +107,10 @@ class BehaviouralAnalysisController:
print(" queries top related queries with this stock")
print(" rise top rising related queries with stock")
print("SentimentInvestor:")
print(" popularsi show most popular stocks on social media right now")
print(
" emerging show stocks that are being talked about more than usual"
)
print(" metrics core social sentiment metrics for this stock")
print(" social social media figures for stock popularity")
print(" historical plot the past week of data for a selected metric")
@@ -264,6 +271,14 @@ class BehaviouralAnalysisController:
"""Process historical command"""
sentimentinvestor_view.historical(self.ticker, other_args)
def call_popularsi(self, other_args: List[str]):
"""Process popular command"""
sentimentinvestor_view.sort_sentiment("AHI", other_args, "popular")
def call_emerging(self, other_args: List[str]):
"""Process emerging command"""
sentimentinvestor_view.sort_sentiment("RHI", other_args, "emerging")
def menu(ticker: str, start: datetime):
"""Behavioural Analysis Menu"""

View File

@@ -22,7 +22,6 @@ def get_ark_orders() -> 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

View File

@@ -1,18 +1,13 @@
""" ARK View """
__docformat__ = "numpy"
import argparse
from typing import List
from colorama import Fore, Style
import os
import pandas as pd
from tabulate import tabulate
from colorama import Fore, Style
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.helper_funcs import export_data
from gamestonk_terminal.stocks.discovery import ark_model
@@ -40,64 +35,45 @@ def direction_color_red_green(val: str) -> str:
return ret
def ark_orders_view(other_args: List[str]):
def ark_orders_view(num: int, export: str):
"""Prints a table of the last N ARK Orders
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
num: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ARK Orders",
description="""
Orders by ARK Investment Management LLC - https://ark-funds.com/. [Source: https://cathiesark.com]
""",
df_orders = ark_model.get_ark_orders()
if df_orders.empty:
print("The ARK orders aren't available at the moment.\n")
return
pd.set_option("mode.chained_assignment", None)
df_orders = ark_model.add_order_total(df_orders.head(num))
if gtff.USE_COLOR:
df_orders["direction"] = df_orders["direction"].apply(direction_color_red_green)
# df_orders["link"] = "https://finviz.com/quote.ashx?t=" + df_orders["ticker"]
print("Orders by ARK Investment Management LLC")
print(
tabulate(
df_orders,
headers=df_orders.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=20,
help="Last N orders.",
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"arkord",
df_orders,
)
try:
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 available 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("")
except Exception as e:
print(e, "\n")

View File

@@ -4,24 +4,28 @@ __docformat__ = "numpy"
import argparse
import os
from typing import List
from datetime import datetime
from matplotlib import pyplot as plt
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.helper_funcs import (
parse_known_args_and_warn,
check_non_negative,
check_positive,
valid_date,
check_int_range,
)
from gamestonk_terminal.stocks.discovery import (
ark_view,
fidelity_view,
seeking_alpha_view,
short_interest_view,
simply_wallst_view,
spachero_view,
unusual_whales_view,
yahoo_finance_view,
shortinterest_view,
yahoofinance_view,
finra_ats_view,
finnhub_view,
stockgrid_view,
sentimentinvestor_view,
)
@@ -35,26 +39,27 @@ class DiscoveryController:
"help",
"q",
"quit",
"ipo",
]
CHOICES_COMMANDS = [
"pipo",
"fipo",
"gainers",
"losers",
"orders",
"ark_orders",
"up_earnings",
"high_short",
"low_float",
"simply_wallst",
"spachero",
"uwhales",
"ford",
"arkord",
"upcoming",
"latest",
"trending",
"highshort",
"lowfloat",
"darkpool",
"darkshort",
"shortvol",
"popular",
"emerging",
]
CHOICES += CHOICES_COMMANDS
def __init__(self):
"""Constructor"""
self.disc_parser = argparse.ArgumentParser(add_help=False, prog="disc")
@@ -66,46 +71,38 @@ class DiscoveryController:
@staticmethod
def print_help():
"""Print help"""
print(
"https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/stocks/discovery"
)
print("\nDiscovery Mode:")
print(" cls clear screen")
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(" ipo past and future IPOs [Finnhub]")
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 [www.cathiesark.com]"
)
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(" latest latest news [Seeking Alpha]")
print(" trending trending news [Seeking Alpha]")
print(
" darkpool promising tickers based on dark pool shares regression [FINRA]"
)
print(" darkshort dark pool short position [Stockgrid.io]")
print(" shortvol short interest and days to cover [Stockgrid.io]")
print(
" popular show most popular stocks on social media right now [SentimentInvestor.com]"
)
print(
" emerging show stocks that are being talked about more than usual [SentimentInvestor.com]"
)
print("")
help_text = """https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/stocks/discovery
Discovery:
cls clear screen")
?/help show this menu again")
q quit this menu, and shows back to main menu")
quit quit to abandon program")
Finnhub:
pipo past IPOs dates
fipo future IPOs dates
Yahoo Finance:
gainers show latest top gainers
losers show latest top losers
Fidelity:
ford orders by Fidelity Customers
cathiesark.com:
arkord orders by ARK Investment Management LLC
Seeking Alpha:
upcoming upcoming earnings release dates
latest latest news
trending trending news
shortinterest.com
highshort show top high short interest stocks of over 20% ratio
lowfloat show low float stocks under 10M shares float
FINRA:
darkpool promising tickers based on dark pool shares regression
Stockgrid:
darkshort dark pool short position
shortvol short interest and days to cover
"""
print(help_text)
def switch(self, an_input: str):
"""Process and dispatch input
@@ -150,57 +147,534 @@ class DiscoveryController:
"""Process Quit command - quit the program"""
return True
def call_ipo(self, other_args: List[str]):
"""Process ipo command"""
finnhub_view.ipo_calendar(other_args)
def call_pipo(self, other_args: List[str]):
"""Process pipo command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="pipo",
description="""
Past IPOs dates. [Source: https://finnhub.io]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="num",
type=check_non_negative,
default=5,
help="Number of past days to look for IPOs.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
finnhub_view.past_ipo(
num_days_behind=ns_parser.num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_fipo(self, other_args: List[str]):
"""Process fipo command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="fipo",
description="""
Future IPOs dates. [Source: https://finnhub.io]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="num",
type=check_non_negative,
default=5,
help="Number of future days to look for IPOs.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
finnhub_view.future_ipo(
num_days_ahead=ns_parser.num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_gainers(self, other_args: List[str]):
"""Process gainers command"""
yahoo_finance_view.gainers_view(other_args)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="gainers",
description="Print up to 25 top ticker gainers. [Source: Yahoo Finance]",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="num",
type=check_int_range(1, 25),
default=5,
help="Number of the top gainers stocks to retrieve.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoofinance_view.display_gainers(
num_stocks=ns_parser.num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_losers(self, other_args: List[str]):
"""Process losers command"""
yahoo_finance_view.losers_view(other_args)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="losers",
description="Print up to 25 top ticker losers. [Source: Yahoo Finance]",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="num",
type=check_int_range(1, 25),
default=5,
help="Number of the top losers stocks to retrieve.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
def call_orders(self, other_args: List[str]):
"""Process orders command"""
fidelity_view.orders_view(other_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
def call_ark_orders(self, other_args: List[str]):
"""Process ark_orders command"""
ark_view.ark_orders_view(other_args)
yahoofinance_view.display_losers(
num_stocks=ns_parser.num,
export=ns_parser.export,
)
def call_up_earnings(self, other_args: List[str]):
"""Process up_earnings command"""
seeking_alpha_view.earnings_release_dates_view(other_args)
except Exception as e:
print(e, "\n")
def call_high_short(self, other_args: List[str]):
"""Process high_short command"""
short_interest_view.high_short_interest_view(other_args)
def call_ford(self, other_args: List[str]):
"""Process ford command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ford",
description="""
Orders by Fidelity customers. Information shown in the table below
is based on the volume of orders entered on the "as of" date shown. Securities
identified are not recommended or endorsed by Fidelity and are displayed for
informational purposes only. [Source: Fidelity]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top ordered stocks to be printed.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
def call_low_float(self, other_args: List[str]):
"""Process low_float command"""
short_interest_view.low_float_view(other_args)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
def call_simply_wallst(self, other_args: List[str]):
"""Process simply_wallst command"""
simply_wallst_view.simply_wallst_view(other_args)
fidelity_view.orders_view(
num=ns_parser.n_num,
export=ns_parser.export,
)
def call_spachero(self, other_args: List[str]):
"""Process spachero command"""
spachero_view.spachero_view(other_args)
except Exception as e:
print(e, "\n")
def call_uwhales(self, other_args: List[str]):
"""Process uwhales command"""
unusual_whales_view.unusual_whales_view(other_args)
def call_arkord(self, other_args: List[str]):
"""Process arkord command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="arkord",
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=10,
help="Last N ARK orders.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
ark_view.ark_orders_view(
num=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_upcoming(self, other_args: List[str]):
"""Process upcoming command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="upcoming",
description="""Upcoming earnings release dates. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-p",
"--pages",
action="store",
dest="n_pages",
type=check_positive,
default=10,
help="Number of pages to read upcoming earnings from in Seeking Alpha website.",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of upcoming earnings release dates to display",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-n")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
seeking_alpha_view.upcoming_earning_release_dates(
num_pages=ns_parser.n_pages,
num_earnings=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_latest(self, other_args: List[str]):
"""Process latest command"""
seeking_alpha_view.latest_news_view(other_args)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="latest",
description="""Latest news articles. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-i",
"--id",
action="store",
dest="n_id",
type=check_positive,
default=-1,
help="article ID",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="number of articles being printed",
)
parser.add_argument(
"-d",
"--date",
action="store",
dest="s_date",
type=valid_date,
default=datetime.now().strftime("%Y-%m-%d"),
help="starting date of articles",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
seeking_alpha_view.news(
news_type="latest",
article_id=ns_parser.n_id,
num=ns_parser.n_num,
start_date=ns_parser.s_date,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_trending(self, other_args: List[str]):
"""Process trending command"""
seeking_alpha_view.trending_news_view(other_args)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="trending",
description="""Trending news articles. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-i",
"--id",
action="store",
dest="n_id",
type=check_positive,
default=-1,
help="article ID",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="number of articles being printed",
)
parser.add_argument(
"-d",
"--date",
action="store",
dest="s_date",
type=valid_date,
default=datetime.now().strftime("%Y-%m-%d"),
help="starting date of articles",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
seeking_alpha_view.news(
news_type="trending",
article_id=ns_parser.n_id,
num=ns_parser.n_num,
start_date=ns_parser.s_date,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_highshort(self, other_args: List[str]):
"""Process highshort command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="highshort",
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.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
shortinterest_view.high_short_interest(
num=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_lowfloat(self, other_args: List[str]):
"""Process lowfloat command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="lowfloat",
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.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
shortinterest_view.low_float(
num=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_darkpool(self, other_args: List[str]):
"""Process darkpool command"""
@@ -214,14 +688,6 @@ class DiscoveryController:
"""Process shortvol command"""
stockgrid_view.shortvol(other_args)
def call_popular(self, other_args: List[str]):
"""Process popular command"""
sentimentinvestor_view.sort("AHI", other_args, "popular")
def call_emerging(self, other_args: List[str]):
"""Process popular command"""
sentimentinvestor_view.sort("RHI", other_args, "emerging")
def menu():
"""Discovery Menu"""

View File

@@ -20,7 +20,6 @@ def get_orders() -> Tuple[str, DataFrame]:
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"
)

View File

@@ -1,17 +1,13 @@
""" Fidelity View """
__docformat__ = "numpy"
import argparse
from typing import List
import os
import re
from tabulate import tabulate
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.helper_funcs import export_data
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.stocks.discovery import fidelity_model
@@ -69,58 +65,45 @@ def price_change_color_red_green(val: str) -> str:
return color + val + Style.RESET_ALL
def orders_view(other_args: List[str]):
"""Prints a table with the last N orders by Fidelity customers
def orders_view(num: int, export: str):
"""Prints last N orders by Fidelity customers. [Source: Fidelity]
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
num: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="orders",
description="""
Orders by Fidelity customers. Information shown in the table below
is based on the volume of orders entered on the "as of" date shown. Securities
identified are not recommended or endorsed by Fidelity and are displayed for
informational purposes only. [Source: Fidelity]
""",
order_header, df_orders = fidelity_model.get_orders()
print(order_header, ":")
pd.set_option("display.max_colwidth", None)
if gtff.USE_COLOR:
df_orders["Buy / Sell Ratio"] = df_orders["Buy / Sell Ratio"].apply(
buy_sell_ratio_color_red_green
)
df_orders["Price Change"] = df_orders["Price Change"].apply(
price_change_color_red_green
)
df_orders = df_orders.head(n=num).iloc[:, :-1]
print(
tabulate(
df_orders,
headers=df_orders.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of top ordered stocks to be printed.",
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"ford",
df_orders,
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
order_header, df_orders = fidelity_model.get_orders()
print(order_header, ":")
pd.set_option("display.max_colwidth", None)
if gtff.USE_COLOR:
df_orders["Buy / Sell Ratio"] = df_orders["Buy / Sell Ratio"].apply(
buy_sell_ratio_color_red_green
)
df_orders["Price Change"] = df_orders["Price Change"].apply(
price_change_color_red_green
)
patch_pandas_text_adjustment()
print(df_orders.head(n=ns_parser.n_num).iloc[:, :-1].to_string(index=False))
print("")
except Exception as e:
print(e, "\n")

View File

@@ -0,0 +1,40 @@
import requests
import pandas as pd
from gamestonk_terminal import config_terminal as cfg
def get_ipo_calendar(from_date: str, to_date: str) -> pd.DataFrame:
"""Get IPO calendar
Parameters
----------
from_date : str
from date (%Y-%m-%d) to get IPO calendar
to_date : str
to date (%Y-%m-%d) to get IPO calendar
Returns
-------
pd.DataFrame
Get dataframe with economic calendar events
"""
response = requests.get(
f"https://finnhub.io/api/v1/calendar/ipo?from={from_date}&to={to_date}&token={cfg.API_FINNHUB_KEY}"
)
if response.status_code == 200:
d_data = response.json()
if "ipoCalendar" in d_data:
d_refactor_columns = {
"numberOfShares": "Number of Shares",
"totalSharesValue": "Total Shares Value",
"date": "Date",
"exchange": "Exchange",
"name": "Name",
"price": "Price",
"status": "Status",
}
return pd.DataFrame(d_data["ipoCalendar"]).rename(
columns=d_refactor_columns
)
return pd.DataFrame()

View File

@@ -1,123 +1,102 @@
import argparse
from typing import List
import os
from datetime import datetime, timedelta
import requests
import pandas as pd
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
check_non_negative,
)
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.discovery import finnhub_model
def get_ipo_calendar(from_date: str, to_date: str) -> pd.DataFrame:
"""Get IPO calendar
def past_ipo(num_days_behind: int, export: str) -> pd.DataFrame:
"""Past IPOs dates. [Source: Finnhub]
Parameters
----------
from_date : str
from date (%Y-%m-%d) to get IPO calendar
to_date : str
to date (%Y-%m-%d) to get IPO calendar
num_days_behind: int
Number of days to look behind for IPOs dates
export : str
Export dataframe data to csv,json,xlsx file
Returns
-------
pd.DataFrame
Get dataframe with economic calendar events
df_past_ipo : pd.DataFrame
Past IPOs dates
"""
response = requests.get(
f"https://finnhub.io/api/v1/calendar/ipo?from={from_date}&to={to_date}&token={cfg.API_FINNHUB_KEY}"
today = datetime.now()
past_date = today - timedelta(days=num_days_behind)
df_past_ipo = (
finnhub_model.get_ipo_calendar(
past_date.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d")
)
.rename(columns={"Date": "Past"})
.fillna("")
)
if response.status_code == 200:
d_data = response.json()
if "ipoCalendar" in d_data:
d_refactor_columns = {
"numberOfShares": "Number of Shares",
"totalSharesValue": "Total Shares Value",
"date": "Date",
"exchange": "Exchange",
"name": "Name",
"price": "Price",
"status": "Status",
}
return pd.DataFrame(d_data["ipoCalendar"]).rename(
columns=d_refactor_columns
if df_past_ipo.empty:
print(f"No IPOs found since the last {num_days_behind} days")
else:
print(
tabulate(
df_past_ipo,
headers=df_past_ipo.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
print("")
return pd.DataFrame()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"pipo",
df_past_ipo,
)
def ipo_calendar(other_args: List[str]):
"""Past and future IPOs calendar [Finnhub]
def future_ipo(num_days_ahead: int, export: str) -> pd.DataFrame:
"""Future IPOs dates. [Source: Finnhub]
Parameters
----------
other_args : List[str]
Command line arguments to be processed with argparse
num_days_ahead: int
Number of days to look ahead for IPOs dates
export : str
Export dataframe data to csv,json,xlsx file
Returns
-------
df_future_ipo : pd.DataFrame
Future IPOs dates
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ipo",
description="""
Past and future IPOs. [Source: https://finnhub.io]
""",
)
parser.add_argument(
"-p",
"--past",
action="store",
dest="past_days",
type=check_non_negative,
default=0,
help="Number of past days to look for IPOs.",
)
parser.add_argument(
"-f",
"--future",
action="store",
dest="future_days",
type=check_non_negative,
default=10,
help="Number of future days to look for IPOs.",
today = datetime.now()
future_date = today + timedelta(days=num_days_ahead)
df_future_ipo = (
finnhub_model.get_ipo_calendar(
today.strftime("%Y-%m-%d"), future_date.strftime("%Y-%m-%d")
)
.rename(columns={"Date": "Future"})
.fillna("")
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-f")
if df_future_ipo.empty:
print(f"No IPOs found for the next {num_days_ahead} days")
else:
print(
tabulate(
df_future_ipo,
headers=df_future_ipo.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
print("")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
today = datetime.now()
if ns_parser.future_days > 0:
future_date = today + timedelta(days=ns_parser.future_days)
df_future_ipo = get_ipo_calendar(
today.strftime("%Y-%m-%d"), future_date.strftime("%Y-%m-%d")
).rename(columns={"Date": "Future"})
if df_future_ipo.empty:
print(f"No IPOs found for the next {ns_parser.future_days} days")
else:
print(df_future_ipo.to_string(index=False))
print("")
if ns_parser.past_days > 0:
past_date = today - timedelta(days=ns_parser.past_days)
df_past_ipo = get_ipo_calendar(
past_date.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d")
).rename(columns={"Date": "Past"})
if df_past_ipo.empty:
print(f"No IPOs found since the last {ns_parser.past_days} days")
else:
print(df_past_ipo.to_string(index=False))
print("")
except Exception as e:
print(e, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"fipo",
df_future_ipo,
)

View File

@@ -44,7 +44,6 @@ def get_next_earnings(pages: int) -> DataFrame:
DataFrame
Upcoming earnings DataFrame
"""
earnings = list()
url_next_earnings = "https://seekingalpha.com/earnings/earnings-calendar"

View File

@@ -1,240 +1,151 @@
""" Seeking Alpha View """
__docformat__ = "numpy"
import argparse
from typing import List
import os
from datetime import datetime
from tabulate import tabulate
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
parse_known_args_and_warn,
valid_date,
)
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.discovery import seeking_alpha_model
def earnings_release_dates_view(other_args: List[str]):
"""Prints a data frame with earnings release dates
def upcoming_earning_release_dates(num_pages: int, num_earnings: int, export: str):
"""Displays upcoming earnings release dates
Parameters
----------
other_args : List[str]
argparse other args - ["-p", "20", "-n", "5"]
num_pages: int
Number of pages to scrap
num_earnings: int
Number of upcoming earnings release dates
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="up_earnings",
description="""Upcoming earnings release dates. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-p",
"--pages",
action="store",
dest="n_pages",
type=check_positive,
default=10,
help="Number of pages to read upcoming earnings from in Seeking Alpha website.",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=3,
help="Number of upcoming earnings release dates to print",
)
# TODO: Check why there are repeated companies
# TODO: Create a similar command that returns not only upcoming, but antecipated earnings
# i.e. companies where expectation on their returns are high
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_earnings = seeking_alpha_model.get_next_earnings(num_pages)
df_earnings = seeking_alpha_model.get_next_earnings(ns_parser.n_pages)
pd.set_option("display.max_colwidth", None)
if export:
l_earnings = list()
l_earnings_dates = list()
pd.set_option("display.max_colwidth", None)
for n_days, earning_date in enumerate(df_earnings.index.unique()):
if n_days > (ns_parser.n_num - 1):
for n_days, earning_date in enumerate(df_earnings.index.unique()):
if n_days > (num_earnings - 1):
break
# TODO: Potentially extract Market Cap for each Ticker, and sort
# by Market Cap. Then cut the number of tickers shown to 10 with
# bigger market cap. Didier attempted this with yfinance, but
# the computational time involved wasn't worth pursuing that solution.
df_earn = df_earnings[earning_date == df_earnings.index][
["Ticker", "Name"]
].dropna()
if export:
l_earnings_dates.append(earning_date.date())
l_earnings.append(df_earn)
df_earn.index = df_earn["Ticker"].values
df_earn.drop(columns=["Ticker"], inplace=True)
print(
tabulate(
df_earn,
showindex=True,
headers=[f"Earnings on {earning_date.date()}"],
tablefmt="fancy_grid",
),
"\n",
)
if export:
for i, _ in enumerate(l_earnings):
l_earnings[i].reset_index(drop=True, inplace=True)
df_data = pd.concat(l_earnings, axis=1, ignore_index=True)
df_data.columns = l_earnings_dates
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"upcoming",
df_data,
)
def news(news_type: str, article_id: int, num: int, start_date: datetime, export: str):
"""Prints the latest news article list. [Source: Seeking Alpha]
Parameters
----------
news_type: str
Select between 'latest' or 'trending'
article_id: int
Article ID. If -1, none is selected
num: int
Number of articles to display. Only used if article_id is -1.
start_date : datetime
Date from when to get articles dates. Only used if article_id is -1.
export : str
Export dataframe data to csv,json,xlsx file
"""
# User wants to see all latest news
if article_id == -1:
if news_type == "latest":
articles = seeking_alpha_model.get_article_list(start_date, num)
elif news_type == "trending":
articles = seeking_alpha_model.get_trending_list(num)
else:
print("Wrong type of news selected", "\n")
if export:
df_articles = pd.DataFrame(articles)
for idx, article in enumerate(articles):
print(
article["publishedAt"].replace("T", " ").replace("Z", ""),
"-",
article["id"],
"-",
article["title"],
)
print(article["url"])
print("")
if idx >= num - 1:
break
print(f"Earning Release on {earning_date.date()}")
print("----------------------------------------------")
print(
df_earnings[earning_date == df_earnings.index][
["Ticker", "Name"]
].to_string(index=False, header=False)
)
print("")
except Exception as e:
print(e, "\n")
def latest_news_view(other_args: List[str]):
"""Prints the latest news article list
Parameters
----------
other_args : List[str]
argparse other args - ["-i", "123123", "-n", "5"]
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="latest",
description="""Latest news articles. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-i",
"--id",
action="store",
dest="n_id",
type=check_positive,
default=-1,
help="article ID number",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of articles being printed",
)
parser.add_argument(
"-d",
"--date",
action="store",
dest="n_date",
type=valid_date,
default=datetime.now().strftime("%Y-%m-%d"),
help="starting date",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
# User wants to see all latest news
if ns_parser.n_id == -1:
articles = seeking_alpha_model.get_article_list(
ns_parser.n_date, ns_parser.n_num
)
for idx, article in enumerate(articles):
print(
article["publishedAt"].replace("T", " ").replace("Z", ""),
"-",
article["id"],
"-",
article["title"],
)
print(article["url"])
print("")
if idx >= ns_parser.n_num - 1:
break
# User wants to access specific article
# User wants to access specific article
else:
if news_type == "latest":
article = seeking_alpha_model.get_article_data(article_id)
elif news_type == "trending":
article = seeking_alpha_model.get_article_data(article_id)
else:
article = seeking_alpha_model.get_article_data(ns_parser.n_id)
print(
article["publishedAt"][: article["publishedAt"].rfind(":") - 3].replace(
"T", " "
),
" ",
article["title"],
)
print(article["url"])
print("")
print(article["content"])
print("Wrong type of news selected", "\n")
except Exception as e:
print(e, "\n")
if export:
df_articles = pd.DataFrame(article)
print(
article["publishedAt"][: article["publishedAt"].rfind(":") - 3].replace(
"T", " "
),
" ",
article["title"],
)
print(article["url"])
print("")
print(article["content"])
def trending_news_view(other_args: List[str]):
"""Prints the trending news article list
Parameters
----------
other_args : List[str]
argparse other args - ["i", "123123", "-n", "5"]
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="trending",
description="""Trending news articles. [Source: Seeking Alpha]""",
)
parser.add_argument(
"-i",
"--id",
action="store",
dest="n_id",
type=check_positive,
default=-1,
help="article ID number",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of articles being printed",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
# User wants to see all trending articles
if ns_parser.n_id == -1:
articles = seeking_alpha_model.get_trending_list(ns_parser.n_num)
for idx, article in enumerate(articles):
print(
article["publishedAt"].replace("T", " ").replace("Z", ""),
"-",
article["id"],
"-",
article["title"],
)
print(article["url"])
print("")
if idx >= ns_parser.n_num - 1:
break
# User wants to access specific article
else:
article = seeking_alpha_model.get_article_data(ns_parser.n_id)
print(
article["publishedAt"][: article["publishedAt"].rfind(":") - 3].replace(
"T", " "
),
" ",
article["title"],
)
print(article["url"])
print("")
print(article["content"])
except Exception as e:
print(e, "\n")
if export:
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
news_type,
df_articles,
)

View File

@@ -1,91 +0,0 @@
import argparse
import logging
import textwrap
from typing import Any, List
from colorama import Style
from sentipy.sentipy import Sentipy
from tabulate import tabulate
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
sentipy: Sentipy = Sentipy(
token=cfg.API_SENTIMENTINVESTOR_TOKEN, key=cfg.API_SENTIMENTINVESTOR_KEY
)
"""Initialise SentiPy with the user's API token and key"""
__command_descriptions = {
"popular": f"""
The {Style.BRIGHT}popular{Style.RESET_ALL} command prints the stocks with highest Average Hype Index right now.
{Style.BRIGHT}AHI (Absolute Hype Index){Style.RESET_ALL}
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock
on a social network by the mean number of mentions any stock receives on that
social medium.
===
{Style.BRIGHT}Sentiment Investor{Style.RESET_ALL} analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
""",
"emerging": f"""
The {Style.BRIGHT}emerging{Style.RESET_ALL} command prints the stocks with highest Relative Hype Index right now.
{Style.BRIGHT}RHI (Relative Hype Index){Style.RESET_ALL}
---
RHI is a measure of whether people are talking about a stock more or less than
usual, calculated by dividing the mean AHI for the past day by the mean AHI for
for the past week for that stock.
===
{Style.BRIGHT}Sentiment Investor{Style.RESET_ALL} analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
""",
}
def sort(metric: str, other_args: List[str], command_name: str) -> None:
parser = argparse.ArgumentParser(
add_help=False,
prog=command_name,
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent(__command_descriptions[command_name]),
)
parser.add_argument(
"-l",
"--limit",
action="store",
dest="limit",
type=int,
default=10,
help="the maximum number of stocks to retrieve",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = sentipy.sort(metric, ns_parser.limit)
table: List[List[Any]] = []
for index, stock in enumerate(data):
if not hasattr(stock, "symbol") or not hasattr(stock, metric):
logging.warning("data for stock %s is incomplete, ignoring", index + 1)
table.append([])
else:
table.append([index + 1, stock.symbol, stock.__getattribute__(metric)])
print(tabulate(table, headers=["Rank", "Ticker", metric], floatfmt=".3f"))
print()
except Exception as e:
logging.error(e)
print(e, "\n")

View File

@@ -1,102 +0,0 @@
""" 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.stocks.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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
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.",
)
try:
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("")
except Exception as e:
print(e, "\n")
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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
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.",
)
try:
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("")
except Exception as e:
print(e, "\n")

View File

@@ -0,0 +1,75 @@
""" Short Interest View """
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.discovery import shortinterest_model
def high_short_interest(num: int, export: str):
"""Prints top N high shorted interest stocks from https://www.highshortinterest.com
Parameters
----------
num: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df_high_short_interest = shortinterest_model.get_high_short_interest()
df_high_short_interest = df_high_short_interest.iloc[1:].head(n=num)
print(
tabulate(
df_high_short_interest,
headers=df_high_short_interest.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"lowfloat",
df_high_short_interest,
)
def low_float(num: int, export: str):
"""Prints top N low float stocks from https://www.lowfloat.com
Parameters
----------
num: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df_low_float = shortinterest_model.get_low_float()
df_low_float = df_low_float.iloc[1:].head(n=num)
print(
tabulate(
df_low_float,
headers=df_low_float.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"lowfloat",
df_low_float,
)
# TODO: Add https://www.pennystockflow.com

View File

@@ -1,76 +0,0 @@
""" 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_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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="simply_wallst",
description="""
Simply Wall Street Research. Opens web browser. Although this does not require
an API key, it requires a subscription to the website by the user
(there's a 14 days free trial).[Source: Simply Wall St.]
""",
)
parser.add_argument(
"-i",
"--industry",
action="store",
dest="s_industry",
type=str,
default="any",
help="Industry of interest.",
choices=[
"any",
"automobiles",
"banks",
"capital-goods",
"commercial-services",
"consumer-durables",
"consumer-services",
"diversified-financials",
"energy",
"consumer-retailing",
"food-beverage-tobacco",
"healthcare",
"household",
"insurance",
"materials",
"media",
"pharmaceuticals-biotech",
"real-estate",
"retail",
"semiconductors",
"software",
"tech",
"telecom",
"transportation",
"utilities",
],
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
webbrowser.open(
f"https://simplywall.st/stocks/us/{ns_parser.s_industry}?page=1"
)
print("")
except Exception as e:
print(e, "\n")

View File

@@ -1,34 +0,0 @@
""" 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_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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="spachero",
description="""Great website for SPACs research. [Source: www.spachero.com]""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
webbrowser.open("https://www.spachero.com")
print("")
except Exception as e:
print(e, "\n")

View File

@@ -1,31 +0,0 @@
import argparse
from typing import List
import webbrowser
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="uwhales",
description="""Good website for SPACs research. [Source: www.unusualwhales.com]""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
webbrowser.open("https://unusualwhales.com/spacs")
print("")
except Exception as e:
print(e, "\n")

View File

@@ -1,93 +0,0 @@
""" Yahoo Finance View """
__docformat__ = "numpy"
import argparse
from typing import List
import pandas as pd
import requests
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="gainers",
description="Print up to 25 top ticker gainers. [Source: Yahoo Finance]",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_gainers",
type=int,
default=5,
choices=range(1, 25),
help="Number of the top gainers stocks to retrieve.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
url = "https://finance.yahoo.com/screener/predefined/day_gainers"
df_gainers = pd.read_html(requests.get(url).text)[0]
print(df_gainers.head(ns_parser.n_gainers).to_string(index=False))
print("")
except Exception as e:
print(e, "\n")
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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="losers",
description="Print up to 25 top ticker losers. [Source: Yahoo Finance]",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_losers",
type=int,
default=5,
choices=range(1, 25),
help="Number of the top losers stocks to retrieve.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
url = "https://finance.yahoo.com/screener/predefined/day_losers"
df_losers = pd.read_html(requests.get(url).text)[0]
print(df_losers.head(ns_parser.n_losers).to_string(index=False))
print("")
except Exception as e:
print(e, "\n")

View File

@@ -0,0 +1,31 @@
""" Yahoo Finance Model """
__docformat__ = "numpy"
import pandas as pd
import requests
def get_gainers() -> pd.DataFrame:
"""Get Yahoo Finance gainers
Returns
-------
pd.DataFrame
Stock Gainers
"""
url_gainers = "https://finance.yahoo.com/screener/predefined/day_gainers"
return pd.read_html(requests.get(url_gainers).text)[0]
def get_losers() -> pd.DataFrame:
"""Get Yahoo Finance losers
Returns
-------
pd.DataFrame
Stock Losers
"""
url_losers = "https://finance.yahoo.com/screener/predefined/day_losers"
return pd.read_html(requests.get(url_losers).text)[0]

View File

@@ -0,0 +1,79 @@
""" Yahoo Finance View """
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.discovery import yahoofinance_model
def display_gainers(num_stocks: int, export: str):
"""Display gainers. [Source: Yahoo Finance]
Parameters
----------
num_stocks: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df_gainers = yahoofinance_model.get_gainers().head(num_stocks)
df_gainers.dropna(how="all", axis=1, inplace=True)
df_gainers = df_gainers.replace(float("NaN"), "")
if df_gainers.empty:
print("No gainers found.")
else:
print(
tabulate(
df_gainers,
headers=df_gainers.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"gainers",
df_gainers,
)
def display_losers(num_stocks: int, export: str):
"""Display losers. [Source: Yahoo Finance]
Parameters
----------
num_stocks: int
Number of stocks to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df_losers = yahoofinance_model.get_losers().head(num_stocks)
df_losers.dropna(how="all", axis=1, inplace=True)
df_losers = df_losers.replace(float("NaN"), "")
if df_losers.empty:
print("No losers found.")
else:
print(
tabulate(
df_losers,
headers=df_losers.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"losers",
df_losers,
)

View File

@@ -41,4 +41,4 @@ class TestDiscoveryArkView:
parse_dates=["date"],
)
ark_orders_view(["-n", "10"])
ark_orders_view(10, "")

View File

@@ -10,7 +10,7 @@ from gamestonk_terminal.stocks.discovery.fidelity_view import (
class TestDiscoveryFidelityApi(unittest.TestCase):
def test_orders(self):
orders_view([])
orders_view(5, "")
def test_buy_sell_ratio_color_red_green(self):
res = buy_sell_ratio_color_red_green("56% Buys, 44% Sells")

View File

@@ -8,7 +8,7 @@ from gamestonk_terminal.test_helper import ( # noqa: F401
pytest_generate_tests,
)
from gamestonk_terminal.stocks.discovery.short_interest_model import (
from gamestonk_terminal.stocks.discovery.shortinterest_model import (
get_high_short_interest,
get_low_float,
)
@@ -17,7 +17,7 @@ assertions = unittest.TestCase("__init__")
class TestDiscoveryShortInterestApi:
@mock.patch("gamestonk_terminal.stocks.discovery.short_interest_model.requests")
@mock.patch("gamestonk_terminal.stocks.discovery.shortinterest_model.requests")
@parameterize_from_file(
"test_get_high_short_interest",
"../tests/data/discovery_short_interest_model.yaml",
@@ -36,7 +36,7 @@ class TestDiscoveryShortInterestApi:
expected_result.replace("\r\n", "\n"),
)
@mock.patch("gamestonk_terminal.stocks.discovery.short_interest_model.requests")
@mock.patch("gamestonk_terminal.stocks.discovery.shortinterest_model.requests")
@parameterize_from_file(
"test_get_low_float",
"../tests/data/discovery_short_interest_model.yaml",