Refactor due-diligence menu to new refactoring style (#681)

* refactor finviz

* start refactor business insider

* fix business insider new refactoring

* refactor FMP view

* refactor market watch in due diligence

* refactor finnhub on dd

* CSI market in dd refactored

* fix test

* fix dd report

* fix test

* fix test

* fix test

* fix test

* fix rating yaml

* try to fix the test_rating

* try for the 1000time

* remove the test for now...

* fix again requirements.txt

* refactor code after review

* merge main to ref-dd branch
This commit is contained in:
DidierRLopes
2021-08-21 19:17:12 +01:00
committed by GitHub
parent 33a7fc6311
commit 1660fe55e5
19 changed files with 2713 additions and 694 deletions

View File

@@ -0,0 +1,201 @@
""" Business Insider Model """
__docformat__ = "numpy"
import json
import re
from typing import Tuple
import requests
import pandas as pd
from bs4 import BeautifulSoup
from gamestonk_terminal.helper_funcs import (
get_user_agent,
)
def get_price_target_from_analysts(ticker: str) -> pd.DataFrame:
"""Get analysts' price targets for a given stock. [Source: Business Insider]
Parameters
----------
ticker : str
Ticker symbol
Returns
-------
pd.DataFrame
Analysts data
"""
url_market_business_insider = (
f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
url_market_business_insider, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
)
d_analyst_data = None
for script in text_soup_market_business_insider.find_all("script"):
# Get Analyst data
if "window.analyseChartConfigs.push" in str(script):
# Extract config data:
s_analyst_data = str(script).split("config: ", 1)[1].split(",\r\n", 1)[0]
d_analyst_data = json.loads(s_analyst_data)
break
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data["Markers"]) # type: ignore
df_analyst_data = df_analyst_data[
["DateLabel", "Company", "InternalRating", "PriceTarget"]
]
df_analyst_data.columns = ["Date", "Company", "Rating", "Price Target"]
# df_analyst_data
df_analyst_data["Rating"].replace(
{"gut": "BUY", "neutral": "HOLD", "schlecht": "SELL"}, inplace=True
)
df_analyst_data["Date"] = pd.to_datetime(df_analyst_data["Date"])
df_analyst_data = df_analyst_data.set_index("Date")
return df_analyst_data
def get_estimates(ticker: str) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
"""Get analysts' estimates for a given ticker. [Source: Business Insider]
Parameters
----------
ticker : str
Ticker to get analysts' estimates
Returns
-------
df_year_estimates : pd.DataFrame
Year estimates
df_quarter_earnings : pd.DataFrame
Quarter earnings estimates
df_quarter_revenues : pd.DataFrame
Quarter revenues estimates
"""
url_market_business_insider = (
f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
url_market_business_insider, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
)
l_estimates_year_header = list()
l_estimates_quarter_header = list()
for estimates_header in text_soup_market_business_insider.findAll(
"th", {"class": "table__th text-right"}
):
s_estimates_header = estimates_header.text.strip()
if s_estimates_header.isdigit():
l_estimates_year_header.append(s_estimates_header)
elif ("in %" not in s_estimates_header) and ("Job" not in s_estimates_header):
l_estimates_quarter_header.append(s_estimates_header)
l_estimates_year_metric = list()
for estimates_year_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td black"}
):
l_estimates_year_metric.append(estimates_year_metric.text)
l_estimates_quarter_metric = list()
for estimates_quarter_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td font-color-dim-gray"}
):
l_estimates_quarter_metric.append(estimates_quarter_metric.text)
d_metric_year = dict()
d_metric_quarter_earnings = dict()
d_metric_quarter_revenues = dict()
l_metrics = list()
n_metrics = 0
b_year = True
for idx, metric_value in enumerate(
text_soup_market_business_insider.findAll(
"td", {"class": "table__td text-right"}
)
):
if b_year:
# YEAR metrics
l_metrics.append(metric_value.text.strip())
# Check if we have processed all year metrics
if n_metrics > len(l_estimates_year_metric) - 1:
b_year = False
n_metrics = 0
l_metrics = list()
idx_y = idx
# Add value to dictionary
if (idx + 1) % len(l_estimates_year_header) == 0:
d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics
l_metrics = list()
n_metrics += 1
if not b_year:
# QUARTER metrics
l_metrics.append(metric_value.text.strip())
# Check if we have processed all quarter metrics
if n_metrics > len(l_estimates_quarter_metric) - 1:
break
# Add value to dictionary
if (idx - idx_y + 1) % len(l_estimates_quarter_header) == 0:
if n_metrics < 4:
d_metric_quarter_earnings[
l_estimates_quarter_metric[n_metrics]
] = l_metrics
else:
d_metric_quarter_revenues[
l_estimates_quarter_metric[n_metrics - 4]
] = l_metrics
l_metrics = list()
n_metrics += 1
df_year_estimates = pd.DataFrame.from_dict(
d_metric_year, orient="index", columns=l_estimates_year_header
)
df_year_estimates.index.name = "YEARLY ESTIMATES"
df_quarter_earnings = pd.DataFrame.from_dict(
d_metric_quarter_earnings,
orient="index",
columns=l_estimates_quarter_header,
)
# df_quarter_earnings.index.name = 'Earnings'
df_quarter_revenues = pd.DataFrame.from_dict(
d_metric_quarter_revenues,
orient="index",
columns=l_estimates_quarter_header,
)
# df_quarter_revenues.index.name = 'Revenues'
l_quarter = list()
l_date = list()
for quarter_title in df_quarter_earnings.columns:
l_quarter.append(re.split(" ending", quarter_title)[0])
if len(re.split(" ending", quarter_title)) == 2:
l_date.append("ending " + re.split(" ending", quarter_title)[1].strip())
else:
l_date.append("-")
df_quarter_earnings.index.name = "QUARTER EARNINGS ESTIMATES"
df_quarter_earnings.columns = l_quarter
df_quarter_earnings.loc["Date"] = l_date
df_quarter_earnings = df_quarter_earnings.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)
df_quarter_revenues.index.name = "QUARTER REVENUES ESTIMATES"
df_quarter_revenues.columns = l_quarter
df_quarter_revenues.loc["Date"] = l_date
df_quarter_revenues = df_quarter_revenues.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)
return df_year_estimates, df_quarter_earnings, df_quarter_revenues

View File

@@ -1,20 +1,14 @@
""" Business Insider View """
__docformat__ = "numpy"
import argparse
from typing import List
import json
import re
import os
from pandas.core.frame import DataFrame
import requests
import matplotlib.pyplot as plt
import pandas as pd
from pandas.plotting import register_matplotlib_converters
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
from tabulate import tabulate
from gamestonk_terminal.stocks.due_diligence import business_insider_model
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
parse_known_args_and_warn,
export_data,
)
from gamestonk_terminal import feature_flags as gtff
@@ -22,78 +16,49 @@ register_matplotlib_converters()
def price_target_from_analysts(
other_args: List[str], stock: DataFrame, ticker: str, start: str, interval: str
ticker: str,
start: str,
interval: str,
stock: DataFrame,
num: int,
raw: bool,
export: str,
):
"""Display analysts' price targets for a given stock
"""Display analysts' price targets for a given stock. [Source: Business Insider]
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
stock : DataFrame
Due diligence stock dataframe
num : int
Number of latest price targets from analysts to print
raw : bool
Display raw data only
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="pt",
description="""Prints price target from analysts. [Source: Business Insider]""",
)
df_analyst_data = business_insider_model.get_price_target_from_analysts(ticker)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of latest price targets from analysts to print.",
)
try:
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/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
url_market_business_insider, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
if raw:
df_analyst_data.index = df_analyst_data.index.strftime("%d/%m/%Y")
print(
tabulate(
df_analyst_data.sort_index(ascending=False).head(num),
headers=df_analyst_data.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
d_analyst_data = None
for script in text_soup_market_business_insider.find_all("script"):
# Get Analyst data
if "window.analyseChartConfigs.push" in str(script):
# Extract config data:
s_analyst_data = (
str(script).split("config: ", 1)[1].split(",\r\n", 1)[0]
)
d_analyst_data = json.loads(s_analyst_data)
break
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data["Markers"]) # type: ignore
df_analyst_data = df_analyst_data[
["DateLabel", "Company", "InternalRating", "PriceTarget"]
]
df_analyst_data.columns = ["Date", "Company", "Rating", "Price Target"]
# df_analyst_data
df_analyst_data["Rating"].replace(
{"gut": "BUY", "neutral": "HOLD", "schlecht": "SELL"}, inplace=True
)
df_analyst_data["Date"] = pd.to_datetime(df_analyst_data["Date"])
df_analyst_data = df_analyst_data.set_index("Date")
else:
# Slice start of ratings
if start:
df_analyst_data = df_analyst_data[start:] # type: ignore
@@ -116,195 +81,85 @@ def price_target_from_analysts(
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.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("")
print("")
pd.set_option("display.max_colwidth", None)
print(
df_analyst_data.sort_index(ascending=False)
.head(ns_parser.n_num)
.to_string()
)
print("")
except Exception as e:
print(e)
print("")
return
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"pt",
df_analyst_data,
)
def estimates(other_args: List[str], ticker: str):
"""Display analysts' estimates for a given ticker
def estimates(ticker: str, export: str):
"""Display analysts' estimates for a given ticker. [Source: Business Insider]
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Due diligence ticker symbol
Ticker to get analysts' estimates
export : str
Export dataframe data to csv,json,xlsx file
"""
(
df_year_estimates,
df_quarter_earnings,
df_quarter_revenues,
) = business_insider_model.get_estimates(ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="est",
description="""Yearly estimates and quarter earnings/revenues [Source: Business Insider]""",
print(
tabulate(
df_year_estimates,
headers=df_year_estimates.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
),
)
try:
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/{ticker.lower()}-stock"
)
text_soup_market_business_insider = BeautifulSoup(
requests.get(
url_market_business_insider, headers={"User-Agent": get_user_agent()}
).text,
"lxml",
print("")
print(
tabulate(
df_quarter_earnings,
headers=df_quarter_earnings.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
),
)
print("")
print(
tabulate(
df_quarter_revenues,
headers=df_quarter_revenues.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
print("")
l_estimates_year_header = []
l_estimates_quarter_header = []
for estimates_header in text_soup_market_business_insider.findAll(
"th", {"class": "table__th text-right"}
):
s_estimates_header = estimates_header.text.strip()
if s_estimates_header.isdigit():
l_estimates_year_header.append(s_estimates_header)
elif ("in %" not in s_estimates_header) and (
"Job" not in s_estimates_header
):
l_estimates_quarter_header.append(s_estimates_header)
l_estimates_year_metric = []
for estimates_year_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td black"}
):
l_estimates_year_metric.append(estimates_year_metric.text)
l_estimates_quarter_metric = []
for estimates_quarter_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td font-color-dim-gray"}
):
l_estimates_quarter_metric.append(estimates_quarter_metric.text)
d_metric_year = dict()
d_metric_quarter_earnings = dict()
d_metric_quarter_revenues = dict()
l_metrics = []
n_metrics = 0
b_year = True
for idx, metric_value in enumerate(
text_soup_market_business_insider.findAll(
"td", {"class": "table__td text-right"}
)
):
if b_year:
# YEAR metrics
l_metrics.append(metric_value.text.strip())
# Check if we have processed all year metrics
if n_metrics > len(l_estimates_year_metric) - 1:
b_year = False
n_metrics = 0
l_metrics = []
idx_y = idx
# Add value to dictionary
if (idx + 1) % len(l_estimates_year_header) == 0:
d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics
l_metrics = []
n_metrics += 1
if not b_year:
# QUARTER metrics
l_metrics.append(metric_value.text.strip())
# Check if we have processed all quarter metrics
if n_metrics > len(l_estimates_quarter_metric) - 1:
break
# Add value to dictionary
if (idx - idx_y + 1) % len(l_estimates_quarter_header) == 0:
if n_metrics < 4:
d_metric_quarter_earnings[
l_estimates_quarter_metric[n_metrics]
] = l_metrics
else:
d_metric_quarter_revenues[
l_estimates_quarter_metric[n_metrics - 4]
] = l_metrics
l_metrics = []
n_metrics += 1
df_year_estimates = pd.DataFrame.from_dict(
d_metric_year, orient="index", columns=l_estimates_year_header
)
df_year_estimates.index.name = "YEARLY ESTIMATES"
df_quarter_earnings = pd.DataFrame.from_dict(
d_metric_quarter_earnings,
orient="index",
columns=l_estimates_quarter_header,
)
# df_quarter_earnings.index.name = 'Earnings'
df_quarter_revenues = pd.DataFrame.from_dict(
d_metric_quarter_revenues,
orient="index",
columns=l_estimates_quarter_header,
)
# df_quarter_revenues.index.name = 'Revenues'
l_quarter = []
l_date = []
for quarter_title in df_quarter_earnings.columns:
l_quarter.append(re.split(" ending", quarter_title)[0])
if len(re.split(" ending", quarter_title)) == 2:
l_date.append(
"ending " + re.split(" ending", quarter_title)[1].strip()
)
else:
l_date.append("-")
df_quarter_earnings.columns = l_quarter
df_quarter_earnings.loc["Date"] = l_date
df_quarter_earnings = df_quarter_earnings.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)
df_quarter_revenues.columns = l_quarter
df_quarter_revenues.loc["Date"] = l_date
df_quarter_revenues = df_quarter_revenues.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)
print(df_year_estimates.to_string())
print("")
print("QUARTER ESTIMATES EARNINGS")
print(df_quarter_earnings.to_string())
print("")
print("QUARTER ESTIMATES REVENUES")
print(df_quarter_revenues.to_string())
print("")
print(
text_soup_market_business_insider.find(
"div", {"class": "text_right instrument-description"}
).text.strip()
)
print("")
except Exception as e:
print(e)
print("")
return
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"pt_year",
df_year_estimates,
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"pt_qtr_earnings",
df_quarter_earnings,
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"pt_qtr_revenues",
df_quarter_revenues,
)

View File

@@ -0,0 +1,65 @@
"""CSIMarket Model"""
__docformat__ = "numpy"
from bs4 import BeautifulSoup
import requests
def get_suppliers(ticker: str) -> str:
"""Get suppliers from ticker provided. [Source: CSIMarket]
Parameters
----------
ticker: str
Ticker to select suppliers from
Returns
-------
str
Suppliers for ticker provided
"""
# TODO: This link has a lot more data that we can display
# TODO: We could at least sort the tickers based on market cap
url_supply_chain = (
f"https://csimarket.com/stocks/competitionNO3.php?supply&code={ticker.upper()}"
)
text_supplier_chain = BeautifulSoup(requests.get(url_supply_chain).text, "lxml")
l_supplier = list()
for supplier in text_supplier_chain.findAll(
"td", {"class": "plavat svjetlirub dae al"}
):
l_supplier.append(supplier.text)
if l_supplier:
return f"List of Suppliers: {', '.join(l_supplier)}\n"
return "No suppliers found.\n"
def get_customers(ticker: str) -> str:
"""Print customers from ticker provided
Parameters
----------
ticker: str
Ticker to select customers from
Returns
-------
str
Customers for ticker provided
"""
# TODO: This link has a lot more data that we can display
# TODO: We could at least sort the tickers based on market cap
url_customer_chain = (
f"https://csimarket.com/stocks/custexNO.php?markets&code={ticker.upper()}"
)
text_customer_chain = BeautifulSoup(requests.get(url_customer_chain).text, "lxml")
l_customer = list()
for customer in text_customer_chain.findAll("td", {"class": "plava svjetlirub"}):
l_customer.append(customer.text)
if l_customer:
return f"List of Customers: {', '.join(l_customer)}\n"
return "No customers found.\n"

View File

@@ -1,94 +1,51 @@
"""Stockgrid DD View"""
"""CSIMarket View"""
__docformat__ = "numpy"
import argparse
from typing import List
from bs4 import BeautifulSoup
import requests
import os
import pandas as pd
from gamestonk_terminal.stocks.due_diligence import csimarket_model
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
export_data,
)
def suppliers(ticker: str, other_args: List[str]):
"""Print suppliers from ticker provided
def suppliers(ticker: str, export: str):
"""Display suppliers from ticker provided. [Source: CSIMarket]
Parameters
----------
ticker: str
Ticker to select suppliers from
other_args : List[str]
Argparse arguments
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
prog="supplier",
add_help=False,
description="List of suppliers from ticker provided. [Source: CSIMarket]",
tickers = csimarket_model.get_suppliers(ticker)
print(tickers)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"supplier",
pd.DataFrame(tickers.split(",")),
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
# TODO: This link has a lot more data that we can display
url_supply_chain = f"https://csimarket.com/stocks/competitionNO3.php?supply&code={ticker.upper()}"
text_supplier_chain = BeautifulSoup(requests.get(url_supply_chain).text, "lxml")
l_supplier = []
for supplier in text_supplier_chain.findAll(
"td", {"class": "plavat svjetlirub dae al"}
):
l_supplier.append(supplier.text)
if l_supplier:
print("List of Suppliers: " + ", ".join(l_supplier) + "\n")
else:
print("No suppliers found.\n")
except Exception as e:
print(e, "\n")
def customers(ticker: str, other_args: List[str]):
"""Print customers from ticker provided
def customers(ticker: str, export: str):
"""Display customers from ticker provided. [Source: CSIMarket]
Parameters
----------
ticker: str
Ticker to select customers from
other_args : List[str]
Argparse arguments
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
prog="customer",
add_help=False,
description="List of customers from ticker provided. [Source: CSIMarket]",
tickers = csimarket_model.get_customers(ticker)
print(tickers)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"customer",
pd.DataFrame(tickers.split(",")),
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
# TODO: This link has a lot more data that we can display
url_customer_chain = (
f"https://csimarket.com/stocks/custexNO.php?markets&code={ticker.upper()}"
)
text_customer_chain = BeautifulSoup(
requests.get(url_customer_chain).text, "lxml"
)
l_customer = []
for customer in text_customer_chain.findAll(
"td", {"class": "plava svjetlirub"}
):
l_customer.append(customer.text)
if l_customer:
print("List of Customers: " + ", ".join(l_customer) + "\n")
else:
print("No customers found.\n")
except Exception as e:
print(e, "\n")

View File

@@ -8,15 +8,19 @@ from pandas.core.frame import DataFrame
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal.stocks.due_diligence import (
financial_modeling_prep_view,
fmp_view,
business_insider_view,
finviz_view,
market_watch_view,
marketwatch_view,
finnhub_view,
csimarket_view,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal.helper_funcs import (
get_flair,
parse_known_args_and_warn,
check_positive,
)
from gamestonk_terminal.menu import session
@@ -30,30 +34,34 @@ class DueDiligenceController:
"help",
"q",
"quit",
]
CHOICES_COMMANDS = [
"sec",
"rating",
"pt",
"rot",
"est",
"analyst",
"sec",
"supplier",
"customer",
]
CHOICES += CHOICES_COMMANDS
def __init__(self, ticker: str, start: str, interval: str, stock: DataFrame):
"""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
stock : DataFrame
Due diligence stock dataframe
"""
self.ticker = ticker
self.start = start
@@ -68,39 +76,40 @@ class DueDiligenceController:
def print_help(self):
"""Print help"""
print(
"https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/stocks/due_diligence"
)
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')})"
)
s_intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"]
if self.ticker and self.start:
stock_text = f"{s_intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})"
else:
print(f"\n{intraday} Stock: {self.ticker}")
stock_text = f"{s_intraday} Stock: {self.ticker}"
print("\nDue Diligence:")
print(" cls clear screen")
print(" ?/help show this menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
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(
" rot rating over timefrom strong sell to strong buy [Finnhub]"
)
print(
" est quarter and year analysts earnings estimates [Business Insider]"
)
print(" sec SEC filings [Market Watch]")
print(" supplier list of suppliers [csimarket]")
print(" customer list of customers [csimarket]")
print("")
help_text = f"""https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/stocks/due_diligence
Due Diligence:
cls clear screen
?/help show this menu again
q quit this menu, and shows back to main menu
quit quit to abandon program
{stock_text}
Finviz:
analyst analyst prices and ratings of the company
FMP:
rating rating over time (daily)
Finnhub:
rot number of analysts ratings over time (monthly)
Business Insider:
pt price targets over time
est quarter and year analysts earnings estimates
Market Watch:
sec SEC filings
csimarket:
supplier list of suppliers
customer list of customers
"""
print(help_text)
def switch(self, an_input: str):
"""Process and dispatch input
@@ -148,37 +157,308 @@ class DueDiligenceController:
def call_analyst(self, other_args: List[str]):
"""Process analyst command"""
finviz_view.analyst(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="analyst",
description="""
Print analyst prices and ratings of the company. The following fields are expected:
date, analyst, category, price from, price to, and rating. [Source: Finviz]
""",
)
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
finviz_view.analyst(ticker=self.ticker, export=ns_parser.export)
except Exception as e:
print(e, "\n")
def call_pt(self, other_args: List[str]):
"""Process pt command"""
business_insider_view.price_target_from_analysts(
other_args, self.stock, self.ticker, self.start, self.interval
parser = argparse.ArgumentParser(
add_help=False,
prog="pt",
description="""Prints price target from analysts. [Source: Business Insider]""",
)
parser.add_argument(
"--raw",
action="store_true",
dest="raw",
help="Only output raw data",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="Number of latest price targets from analysts to print.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
def call_rot(self, other_args: List[str]):
"""Process rot command"""
finnhub_view.rating_over_time(other_args, self.ticker)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
business_insider_view.price_target_from_analysts(
ticker=self.ticker,
start=self.start,
interval=self.interval,
stock=self.stock,
num=ns_parser.n_num,
raw=ns_parser.raw,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_est(self, other_args: List[str]):
"""Process est command"""
business_insider_view.estimates(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="est",
description="""Yearly estimates and quarter earnings/revenues. [Source: Business Insider]""",
)
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
business_insider_view.estimates(
ticker=self.ticker,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_rot(self, other_args: List[str]):
"""Process rot command"""
parser = argparse.ArgumentParser(
add_help=False,
prog="rot",
description="""
Rating over time (monthly). [Source: Finnhub]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of last months",
)
parser.add_argument(
"--raw",
action="store_true",
dest="raw",
help="Only output raw data",
)
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.rating_over_time(
ticker=self.ticker,
num=ns_parser.n_num,
raw=ns_parser.raw,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_rating(self, other_args: List[str]):
"""Process rating command"""
financial_modeling_prep_view.rating(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="rating",
description="""
Based on specific ratios, prints information whether the company
is a (strong) buy, neutral or a (strong) sell. The following fields are expected:
P/B, ROA, DCF, P/E, ROE, and D/E. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of last days to display ratings",
)
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
fmp_view.rating(
ticker=self.ticker,
num=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_sec(self, other_args: List[str]):
"""Process sec command"""
market_watch_view.sec_fillings(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="sec",
description="""
Prints SEC filings of the company. The following fields are expected: Filing Date,
Document Date, Type, Category, Amended, and Link. [Source: Market Watch]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="number of latest SEC filings.",
)
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
marketwatch_view.sec_filings(
ticker=self.ticker,
num=ns_parser.n_num,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_supplier(self, other_args: List[str]):
"""Process supplier command"""
csimarket_view.suppliers(self.ticker, other_args)
parser = argparse.ArgumentParser(
prog="supplier",
add_help=False,
description="List of suppliers from ticker provided. [Source: CSIMarket]",
)
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
csimarket_view.suppliers(
ticker=self.ticker,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_customer(self, other_args: List[str]):
"""Process customer command"""
csimarket_view.customers(self.ticker, other_args)
parser = argparse.ArgumentParser(
prog="customer",
add_help=False,
description="List of customers from ticker provided. [Source: CSIMarket]",
)
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
csimarket_view.customers(
ticker=self.ticker,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def menu(ticker: str, start: str, interval: str, stock: DataFrame):
@@ -186,14 +466,14 @@ def menu(ticker: str, start: str, interval: str, stock: DataFrame):
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
stock : DataFrame
Due diligence stock dataframe
"""
dd_controller = DueDiligenceController(ticker, start, interval, stock)

View File

@@ -1,78 +0,0 @@
""" Financial Modeling Prep View """
__docformat__ = "numpy"
import argparse
from typing import List
from tabulate import tabulate
import FundamentalAnalysis as fa
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, check_positive
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",
description="""
Based on specific ratios, prints information whether the company
is a (strong) buy, neutral or a (strong) sell. The following fields are expected:
P/B, ROA, DCF, P/E, ROE, and D/E. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=10,
help="number of regions to plot that show highest interest.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_fa = fa.rating(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
# TODO: This could be displayed in a nice rating plot over time
l_recoms = [col for col in df_fa.columns if "Recommendation" in col]
l_recoms_show = [
recom.replace("rating", "")
.replace("Details", "")
.replace("Recommendation", " Recommendation")
for recom in l_recoms
]
print(
tabulate(
df_fa[l_recoms].head(ns_parser.n_num),
headers=l_recoms_show,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
print("")
except KeyError:
print(
f"Financialmodelingprep.com is returning empty response the ticker {ticker}."
)
print("")
return
except Exception as e:
print(e)
print("")
return

View File

@@ -0,0 +1,28 @@
""" Finnhub Model """
__docformat__ = "numpy"
import requests
import pandas as pd
from gamestonk_terminal import config_terminal as cfg
def get_rating_over_time(ticker: str) -> pd.DataFrame:
"""Get rating over time data. [Source: Finnhub]
Parameters
----------
ticker : str
Ticker to get ratings from
Returns
-------
pd.DataFrame
Get dataframe with ratings
"""
response = requests.get(
f"https://finnhub.io/api/v1/stock/recommendation?symbol={ticker}&token={cfg.API_FINNHUB_KEY}"
)
if response.status_code == 200:
return pd.DataFrame(response.json())
return pd.DataFrame()

View File

@@ -1,42 +1,19 @@
import argparse
from typing import List
import requests
""" Finnhub View """
__docformat__ = "numpy"
import os
from tabulate import tabulate
import pandas as pd
from matplotlib import pyplot as plt
from pandas.plotting import register_matplotlib_converters
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
plot_autoscale,
)
from gamestonk_terminal.stocks.due_diligence import finnhub_model
from gamestonk_terminal.helper_funcs import plot_autoscale, export_data
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal import feature_flags as gtff
register_matplotlib_converters()
def get_rating_over_time(ticker: str) -> pd.DataFrame:
"""Get rating over time
Parameters
----------
ticker : str
Ticker to get ratings from
Returns
-------
pd.DataFrame
Get dataframe with economic calendar events
"""
response = requests.get(
f"https://finnhub.io/api/v1/stock/recommendation?symbol={ticker}&token={cfg.API_FINNHUB_KEY}"
)
if response.status_code == 200:
return pd.DataFrame(response.json())
return pd.DataFrame()
def plot_rating_over_time(rot: pd.DataFrame, ticker: str):
"""Plot rating over time
@@ -46,7 +23,6 @@ def plot_rating_over_time(rot: pd.DataFrame, ticker: str):
Rating over time
ticker : str
Ticker associated with ratings
"""
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
@@ -65,6 +41,7 @@ def plot_rating_over_time(rot: pd.DataFrame, ticker: str):
plt.xlabel("Time")
plt.ylabel("Rating")
plt.legend(["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"])
plt.gcf().autofmt_xdate()
if gtff.USE_ION:
plt.ion()
@@ -72,37 +49,56 @@ def plot_rating_over_time(rot: pd.DataFrame, ticker: str):
plt.show()
def rating_over_time(other_args: List[str], ticker: str):
"""Rating over time
def rating_over_time(ticker: str, num: int, raw: bool, export: str):
"""Rating over time (monthly). [Source: Finnhub]
Parameters
----------
other_args : List[str]
Command line arguments to be processed with argparse
ticker : str
Ticker to get ratings from
num : int
Number of last months ratings to show
raw : bool
Display raw data only
export : str
Export dataframe data to csv,json,xlsx file
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="rot",
description="""
Rating over time. [Source: https://finnhub.io]
""",
df_rot = finnhub_model.get_rating_over_time(ticker)
if df_rot.empty:
print("No ratings over time found", "\n")
return
if raw:
d_cols = {
"strongSell": "Strong Sell",
"sell": "Sell",
"hold": "Hold",
"buy": "Buy",
"strongBuy": "Strong Buy",
}
df_rot_raw = (
df_rot[["period", "strongSell", "sell", "hold", "buy", "strongBuy"]]
.rename(columns=d_cols)
.head(num)
)
print(
tabulate(
df_rot_raw,
headers=df_rot_raw.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
)
)
else:
plot_rating_over_time(df_rot.head(num), ticker)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"rot",
df_rot,
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_rot = get_rating_over_time(ticker)
if df_rot.empty:
print("No ratings over time found\n")
return
plot_rating_over_time(df_rot, ticker)
print("")
except Exception as e:
print(e, "\n")

View File

@@ -0,0 +1,43 @@
""" Finviz Model """
__docformat__ = "numpy"
from typing import Dict
import finviz
import pandas as pd
from pandas.core.frame import DataFrame
def get_news(ticker: str) -> Dict:
"""Get news from Finviz
Parameters
----------
ticker : str
Stock ticker
Returns
-------
Dict
News
"""
return finviz.get_news(ticker)
def get_analyst_data(ticker: str) -> DataFrame:
"""Get analyst data. [Source: Finviz]
Parameters
----------
ticker : str
Stock ticker
Returns
-------
df_fa: DataFrame
Analyst price targets
"""
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)
return df_fa

View File

@@ -1,17 +1,12 @@
""" FinViz View """
""" Finviz View """
__docformat__ = "numpy"
import argparse
from typing import List
import os
from colorama import Fore, Style
import finviz
import pandas as pd
from pandas.core.frame import DataFrame
from gamestonk_terminal.helper_funcs import (
check_positive,
patch_pandas_text_adjustment,
parse_known_args_and_warn,
)
from tabulate import tabulate
from gamestonk_terminal.stocks.due_diligence import finviz_model
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal import feature_flags as gtff
def category_color_red_green(val: str) -> str:
@@ -32,133 +27,63 @@ def category_color_red_green(val: str) -> str:
return Fore.GREEN + val + Style.RESET_ALL
if val == "Downgrade":
return Fore.RED + val + Style.RESET_ALL
if val == "Reiterated":
return Fore.YELLOW + val + Style.RESET_ALL
return val
def news(other_args: List[str], ticker: str):
def news(ticker: str, num: int):
"""Display news for a given stock ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
num : int
Number of latest news being printed
"""
d_finviz_news = finviz_model.get_news(ticker)
i = 0
for s_news_title, s_news_link in {*d_finviz_news}:
print(f"-> {s_news_title}")
print(f"{s_news_link}\n")
i += 1
parser = argparse.ArgumentParser(
add_help=False,
prog="news",
description="""
Prints latest news about company, including title and web link. [Source: Finviz]
""",
)
if i > (num - 1):
break
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="Number of latest news being printed.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
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}")
print(f"{s_news_link}\n")
i += 1
if i > (ns_parser.n_num - 1):
break
print("")
except Exception as e:
print(e)
print("")
return
print("")
def analyst_df(ticker: str) -> DataFrame:
"""[summary]
def analyst(ticker: str, export: str):
"""Display analyst ratings. [Source: Finviz]
Parameters
----------
ticker : str
Stock ticker
Returns
-------
DataFrame
[description]
export : str
Export dataframe data to csv,json,xlsx file
"""
df = finviz_model.get_analyst_data(ticker)
try:
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:
print(e)
print("Encountered a potential connectivity issue trying to access Finviz.")
if gtff.USE_COLOR:
df["category"] = df["category"].apply(category_color_red_green)
return df_fa
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",
description="""
Print analyst prices and ratings of the company. The following fields are expected:
date, analyst, category, price from, price to, and rating. [Source: Finviz]
""",
print(
tabulate(
df,
headers=df.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
),
"\n",
)
parser.add_argument(
"-c",
"--color",
action="store",
dest="n_color",
type=int,
choices=[0, 1],
default=1,
help="Add / remove color",
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"analyst",
df,
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_fa = analyst_df(ticker)
if ns_parser.n_color == 1:
df_fa["category"] = df_fa["category"].apply(category_color_red_green)
patch_pandas_text_adjustment()
print(df_fa)
print("")
except Exception as e:
print(e)
print("")
return

View File

@@ -0,0 +1,22 @@
""" Financial Modeling Prep Model """
__docformat__ = "numpy"
import pandas as pd
import FundamentalAnalysis as fa
from gamestonk_terminal import config_terminal as cfg
def get_rating(ticker: str) -> pd.DataFrame:
"""Get ratings for a given ticker. [Source: Financial Modeling Prep]
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
Rating data
"""
return fa.rating(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)

View File

@@ -0,0 +1,52 @@
""" Financial Modeling Prep View """
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.due_diligence import fmp_model
def rating(ticker: str, num: int, export: str):
"""Display ratings for a given ticker. [Source: Financial Modeling Prep]
Parameters
----------
ticker : str
Stock ticker
num : int
Number of last days ratings to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df = fmp_model.get_rating(ticker)
# TODO: This could be displayed in a nice rating plot over time
# TODO: Add coloring to table
if not df.empty:
l_recoms = [col for col in df.columns if "Recommendation" in col]
l_recoms_show = [
recom.replace("rating", "")
.replace("Details", "")
.replace("Recommendation", "")
for recom in l_recoms
]
l_recoms_show[0] = "Rating"
print(
tabulate(
df[l_recoms].head(num),
headers=l_recoms_show,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"rot",
df,
)

View File

@@ -0,0 +1,64 @@
""" Market Watch Model """
__docformat__ = "numpy"
import requests
import pandas as pd
from bs4 import BeautifulSoup
from gamestonk_terminal.helper_funcs import get_user_agent
# pylint: disable=too-many-branches
def get_sec_filings(ticker: str) -> pd.DataFrame:
"""Get SEC filings for a given stock ticker. [Source: Market Watch]
Parameters
----------
ticker : str
Stock ticker
Returns
-------
df_financials : pd.DataFrame
SEC filings data
"""
pd.set_option("display.max_colwidth", None)
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,
"lxml",
)
# a_financials_header = list()
df_financials = None
b_ready_to_process_info = False
soup_financials = text_soup_financials.findAll("tr", {"class": "table__row"})
for financials_info in soup_financials:
a_financials = financials_info.text.split("\n")
# If header has been processed and dataframe created ready to populate the SEC information
if b_ready_to_process_info:
l_financials_info = [a_financials[2]]
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 # type: ignore
if "Filing Date" in a_financials:
l_financials_header = [a_financials[2]]
l_financials_header.extend(a_financials[5:-1])
l_financials_header.append("Link")
df_financials = pd.DataFrame(columns=l_financials_header)
df_financials.set_index("Filing Date")
b_ready_to_process_info = True
# Set Filing Date as index
df_financials = df_financials.set_index("Filing Date") # type: ignore
return df_financials

View File

@@ -0,0 +1,41 @@
""" Market Watch View """
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.due_diligence import marketwatch_model
# pylint: disable=too-many-branches
def sec_filings(ticker: str, num: int, export: str):
"""Display SEC filings for a given stock ticker. [Source: Market Watch]
Parameters
----------
ticker : str
Stock ticker
num : int
Number of ratings to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df_financials = marketwatch_model.get_sec_filings(ticker)
print(
tabulate(
df_financials.head(num),
headers=df_financials.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"sec",
df_financials,
)

View File

@@ -3,7 +3,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "collaborative-pharmacology",
"id": "phantom-facility",
"metadata": {
"collapsed": true
},
@@ -27,7 +27,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "future-association",
"id": "compact-count",
"metadata": {
"collapsed": true,
"tags": [
@@ -44,7 +44,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "oriental-wells",
"id": "possible-constraint",
"metadata": {
"collapsed": true
},
@@ -56,7 +56,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "fitted-affect",
"id": "local-preference",
"metadata": {
"collapsed": true
},
@@ -75,20 +75,20 @@
{
"cell_type": "code",
"execution_count": null,
"id": "black-latvia",
"id": "undefined-stadium",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from gamestonk_terminal.common.technical_analysis import trendline_api as trend\n",
"from gamestonk_terminal.stocks.due_diligence import finviz_view as finviz"
"from gamestonk_terminal.stocks.due_diligence import finviz_view"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "loved-dietary",
"id": "competitive-membership",
"metadata": {
"collapsed": true
},
@@ -109,7 +109,7 @@
},
{
"cell_type": "markdown",
"id": "transparent-change",
"id": "temporal-clerk",
"metadata": {},
"source": [
"## Candle View"
@@ -118,7 +118,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "ruled-marks",
"id": "transsexual-trance",
"metadata": {
"collapsed": true
},
@@ -148,7 +148,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "ahead-return",
"id": "convenient-great",
"metadata": {
"collapsed": true
},
@@ -161,7 +161,7 @@
},
{
"cell_type": "markdown",
"id": "amber-hayes",
"id": "political-intake",
"metadata": {},
"source": [
"## Analyst Targets"
@@ -170,20 +170,19 @@
{
"cell_type": "code",
"execution_count": null,
"id": "conservative-baking",
"id": "numerous-begin",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"df_fa = finviz.analyst_df(ticker)\n",
"print(df_fa.to_string())"
"finviz_view.analyst(ticker=ticker, no_color=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "moderate-dealer",
"id": "nuclear-trailer",
"metadata": {
"collapsed": true
},
@@ -194,7 +193,7 @@
},
{
"cell_type": "markdown",
"id": "victorian-classic",
"id": "written-lease",
"metadata": {},
"source": [
"## Annual Income Statement"
@@ -203,7 +202,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "three-vegetation",
"id": "played-vancouver",
"metadata": {
"collapsed": true
},
@@ -215,7 +214,7 @@
},
{
"cell_type": "markdown",
"id": "collected-deployment",
"id": "smooth-forge",
"metadata": {},
"source": [
"## Quarterly Income Statement"
@@ -224,7 +223,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "grateful-minnesota",
"id": "juvenile-throw",
"metadata": {
"collapsed": true
},
@@ -236,7 +235,7 @@
},
{
"cell_type": "markdown",
"id": "angry-somerset",
"id": "passive-nerve",
"metadata": {},
"source": [
"## Annual Balance Sheet"
@@ -245,7 +244,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "fifty-angola",
"id": "nominated-empire",
"metadata": {
"collapsed": true
},
@@ -257,7 +256,7 @@
},
{
"cell_type": "markdown",
"id": "typical-fundamentals",
"id": "special-bargain",
"metadata": {},
"source": [
"## Annual Cash Flow"
@@ -266,7 +265,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "magnetic-throat",
"id": "focused-thanks",
"metadata": {
"collapsed": true
},
@@ -279,7 +278,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "instructional-skating",
"id": "sought-phase",
"metadata": {
"collapsed": true
},

View File

@@ -1,39 +0,0 @@
interactions:
- request:
body: null
headers:
Connection:
- close
Host:
- financialmodelingprep.com
User-Agent:
- Python-urllib/3.8
method: GET
uri: https://financialmodelingprep.com/api/v3/historical-rating/PLTR?apikey=REPLACE_ME
response:
body:
string: '{"Error Message" : "Invalid API KEY. Please retry or visit our documentation
to create one FREE https://financialmodelingprep.com/developer/docs"}'
headers:
Access-Control-Allow-Headers:
- origin, content-type, accept, Authorization, authorization
Access-Control-Allow-Methods:
- GET, OPTIONS
Access-Control-Allow-Origin:
- '*'
Access-Control-Max-Age:
- '3600'
Connection:
- close
Content-Length:
- '146'
Content-Type:
- application/json;charset=UTF-8
Date:
- Thu, 12 Aug 2021 19:14:33 GMT
Server:
- nginx/1.14.0 (Ubuntu)
status:
code: 200
message: ''
version: 1

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
""" fundamental_analysis/business_insider_api.py tests """
import unittest
import vcr
from gamestonk_terminal.stocks.due_diligence.financial_modeling_prep_view import rating
from tests.helpers import check_print
class TestDdFinancialModelingPrepView(unittest.TestCase):
@check_print(assert_in="Invalid API KEY")
@vcr.use_cassette("tests/cassettes/test_dd/test_financial_model/test_rating.yaml")
def test_rating(self):
rating([], "PLTR")

View File

@@ -3,7 +3,7 @@ import unittest
import vcr
from gamestonk_terminal.stocks.due_diligence.finviz_view import analyst
from gamestonk_terminal.stocks.due_diligence.finviz_model import get_analyst_data
from tests.helpers import check_print
@@ -11,4 +11,5 @@ class TestDdFinvizApi(unittest.TestCase):
@check_print(assert_in="category")
@vcr.use_cassette("tests/cassettes/test_dd/test_finzin/test_analyst.yaml")
def test_analyst(self):
analyst([], "PLTR")
df = get_analyst_data(ticker="PLTR")
print(df.to_string())