Merge pull request #332 from DidierRLopes/refactor-dd

Refactoring Due Diligence controller
This commit is contained in:
Artem Veremey
2021-04-12 16:46:35 -07:00
committed by GitHub
13 changed files with 510 additions and 238 deletions

View File

@@ -1,6 +1,11 @@
""" Business Insider View """
__docformat__ = "numpy"
import argparse
from typing import List
import json
import re
from pandas.core.frame import DataFrame
import requests
import matplotlib.pyplot as plt
import pandas as pd
@@ -12,11 +17,30 @@ from gamestonk_terminal.helper_funcs import (
get_user_agent,
parse_known_args_and_warn,
)
from gamestonk_terminal import feature_flags as gtff
register_matplotlib_converters()
def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
def price_target_from_analysts(
other_args: List[str], stock: DataFrame, ticker: str, start: str, interval: str
):
"""Display analysts' price targets for a given stock
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
stock : DataFrame
Due diligence stock dataframe
ticker : str
Due diligence ticker symbol
start : str
Start date of the stock data
interval : str
Stock data interval
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="pt",
@@ -34,12 +58,12 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
)
try:
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_market_business_insider = (
f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock"
f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
@@ -59,8 +83,7 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
d_analyst_data = json.loads(s_analyst_data)
break
# pprint.pprint(d_analyst_data)
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data["Markers"])
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data["Markers"]) # type: ignore
df_analyst_data = df_analyst_data[
["DateLabel", "Company", "InternalRating", "PriceTarget"]
]
@@ -73,17 +96,17 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
df_analyst_data = df_analyst_data.set_index("Date")
# Slice start of ratings
if s_start:
df_analyst_data = df_analyst_data[s_start:]
if start:
df_analyst_data = df_analyst_data[start:] # type: ignore
if s_interval == "1440min":
plt.plot(df_stock.index, df_stock["5. adjusted close"].values, lw=3)
if interval == "1440min":
plt.plot(stock.index, stock["5. adjusted close"].values, lw=3)
# Intraday
else:
plt.plot(df_stock.index, df_stock["4. close"].values, lw=3)
plt.plot(stock.index, stock["4. close"].values, lw=3)
if s_start:
plt.plot(df_analyst_data.groupby(by=["Date"]).mean()[s_start:])
if start:
plt.plot(df_analyst_data.groupby(by=["Date"]).mean()[start:]) # type: ignore
else:
plt.plot(df_analyst_data.groupby(by=["Date"]).mean())
@@ -91,13 +114,17 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
plt.legend(["Closing Price", "Average Price Target", "Price Target"])
plt.title(f"{s_ticker} (Time Series) and Price Target")
plt.xlim(df_stock.index[0], df_stock.index[-1])
plt.title(f"{ticker} (Time Series) and Price Target")
plt.xlim(stock.index[0], stock.index[-1])
plt.xlabel("Time")
plt.ylabel("Share Price ($)")
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
if gtff.USE_ION:
plt.ion()
plt.show()
print("")
@@ -115,7 +142,17 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
return
def estimates(l_args, s_ticker):
def estimates(other_args: List[str], ticker: str):
"""Display analysts' estimates for a given ticker
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Due diligence ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="est",
@@ -123,12 +160,12 @@ def estimates(l_args, s_ticker):
)
try:
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_market_business_insider = (
f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock"
f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
@@ -274,7 +311,24 @@ def estimates(l_args, s_ticker):
return
def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
def insider_activity(
other_args: List[str], stock: DataFrame, ticker: str, start: str, interval: str
):
"""Display insider activity
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
stock : DataFrame
Due diligence stock dataframe
ticker : str
Due diligence ticker symbol
start : str
Start date of the stock data
interval : str
Stock data interval
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="ins",
@@ -291,12 +345,12 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
)
try:
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_market_business_insider = (
f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock"
f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
@@ -334,17 +388,17 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
df_insider = df_insider.set_index("Date")
df_insider = df_insider.sort_index(ascending=True)
if s_start:
df_insider = df_insider[s_start:]
if start:
df_insider = df_insider[start:] # type: ignore
_, ax = plt.subplots()
if s_interval == "1440min":
plt.plot(df_stock.index, df_stock["5. adjusted close"].values, lw=3)
if interval == "1440min":
plt.plot(stock.index, stock["5. adjusted close"].values, lw=3)
else: # Intraday
plt.plot(df_stock.index, df_stock["4. close"].values, lw=3)
plt.plot(stock.index, stock["4. close"].values, lw=3)
plt.title(f"{s_ticker.upper()} (Time Series) and Price Target")
plt.title(f"{ticker.upper()} (Time Series) and Price Target")
plt.xlabel("Time")
plt.ylabel("Share Price ($)")
@@ -354,7 +408,7 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
* float(row["Shares Traded"].replace(",", "")),
axis=1,
)
plt.xlim(df_insider.index[0], df_stock.index[-1])
plt.xlim(df_insider.index[0], stock.index[-1])
min_price, max_price = ax.get_ylim()
price_range = max_price - min_price
@@ -373,16 +427,16 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
for ind in (
df_insider[df_insider["Type"] == "Sell"].groupby(by=["Date"]).sum().index
):
if ind in df_stock.index:
if ind in stock.index:
ind_dt = ind
else:
ind_dt = get_next_stock_market_days(ind, 1)[0]
n_stock_price = 0
if s_interval == "1440min":
n_stock_price = df_stock["5. adjusted close"][ind_dt]
if interval == "1440min":
n_stock_price = stock["5. adjusted close"][ind_dt]
else:
n_stock_price = df_stock["4. close"][ind_dt]
n_stock_price = stock["4. close"][ind_dt]
plt.vlines(
x=ind_dt,
@@ -402,16 +456,16 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
for ind in (
df_insider[df_insider["Type"] == "Buy"].groupby(by=["Date"]).sum().index
):
if ind in df_stock.index:
if ind in stock.index:
ind_dt = ind
else:
ind_dt = get_next_stock_market_days(ind, 1)[0]
n_stock_price = 0
if s_interval == "1440min":
n_stock_price = df_stock["5. adjusted close"][ind_dt]
if interval == "1440min":
n_stock_price = stock["5. adjusted close"][ind_dt]
else:
n_stock_price = df_stock["4. close"][ind_dt]
n_stock_price = stock["4. close"][ind_dt]
plt.vlines(
x=ind_dt,
@@ -431,6 +485,10 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
if gtff.USE_ION:
plt.ion()
plt.show()
l_names = list()

View File

@@ -0,0 +1,219 @@
""" Due Diligence Controller """
__docformat__ = "numpy"
import argparse
from typing import List
from pandas.core.frame import DataFrame
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal.due_diligence import business_insider_view as bi_view
from gamestonk_terminal.due_diligence import financial_modeling_prep_view as fmp_view
from gamestonk_terminal.due_diligence import finviz_view as fvz_view
from gamestonk_terminal.due_diligence import market_watch_view as mw_view
from gamestonk_terminal.due_diligence import quandl_view as q_view
from gamestonk_terminal.due_diligence import reddit_view as r_view
from gamestonk_terminal.due_diligence import news_view
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal.menu import session
class DueDiligenceController:
""" Due Diligence Controller """
# Command choices
CHOICES = [
"help",
"q",
"quit",
"red",
"short",
"rating",
"pt",
"est",
"ins",
"insider",
"news",
"analyst",
"warnings",
"sec",
]
def __init__(self, stock: DataFrame, ticker: str, start: str, interval: str):
"""Constructor
Parameters
----------
stock : DataFrame
Due diligence stock dataframe
ticker : str
Due diligence ticker symbol
start : str
Start date of the stock data
interval : str
Stock data interval
"""
self.stock = stock
self.ticker = ticker
self.start = start
self.interval = interval
self.dd_parser = argparse.ArgumentParser(add_help=False, prog="dd")
self.dd_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
def print_help(self):
""" Print help """
intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"]
if self.start:
print(
f"\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})"
)
else:
print(f"\n{intraday} Stock: {self.ticker}")
print("\nDue Diligence:")
print(" help show this fundamental analysis menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" news latest news of the company [News API]")
print(" red gets due diligence from another user's post [Reddit]")
print(" analyst analyst prices and ratings of the company [Finviz]")
print(
" rating rating of the company from strong sell to strong buy [FMP]"
)
print(" pt price targets over time [Business Insider]")
print(
" est quarter and year analysts earnings estimates [Business Insider]"
)
print(" ins insider activity over time [Business Insider]")
print(" insider insider trading of the company [Finviz]")
print(" sec SEC filings [Market Watch]")
print(" short short interest [Quandl]")
print(
" warnings company warnings according to Sean Seah book [Market Watch]"
)
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.dd_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_red(self, other_args: List[str]):
""" Process red command """
r_view.due_diligence(other_args, self.ticker)
def call_insider(self, other_args: List[str]):
""" Process insider command """
fvz_view.insider(other_args, self.ticker)
def call_news(self, other_args: List[str]):
""" Process news command """
news_view.news(other_args, self.ticker)
def call_analyst(self, other_args: List[str]):
""" Process analyst command """
fvz_view.analyst(other_args, self.ticker)
def call_pt(self, other_args: List[str]):
""" Process pt command """
bi_view.price_target_from_analysts(
other_args, self.stock, self.ticker, self.start, self.interval
)
def call_est(self, other_args: List[str]):
""" Process est command """
bi_view.estimates(other_args, self.ticker)
def call_ins(self, other_args: List[str]):
""" Process ins command """
bi_view.insider_activity(
other_args, self.stock, self.ticker, self.start, self.interval
)
def call_rating(self, other_args: List[str]):
""" Process rating command """
fmp_view.rating(other_args, self.ticker)
def call_warnings(self, other_args: List[str]):
""" Process rating command """
mw_view.sean_seah_warnings(other_args, self.ticker)
def call_sec(self, other_args: List[str]):
""" Process sec command """
mw_view.sec_fillings(other_args, self.ticker)
def call_short(self, other_args: List[str]):
""" Process short command """
q_view.short_interest(other_args, self.ticker, self.start)
def menu(stock: DataFrame, ticker: str, start: str, interval: str):
"""Due Diligence Menu
Parameters
----------
stock : DataFrame
Due diligence stock dataframe
ticker : str
Due diligence ticker symbol
start : str
Start date of the stock data
interval : str
Stock data interval
"""
dd_controller = DueDiligenceController(stock, ticker, start, interval)
dd_controller.call_help(None)
while True:
# Get input command from user
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in dd_controller.CHOICES}
)
an_input = session.prompt(
f"{get_flair()} (dd)> ",
completer=completer,
)
else:
an_input = input(f"{get_flair()} (dd)> ")
try:
process_input = dd_controller.switch(an_input)
if process_input is not None:
return process_input
except SystemExit:
print("The command selected doesn't exist\n")
continue

View File

@@ -1,148 +0,0 @@
import argparse
from gamestonk_terminal.due_diligence import business_insider_api as bi_api
from gamestonk_terminal.due_diligence import financial_modeling_prep_api as fmp_api
from gamestonk_terminal.due_diligence import finviz_api as fvz_api
from gamestonk_terminal.due_diligence import market_watch_api as mw_api
from gamestonk_terminal.due_diligence import quandl_api as q_api
from gamestonk_terminal.due_diligence import reddit_api as r_api
from gamestonk_terminal.due_diligence import news_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_due_diligence(s_ticker, s_start, s_interval):
""" Print help """
s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"]
if s_start:
print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})")
else:
print(f"\n{s_intraday} Stock: {s_ticker}")
print("\nDue Diligence:")
print(" help show this fundamental analysis menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" news latest news of the company [News API]")
print(" red gets due diligence from another user's post [Reddit]")
print(" analyst analyst prices and ratings of the company [Finviz]")
print(" rating rating of the company from strong sell to strong buy [FMP]")
print(" pt price targets over time [Business Insider]")
print(
" est quarter and year analysts earnings estimates [Business Insider]"
)
print(" ins insider activity over time [Business Insider]")
print(" insider insider trading of the company [Finviz]")
print(" sec SEC filings [Market Watch]")
print(" short short interest [Quandl]")
print(
" warnings company warnings according to Sean Seah book [Market Watch]"
)
print("")
return
def dd_menu(df_stock, s_ticker, s_start, s_interval):
# Add list of arguments that the due diligence parser accepts
dd_parser = argparse.ArgumentParser(prog="dd", add_help=False)
choices = [
"info",
"help",
"q",
"quit",
"red",
"short",
"rating",
"pt",
"est",
"ins",
"insider",
"news",
"analyst",
"warnings",
"sec",
]
dd_parser.add_argument("cmd", choices=choices)
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
print_due_diligence(s_ticker, s_start, s_interval)
# 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()} (dd)> ",
completer=completer,
)
else:
as_input = input(f"{get_flair()} (dd)> ")
# Parse due diligence command of the list of possible commands
try:
(ns_known_args, l_args) = dd_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_due_diligence(s_ticker, s_start, s_interval)
elif ns_known_args.cmd == "q":
# Just leave the DD menu
return False
elif ns_known_args.cmd == "quit":
# Abandon the program
return True
# REDDIT API
elif ns_known_args.cmd == "red":
r_api.due_diligence(l_args, s_ticker)
# FINVIZ API
elif ns_known_args.cmd == "insider":
fvz_api.insider(l_args, s_ticker)
elif ns_known_args.cmd == "news":
news_api.news(l_args, s_ticker)
elif ns_known_args.cmd == "analyst":
fvz_api.analyst(l_args, s_ticker)
# BUSINESS INSIDER API
elif ns_known_args.cmd == "pt":
bi_api.price_target_from_analysts(
l_args, df_stock, s_ticker, s_start, s_interval
)
elif ns_known_args.cmd == "est":
bi_api.estimates(l_args, s_ticker)
elif ns_known_args.cmd == "ins":
bi_api.insider_activity(l_args, df_stock, s_ticker, s_start, s_interval)
# FINANCIAL MODELING PREP API
elif ns_known_args.cmd == "rating":
fmp_api.rating(l_args, s_ticker)
# MARKET WATCH API
elif ns_known_args.cmd == "sec":
mw_api.sec_fillings(l_args, s_ticker)
elif ns_known_args.cmd == "warnings":
mw_api.sean_seah_warnings(l_args, s_ticker)
# QUANDL API
elif ns_known_args.cmd == "short":
q_api.short_interest(l_args, s_ticker, s_start)
else:
print("Command not recognized!")

View File

@@ -1,10 +1,24 @@
""" Financial Modeling Prep View """
__docformat__ = "numpy"
import argparse
from typing import List
import FundamentalAnalysis as fa # Financial Modeling Prep
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def rating(l_args, s_ticker):
def rating(other_args: List[str], ticker: str):
"""Display ratings for a given ticker
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="rating",
@@ -16,18 +30,18 @@ def rating(l_args, s_ticker):
)
try:
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
df_fa = fa.rating(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = fa.rating(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
print(df_fa)
print("")
except KeyError:
print(
f"Financialmodelingprep.com is returning empty response the ticker {s_ticker}."
f"Financialmodelingprep.com is returning empty response the ticker {ticker}."
)
print("")
return

View File

@@ -1,4 +1,8 @@
""" FinViz View """
__docformat__ = "numpy"
import argparse
from typing import List
from colorama import Fore, Style
import finviz
import pandas as pd
@@ -11,6 +15,19 @@ from gamestonk_terminal.helper_funcs import (
def category_color_red_green(val: str) -> str:
"""Add color to analyst rating
Parameters
----------
val : str
Analyst rating - Upgrade/Downgrade
Returns
-------
str
Analyst rating with color
"""
if val == "Upgrade":
return Fore.GREEN + val + Style.RESET_ALL
if val == "Downgrade":
@@ -18,7 +35,16 @@ def category_color_red_green(val: str) -> str:
return val
def insider(l_args, s_ticker):
def insider(other_args: List[str], ticker: str):
"""Display insider activity for a given stock ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="insider",
@@ -39,11 +65,11 @@ def insider(l_args, s_ticker):
)
try:
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
d_finviz_insider = finviz.get_insider(s_ticker)
d_finviz_insider = finviz.get_insider(ticker)
df_fa = pd.DataFrame.from_dict(d_finviz_insider)
df_fa.set_index("Date", inplace=True)
df_fa = df_fa[
@@ -68,7 +94,17 @@ def insider(l_args, s_ticker):
return
def news(l_args, s_ticker):
def news(other_args: List[str], ticker: str):
"""Display news for a given stock ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="news",
@@ -88,11 +124,11 @@ def news(l_args, s_ticker):
)
try:
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
d_finviz_news = finviz.get_news(s_ticker)
d_finviz_news = finviz.get_news(ticker)
i = 0
for s_news_title, s_news_link in {*d_finviz_news}:
print(f"-> {s_news_title}")
@@ -110,9 +146,22 @@ def news(l_args, s_ticker):
return
def analyst_df(s_ticker: str) -> DataFrame:
def analyst_df(ticker: str) -> DataFrame:
"""[summary]
Parameters
----------
ticker : str
Stock ticker
Returns
-------
DataFrame
[description]
"""
try:
d_finviz_analyst_price = finviz.get_analyst_price_targets(s_ticker)
d_finviz_analyst_price = finviz.get_analyst_price_targets(ticker)
df_fa = pd.DataFrame.from_dict(d_finviz_analyst_price)
df_fa.set_index("date", inplace=True)
except Exception as e:
@@ -122,7 +171,17 @@ def analyst_df(s_ticker: str) -> DataFrame:
return df_fa
def analyst(l_args, s_ticker):
def analyst(other_args, ticker):
"""Display analyst ratings
Parameters
----------
other_args : [type]
argparse other args
ticker : [type]
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="analyst",
@@ -144,11 +203,11 @@ def analyst(l_args, s_ticker):
)
try:
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
df_fa = analyst_df(s_ticker)
df_fa = analyst_df(ticker)
if ns_parser.n_color == 1:
df_fa["category"] = df_fa["category"].apply(category_color_red_green)

View File

@@ -1,4 +1,8 @@
""" Market Watch View """
__docformat__ = "numpy"
import argparse
from typing import List
import re
import requests
import pandas as pd
@@ -13,7 +17,17 @@ from gamestonk_terminal.helper_funcs import (
)
def sec_fillings(l_args, s_ticker):
def sec_fillings(other_args: List[str], ticker: str):
"""Display SEC filings for a given stock ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="sec",
@@ -34,13 +48,13 @@ def sec_fillings(l_args, s_ticker):
)
try:
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
pd.set_option("display.max_colwidth", None)
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/secfilings"
url_financials = f"https://www.marketwatch.com/investing/stock/{ticker}/financials/secfilings"
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
@@ -60,7 +74,7 @@ def sec_fillings(l_args, s_ticker):
l_financials_info.extend(a_financials[5:-1])
l_financials_info.append(financials_info.a["href"])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials_info
df_financials.loc[len(df_financials.index)] = l_financials_info # type: ignore
if "Filing Date" in a_financials:
l_financials_header = [a_financials[2]]
@@ -72,7 +86,7 @@ def sec_fillings(l_args, s_ticker):
b_ready_to_process_info = True
# Set Filing Date as index
df_financials = df_financials.set_index("Filing Date")
df_financials = df_financials.set_index("Filing Date") # type: ignore
print(df_financials.head(n=ns_parser.n_num).to_string())
print("")
@@ -83,7 +97,17 @@ def sec_fillings(l_args, s_ticker):
return
def sean_seah_warnings(l_args, s_ticker):
def sean_seah_warnings(other_args: List[str], ticker: str):
"""Display Sean Seah warnings
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="warnings",
@@ -114,7 +138,7 @@ def sean_seah_warnings(l_args, s_ticker):
)
try:
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
@@ -129,7 +153,7 @@ def sean_seah_warnings(l_args, s_ticker):
# From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA'
url_financials = (
f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income"
f"https://www.marketwatch.com/investing/stock/{ticker}/financials/income"
)
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
@@ -173,7 +197,7 @@ def sean_seah_warnings(l_args, s_ticker):
]
# From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt'
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet"
url_financials = f"https://www.marketwatch.com/investing/stock/{ticker}/financials/balance-sheet"
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",

View File

@@ -1,4 +1,8 @@
""" News View """
__docformat__ = "numpy"
import argparse
from typing import List
from datetime import datetime, timedelta
import requests
from gamestonk_terminal import config_terminal as cfg
@@ -8,7 +12,17 @@ from gamestonk_terminal.helper_funcs import (
)
def news(l_args, s_ticker):
def news(other_args: List[str], ticker: str):
"""Display news for a given ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="news",
@@ -28,14 +42,14 @@ def news(l_args, s_ticker):
)
try:
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
s_from = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
response = requests.get(
f"https://newsapi.org/v2/everything?q={s_ticker}&from={s_from}"
f"https://newsapi.org/v2/everything?q={ticker}&from={s_from}"
f"&sortBy=publishedAt&language=en&apiKey={cfg.API_NEWS_TOKEN}",
)
@@ -45,7 +59,7 @@ def news(l_args, s_ticker):
else:
print(
f"{response.json()['totalResults']} news articles from {s_ticker} were found since {s_from}\n"
f"{response.json()['totalResults']} news articles from {ticker} were found since {s_from}\n"
)
for idx, article in enumerate(response.json()["articles"]):

View File

@@ -1,7 +1,11 @@
""" Quandl View """
__docformat__ = "numpy"
import argparse
from typing import List
import quandl
from matplotlib import pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.ticker
import pandas as pd
from gamestonk_terminal.helper_funcs import (
check_positive,
@@ -11,7 +15,19 @@ from gamestonk_terminal.helper_funcs import (
from gamestonk_terminal import config_terminal as cfg
def short_interest(l_args, s_ticker, s_start):
def short_interest(other_args: List[str], ticker: str, start: str):
"""Display short interest for a given ticker and a given start date
Parameters
----------
other_args : List[str]
argparse other args - ["-d", "10"]
ticker : str
Stock ticker
start : str
Start date of the stock data
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="short",
@@ -40,18 +56,18 @@ def short_interest(l_args, s_ticker, s_start):
)
try:
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
quandl.ApiConfig.api_key = cfg.API_KEY_QUANDL
if ns_parser.b_nyse:
df_short_interest = quandl.get(f"FINRA/FNYX_{s_ticker}")
df_short_interest = quandl.get(f"FINRA/FNYX_{ticker}")
else:
df_short_interest = quandl.get(f"FINRA/FNSQ_{s_ticker}")
df_short_interest = quandl.get(f"FINRA/FNSQ_{ticker}")
df_short_interest = df_short_interest[s_start:]
df_short_interest = df_short_interest[start:] # type: ignore
df_short_interest.columns = [
"".join(
" " + char if char.isupper() else char.strip() for char in idx
@@ -77,18 +93,18 @@ def short_interest(l_args, s_ticker, s_start):
ax.set_ylabel("Shares")
ax.set_xlabel("Date")
if s_start:
if start:
ax.set_title(
f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker} from {s_start.date()}"
f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {ticker} from {start.date()}" # type: ignore
)
else:
ax.set_title(
f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker}"
f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {ticker}"
)
ax.legend(labels=["Short Volume", "Total Volume"])
ax.tick_params(axis="both", which="major")
ax.yaxis.set_major_formatter(ticker.EngFormatter())
ax.yaxis.set_major_formatter(matplotlib.ticker.EngFormatter())
ax_twin = ax.twinx()
ax_twin.tick_params(axis="y", colors="green")
ax_twin.set_ylabel("Percentage of Volume Shorted", color="green")
@@ -98,7 +114,9 @@ def short_interest(l_args, s_ticker, s_start):
color="green",
)
ax_twin.tick_params(axis="y", which="major", color="green")
ax_twin.yaxis.set_major_formatter(ticker.FormatStrFormatter("%.0f%%"))
ax_twin.yaxis.set_major_formatter(
matplotlib.ticker.FormatStrFormatter("%.0f%%")
)
plt.xlim([df_short_interest.index[0], df_short_interest.index[-1]])
df_short_interest["% of Volume Shorted"] = df_short_interest[

View File

@@ -1,4 +1,8 @@
""" Reddit View """
__docformat__ = "numpy"
import argparse
from typing import List
from datetime import datetime, timedelta
from psaw import PushshiftAPI
import praw
@@ -7,7 +11,17 @@ from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.reddit_helpers import print_and_record_reddit_post
def due_diligence(l_args, s_ticker):
def due_diligence(other_args: List[str], ticker: str):
"""Display Reddit due diligence data for a given ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-l", "5"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="red",
@@ -47,7 +61,7 @@ def due_diligence(l_args, s_ticker):
)
try:
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
@@ -83,9 +97,9 @@ def due_diligence(l_args, s_ticker):
]
submissions = psaw_api.search_submissions(
after=int(n_ts_after), subreddit=l_sub_reddits, q=s_ticker, filter=["id"]
after=int(n_ts_after), subreddit=l_sub_reddits, q=ticker, filter=["id"]
)
d_submission = {}
d_submission = {} # type: ignore
n_flair_posts_found = 0
while True:
submission = next(submissions, None)

View File

@@ -15,7 +15,7 @@ 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_controller
from gamestonk_terminal.due_diligence import dd_menu as ddm
from gamestonk_terminal.due_diligence import dd_controller
from gamestonk_terminal.fundamental_analysis import fa_menu as fam
from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair
from gamestonk_terminal.main_helper import clear, export, load, print_help, view, candle
@@ -208,7 +208,7 @@ def main():
b_quit = ta_controller.menu(df_stock, s_ticker, s_start, s_interval)
elif ns_known_args.opt == "dd":
b_quit = ddm.dd_menu(df_stock, s_ticker, s_start, s_interval)
b_quit = dd_controller.menu(df_stock, s_ticker, s_start, s_interval)
elif ns_known_args.opt == "eda":
if s_interval == "1440min":

View File

@@ -1,9 +0,0 @@
""" fundamental_analysis/business_insider_api.py tests """
import unittest
from gamestonk_terminal.due_diligence.financial_modeling_prep_api import rating
class TestDdFinancialModelingPrepApi(unittest.TestCase):
def test_rating(self):
rating([], "PLTR")

View File

@@ -0,0 +1,9 @@
""" fundamental_analysis/business_insider_api.py tests """
import unittest
from gamestonk_terminal.due_diligence.financial_modeling_prep_view import rating
class TestDdFinancialModelingPrepView(unittest.TestCase):
def test_rating(self):
rating([], "PLTR")

View File

@@ -1,7 +1,7 @@
""" due_diligence/finviz_api.py tests """
import unittest
from gamestonk_terminal.due_diligence.finviz_api import analyst
from gamestonk_terminal.due_diligence.finviz_view import analyst
class TestDdFinvizApi(unittest.TestCase):