mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-12 04:13:06 +00:00
Merge pull request #345 from DidierRLopes/refactor-fa
Refactor Fundamental Analysis menu
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
""" Alpha Vantage Controller """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis import alpha_vantage_view as avv
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import get_flair
|
||||
from gamestonk_terminal.menu import session
|
||||
|
||||
|
||||
class AlphaVantageController:
|
||||
""" Alpha Vantage Controller """
|
||||
|
||||
# Command choices
|
||||
CHOICES = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"overview",
|
||||
"key",
|
||||
"income",
|
||||
"balance",
|
||||
"cash",
|
||||
"earnings",
|
||||
]
|
||||
|
||||
def __init__(self, ticker: str, start: str, interval: str):
|
||||
"""Constructor
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Stat date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
self.ticker = ticker
|
||||
self.start = start
|
||||
self.interval = interval
|
||||
self.av_parser = argparse.ArgumentParser(add_help=False, prog="av")
|
||||
self.av_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("\nAlpha Vantage:")
|
||||
print(" help show this alpha vantage menu again")
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" overview overview of the company")
|
||||
print(" key company key metrics")
|
||||
print(" income income statements of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow of the company")
|
||||
print(" earnings earnings dates and reported EPS")
|
||||
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.av_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_overview(self, other_args: List[str]):
|
||||
""" Process overview command """
|
||||
avv.overview(other_args, self.ticker)
|
||||
|
||||
def call_key(self, other_args: List[str]):
|
||||
""" Process overview command """
|
||||
avv.key(other_args, self.ticker)
|
||||
|
||||
def call_income(self, other_args: List[str]):
|
||||
""" Process income command """
|
||||
avv.income_statement(other_args, self.ticker)
|
||||
|
||||
def call_balance(self, other_args: List[str]):
|
||||
""" Process balance command """
|
||||
avv.balance_sheet(other_args, self.ticker)
|
||||
|
||||
def call_cash(self, other_args: List[str]):
|
||||
""" Process cash command """
|
||||
avv.cash_flow(other_args, self.ticker)
|
||||
|
||||
def call_earnings(self, other_args: List[str]):
|
||||
""" Process earnings command """
|
||||
avv.earnings(other_args, self.ticker)
|
||||
|
||||
|
||||
def menu(ticker: str, start: str, interval: str):
|
||||
"""Alpha Vantage menu
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Start date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
av_controller = AlphaVantageController(ticker, start, interval)
|
||||
av_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 av_controller.CHOICES}
|
||||
)
|
||||
|
||||
an_input = session.prompt(
|
||||
f"{get_flair()} (fa)>(av)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
an_input = input(f"{get_flair()} (fa)>(av)> ")
|
||||
|
||||
try:
|
||||
process_input = av_controller.switch(an_input)
|
||||
|
||||
if process_input is not None:
|
||||
return process_input
|
||||
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
@@ -1,112 +1,33 @@
|
||||
""" Alpha Vantage View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import requests
|
||||
|
||||
from alpha_vantage.fundamentaldata import FundamentalData
|
||||
import pandas as pd
|
||||
from pandas.io.json import json_normalize
|
||||
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.dataframe_helpers import clean_df_index
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
long_number_format,
|
||||
parse_known_args_and_warn,
|
||||
get_flair,
|
||||
)
|
||||
from gamestonk_terminal.menu import session
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
|
||||
def print_menu(s_ticker, s_start, s_interval):
|
||||
""" Print help """
|
||||
def overview(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage stock ticker overview
|
||||
|
||||
s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"]
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
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("\nAlpha Vantage:")
|
||||
print(" help show this alpha vantage menu again")
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" overview overview of the company")
|
||||
print(" income income statements of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow of the company")
|
||||
print(" earnings earnings dates and reported EPS")
|
||||
print("")
|
||||
|
||||
|
||||
def menu(s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the fundamental analysis parser accepts
|
||||
av_parser = argparse.ArgumentParser(prog="av", add_help=False)
|
||||
choices = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"overview",
|
||||
"income",
|
||||
"balance",
|
||||
"cash",
|
||||
"earnings",
|
||||
]
|
||||
av_parser.add_argument("cmd", choices=choices)
|
||||
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
|
||||
|
||||
print_menu(s_ticker, s_start, s_interval)
|
||||
|
||||
# Loop forever and ever
|
||||
while True:
|
||||
# Get input command from user
|
||||
if session:
|
||||
as_input = session.prompt(
|
||||
f"{get_flair()} (fa)>(av)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
as_input = input(f"{get_flair()} (fa)>(av)> ")
|
||||
|
||||
# Parse alpha vantage command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = av_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_menu(s_ticker, s_start, s_interval)
|
||||
|
||||
elif ns_known_args.cmd == "q":
|
||||
# Just leave the menu
|
||||
return False
|
||||
|
||||
elif ns_known_args.cmd == "quit":
|
||||
# Abandon the program
|
||||
return True
|
||||
|
||||
elif ns_known_args.cmd == "overview":
|
||||
overview(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "income":
|
||||
income_statement(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "balance":
|
||||
balance_sheet(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "cash":
|
||||
cash_flow(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "earnings":
|
||||
earnings(l_args, s_ticker)
|
||||
|
||||
else:
|
||||
print("Command not recognized!")
|
||||
|
||||
|
||||
def overview(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="overview",
|
||||
@@ -128,18 +49,18 @@ def overview(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
|
||||
|
||||
# Request OVERVIEW data from Alpha Vantage API
|
||||
s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
result = requests.get(s_req, stream=True)
|
||||
|
||||
# If the returned data was successful
|
||||
if result.status_code == 200:
|
||||
# Parse json data to dataframe
|
||||
df_fa = json_normalize(result.json())
|
||||
df_fa = pd.json_normalize(result.json())
|
||||
# Keep json data sorting in dataframe
|
||||
df_fa = df_fa[list(result.json().keys())].T
|
||||
df_fa = df_fa.applymap(lambda x: long_number_format(x))
|
||||
@@ -182,7 +103,17 @@ def overview(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def key(l_args, s_ticker):
|
||||
def key(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage key metrics
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="key",
|
||||
@@ -196,17 +127,17 @@ def key(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
|
||||
|
||||
# Request OVERVIEW data
|
||||
s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
result = requests.get(s_req, stream=True)
|
||||
|
||||
# If the returned data was successful
|
||||
if result.status_code == 200:
|
||||
df_fa = json_normalize(result.json())
|
||||
df_fa = pd.json_normalize(result.json())
|
||||
df_fa = df_fa[list(result.json().keys())].T
|
||||
df_fa = df_fa.applymap(lambda x: long_number_format(x))
|
||||
clean_df_index(df_fa)
|
||||
@@ -248,10 +179,20 @@ def key(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def income_statement(l_args, s_ticker):
|
||||
def income_statement(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage income statement
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="incom",
|
||||
prog="income",
|
||||
description="""
|
||||
Prints a complete income statement over time. This can be either quarterly or annually.
|
||||
The following fields are expected: Accepted date, Cost and expenses, Cost of revenue,
|
||||
@@ -283,7 +224,7 @@ def income_statement(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
|
||||
|
||||
@@ -295,10 +236,10 @@ def income_statement(l_args, s_ticker):
|
||||
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
|
||||
if ns_parser.b_quarter:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_income_statement_quarterly(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_income_statement_quarterly(symbol=ticker)
|
||||
else:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_income_statement_annual(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_income_statement_annual(symbol=ticker)
|
||||
|
||||
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
|
||||
print(df_fa)
|
||||
@@ -310,7 +251,17 @@ def income_statement(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def balance_sheet(l_args, s_ticker):
|
||||
def balance_sheet(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage balance sheet
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="balance",
|
||||
@@ -351,7 +302,7 @@ def balance_sheet(l_args, s_ticker):
|
||||
)
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(other_args)
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}\n")
|
||||
@@ -365,10 +316,10 @@ def balance_sheet(l_args, s_ticker):
|
||||
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
|
||||
if ns_parser.b_quarter:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_balance_sheet_quarterly(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_balance_sheet_quarterly(symbol=ticker)
|
||||
else:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_balance_sheet_annual(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_balance_sheet_annual(symbol=ticker)
|
||||
|
||||
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
|
||||
print(df_fa)
|
||||
@@ -380,7 +331,17 @@ def balance_sheet(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def cash_flow(l_args, s_ticker):
|
||||
def cash_flow(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage cash flow
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="cash",
|
||||
@@ -419,7 +380,7 @@ def cash_flow(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
|
||||
|
||||
@@ -431,10 +392,10 @@ def cash_flow(l_args, s_ticker):
|
||||
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
|
||||
if ns_parser.b_quarter:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_cash_flow_quarterly(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_cash_flow_quarterly(symbol=ticker)
|
||||
else:
|
||||
# pylint: disable=unbalanced-tuple-unpacking
|
||||
df_fa, _ = fd.get_cash_flow_annual(symbol=s_ticker)
|
||||
df_fa, _ = fd.get_cash_flow_annual(symbol=ticker)
|
||||
|
||||
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
|
||||
print(df_fa)
|
||||
@@ -446,7 +407,17 @@ def cash_flow(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def earnings(l_args, s_ticker):
|
||||
def earnings(other_args: List[str], ticker: str):
|
||||
"""Alpha Vantage earnings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="earnings",
|
||||
@@ -475,7 +446,7 @@ def earnings(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
|
||||
|
||||
@@ -487,13 +458,13 @@ def earnings(l_args, s_ticker):
|
||||
# Request EARNINGS data from Alpha Vantage API
|
||||
s_req = (
|
||||
"https://www.alphavantage.co/query?function=EARNINGS&"
|
||||
f"symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
f"symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
|
||||
)
|
||||
result = requests.get(s_req, stream=True)
|
||||
|
||||
# If the returned data was successful
|
||||
if result.status_code == 200:
|
||||
df_fa = json_normalize(result.json())
|
||||
df_fa = pd.json_normalize(result.json())
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0])
|
||||
df_fa = df_fa[
|
||||
@@ -1,4 +1,8 @@
|
||||
""" Business Insider View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import pandas as pd
|
||||
@@ -6,7 +10,17 @@ from rapidfuzz import fuzz
|
||||
from gamestonk_terminal.helper_funcs import get_user_agent, parse_known_args_and_warn
|
||||
|
||||
|
||||
def management(l_args, s_ticker):
|
||||
def management(other_args: List[str], ticker: str):
|
||||
"""Display company's managers
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Stock ticker
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="mgmt",
|
||||
@@ -17,12 +31,12 @@ def management(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(
|
||||
@@ -42,7 +56,7 @@ def management(l_args, s_ticker):
|
||||
found_h2s[next_h2.text] = next_table
|
||||
|
||||
if found_h2s.get("Management") is None:
|
||||
print(f"No management information in Business Insider for {s_ticker}")
|
||||
print(f"No management information in Business Insider for {ticker}")
|
||||
print("")
|
||||
return
|
||||
|
||||
@@ -73,7 +87,7 @@ def management(l_args, s_ticker):
|
||||
for s_name in df_management.index:
|
||||
df_management.loc[s_name][
|
||||
"Info"
|
||||
] = f"http://www.google.com/search?q={s_name} {s_ticker.upper()}".replace(
|
||||
] = f"http://www.google.com/search?q={s_name} {ticker.upper()}".replace(
|
||||
" ", "%20"
|
||||
)
|
||||
|
||||
253
gamestonk_terminal/fundamental_analysis/fa_controller.py
Normal file
253
gamestonk_terminal/fundamental_analysis/fa_controller.py
Normal file
@@ -0,0 +1,253 @@
|
||||
""" Fundamental Analysis Controller """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis import alpha_vantage_controller as avc
|
||||
from gamestonk_terminal.fundamental_analysis import business_insider_view as biw
|
||||
from gamestonk_terminal.fundamental_analysis import (
|
||||
financial_modeling_prep_controller as fmpc,
|
||||
)
|
||||
from gamestonk_terminal.fundamental_analysis import finviz_view
|
||||
from gamestonk_terminal.fundamental_analysis import market_watch_view
|
||||
from gamestonk_terminal.fundamental_analysis import yahoo_finance_view
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import get_flair
|
||||
from gamestonk_terminal.menu import session
|
||||
|
||||
|
||||
class FundamentalAnalysisController:
|
||||
""" Fundamental Analysis Controller """
|
||||
|
||||
# Command choices
|
||||
CHOICES = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"screener",
|
||||
"income",
|
||||
"balance",
|
||||
"cash",
|
||||
"mgmt",
|
||||
"info",
|
||||
"shrs",
|
||||
"sust",
|
||||
"cal",
|
||||
"av",
|
||||
"fmp",
|
||||
]
|
||||
|
||||
def __init__(self, ticker: str, start: str, interval: str):
|
||||
"""Constructor
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Stat date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
self.ticker = ticker
|
||||
self.start = start
|
||||
self.interval = interval
|
||||
|
||||
self.fa_parser = argparse.ArgumentParser(add_help=False, prog="fa")
|
||||
self.fa_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(
|
||||
"\nFundamental Analysis:"
|
||||
) # https://github.com/JerBouma/FundamentalAnalysis
|
||||
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(" screener screen info about the company [Finviz]")
|
||||
print(" mgmt management team of the company [Business Insider]")
|
||||
print("")
|
||||
print("Market Watch API")
|
||||
print(" income income statement of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow statement of the company")
|
||||
print("")
|
||||
print("Yahoo Finance API")
|
||||
print(" info information scope of the company")
|
||||
print(" shrs shareholders of the company")
|
||||
print(" sust sustainability values of the company")
|
||||
print(" cal calendar earnings and estimates of the company")
|
||||
print("")
|
||||
print("Other Sources:")
|
||||
print("> av Alpha Vantage MENU")
|
||||
print("> fmp Financial Modeling Prep MENU")
|
||||
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.fa_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_mgmt(self, other_args: List[str]):
|
||||
""" Process mgmt command """
|
||||
biw.management(other_args, self.ticker)
|
||||
|
||||
def call_screener(self, other_args: List[str]):
|
||||
""" Process screener command """
|
||||
finviz_view.screener(other_args, self.ticker)
|
||||
|
||||
def call_income(self, other_args: List[str]):
|
||||
""" Process income command """
|
||||
market_watch_view.income(other_args, self.ticker)
|
||||
|
||||
def call_balance(self, other_args: List[str]):
|
||||
""" Process balance command """
|
||||
market_watch_view.balance(other_args, self.ticker)
|
||||
|
||||
def call_cash(self, other_args: List[str]):
|
||||
""" Process cash command """
|
||||
market_watch_view.cash(other_args, self.ticker)
|
||||
|
||||
def call_info(self, other_args: List[str]):
|
||||
""" Process info command """
|
||||
yahoo_finance_view.info(other_args, self.ticker)
|
||||
|
||||
def call_shrs(self, other_args: List[str]):
|
||||
""" Process shrs command """
|
||||
yahoo_finance_view.shareholders(other_args, self.ticker)
|
||||
|
||||
def call_sust(self, other_args: List[str]):
|
||||
""" Process sust command """
|
||||
yahoo_finance_view.sustainability(other_args, self.ticker)
|
||||
|
||||
def call_cal(self, other_args: List[str]):
|
||||
""" Process cal command """
|
||||
yahoo_finance_view.calendar_earnings(other_args, self.ticker)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def call_av(self, other_args: List[str]):
|
||||
""" Process av command """
|
||||
ret = avc.menu(self.ticker, self.start, self.interval)
|
||||
|
||||
if ret is not True:
|
||||
self.print_help()
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def call_fmp(self, other_args: List[str]):
|
||||
""" Process fmp command """
|
||||
ret = fmpc.menu(self.ticker, self.start, self.interval)
|
||||
|
||||
if ret is not True:
|
||||
self.print_help()
|
||||
|
||||
|
||||
def key_metrics_explained(other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="info",
|
||||
description="""
|
||||
Provides information about main key metrics. Namely: EBITDA,
|
||||
EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta.
|
||||
""",
|
||||
)
|
||||
|
||||
try:
|
||||
(_, l_unknown_args) = parser.parse_known_args(other_args)
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
filepath = "fundamental_analysis/key_metrics_explained.txt"
|
||||
with open(filepath) as fp:
|
||||
line = fp.readline()
|
||||
while line:
|
||||
print(f"{line.strip()}")
|
||||
line = fp.readline()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("ERROR!\n")
|
||||
return
|
||||
|
||||
|
||||
def menu(ticker: str, start: str, interval: str):
|
||||
"""Fundamental Analysis menu
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Start date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
fa_controller = FundamentalAnalysisController(ticker, start, interval)
|
||||
fa_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 fa_controller.CHOICES}
|
||||
)
|
||||
|
||||
an_input = session.prompt(
|
||||
f"{get_flair()} (fa)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
an_input = input(f"{get_flair()} (fa)> ")
|
||||
|
||||
try:
|
||||
process_input = fa_controller.switch(an_input)
|
||||
|
||||
if process_input is not None:
|
||||
return process_input
|
||||
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
@@ -1,193 +0,0 @@
|
||||
import argparse
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis import alpha_vantage_api as av_api
|
||||
from gamestonk_terminal.fundamental_analysis import business_insider_api as bi_api
|
||||
from gamestonk_terminal.fundamental_analysis import (
|
||||
financial_modeling_prep_api as fmp_api,
|
||||
)
|
||||
from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api
|
||||
from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api
|
||||
from gamestonk_terminal.fundamental_analysis import yahoo_finance_api as yf_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_fundamental_analysis(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("\nFundamental Analysis:") # https://github.com/JerBouma/FundamentalAnalysis
|
||||
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(" screener screen info about the company [Finviz]")
|
||||
print(" mgmt management team of the company [Business Insider]")
|
||||
print("")
|
||||
print("Market Watch API")
|
||||
print(" income income statement of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow statement of the company")
|
||||
print("")
|
||||
print("Yahoo Finance API")
|
||||
print(" info information scope of the company")
|
||||
print(" shrs shareholders of the company")
|
||||
print(" sust sustainability values of the company")
|
||||
print(" cal calendar earnings and estimates of the company")
|
||||
print("")
|
||||
print("Other Sources:")
|
||||
print("> av Alpha Vantage MENU")
|
||||
print("> fmp Financial Modeling Prep MENU")
|
||||
print("")
|
||||
return
|
||||
|
||||
|
||||
def key_metrics_explained(l_args):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="info",
|
||||
description="""
|
||||
Provides information about main key metrics. Namely: EBITDA,
|
||||
EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta.
|
||||
""",
|
||||
)
|
||||
|
||||
try:
|
||||
(_, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
filepath = "fundamental_analysis/key_metrics_explained.txt"
|
||||
with open(filepath) as fp:
|
||||
line = fp.readline()
|
||||
while line:
|
||||
print(f"{line.strip()}")
|
||||
line = fp.readline()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("ERROR!\n")
|
||||
return
|
||||
|
||||
|
||||
# pylint: disable=too-many-branches
|
||||
def fa_menu(s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the fundamental analysis parser accepts
|
||||
fa_parser = argparse.ArgumentParser(prog="fa", add_help=False)
|
||||
choices = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"screener",
|
||||
"income",
|
||||
"balance",
|
||||
"cash",
|
||||
"mgmt",
|
||||
"info",
|
||||
"shrs",
|
||||
"sust",
|
||||
"cal",
|
||||
"av",
|
||||
"fmp",
|
||||
]
|
||||
fa_parser.add_argument("cmd", choices=choices)
|
||||
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
|
||||
|
||||
should_print_help = True
|
||||
|
||||
# Loop forever and ever
|
||||
while True:
|
||||
if should_print_help:
|
||||
print_fundamental_analysis(s_ticker, s_start, s_interval)
|
||||
should_print_help = False
|
||||
|
||||
# Get input command from user
|
||||
if session and gtff.USE_PROMPT_TOOLKIT:
|
||||
as_input = session.prompt(
|
||||
f"{get_flair()} (fa)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
as_input = input(f"{get_flair()} (fa)> ")
|
||||
|
||||
# Parse fundamental analysis command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = fa_parser.parse_known_args(as_input.split())
|
||||
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
|
||||
if ns_known_args.cmd == "help":
|
||||
should_print_help = True
|
||||
|
||||
elif ns_known_args.cmd == "q":
|
||||
# Just leave the FA menu
|
||||
return False
|
||||
|
||||
elif ns_known_args.cmd == "quit":
|
||||
# Abandon the program
|
||||
return True
|
||||
|
||||
# BUSINESS INSIDER API
|
||||
elif ns_known_args.cmd == "mgmt":
|
||||
bi_api.management(l_args, s_ticker)
|
||||
|
||||
# FINVIZ API
|
||||
elif ns_known_args.cmd == "screener":
|
||||
fvz_api.screener(l_args, s_ticker)
|
||||
|
||||
# MARKET WATCH API
|
||||
elif ns_known_args.cmd == "income":
|
||||
mw_api.income(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "balance":
|
||||
mw_api.balance(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "cash":
|
||||
mw_api.cash(l_args, s_ticker)
|
||||
|
||||
# YAHOO FINANCE API
|
||||
elif ns_known_args.cmd == "info":
|
||||
yf_api.info(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "shrs":
|
||||
yf_api.shareholders(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "sust":
|
||||
yf_api.sustainability(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "cal":
|
||||
yf_api.calendar_earnings(l_args, s_ticker)
|
||||
|
||||
# ALPHA VANTAGE API
|
||||
elif ns_known_args.cmd == "av":
|
||||
b_quit = av_api.menu(s_ticker, s_start, s_interval)
|
||||
|
||||
if b_quit:
|
||||
return True
|
||||
else:
|
||||
should_print_help = True
|
||||
|
||||
# FINANCIAL MODELING PREP API
|
||||
elif ns_known_args.cmd == "fmp":
|
||||
b_quit = fmp_api.menu(s_ticker, s_start, s_interval)
|
||||
|
||||
if b_quit:
|
||||
return True
|
||||
else:
|
||||
should_print_help = True
|
||||
|
||||
else:
|
||||
print("Command not recognized!")
|
||||
@@ -0,0 +1,194 @@
|
||||
""" Financial Modeling Prep Controller """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis import financial_modeling_prep_view as fmpv
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
get_flair,
|
||||
)
|
||||
from gamestonk_terminal.menu import session
|
||||
|
||||
|
||||
class FinancialModelingPrepController:
|
||||
""" Financial Modeling Prep Controller """
|
||||
|
||||
# Command choices
|
||||
CHOICES = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"profile",
|
||||
"quote",
|
||||
"enterprise",
|
||||
"dcf",
|
||||
"income",
|
||||
"balance",
|
||||
"cash",
|
||||
"metrics",
|
||||
"ratios",
|
||||
"growth",
|
||||
]
|
||||
|
||||
def __init__(self, ticker: str, start: str, interval: str):
|
||||
"""Constructor
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Stat date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
self.ticker = ticker
|
||||
self.start = start
|
||||
self.interval = interval
|
||||
self.fmp_parser = argparse.ArgumentParser(add_help=False, prog="fmp")
|
||||
self.fmp_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("\nFinancial Modeling Prep API")
|
||||
print(" help show this financial modeling prep menu again")
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" profile profile of the company")
|
||||
print(" quote quote of the company")
|
||||
print(" enterprise enterprise value of the company over time")
|
||||
print(" dcf discounted cash flow of the company over time")
|
||||
print(" income income statements of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow statement of the company")
|
||||
print(" metrics key metrics of the company")
|
||||
print(" ratios financial ratios of the company")
|
||||
print(" growth financial statement growth of the company")
|
||||
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.fmp_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_profile(self, other_args: List[str]):
|
||||
""" Process profile command """
|
||||
fmpv.profile(other_args, self.ticker)
|
||||
|
||||
def call_quote(self, other_args: List[str]):
|
||||
""" Process quote command """
|
||||
fmpv.quote(other_args, self.ticker)
|
||||
|
||||
def call_enterprise(self, other_args: List[str]):
|
||||
""" Process income command """
|
||||
fmpv.enterprise(other_args, self.ticker)
|
||||
|
||||
def call_dcf(self, other_args: List[str]):
|
||||
""" Process dcf command """
|
||||
fmpv.discounted_cash_flow(other_args, self.ticker)
|
||||
|
||||
def call_income(self, other_args: List[str]):
|
||||
""" Process income command """
|
||||
fmpv.income_statement(other_args, self.ticker)
|
||||
|
||||
def call_balance(self, other_args: List[str]):
|
||||
""" Process balance command """
|
||||
fmpv.balance_sheet(other_args, self.ticker)
|
||||
|
||||
def call_cash(self, other_args: List[str]):
|
||||
""" Process cash command """
|
||||
fmpv.cash_flow(other_args, self.ticker)
|
||||
|
||||
def call_metrics(self, other_args: List[str]):
|
||||
""" Process metrics command """
|
||||
fmpv.key_metrics(other_args, self.ticker)
|
||||
|
||||
def call_ratios(self, other_args: List[str]):
|
||||
""" Process cash command """
|
||||
fmpv.financial_ratios(other_args, self.ticker)
|
||||
|
||||
def call_growth(self, other_args: List[str]):
|
||||
""" Process cash command """
|
||||
fmpv.financial_statement_growth(other_args, self.ticker)
|
||||
|
||||
|
||||
def menu(ticker: str, start: str, interval: str):
|
||||
"""Financial Modeling Prep menu
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
start : str
|
||||
Start date of the stock data
|
||||
interval : str
|
||||
Stock data interval
|
||||
"""
|
||||
|
||||
fmp_controller = FinancialModelingPrepController(ticker, start, interval)
|
||||
fmp_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 fmp_controller.CHOICES}
|
||||
)
|
||||
|
||||
an_input = session.prompt(
|
||||
f"{get_flair()} (fa)>(fmp)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
an_input = input(f"{get_flair()} (fa)>(fmp)> ")
|
||||
|
||||
try:
|
||||
process_input = fmp_controller.switch(an_input)
|
||||
|
||||
if process_input is not None:
|
||||
return process_input
|
||||
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
@@ -1,139 +1,31 @@
|
||||
""" Financial Modeling Prep View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
import pandas as pd
|
||||
import FundamentalAnalysis as fa # Financial Modeling Prep
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.dataframe_helpers import clean_df_index
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
long_number_format,
|
||||
check_positive,
|
||||
parse_known_args_and_warn,
|
||||
get_flair,
|
||||
)
|
||||
from gamestonk_terminal.menu import session
|
||||
|
||||
|
||||
def print_menu(s_ticker, s_start, s_interval):
|
||||
""" Print help """
|
||||
def profile(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker profile
|
||||
|
||||
s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"]
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
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("\nFinancial Modeling Prep API")
|
||||
print(" help show this financial modeling prep menu again")
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" profile profile of the company")
|
||||
print(" quote quote of the company")
|
||||
print(" enterprise enterprise value of the company over time")
|
||||
print(" dcf discounted cash flow of the company over time")
|
||||
print(" income income statements of the company")
|
||||
print(" balance balance sheet of the company")
|
||||
print(" cash cash flow statement of the company")
|
||||
print(" metrics key metrics of the company")
|
||||
print(" ratios financial ratios of the company")
|
||||
print(" growth financial statement growth of the company")
|
||||
print("")
|
||||
|
||||
|
||||
def menu(s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the fundamental analysis parser accepts
|
||||
fmp_parser = argparse.ArgumentParser(prog="fmp", add_help=False)
|
||||
choices = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"profile",
|
||||
"quote",
|
||||
"enterprise",
|
||||
"dcf",
|
||||
"fmp_income",
|
||||
"fmp_balance",
|
||||
"fmp_cash",
|
||||
"metrics",
|
||||
"ratios",
|
||||
"growth",
|
||||
]
|
||||
fmp_parser.add_argument("cmd", choices=choices)
|
||||
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
|
||||
|
||||
print_menu(s_ticker, s_start, s_interval)
|
||||
|
||||
# Loop forever and ever
|
||||
while True:
|
||||
# Get input command from user
|
||||
if session:
|
||||
as_input = session.prompt(
|
||||
f"{get_flair()} (fa)>(fmp)> ",
|
||||
completer=completer,
|
||||
)
|
||||
else:
|
||||
as_input = input(f"{get_flair()} (fa)>(av)> ")
|
||||
|
||||
# Parse alpha vantage command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = fmp_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_menu(s_ticker, s_start, s_interval)
|
||||
|
||||
elif ns_known_args.cmd == "q":
|
||||
# Just leave the menu
|
||||
return False
|
||||
|
||||
elif ns_known_args.cmd == "quit":
|
||||
# Abandon the program
|
||||
return True
|
||||
|
||||
# Details:
|
||||
elif ns_known_args.cmd == "profile":
|
||||
profile(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "quote":
|
||||
quote(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "enterprise":
|
||||
enterprise(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "dcf":
|
||||
discounted_cash_flow(l_args, s_ticker)
|
||||
|
||||
# Financial statement:
|
||||
elif ns_known_args.cmd == "income":
|
||||
income_statement(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "balance":
|
||||
balance_sheet(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "cash":
|
||||
cash_flow(l_args, s_ticker)
|
||||
|
||||
# Ratios:
|
||||
elif ns_known_args.cmd == "metrics":
|
||||
key_metrics(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "ratios":
|
||||
financial_ratios(l_args, s_ticker)
|
||||
|
||||
elif ns_known_args.cmd == "growth":
|
||||
financial_statement_growth(l_args, s_ticker)
|
||||
|
||||
else:
|
||||
print("Command not recognized!")
|
||||
|
||||
|
||||
def profile(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="profile",
|
||||
@@ -148,11 +40,11 @@ def profile(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.profile(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.profile(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
clean_df_index(df_fa)
|
||||
|
||||
print(df_fa.drop(index=["Description", "Image"]).to_string(header=False))
|
||||
@@ -166,7 +58,17 @@ def profile(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def quote(l_args, s_ticker):
|
||||
def quote(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker quote
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="quote",
|
||||
@@ -181,11 +83,11 @@ def quote(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.quote(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
clean_df_index(df_fa)
|
||||
|
||||
@@ -211,7 +113,17 @@ def quote(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def enterprise(l_args, s_ticker):
|
||||
def enterprise(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker enterprise
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="enterprise",
|
||||
@@ -242,7 +154,7 @@ def enterprise(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
|
||||
|
||||
@@ -253,10 +165,10 @@ def enterprise(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.enterprise(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.enterprise(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num, mask=False)
|
||||
|
||||
@@ -269,7 +181,17 @@ def enterprise(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def discounted_cash_flow(l_args, s_ticker):
|
||||
def discounted_cash_flow(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker discounted cash flow
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="dcf",
|
||||
@@ -298,7 +220,7 @@ def discounted_cash_flow(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
|
||||
|
||||
@@ -309,10 +231,10 @@ def discounted_cash_flow(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.discounted_cash_flow(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.discounted_cash_flow(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num, mask=False)
|
||||
|
||||
@@ -325,7 +247,17 @@ def discounted_cash_flow(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def income_statement(l_args, s_ticker):
|
||||
def income_statement(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker income statement
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="inc",
|
||||
@@ -361,7 +293,7 @@ def income_statement(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
|
||||
|
||||
@@ -372,10 +304,10 @@ def income_statement(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.income_statement(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.income_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
|
||||
@@ -394,7 +326,17 @@ def income_statement(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def balance_sheet(l_args, s_ticker):
|
||||
def balance_sheet(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker balance sheet
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="bal",
|
||||
@@ -435,7 +377,7 @@ def balance_sheet(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
|
||||
|
||||
@@ -446,11 +388,11 @@ def balance_sheet(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.balance_sheet_statement(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.balance_sheet_statement(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP
|
||||
)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
@@ -470,7 +412,17 @@ def balance_sheet(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def cash_flow(l_args, s_ticker):
|
||||
def cash_flow(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker cash flow
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="cash",
|
||||
@@ -509,7 +461,7 @@ def cash_flow(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
|
||||
|
||||
@@ -520,10 +472,10 @@ def cash_flow(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.cash_flow_statement(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.cash_flow_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
|
||||
@@ -542,7 +494,17 @@ def cash_flow(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def key_metrics(l_args, s_ticker):
|
||||
def key_metrics(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker key metrics
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="metrics",
|
||||
@@ -560,7 +522,7 @@ def key_metrics(l_args, s_ticker):
|
||||
Inventory turnover, Market cap, Net current asset value, Net debt to EBITDA, Net income
|
||||
per share, Operating cash flow per share, Payables turnover, Payout ratio, Pb ratio, Pe
|
||||
ratio, Pfcf ratio, Pocfratio, Price to sales ratio, Ptb ratio, Receivables turnover,
|
||||
Research and ddevelopement to revenue, Return on tangible assets, Revenue per share,
|
||||
Research and development to revenue, Return on tangible assets, Revenue per share,
|
||||
Roe, Roic, Sales general and administrative to revenue, Shareholders equity per
|
||||
share, Stock based compensation to revenue, Tangible book value per share, and Working
|
||||
capital. [Source: Financial Modeling Prep]
|
||||
@@ -586,7 +548,7 @@ def key_metrics(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
|
||||
|
||||
@@ -597,10 +559,10 @@ def key_metrics(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.key_metrics(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.key_metrics(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
|
||||
@@ -613,7 +575,17 @@ def key_metrics(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def financial_ratios(l_args, s_ticker):
|
||||
def financial_ratios(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker ratios
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="ratios",
|
||||
@@ -658,7 +630,7 @@ def financial_ratios(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
|
||||
|
||||
@@ -669,10 +641,10 @@ def financial_ratios(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.financial_ratios(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
df_fa = fa.financial_ratios(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
|
||||
@@ -685,7 +657,17 @@ def financial_ratios(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def financial_statement_growth(l_args, s_ticker):
|
||||
def financial_statement_growth(other_args: List[str], ticker: str):
|
||||
"""Financial Modeling Prep ticker growth
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="growth",
|
||||
@@ -726,7 +708,7 @@ def financial_statement_growth(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
|
||||
|
||||
@@ -737,11 +719,11 @@ def financial_statement_growth(l_args, s_ticker):
|
||||
|
||||
if ns_parser.b_quarter:
|
||||
df_fa = fa.financial_statement_growth(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
|
||||
)
|
||||
else:
|
||||
df_fa = fa.financial_statement_growth(
|
||||
s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP
|
||||
ticker, cfg.API_KEY_FINANCIALMODELINGPREP
|
||||
)
|
||||
|
||||
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
|
||||
@@ -756,6 +738,23 @@ def financial_statement_growth(l_args, s_ticker):
|
||||
|
||||
|
||||
def clean_metrics_df(df_fa: pd.DataFrame, num: int, mask: bool = True) -> pd.DataFrame:
|
||||
"""Clean metrics data frame
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_fa : pd.DataFrame
|
||||
Metrics data frame
|
||||
num : int
|
||||
Number of columns to clean
|
||||
mask : bool, optional
|
||||
Apply mask, by default True
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Cleaned metrics data frame
|
||||
"""
|
||||
|
||||
df_fa = df_fa.iloc[:, 0:num]
|
||||
if mask:
|
||||
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["None"])).dropna()
|
||||
@@ -1,10 +1,25 @@
|
||||
""" FinViz View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import finviz
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
|
||||
|
||||
|
||||
def screener(l_args, s_ticker):
|
||||
def screener(other_args: List[str], ticker: str):
|
||||
"""FinViz ticker screener
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="screener",
|
||||
@@ -24,11 +39,11 @@ def screener(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_stock = finviz.get_stock(s_ticker)
|
||||
d_finviz_stock = finviz.get_stock(ticker)
|
||||
df_fa = pd.DataFrame.from_dict(
|
||||
d_finviz_stock, orient="index", columns=["Values"]
|
||||
)
|
||||
111
gamestonk_terminal/fundamental_analysis/market_watch_model.py
Normal file
111
gamestonk_terminal/fundamental_analysis/market_watch_model.py
Normal file
@@ -0,0 +1,111 @@
|
||||
""" Fundamental Analysis Market Watch Model """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import requests
|
||||
import pandas as pd
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
get_user_agent,
|
||||
)
|
||||
|
||||
|
||||
def prepare_df_financials(
|
||||
ticker: str, statement: str, quarter: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Builds a DataFrame with financial statements for a given company
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Company's stock ticker
|
||||
statement : str
|
||||
Either income, balance or cashflow
|
||||
quarter : bool, optional
|
||||
Return quarterly financial statements instead of annual, by default False
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
A DataFrame with financial info
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If statement is not income, balance or cashflow
|
||||
"""
|
||||
financial_urls = {
|
||||
"income": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/income/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/income",
|
||||
},
|
||||
"balance": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet",
|
||||
},
|
||||
"cashflow": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow",
|
||||
},
|
||||
}
|
||||
|
||||
if statement not in financial_urls.keys():
|
||||
raise ValueError(f"type {statement} is not in {financial_urls.keys()}")
|
||||
|
||||
if quarter:
|
||||
period = "quarter"
|
||||
else:
|
||||
period = "annual"
|
||||
|
||||
text_soup_financials = BeautifulSoup(
|
||||
requests.get(
|
||||
financial_urls[statement][period].format(ticker),
|
||||
headers={"User-Agent": get_user_agent()},
|
||||
).text,
|
||||
"lxml",
|
||||
)
|
||||
|
||||
# Define financials columns
|
||||
a_financials_header = list()
|
||||
for financials_header in text_soup_financials.findAll(
|
||||
"th", {"class": "overflow__heading"}
|
||||
):
|
||||
a_financials_header.append(financials_header.text.strip("\n").split("\n")[0])
|
||||
|
||||
s_header_end_trend = ("5-year trend", "5- qtr trend")[quarter]
|
||||
df_financials = pd.DataFrame(
|
||||
columns=a_financials_header[0 : a_financials_header.index(s_header_end_trend)]
|
||||
)
|
||||
|
||||
find_table = text_soup_financials.findAll(
|
||||
"div", {"class": "element element--table table--fixed financials"}
|
||||
)
|
||||
|
||||
if not find_table:
|
||||
return df_financials
|
||||
|
||||
financials_rows = find_table[0].findAll(
|
||||
"tr", {"class": ["table__row is-highlighted", "table__row"]}
|
||||
)
|
||||
|
||||
for a_row in financials_rows:
|
||||
constructed_row = list()
|
||||
financial_columns = a_row.findAll(
|
||||
"td", {"class": ["overflow__cell", "overflow__cell fixed--column"]}
|
||||
)
|
||||
|
||||
if not financial_columns:
|
||||
continue
|
||||
|
||||
for a_column in financial_columns:
|
||||
column_to_text = a_column.text.strip()
|
||||
if "\n" in column_to_text:
|
||||
column_to_text = column_to_text.split("\n")[0]
|
||||
|
||||
if column_to_text == "":
|
||||
continue
|
||||
constructed_row.append(column_to_text)
|
||||
|
||||
df_financials.loc[len(df_financials)] = constructed_row
|
||||
|
||||
return df_financials
|
||||
@@ -1,12 +1,12 @@
|
||||
""" Fundamental Analysis Market Watch API """
|
||||
""" Fundamental Analysis Market Watch View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
import requests
|
||||
from typing import List
|
||||
import pandas as pd
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis import market_watch_model as mwm
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
get_user_agent,
|
||||
parse_known_args_and_warn,
|
||||
patch_pandas_text_adjustment,
|
||||
financials_colored_values,
|
||||
@@ -14,7 +14,17 @@ from gamestonk_terminal.helper_funcs import (
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
|
||||
|
||||
def income(l_args, s_ticker):
|
||||
def income(other_args: List[str], ticker: str):
|
||||
"""Market Watch ticker income statement
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="income",
|
||||
@@ -50,11 +60,11 @@ def income(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_financials = prepare_df_financials(s_ticker, "income", ns_parser.b_quarter)
|
||||
df_financials = mwm.prepare_df_financials(ticker, "income", ns_parser.b_quarter)
|
||||
|
||||
if gtff.USE_COLOR:
|
||||
df_financials = df_financials.applymap(financials_colored_values)
|
||||
@@ -72,7 +82,17 @@ def income(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def balance(l_args, s_ticker):
|
||||
def balance(other_args: List[str], ticker: str):
|
||||
"""Market Watch ticker balance statement
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="balance",
|
||||
@@ -120,11 +140,13 @@ def balance(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_financials = prepare_df_financials(s_ticker, "balance", ns_parser.b_quarter)
|
||||
df_financials = mwm.prepare_df_financials(
|
||||
ticker, "balance", ns_parser.b_quarter
|
||||
)
|
||||
|
||||
if gtff.USE_COLOR:
|
||||
df_financials = df_financials.applymap(financials_colored_values)
|
||||
@@ -142,7 +164,17 @@ def balance(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def cash(l_args, s_ticker):
|
||||
def cash(other_args: List[str], ticker: str):
|
||||
"""Market Watch ticker cash flow statement
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="cash_flow",
|
||||
@@ -186,11 +218,13 @@ def cash(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_financials = prepare_df_financials(s_ticker, "cashflow", ns_parser.b_quarter)
|
||||
df_financials = mwm.prepare_df_financials(
|
||||
ticker, "cashflow", ns_parser.b_quarter
|
||||
)
|
||||
|
||||
if gtff.USE_COLOR:
|
||||
df_financials = df_financials.applymap(financials_colored_values)
|
||||
@@ -206,104 +240,3 @@ def cash(l_args, s_ticker):
|
||||
print(e)
|
||||
print("")
|
||||
return
|
||||
|
||||
|
||||
def prepare_df_financials(
|
||||
ticker: str, statement: str, quarter: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Builds a DataFrame with financial statements for a given company
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Company's stock ticker
|
||||
statement : str
|
||||
Either income, balance or cashflow
|
||||
quarter : bool, optional
|
||||
Return quarterly financial statements instead of annual, by default False
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
A DataFrame with financial info
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If statement is not income, balance or cashflow
|
||||
"""
|
||||
financial_urls = {
|
||||
"income": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/income/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/income",
|
||||
},
|
||||
"balance": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet",
|
||||
},
|
||||
"cashflow": {
|
||||
"quarter": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow/quarter",
|
||||
"annual": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow",
|
||||
},
|
||||
}
|
||||
|
||||
if statement not in financial_urls.keys():
|
||||
raise ValueError(f"type {statement} is not in {financial_urls.keys()}")
|
||||
|
||||
if quarter:
|
||||
period = "quarter"
|
||||
else:
|
||||
period = "annual"
|
||||
|
||||
text_soup_financials = BeautifulSoup(
|
||||
requests.get(
|
||||
financial_urls[statement][period].format(ticker),
|
||||
headers={"User-Agent": get_user_agent()},
|
||||
).text,
|
||||
"lxml",
|
||||
)
|
||||
|
||||
# Define financials columns
|
||||
a_financials_header = list()
|
||||
for financials_header in text_soup_financials.findAll(
|
||||
"th", {"class": "overflow__heading"}
|
||||
):
|
||||
a_financials_header.append(financials_header.text.strip("\n").split("\n")[0])
|
||||
|
||||
s_header_end_trend = ("5-year trend", "5- qtr trend")[quarter]
|
||||
df_financials = pd.DataFrame(
|
||||
columns=a_financials_header[0 : a_financials_header.index(s_header_end_trend)]
|
||||
)
|
||||
|
||||
find_table = text_soup_financials.findAll(
|
||||
"div", {"class": "element element--table table--fixed financials"}
|
||||
)
|
||||
|
||||
if not find_table:
|
||||
return df_financials
|
||||
|
||||
financials_rows = find_table[0].findAll(
|
||||
"tr", {"class": ["table__row is-highlighted", "table__row"]}
|
||||
)
|
||||
|
||||
for a_row in financials_rows:
|
||||
constructed_row = list()
|
||||
financial_columns = a_row.findAll(
|
||||
"td", {"class": ["overflow__cell", "overflow__cell fixed--column"]}
|
||||
)
|
||||
|
||||
if not financial_columns:
|
||||
continue
|
||||
|
||||
for a_column in financial_columns:
|
||||
column_to_text = a_column.text.strip()
|
||||
if "\n" in column_to_text:
|
||||
column_to_text = column_to_text.split("\n")[0]
|
||||
|
||||
if column_to_text == "":
|
||||
continue
|
||||
constructed_row.append(column_to_text)
|
||||
|
||||
df_financials.loc[len(df_financials)] = constructed_row
|
||||
|
||||
return df_financials
|
||||
@@ -1,7 +1,12 @@
|
||||
""" Yahoo Finance View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
import yfinance as yf
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.dataframe_helpers import clean_df_index
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
long_number_format,
|
||||
@@ -9,7 +14,17 @@ from gamestonk_terminal.helper_funcs import (
|
||||
)
|
||||
|
||||
|
||||
def info(l_args, s_ticker):
|
||||
def info(other_args: List[str], ticker: str):
|
||||
"""Yahoo Finance ticker info
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="info",
|
||||
@@ -36,11 +51,11 @@ def info(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
|
||||
|
||||
stock = yf.Ticker(s_ticker)
|
||||
stock = yf.Ticker(ticker)
|
||||
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
|
||||
df_info = df_info.set_index("Metric")
|
||||
|
||||
@@ -86,7 +101,17 @@ def info(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def shareholders(l_args, s_ticker):
|
||||
def shareholders(other_args: List[str], ticker: str):
|
||||
"""Yahoo Finance ticker shareholders
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="shrs",
|
||||
@@ -95,11 +120,11 @@ def shareholders(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
|
||||
|
||||
stock = yf.Ticker(s_ticker)
|
||||
stock = yf.Ticker(ticker)
|
||||
pd.set_option("display.max_colwidth", None)
|
||||
|
||||
# Major holders
|
||||
@@ -154,7 +179,17 @@ def shareholders(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def sustainability(l_args, s_ticker):
|
||||
def sustainability(other_args: List[str], ticker: str):
|
||||
"""Yahoo Finance ticker sustainability
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="sust",
|
||||
@@ -169,17 +204,17 @@ def sustainability(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
|
||||
|
||||
stock = yf.Ticker(s_ticker)
|
||||
stock = yf.Ticker(ticker)
|
||||
pd.set_option("display.max_colwidth", None)
|
||||
|
||||
df_sustainability = stock.sustainability
|
||||
|
||||
if not df_sustainability:
|
||||
print(f"No sustainability information in Yahoo for {s_ticker}")
|
||||
print(f"No sustainability information in Yahoo for {ticker}")
|
||||
print("")
|
||||
return
|
||||
|
||||
@@ -209,7 +244,17 @@ def sustainability(l_args, s_ticker):
|
||||
return
|
||||
|
||||
|
||||
def calendar_earnings(l_args, s_ticker):
|
||||
def calendar_earnings(other_args: List[str], ticker: str):
|
||||
"""Yahoo Finance ticker calendar earnings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args
|
||||
ticker : str
|
||||
Fundamental analysis ticker symbol
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="cal",
|
||||
@@ -220,15 +265,15 @@ def calendar_earnings(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
|
||||
|
||||
stock = yf.Ticker(s_ticker)
|
||||
stock = yf.Ticker(ticker)
|
||||
df_calendar = stock.calendar
|
||||
|
||||
if df_calendar.empty:
|
||||
print(f"No earnings calendar information in Yahoo for {s_ticker}")
|
||||
print(f"No earnings calendar information in Yahoo for {ticker}")
|
||||
print("")
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@ 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_controller
|
||||
from gamestonk_terminal.fundamental_analysis import fa_menu as fam
|
||||
from gamestonk_terminal.fundamental_analysis import fa_controller
|
||||
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
|
||||
from gamestonk_terminal.menu import session
|
||||
@@ -211,7 +211,7 @@ def main():
|
||||
b_quit = ca_controller.menu(df_stock, s_ticker, s_start, s_interval)
|
||||
|
||||
elif ns_known_args.opt == "fa":
|
||||
b_quit = fam.fa_menu(
|
||||
b_quit = fa_controller.menu(
|
||||
s_ticker.split(".")[0] if "." in s_ticker else s_ticker,
|
||||
s_start,
|
||||
s_interval,
|
||||
@@ -329,7 +329,7 @@ def main():
|
||||
df_stock_pred,
|
||||
s_ticker.split(".")[0] if "." in s_ticker else s_ticker,
|
||||
s_start,
|
||||
s_interval="1440min",
|
||||
interval="1440min",
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
""" fundamental_analysis/business_insider_api.py tests """
|
||||
import unittest
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis.business_insider_api import management
|
||||
from gamestonk_terminal.fundamental_analysis.business_insider_view import management
|
||||
|
||||
|
||||
class TestFaBusinessInsiderApi(unittest.TestCase):
|
||||
@@ -8,7 +8,7 @@ from gamestonk_terminal.test_helper import ( # noqa: F401
|
||||
pytest_generate_tests,
|
||||
)
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis.market_watch_api import (
|
||||
from gamestonk_terminal.fundamental_analysis.market_watch_model import (
|
||||
prepare_df_financials,
|
||||
)
|
||||
|
||||
@@ -16,10 +16,10 @@ assertions = unittest.TestCase("__init__")
|
||||
|
||||
|
||||
class TestFaMarketWatchApiUnit:
|
||||
@mock.patch("gamestonk_terminal.fundamental_analysis.market_watch_api.requests")
|
||||
@mock.patch("gamestonk_terminal.fundamental_analysis.market_watch_model.requests")
|
||||
@parameterize_from_file(
|
||||
"test_prepare_df_financials",
|
||||
"../tests/data/fa_market_watch_api.yaml",
|
||||
"../tests/data/fa_market_watch_model.yaml",
|
||||
)
|
||||
# pylint: disable=too-many-arguments
|
||||
def test_prepare_df_financials(
|
||||
@@ -1,7 +1,7 @@
|
||||
""" fundamental_analysis/market_watch_api.py tests """
|
||||
import unittest
|
||||
|
||||
from gamestonk_terminal.fundamental_analysis.market_watch_api import income
|
||||
from gamestonk_terminal.fundamental_analysis.market_watch_view import income
|
||||
|
||||
|
||||
class TestFaMarketWatchApi(unittest.TestCase):
|
||||
@@ -2,7 +2,7 @@
|
||||
import unittest
|
||||
|
||||
# pylint: disable=unused-import
|
||||
from gamestonk_terminal.fundamental_analysis.yahoo_finance_api import ( # noqa: F401
|
||||
from gamestonk_terminal.fundamental_analysis.yahoo_finance_view import ( # noqa: F401
|
||||
info,
|
||||
sustainability,
|
||||
calendar_earnings,
|
||||
Reference in New Issue
Block a user