Refactor FA menu (#845)

* Business insider

* cleanup BI + test

* Finviz fns

* Market watch fa

* yahoo fa stuff

* yahoo fa tests

* AV FA menu

* FMP Menu

* Fix fmp test

* Update dd notebook template

* Actually fix fmp test

* Add missing docstring

Co-authored-by: James Maslek <james@macbook-pro.myfiosgateway.com>
Co-authored-by: James Maslek <james@Jamess-MacBook-Pro.local>
This commit is contained in:
jmaslek
2021-10-24 18:53:29 -04:00
committed by GitHub
parent 43dd95cc49
commit 45d7a60ac6
20 changed files with 12821 additions and 2037 deletions

View File

@@ -0,0 +1,376 @@
"""Alpha Vantage Model"""
__docformat__ = "numpy"
from typing import Dict, Tuple
import requests
from alpha_vantage.fundamentaldata import FundamentalData
import pandas as pd
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
from gamestonk_terminal.helper_funcs import long_number_format
from gamestonk_terminal import config_terminal as cfg
def get_overview(ticker: str) -> pd.DataFrame:
"""Get alpha vantage company overview
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
Dataframe of fundamentals
"""
# Request OVERVIEW data from Alpha Vantage API
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 = pd.json_normalize(result.json())
# Keep json data sorting in dataframe
df_fa = df_fa[list(result.json().keys())].T
df_fa.iloc[5:] = df_fa.iloc[5:].applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa = df_fa.rename(
index={
"E b i t d a": "EBITDA",
"P e ratio": "PE ratio",
"P e g ratio": "PEG ratio",
"E p s": "EPS",
"Revenue per share t t m": "Revenue per share TTM",
"Operating margin t t m": "Operating margin TTM",
"Return on assets t t m": "Return on assets TTM",
"Return on equity t t m": "Return on equity TTM",
"Revenue t t m": "Revenue TTM",
"Gross profit t t m": "Gross profit TTM",
"Diluted e p s t t m": "Diluted EPS TTM",
"Quarterly earnings growth y o y": "Quarterly earnings growth YOY",
"Quarterly revenue growth y o y": "Quarterly revenue growth YOY",
"Trailing p e": "Trailing PE",
"Forward p e": "Forward PE",
"Price to sales ratio t t m": "Price to sales ratio TTM",
"E v to revenue": "EV to revenue",
"E v to e b i t d a": "EV to EBITDA",
}
)
return df_fa
return pd.DataFrame()
def get_key_metrics(ticker: str) -> pd.DataFrame:
"""Get key metrics from overview
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
Dataframe of key metrics
"""
# Request OVERVIEW data
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 = 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)
df_fa = df_fa.rename(
index={
"E b i t d a": "EBITDA",
"P e ratio": "PE ratio",
"P e g ratio": "PEG ratio",
"E p s": "EPS",
"Return on equity t t m": "Return on equity TTM",
"Price to sales ratio t t m": "Price to sales ratio TTM",
}
)
as_key_metrics = [
"Market capitalization",
"EBITDA",
"EPS",
"PE ratio",
"PEG ratio",
"Price to book ratio",
"Return on equity TTM",
"Payout ratio",
"Price to sales ratio TTM",
"Dividend yield",
"50 day moving average",
"Analyst target price",
"Beta",
]
return df_fa.loc[as_key_metrics]
return pd.DataFrame()
def get_income_statements(
ticker: str, number: int, quarterly: bool = False
) -> pd.DataFrame:
"""Get income statements for company
Parameters
----------
ticker : str
Stock ticker
number : int
Number of past to get
quarterly : bool, optional
Flag to get quarterly instead of annual, by default False
Returns
-------
pd.DataFrame
Dataframe of income statements
"""
url = f"https://www.alphavantage.co/query?function=INCOME_STATEMENT&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
r = requests.get(url)
statements = r.json()
if quarterly:
# pylint: disable=unbalanced-tuple-unpacking
df_fa = pd.DataFrame(statements["quarterlyReports"])
else:
# pylint: disable=unbalanced-tuple-unpacking
df_fa = pd.DataFrame(statements["annualReports"])
df_fa = df_fa.set_index("fiscalDateEnding")
df_fa = df_fa.head(number)
df_fa = df_fa.applymap(lambda x: long_number_format(x))
return df_fa[::-1].T
def get_balance_sheet(
ticker: str, number: int, quarterly: bool = False
) -> pd.DataFrame:
"""Get balance sheets for company
Parameters
----------
ticker : str
Stock ticker
number : int
Number of past to get
quarterly : bool, optional
Flag to get quarterly instead of annual, by default False
Returns
-------
pd.DataFrame
Dataframe of income statements
"""
url = f"https://www.alphavantage.co/query?function=BALANCE_SHEET&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
r = requests.get(url)
statements = r.json()
if quarterly:
df_fa = pd.DataFrame(statements["quarterlyReports"])
else:
df_fa = pd.DataFrame(statements["annualReports"])
df_fa = df_fa.set_index("fiscalDateEnding")
df_fa = df_fa.head(number)
df_fa = df_fa.applymap(lambda x: long_number_format(x))
return df_fa[::-1].T
def get_cash_flow(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get cash flows for company
Parameters
----------
ticker : str
Stock ticker
number : int
Number of past to get
quarterly : bool, optional
Flag to get quarterly instead of annual, by default False
Returns
-------
pd.DataFrame
Dataframe of income statements
"""
url = f"https://www.alphavantage.co/query?function=CASH_FLOW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
r = requests.get(url)
statements = r.json()
if quarterly:
df_fa = pd.DataFrame(statements["quarterlyReports"])
else:
df_fa = pd.DataFrame(statements["annualReports"])
df_fa = df_fa.set_index("fiscalDateEnding")
df_fa = df_fa.head(number)
df_fa = df_fa.applymap(lambda x: long_number_format(x))
return df_fa[::-1].T
def get_earnings(ticker: str, quarterly: bool = False) -> pd.DataFrame:
"""Get earnings calendar for ticker
Parameters
----------
ticker : str
Stock ticker
quarterly : bool, optional
[Flag to get quarterly and not annual, by default False
Returns
-------
pd.DataFrame
Dataframe of earnings
"""
# Request EARNINGS data from Alpha Vantage API
s_req = (
"https://www.alphavantage.co/query?function=EARNINGS&"
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 = pd.json_normalize(result.json())
if quarterly:
df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0])
df_fa = df_fa[
[
"fiscalDateEnding",
"reportedDate",
"reportedEPS",
"estimatedEPS",
"surprise",
"surprisePercentage",
]
]
df_fa = df_fa.rename(
columns={
"fiscalDateEnding": "Fiscal Date Ending",
"reportedEPS": "Reported EPS",
"estimatedEPS": "Estimated EPS",
"reportedDate": "Reported Date",
"surprise": "Surprise",
"surprisePercentage": "Surprise Percentage",
}
)
else:
df_fa = pd.DataFrame(df_fa["annualEarnings"][0])
df_fa = df_fa.rename(
columns={
"fiscalDateEnding": "Fiscal Date Ending",
"reportedEPS": "Reported EPS",
}
)
return df_fa
return pd.DataFrame()
def clean_fundamentals_df(df_fa: pd.DataFrame, num: int) -> pd.DataFrame:
"""Clean fundamentals dataframe
Parameters
----------
df_fa : pd.DataFrame
Fundamentals dataframe
num : int
Number of data rows to display
Returns
----------
pd.DataFrame
Clean dataframe to output
"""
# pylint: disable=no-member
df_fa = df_fa.set_index("fiscalDateEnding")
df_fa = df_fa.head(n=num).T
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["None"])).dropna()
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["0"])).dropna()
df_fa = df_fa.applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa.columns.name = "Fiscal Date Ending"
return df_fa
def get_fraud_ratios(ticker: str) -> Tuple[Dict[str, float], float]:
"""Get fraud ratios based on fundamentals
Parameters
----------
ticker : str
Stock ticker
Returns
-------
Dict[float]:
Dictionary of fraud metrics
float:
Z score for fraud metrics
"""
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
# pylint: disable=unbalanced-tuple-unpacking
# pylint: disable=no-member
df_cf, _ = fd.get_cash_flow_annual(symbol=ticker)
df_bs, _ = fd.get_balance_sheet_annual(symbol=ticker)
df_is, _ = fd.get_income_statement_annual(symbol=ticker)
df_cf = df_cf.set_index("fiscalDateEnding").iloc[:2]
df_bs = df_bs.set_index("fiscalDateEnding").iloc[:2]
df_is = df_is.set_index("fiscalDateEnding").iloc[:2]
ar = df_bs["currentNetReceivables"].apply(lambda x: int(x)).values
sales = df_is["totalRevenue"].apply(lambda x: int(x)).values
cogs = df_is["costofGoodsAndServicesSold"].apply(lambda x: int(x)).values
ni = df_is["netIncome"].apply(lambda x: int(x)).values
ca = df_bs["totalCurrentAssets"].apply(lambda x: int(x)).values
cl = df_bs["totalCurrentLiabilities"].apply(lambda x: int(x)).values
ppe = df_bs["propertyPlantEquipment"].apply(lambda x: int(x)).values
cash = df_bs["cashAndCashEquivalentsAtCarryingValue"].apply(lambda x: int(x)).values
cash_and_sec = df_bs["cashAndShortTermInvestments"].apply(lambda x: int(x)).values
sec = [y - x for (x, y) in zip(cash, cash_and_sec)]
ta = df_bs["totalAssets"].apply(lambda x: int(x)).values
dep = df_bs["accumulatedDepreciationAmortizationPPE"].apply(lambda x: int(x)).values
sga = df_is["sellingGeneralAndAdministrative"].apply(lambda x: int(x)).values
tl = df_bs["totalLiabilities"].apply(lambda x: int(x)).values
icfo = df_is["netIncomeFromContinuingOperations"].apply(lambda x: int(x)).values
cfo = df_cf["operatingCashflow"].apply(lambda x: int(x)).values
ratios: Dict = {}
ratios["DSRI"] = (ar[0] / sales[0]) / (ar[1] / sales[1])
ratios["GMI"] = ((sales[1] - cogs[1]) / sales[1]) / (
(sales[0] - cogs[0]) / sales[0]
)
ratios["AQI"] = (1 - ((ca[0] + ppe[0] + sec[0]) / ta[0])) / (
1 - ((ca[1] + ppe[1] + sec[1]) / ta[1])
)
ratios["SGI"] = sales[0] / sales[1]
ratios["DEPI"] = (dep[1] / (ppe[1] + dep[1])) / (dep[0] / (ppe[0] + dep[0]))
ratios["SGAI"] = (sga[0] / sales[0]) / (sga[1] / sales[1])
ratios["LVGI"] = (tl[0] / ta[0]) / (tl[1] / ta[1])
ratios["TATA"] = (icfo[0] - cfo[0]) / ta[0]
ratios["MSCORE"] = (
-4.84
+ (0.92 * ratios["DSRI"])
+ (0.58 * ratios["GMI"])
+ (0.404 * ratios["AQI"])
+ (0.892 * ratios["SGI"])
+ (0.115 * ratios["DEPI"] - (0.172 * ratios["SGAI"]))
+ (4.679 * ratios["TATA"])
- (0.327 * ratios["LVGI"])
)
zscore = (
-4.336
- (4.513 * (ni[0] / ta[0]))
+ (5.679 * (tl[0] / ta[0]))
+ (0.004 * (ca[0] / cl[0]))
)
return ratios, zscore

View File

@@ -1,669 +1,205 @@
""" Alpha Vantage View """
__docformat__ = "numpy"
import argparse
from typing import List, Dict
import os
import requests
from tabulate import tabulate
from alpha_vantage.fundamentaldata import FundamentalData
import pandas as pd
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
from gamestonk_terminal.helper_funcs import (
check_positive,
long_number_format,
parse_known_args_and_warn,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.fundamental_analysis import av_model
def overview(other_args: List[str], ticker: str):
def display_overview(ticker: str):
"""Alpha Vantage stock ticker overview
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="overview",
description="""
Prints an overview about the company. The following fields are expected:
Symbol, Asset type, Name, Description, Exchange, Currency, Country, Sector, Industry,
Address, Full time employees, Fiscal year end, Latest quarter, Market capitalization,
EBITDA, PE ratio, PEG ratio, Book value, Dividend per share, Dividend yield, EPS,
Revenue per share TTM, Profit margin, Operating margin TTM, Return on assets TTM,
Return on equity TTM, Revenue TTM, Gross profit TTM, Diluted EPS TTM, Quarterly
earnings growth YOY, Quarterly revenue growth YOY, Analyst target price, Trailing PE,
Forward PE, Price to sales ratio TTM, Price to book ratio, EV to revenue, EV to EBITDA,
Beta, 52 week high, 52 week low, 50 day moving average, 200 day moving average, Shares
outstanding, Shares float, Shares short, Shares short prior month, Short ratio, Short
percent outstanding, Short percent float, Percent insiders, Percent institutions,
Forward annual dividend rate, Forward annual dividend yield, Payout ratio, Dividend
date, Ex dividend date, Last split factor, and Last split date. Also, the C i k field
corresponds to Central Index Key, which can be used to search a company on
https://www.sec.gov/edgar/searchedgar/cik.htm [Source: Alpha Vantage]
""",
)
try:
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={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 = pd.json_normalize(result.json())
# Keep json data sorting in dataframe
df_fa = df_fa[list(result.json().keys())].T
df_fa.iloc[5:] = df_fa.iloc[5:].applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa = df_fa.rename(
index={
"E b i t d a": "EBITDA",
"P e ratio": "PE ratio",
"P e g ratio": "PEG ratio",
"E p s": "EPS",
"Revenue per share t t m": "Revenue per share TTM",
"Operating margin t t m": "Operating margin TTM",
"Return on assets t t m": "Return on assets TTM",
"Return on equity t t m": "Return on equity TTM",
"Revenue t t m": "Revenue TTM",
"Gross profit t t m": "Gross profit TTM",
"Diluted e p s t t m": "Diluted EPS TTM",
"Quarterly earnings growth y o y": "Quarterly earnings growth YOY",
"Quarterly revenue growth y o y": "Quarterly revenue growth YOY",
"Trailing p e": "Trailing PE",
"Forward p e": "Forward PE",
"Price to sales ratio t t m": "Price to sales ratio TTM",
"E v to revenue": "EV to revenue",
"E v to e b i t d a": "EV to EBITDA",
}
df_fa = av_model.get_overview(ticker)
if df_fa.empty:
print(f"No data found from alphavantage for {ticker}.\n")
return
if gtff.USE_TABULATE_DF:
print(
tabulate(
df_fa.drop(index=["Description"]), headers=[], tablefmt="fancy_grid"
)
)
else:
print(df_fa.drop(index=["Description"]).to_string(header=False))
pd.set_option("display.max_colwidth", None)
print(df_fa.drop(index=["Description"]).to_string(header=False))
print(f"Description: {df_fa.loc['Description'][0]}")
print("")
else:
print(f"Error: {result.status_code}")
print("")
except Exception as e:
print(e, "\n")
print(f"\nCompany Description:\n\n{df_fa.loc['Description'][0]}")
print("")
def key(other_args: List[str], ticker: str):
def display_key(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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="key",
description="""
Gives main key metrics about the company (it's a subset of the Overview data from Alpha
Vantage API). The following fields are expected: Market capitalization, EBITDA, EPS, PE
ratio, PEG ratio, Price to book ratio, Return on equity TTM, Payout ratio, Price to
sales ratio TTM, Dividend yield, 50 day moving average, Analyst target price, Beta
[Source: Alpha Vantage API]
""",
)
df_key = av_model.get_key_metrics(ticker)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if df_key.empty:
print("Issue getting key metrics from alpha vantage.")
return
# Request OVERVIEW data
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 gtff.USE_TABULATE_DF:
print(tabulate(df_key, headers=[], tablefmt="fancy_grid"))
else:
print(df_key.to_string(header=False))
# If the returned data was successful
if result.status_code == 200:
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)
df_fa = df_fa.rename(
index={
"E b i t d a": "EBITDA",
"P e ratio": "PE ratio",
"P e g ratio": "PEG ratio",
"E p s": "EPS",
"Return on equity t t m": "Return on equity TTM",
"Price to sales ratio t t m": "Price to sales ratio TTM",
}
)
as_key_metrics = [
"Market capitalization",
"EBITDA",
"EPS",
"PE ratio",
"PEG ratio",
"Price to book ratio",
"Return on equity TTM",
"Payout ratio",
"Price to sales ratio TTM",
"Dividend yield",
"50 day moving average",
"Analyst target price",
"Beta",
]
print(df_fa.loc[as_key_metrics].to_string(header=False))
else:
print(f"Error: {result.status_code}")
print("")
except Exception as e:
print(e, "\n")
print("")
def income_statement(other_args: List[str], ticker: str):
def display_income_statement(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Alpha Vantage income statement
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number of past statements
quarterly: bool
Flag to get quarterly instead of annual
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
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,
Depreciation and amortization, Ebitda, Ebitdaratio, Eps, Epsdiluted, Filling date,
Final link, General and administrative expenses, Gross profit, Gross profit ratio,
Income before tax, Income before tax ratio, Income tax expense, Interest expense, Link,
Net income, Net income ratio, Operating expenses, Operating income, Operating income
ratio, Other expenses, Period, Research and development expenses, Revenue, Selling and
marketing expenses, Total other income expenses net, Weighted average shs out, Weighted
average shs out dil [Source: Alpha Vantage]""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
df_income = av_model.get_income_statements(ticker, number, quarterly)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if gtff.USE_TABULATE_DF:
print(tabulate(df_income, headers=df_income.columns, tablefmt="fancy_grid"))
else:
print(df_income.to_string())
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
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=ticker)
else:
# pylint: disable=unbalanced-tuple-unpacking
df_fa, _ = fd.get_income_statement_annual(symbol=ticker)
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "income", df_income)
def balance_sheet(other_args: List[str], ticker: str):
"""Alpha Vantage balance sheet
def display_balance_sheet(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Alpha Vantage income statement
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number of past statements
quarterly: bool
Flag to get quarterly instead of annual
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="balance",
description="""
Prints a complete balance sheet statement over time. This can be either quarterly or
annually. The following fields are expected: Accepted date, Account payables,
Accumulated other comprehensive income loss, Cash and cash equivalents, Cash and short
term investments, Common stock, Deferred revenue, Deferred revenue non current,
Deferred tax liabilities non current, Filling date, Final link, Goodwill,
Goodwill and intangible assets, Intangible assets, Inventory, Link, Long term debt,
Long term investments, Net debt, Net receivables, Other assets, Other current assets,
Other current liabilities, Other liabilities, Other non current assets, Other non
current liabilities, Othertotal stockholders equity, Period, Property plant equipment
net, Retained earnings, Short term debt, Short term investments, Tax assets, Tax
payables, Total assets, Total current assets, Total current liabilities, Total debt,
Total investments, Total liabilities, Total liabilities and stockholders equity, Total
non current assets, Total non current liabilities, and Total stockholders equity.
[Source: Alpha Vantage]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
df_balance = av_model.get_balance_sheet(ticker, number, quarterly)
if gtff.USE_TABULATE_DF:
print(tabulate(df_balance, headers=df_balance.columns, tablefmt="fancy_grid"))
else:
print(df_balance.to_string())
print("")
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "balance", df_balance
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
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=ticker)
else:
# pylint: disable=unbalanced-tuple-unpacking
df_fa, _ = fd.get_balance_sheet_annual(symbol=ticker)
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
def cash_flow(other_args: List[str], ticker: str):
"""Alpha Vantage cash flow
def display_cash_flow(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Alpha Vantage income statement
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number of past statements
quarterly: bool
Flag to get quarterly instead of annual
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cash",
description="""
Prints a complete cash flow statement over time. This can be either quarterly or
annually. The following fields are expected: Accepted date, Accounts payables, Accounts
receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash
at end of period, Change in working capital, Common stock issued, Common stock
repurchased, Debt repayment, Deferred income tax, Depreciation and amortization,
Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash
flow, Inventory, Investments in property plant and equipment, Link, Net cash provided
by operating activities, Net cash used for investing activities, Net cash used provided
by financing activities, Net change in cash, Net income, Operating cash flow, Other
financing activities, Other investing activities, Other non cash items, Other working
capital, Period, Purchases of investments, Sales maturities of investments, Stock based
compensation. [Source: Alpha Vantage]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
df_cash = av_model.get_cash_flow(ticker, number, quarterly)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if gtff.USE_TABULATE_DF:
print(tabulate(df_cash, headers=df_cash.columns, tablefmt="fancy_grid"))
else:
print(df_cash.to_string())
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
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=ticker)
else:
# pylint: disable=unbalanced-tuple-unpacking
df_fa, _ = fd.get_cash_flow_annual(symbol=ticker)
df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "cash", df_cash)
def earnings(other_args: List[str], ticker: str):
def display_earnings(ticker: str, number: int, quarterly: bool = False):
"""Alpha Vantage earnings
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number:int
Number of events to show
quarterly: bool
Flag to show quarterly instead of annual
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="earnings",
description="""
Print earnings dates and reported EPS of the company. The following fields are
expected: Fiscal Date Ending and Reported EPS. [Source: Alpha Vantage]
""",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="Number of latest info",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
# Request EARNINGS data from Alpha Vantage API
s_req = (
"https://www.alphavantage.co/query?function=EARNINGS&"
f"symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}"
df_fa = av_model.get_earnings(ticker, quarterly)
if df_fa.empty:
print("Error getting earnings data.\n")
return
if gtff.USE_TABULATE_DF:
print(
tabulate(
df_fa.head(number),
headers=df_fa.columns,
showindex=False,
tablefmt="fancy_grid",
)
)
result = requests.get(s_req, stream=True)
else:
print(df_fa.head(n=number).T.to_string(header=False))
# If the returned data was successful
if result.status_code == 200:
df_fa = pd.json_normalize(result.json())
if ns_parser.b_quarter:
df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0])
df_fa = df_fa[
[
"fiscalDateEnding",
"reportedDate",
"reportedEPS",
"estimatedEPS",
"surprise",
"surprisePercentage",
]
]
df_fa = df_fa.rename(
columns={
"fiscalDateEnding": "Fiscal Date Ending",
"reportedEPS": "Reported EPS",
"estimatedEPS": "Estimated EPS",
"reportedDate": "Reported Date",
"surprise": "Surprise",
"surprisePercentage": "Surprise Percentage",
}
)
else:
df_fa = pd.DataFrame(df_fa["annualEarnings"][0])
df_fa = df_fa.rename(
columns={
"fiscalDateEnding": "Fiscal Date Ending",
"reportedEPS": "Reported EPS",
}
)
print(df_fa.head(n=ns_parser.n_num).T.to_string(header=False))
else:
print(f"Error: {result.status_code}")
print("")
except Exception as e:
print(e, "\n")
print("")
def clean_fundamentals_df(df_fa: pd.DataFrame, num: int) -> pd.DataFrame:
"""Clean fundamentals dataframe
Parameters
----------
df_fa : pd.DataFrame
Fundamentals dataframe
num : int
Number of data rows to display
Returns
----------
pd.DataFrame
Clean dataframe to output
"""
# pylint: disable=no-member
df_fa = df_fa.set_index("fiscalDateEnding")
df_fa = df_fa.head(n=num).T
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["None"])).dropna()
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["0"])).dropna()
df_fa = df_fa.applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa.columns.name = "Fiscal Date Ending"
return df_fa
def fraud(other_args: List[str], ticker: str):
def display_fraud(ticker: str):
"""Fraud indicators for given ticker
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.RawTextHelpFormatter,
prog="fraud",
description=(
"Mscore:\n------------------------------------------------\n"
"The Beneish model is a statistical model that uses financial ratios calculated with"
" accounting data of a specific company in order to check if it is likely (high"
" probability) that the reported earnings of the company have been manipulated."
" A score of -5 to -2.22 indicated a low chance of fraud, a score of -2.22 to -1.78"
" indicates a moderate change of fraud, and a score above -1.78 indicated a high"
" chance of fraud.[Source: Wikipedia]\n\nDSRI:\nDays Sales in Receivables Index"
" gauges whether receivables and revenue are out of balance, a large number is"
" expected to be associated with a higher likelihood that revenues and earnings are"
" overstated.\n\nGMI:\nGross Margin Index shows if gross margins are deteriorating."
" Research suggests that firms with worsening gross margin are more likely to engage"
" in earnings management, therefore there should be a positive correlation between"
" GMI and probability of earnings management.\n\nAQI:\nAsset Quality Index measures"
" the proportion of assets where potential benefit is less certain. A positive"
" relation between AQI and earnings manipulation is expected.\n\nSGI:\nSales Growth"
" Index shows the amount of growth companies are having. Higher growth companies are"
" more likely to commit fraud so there should be a positive relation between SGI and"
" earnings management.\n\nDEPI:\nDepreciation Index is the ratio for the rate of"
" depreciation. A DEPI greater than 1 shows that the depreciation rate has slowed and"
" is positively correlated with earnings management.\n\nSGAI:\nSales General and"
" Administrative Expenses Index measures the change in SG&A over sales. There should"
" be a positive relationship between SGAI and earnings management.\n\nLVGI:\nLeverage"
" Index represents change in leverage. A LVGI greater than one indicates a lower"
" change of fraud.\n\nTATA: \nTotal Accruals to Total Assets is a proxy for the"
" extent that cash underlies earnigns. A higher number is associated with a higher"
" likelihood of manipulation.\n\n\n"
"Zscore:\n------------------------------------------------\n"
"The Zmijewski Score is a bankruptcy model used to predict a firm's bankruptcy in two"
" years. The ratio uses in the Zmijewski score were determined by probit analysis ("
"think of probit as probability unit). In this case, scores less than .5 represent a"
" higher probability of default. One of the criticisms that Zmijewski made was that"
" other bankruptcy scoring models oversampled distressed firms and favored situations"
" with more complete data.[Source: YCharts]"
),
ratios, zscore = av_model.get_fraud_ratios(ticker)
if ratios["MSCORE"] > -1.78:
chanceM = "high"
elif ratios["MSCORE"] > -2.22:
chanceM = "moderate"
else:
chanceM = "low"
if zscore < 0.5:
chanceZ = "high"
else:
chanceZ = "low"
print("Mscore Sub Stats:")
for rkey, value in ratios.items():
if rkey != "MSCORE":
print(" ", f"{rkey} : {value:.2f}")
print(
"\n" + "MSCORE: ",
f"{ratios['MSCORE']:.2f} ({chanceM} chance of fraud)",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
# pylint: disable=unbalanced-tuple-unpacking
# pylint: disable=no-member
df_cf, _ = fd.get_cash_flow_annual(symbol=ticker)
df_bs, _ = fd.get_balance_sheet_annual(symbol=ticker)
df_is, _ = fd.get_income_statement_annual(symbol=ticker)
df_cf = df_cf.set_index("fiscalDateEnding").iloc[:2]
df_bs = df_bs.set_index("fiscalDateEnding").iloc[:2]
df_is = df_is.set_index("fiscalDateEnding").iloc[:2]
ar = df_bs["currentNetReceivables"].apply(lambda x: int(x)).values
sales = df_is["totalRevenue"].apply(lambda x: int(x)).values
cogs = df_is["costofGoodsAndServicesSold"].apply(lambda x: int(x)).values
ni = df_is["netIncome"].apply(lambda x: int(x)).values
ca = df_bs["totalCurrentAssets"].apply(lambda x: int(x)).values
cl = df_bs["totalCurrentLiabilities"].apply(lambda x: int(x)).values
ppe = df_bs["propertyPlantEquipment"].apply(lambda x: int(x)).values
cash = (
df_bs["cashAndCashEquivalentsAtCarryingValue"]
.apply(lambda x: int(x))
.values
)
cash_and_sec = (
df_bs["cashAndShortTermInvestments"].apply(lambda x: int(x)).values
)
sec = [y - x for (x, y) in zip(cash, cash_and_sec)]
ta = df_bs["totalAssets"].apply(lambda x: int(x)).values
dep = (
df_bs["accumulatedDepreciationAmortizationPPE"]
.apply(lambda x: int(x))
.values
)
sga = df_is["sellingGeneralAndAdministrative"].apply(lambda x: int(x)).values
tl = df_bs["totalLiabilities"].apply(lambda x: int(x)).values
icfo = df_is["netIncomeFromContinuingOperations"].apply(lambda x: int(x)).values
cfo = df_cf["operatingCashflow"].apply(lambda x: int(x)).values
ratios: Dict = {}
ratios["DSRI"] = (ar[0] / sales[0]) / (ar[1] / sales[1])
ratios["GMI"] = ((sales[1] - cogs[1]) / sales[1]) / (
(sales[0] - cogs[0]) / sales[0]
)
ratios["AQI"] = (1 - ((ca[0] + ppe[0] + sec[0]) / ta[0])) / (
1 - ((ca[1] + ppe[1] + sec[1]) / ta[1])
)
ratios["SGI"] = sales[0] / sales[1]
ratios["DEPI"] = (dep[1] / (ppe[1] + dep[1])) / (dep[0] / (ppe[0] + dep[0]))
ratios["SGAI"] = (sga[0] / sales[0]) / (sga[1] / sales[1])
ratios["LVGI"] = (tl[0] / ta[0]) / (tl[1] / ta[1])
ratios["TATA"] = (icfo[0] - cfo[0]) / ta[0]
ratios["MSCORE"] = (
-4.84
+ (0.92 * ratios["DSRI"])
+ (0.58 * ratios["GMI"])
+ (0.404 * ratios["AQI"])
+ (0.892 * ratios["SGI"])
+ (0.115 * ratios["DEPI"] - (0.172 * ratios["SGAI"]))
+ (4.679 * ratios["TATA"])
- (0.327 * ratios["LVGI"])
)
zscore = (
-4.336
- (4.513 * (ni[0] / ta[0]))
+ (5.679 * (tl[0] / ta[0]))
+ (0.004 * (ca[0] / cl[0]))
)
if ratios["MSCORE"] > -1.78:
chanceM = "high"
elif ratios["MSCORE"] > -2.22:
chanceM = "moderate"
else:
chanceM = "low"
if zscore < 0.5:
chanceZ = "high"
else:
chanceZ = "low"
print("Mscore Sub Stats:")
for rkey, value in ratios.items():
if rkey != "MSCORE":
print(" ", f"{rkey} : {value:.2f}")
print(
"\n" + "MSCORE: ",
f"{ratios['MSCORE']:.2f} ({chanceM} chance of fraud)",
)
print("ZSCORE: ", f"{zscore:.2f} ({chanceZ} chance of bankruptcy)", "\n")
except Exception as e:
print(e, "\n")
print("ZSCORE: ", f"{zscore:.2f} ({chanceZ} chance of bankruptcy)", "\n")

View File

@@ -0,0 +1,89 @@
"""Business Insider Model"""
__docformat__ = "numpy"
import requests
from bs4 import BeautifulSoup
import pandas as pd
from rapidfuzz import fuzz
from gamestonk_terminal.helper_funcs import get_user_agent
def get_management(ticker: str) -> pd.DataFrame:
"""Get company managers from Business Insider
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
Dataframe of managers
"""
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",
)
found_h2s = {}
for next_h2 in text_soup_market_business_insider.findAll(
"h2", {"class": "header-underline"}
):
next_table = next_h2.find_next_sibling("table", {"class": "table"})
if next_table:
found_h2s[next_h2.text] = next_table
if found_h2s.get("Management") is None:
print(f"No management information in Business Insider for {ticker}")
print("")
return pd.DataFrame()
l_titles = []
for s_title in found_h2s["Management"].findAll(
"td", {"class": "table__td text-right"}
):
if any(c.isalpha() for c in s_title.text.strip()) and (
"USD" not in s_title.text.strip()
):
l_titles.append(s_title.text.strip())
l_names = []
for s_name in found_h2s["Management"].findAll(
"td", {"class": "table__td table--allow-wrap"}
):
l_names.append(s_name.text.strip())
df_management = pd.DataFrame(
{"Name": l_names[-len(l_titles) :], "Title": l_titles},
columns=["Name", "Title"],
)
df_management["Info"] = "-"
df_management["Insider Activity"] = "-"
df_management = df_management.set_index("Name")
for s_name in df_management.index:
df_management.loc[s_name][
"Info"
] = f"http://www.google.com/search?q={s_name} {ticker.upper()}".replace(
" ", "%20"
)
s_url_base = "https://markets.businessinsider.com"
for insider in text_soup_market_business_insider.findAll(
"a", {"onclick": "silentTrackPI()"}
):
for s_name in df_management.index:
if fuzz.token_set_ratio(s_name, insider.text.strip()) > 70:
df_management.loc[s_name]["Insider Activity"] = (
s_url_base + insider.attrs["href"]
)
return df_management

View File

@@ -1,116 +1,46 @@
""" Business Insider View """
__docformat__ = "numpy"
import argparse
from typing import List
import requests
from bs4 import BeautifulSoup
import pandas as pd
from rapidfuzz import fuzz
from gamestonk_terminal.helper_funcs import get_user_agent, parse_known_args_and_warn
import os
import textwrap
from tabulate import tabulate
import gamestonk_terminal.feature_flags as gtff
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.fundamental_analysis import business_insider_model
def management(other_args: List[str], ticker: str):
def display_management(ticker: str, export: str = ""):
"""Display company's managers
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Stock ticker
export : str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="mgmt",
description="""
Print management team. Namely: Name, Title, Information from google and
(potentially) Insider Activity page. [Source: Business Insider]
""",
)
df_management = business_insider_model.get_management(ticker)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
names = ["Name"] + list(df_management.columns)
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",
)
found_h2s = dict()
for next_h2 in text_soup_market_business_insider.findAll(
"h2", {"class": "header-underline"}
):
next_table = next_h2.find_next_sibling("table", {"class": "table"})
if next_table:
found_h2s[next_h2.text] = next_table
if found_h2s.get("Management") is None:
print(f"No management information in Business Insider for {ticker}")
print("")
return
l_titles = []
for s_title in found_h2s["Management"].findAll(
"td", {"class": "table__td text-right"}
):
if any(c.isalpha() for c in s_title.text.strip()) and (
"USD" not in s_title.text.strip()
):
l_titles.append(s_title.text.strip())
l_names = []
for s_name in found_h2s["Management"].findAll(
"td", {"class": "table__td table--allow-wrap"}
):
l_names.append(s_name.text.strip())
df_management = pd.DataFrame(
{"Name": l_names[-len(l_titles) :], "Title": l_titles},
columns=["Name", "Title"],
)
df_management["Info"] = "-"
df_management["Insider Activity"] = "-"
df_management = df_management.set_index("Name")
for s_name in df_management.index:
df_management.loc[s_name][
"Info"
] = f"http://www.google.com/search?q={s_name} {ticker.upper()}".replace(
" ", "%20"
if gtff.USE_TABULATE_DF:
print(
tabulate(
df_management.applymap(
lambda x: "\n".join(textwrap.wrap(x, width=30))
if isinstance(x, str)
else x
),
tablefmt="fancy_grid",
headers=names,
)
)
else:
print(df_management.to_string())
s_url_base = "https://markets.businessinsider.com"
for insider in text_soup_market_business_insider.findAll(
"a", {"onclick": "silentTrackPI()"}
):
for s_name in df_management.index:
if fuzz.token_set_ratio(s_name, insider.text.strip()) > 70:
df_management.loc[s_name]["Insider Activity"] = (
s_url_base + insider.attrs["href"]
)
for ind in df_management.index:
s_name = f"{ind}{(max([len(x) for x in df_management.index])-len(ind))*' '}"
df_mgmt_title = df_management["Title"]
spaces = max(len(x) for x in df_mgmt_title) - len(df_mgmt_title[ind])
s_title = f"{df_mgmt_title[ind]}{spaces * ' '}"
s_management = f"""{s_name} {s_title} {df_management['Info'][ind]}"""
print(s_management)
if df_management["Insider Activity"][ind] not in "-":
print(f"{df_management['Insider Activity'][ind]}")
print("")
except Exception as e:
print(e, "\n")
print("")
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "mgmt", df_management
)

View File

@@ -20,7 +20,12 @@ from gamestonk_terminal.stocks.fundamental_analysis import (
market_watch_view,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn
from gamestonk_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
get_flair,
parse_known_args_and_warn,
check_positive,
)
from gamestonk_terminal.menu import session
# pylint: disable=inconsistent-return-statements
@@ -41,7 +46,7 @@ class FundamentalAnalysisController:
"analysis",
"score",
"dcf",
"screener",
"data",
"fraud",
"income",
"balance",
@@ -97,23 +102,28 @@ class FundamentalAnalysisController:
intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"]
if self.start:
help_text = f"\n\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})"
stock_text = f"\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})"
else:
help_text = f"\n\n{intraday} Stock: {self.ticker}"
stock_text = f"\n{intraday} Stock: {self.ticker}"
help_text += """
Fundamental Analysis:
help_text = f"""
>>>Fundamental Analysis<<<
What would you like to do?
cls clear screen
?/help show this menu again
q quit this menu, and shows back to main menu
quit quit to abandon program
load load a new ticker
{stock_text}
screener screen info about the company [Finviz]
data fundamental and technical data of company [FinViz]
mgmt management team of the company [Business Insider]
analysis analyse SEC filings with the help of machine learning [Elect.us]
score investing score from Warren Buffett, Joseph Piotroski and Benjamin Graham [FMP]
warnings company warnings according to Sean Seah book [Market Watch]
dcf a customizable discounted cash flow created in excel [stockanalysis]
Yahoo Finance:
info information scope of the company
shrs shareholders of the company
@@ -121,6 +131,7 @@ Yahoo Finance:
cal calendar earnings and estimates of the company
web open web browser of the company
hq open HQ location of the company
Alpha Vantage:
overview overview of the company
key company key metrics
@@ -129,6 +140,7 @@ Alpha Vantage:
cash cash flow of the company
earnings earnings dates and reported EPS
fraud key fraud ratios
Other Sources:
> fmp profile,quote,enterprise,dcf,income,ratios,growth from FMP
"""
@@ -204,67 +216,526 @@ Other Sources:
def call_mgmt(self, other_args: List[str]):
"""Process mgmt command"""
business_insider_view.management(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="mgmt",
description="""
Print management team. Namely: Name, Title, Information from google and
(potentially) Insider Activity page. [Source: Business Insider]
""",
)
def call_screener(self, other_args: List[str]):
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
business_insider_view.display_management(
ticker=self.ticker, export=ns_parser.export
)
except Exception as e:
print(e, "\n")
def call_data(self, other_args: List[str]):
"""Process screener command"""
finviz_view.screener(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="data",
description="""
Print several metrics about the company. The following fields are expected:
Company, Sector, Industry, Country, Index, P/E, EPS (ttm), Insider Own,
Shs Outstand, Perf Week, Market Cap, Forward P/E, EPS next Y, Insider Trans,
Shs Float, Perf Month, Income, EPS next Q, Inst Own, Short Float, Perf Quarter,
Sales, P/S, EPS this Y, Inst Trans, Short Ratio, Perf Half Y, Book/sh, P/B, ROA,
Target Price, Perf Year, Cash/sh, P/C, ROE, 52W Range, Perf YTD, P/FCF, EPS past 5Y,
ROI, 52W High, Beta, Quick Ratio, Sales past 5Y, Gross Margin, 52W Low, ATR,
Employees, Current Ratio, Sales Q/Q, Oper. Margin, RSI (14), Volatility, Optionable,
Debt/Eq, EPS Q/Q, Profit Margin, Rel Volume, Prev Close, Shortable, LT Debt/Eq,
Earnings, Payout, Avg Volume, Price, Recom, SMA20, SMA50, SMA200, Volume, Change.
[Source: Finviz]
""",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
finviz_view.display_screen_data(self.ticker)
except Exception as e:
print(e, "\n")
def call_score(self, other_args: List[str]):
"""Process score command"""
fmp_view.valinvest_score(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="score",
description="""
Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: FMP]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
fmp_view.valinvest_score(self.ticker)
except Exception as e:
print(e, "\n")
def call_info(self, other_args: List[str]):
"""Process info command"""
yahoo_finance_view.info(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="info",
description="""
Print information about the company. The following fields are expected:
Zip, Sector, Full time employees, Long business summary, City, Phone, State, Country,
Website, Max age, Address, Industry, Previous close, Regular market open, Two hundred
day average, Payout ratio, Regular market day high, Average daily volume 10 day,
Regular market previous close, Fifty day average, Open, Average volume 10 days, Beta,
Regular market day low, Price hint, Currency, Trailing PE, Regular market volume,
Market cap, Average volume, Price to sales trailing 12 months, Day low, Ask, Ask size,
Volume, Fifty two week high, Forward PE, Fifty two week low, Bid, Tradeable, Bid size,
Day high, Exchange, Short name, Long name, Exchange timezone name, Exchange timezone
short name, Is esg populated, Gmt off set milliseconds, Quote type, Symbol, Message
board id, Market, Enterprise to revenue, Profit margins, Enterprise to ebitda, 52 week
change, Forward EPS, Shares outstanding, Book value, Shares short, Shares percent
shares out, Last fiscal year end, Held percent institutions, Net income to common,
Trailing EPS, Sand p52 week change, Price to book, Held percent insiders, Next fiscal
year end, Most recent quarter, Short ratio, Shares short previous month date, Float
shares, Enterprise value, Last split date, Last split factor, Earnings quarterly growth,
Date short interest, PEG ratio, Short percent of float, Shares short prior month,
Regular market price, Logo_url. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.display_info(self.ticker)
except Exception as e:
print(e, "\n")
def call_shrs(self, other_args: List[str]):
"""Process shrs command"""
yahoo_finance_view.shareholders(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="shrs",
description="""Print Major, institutional and mutualfunds shareholders.
[Source: Yahoo Finance]""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.display_shareholders(self.ticker)
except Exception as e:
print(e, "\n")
def call_sust(self, other_args: List[str]):
"""Process sust command"""
yahoo_finance_view.sustainability(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sust",
description="""
Print sustainability values of the company. The following fields are expected:
Palmoil, Controversialweapons, Gambling, Socialscore, Nuclear, Furleather, Alcoholic,
Gmo, Catholic, Socialpercentile, Peercount, Governancescore, Environmentpercentile,
Animaltesting, Tobacco, Totalesg, Highestcontroversy, Esgperformance, Coal, Pesticides,
Adult, Percentile, Peergroup, Smallarms, Environmentscore, Governancepercentile,
Militarycontract. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.display_sustainability(self.ticker)
except Exception as e:
print(e, "\n")
def call_cal(self, other_args: List[str]):
"""Process cal command"""
yahoo_finance_view.calendar_earnings(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cal",
description="""
Calendar earnings of the company. Including revenue and earnings estimates.
[Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.display_calendar_earnings(ticker=self.ticker)
except Exception as e:
print(e, "\n")
def call_web(self, other_args: List[str]):
"""Process web command"""
yahoo_finance_view.web(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="web",
description="""
Opens company's website. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.open_web(self.ticker)
except Exception as e:
print(e, "\n")
def call_hq(self, other_args: List[str]):
"""Process hq command"""
yahoo_finance_view.headquarters(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="hq",
description="""
Opens in Google Maps HQ location of the company. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
yahoo_finance_view.open_headquarters_map(self.ticker)
except Exception as e:
print(e, "\n")
def call_overview(self, other_args: List[str]):
"""Process overview command"""
av_view.overview(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="overview",
description="""
Prints an overview about the company. The following fields are expected:
Symbol, Asset type, Name, Description, Exchange, Currency, Country, Sector, Industry,
Address, Full time employees, Fiscal year end, Latest quarter, Market capitalization,
EBITDA, PE ratio, PEG ratio, Book value, Dividend per share, Dividend yield, EPS,
Revenue per share TTM, Profit margin, Operating margin TTM, Return on assets TTM,
Return on equity TTM, Revenue TTM, Gross profit TTM, Diluted EPS TTM, Quarterly
earnings growth YOY, Quarterly revenue growth YOY, Analyst target price, Trailing PE,
Forward PE, Price to sales ratio TTM, Price to book ratio, EV to revenue, EV to EBITDA,
Beta, 52 week high, 52 week low, 50 day moving average, 200 day moving average, Shares
outstanding, Shares float, Shares short, Shares short prior month, Short ratio, Short
percent outstanding, Short percent float, Percent insiders, Percent institutions,
Forward annual dividend rate, Forward annual dividend yield, Payout ratio, Dividend
date, Ex dividend date, Last split factor, and Last split date. Also, the C i k field
corresponds to Central Index Key, which can be used to search a company on
https://www.sec.gov/edgar/searchedgar/cik.htm [Source: Alpha Vantage]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
av_view.display_overview(self.ticker)
except Exception as e:
print(e, "\n")
def call_key(self, other_args: List[str]):
"""Process overview command"""
av_view.key(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="key",
description="""
Gives main key metrics about the company (it's a subset of the Overview data from Alpha
Vantage API). The following fields are expected: Market capitalization, EBITDA, EPS, PE
ratio, PEG ratio, Price to book ratio, Return on equity TTM, Payout ratio, Price to
sales ratio TTM, Dividend yield, 50 day moving average, Analyst target price, Beta
[Source: Alpha Vantage API]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
av_view.display_key(self.ticker)
except Exception as e:
print(e, "\n")
def call_income(self, other_args: List[str]):
"""Process income command"""
av_view.income_statement(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
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,
Depreciation and amortization, Ebitda, Ebitdaratio, Eps, Epsdiluted, Filling date,
Final link, General and administrative expenses, Gross profit, Gross profit ratio,
Income before tax, Income before tax ratio, Income tax expense, Interest expense, Link,
Net income, Net income ratio, Operating expenses, Operating income, Operating income
ratio, Other expenses, Period, Research and development expenses, Revenue, Selling and
marketing expenses, Total other income expenses net, Weighted average shs out, Weighted
average shs out dil [Source: Alpha Vantage]""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
av_view.display_income_statement(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_balance(self, other_args: List[str]):
"""Process balance command"""
av_view.balance_sheet(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="balance",
description="""
Prints a complete balance sheet statement over time. This can be either quarterly or
annually. The following fields are expected: Accepted date, Account payables,
Accumulated other comprehensive income loss, Cash and cash equivalents, Cash and short
term investments, Common stock, Deferred revenue, Deferred revenue non current,
Deferred tax liabilities non current, Filling date, Final link, Goodwill,
Goodwill and intangible assets, Intangible assets, Inventory, Link, Long term debt,
Long term investments, Net debt, Net receivables, Other assets, Other current assets,
Other current liabilities, Other liabilities, Other non current assets, Other non
current liabilities, Othertotal stockholders equity, Period, Property plant equipment
net, Retained earnings, Short term debt, Short term investments, Tax assets, Tax
payables, Total assets, Total current assets, Total current liabilities, Total debt,
Total investments, Total liabilities, Total liabilities and stockholders equity, Total
non current assets, Total non current liabilities, and Total stockholders equity.
[Source: Alpha Vantage]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
av_view.display_balance_sheet(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_cash(self, other_args: List[str]):
"""Process cash command"""
av_view.cash_flow(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cash",
description="""
Prints a complete cash flow statement over time. This can be either quarterly or
annually. The following fields are expected: Accepted date, Accounts payables, Accounts
receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash
at end of period, Change in working capital, Common stock issued, Common stock
repurchased, Debt repayment, Deferred income tax, Depreciation and amortization,
Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash
flow, Inventory, Investments in property plant and equipment, Link, Net cash provided
by operating activities, Net cash used for investing activities, Net cash used provided
by financing activities, Net change in cash, Net income, Operating cash flow, Other
financing activities, Other investing activities, Other non cash items, Other working
capital, Period, Purchases of investments, Sales maturities of investments, Stock based
compensation. [Source: Alpha Vantage]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
av_view.display_cash_flow(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_earnings(self, other_args: List[str]):
"""Process earnings command"""
av_view.earnings(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="earnings",
description="""
Print earnings dates and reported EPS of the company. The following fields are
expected: Fiscal Date Ending and Reported EPS. [Source: Alpha Vantage]
""",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="Number of latest info",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
av_view.display_earnings(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
)
except Exception as e:
print(e, "\n")
def call_fraud(self, other_args: List[str]):
"""Process fraud command"""
av_view.fraud(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.RawTextHelpFormatter,
prog="fraud",
description=(
"Mscore:\n------------------------------------------------\n"
"The Beneish model is a statistical model that uses financial ratios calculated with"
" accounting data of a specific company in order to check if it is likely (high"
" probability) that the reported earnings of the company have been manipulated."
" A score of -5 to -2.22 indicated a low chance of fraud, a score of -2.22 to -1.78"
" indicates a moderate change of fraud, and a score above -1.78 indicated a high"
" chance of fraud.[Source: Wikipedia]\n\nDSRI:\nDays Sales in Receivables Index"
" gauges whether receivables and revenue are out of balance, a large number is"
" expected to be associated with a higher likelihood that revenues and earnings are"
" overstated.\n\nGMI:\nGross Margin Index shows if gross margins are deteriorating."
" Research suggests that firms with worsening gross margin are more likely to engage"
" in earnings management, therefore there should be a positive correlation between"
" GMI and probability of earnings management.\n\nAQI:\nAsset Quality Index measures"
" the proportion of assets where potential benefit is less certain. A positive"
" relation between AQI and earnings manipulation is expected.\n\nSGI:\nSales Growth"
" Index shows the amount of growth companies are having. Higher growth companies are"
" more likely to commit fraud so there should be a positive relation between SGI and"
" earnings management.\n\nDEPI:\nDepreciation Index is the ratio for the rate of"
" depreciation. A DEPI greater than 1 shows that the depreciation rate has slowed and"
" is positively correlated with earnings management.\n\nSGAI:\nSales General and"
" Administrative Expenses Index measures the change in SG&A over sales. There should"
" be a positive relationship between SGAI and earnings management.\n\nLVGI:\nLeverage"
" Index represents change in leverage. A LVGI greater than one indicates a lower"
" change of fraud.\n\nTATA: \nTotal Accruals to Total Assets is a proxy for the"
" extent that cash underlies earnigns. A higher number is associated with a higher"
" likelihood of manipulation.\n\n\n"
"Zscore:\n------------------------------------------------\n"
"The Zmijewski Score is a bankruptcy model used to predict a firm's bankruptcy in two"
" years. The ratio uses in the Zmijewski score were determined by probit analysis ("
"think of probit as probability unit). In this case, scores less than .5 represent a"
" higher probability of default. One of the criticisms that Zmijewski made was that"
" other bankruptcy scoring models oversampled distressed firms and favored situations"
" with more complete data.[Source: YCharts]"
),
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
av_view.display_fraud(self.ticker)
except Exception as e:
print(e, "\n")
def call_dcf(self, other_args: List[str]):
"""Process dcf command"""
@@ -272,7 +743,37 @@ Other Sources:
def call_warnings(self, other_args: List[str]):
"""Process warnings command"""
market_watch_view.sean_seah_warnings(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
prog="warnings",
description="""
Sean Seah warnings. Check: Consistent historical earnings per share;
Consistently high return on equity; Consistently high return on assets; 5x Net
Income > Long-Term Debt; and Interest coverage ratio more than 3. See
https://www.drwealth.com/gone-fishing-with-buffett-by-sean-seah/comment-page-1/
[Source: Market Watch]
""",
)
parser.add_argument(
"-d",
"--debug",
action="store_true",
default=False,
dest="b_debug",
help="print insights into warnings calculation.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
market_watch_view.display_sean_seah_warnings(
ticker=self.ticker, debug=ns_parser.b_debug
)
except Exception as e:
print(e, "\n")
def call_fmp(self, _):
"""Process fmp command"""

View File

@@ -12,6 +12,9 @@ from gamestonk_terminal.stocks.fundamental_analysis.financial_modeling_prep impo
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import (
get_flair,
parse_known_args_and_warn,
check_positive,
EXPORT_ONLY_RAW_DATA_ALLOWED,
)
from gamestonk_terminal.menu import session
@@ -20,12 +23,8 @@ class FinancialModelingPrepController:
"""Financial Modeling Prep Controller"""
# Command choices
CHOICES = [
"cls",
"?",
"help",
"q",
"quit",
CHOICES = ["cls", "?", "help", "q", "quit"]
CHOICES_COMMANDS = [
"profile",
"quote",
"enterprise",
@@ -37,6 +36,7 @@ class FinancialModelingPrepController:
"ratios",
"growth",
]
CHOICES += CHOICES_COMMANDS
def __init__(self, ticker: str, start: str, interval: str):
"""Constructor
@@ -135,43 +135,471 @@ Financial Modeling Prep:
def call_profile(self, other_args: List[str]):
"""Process profile command"""
fmp_view.profile(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="profile",
description="""
Prints information about, among other things, the industry, sector exchange and company
description. The following fields are expected: Address, Beta, Ceo, Changes, Cik, City
Company name, Country, Currency, Cusip, Dcf, Dcf diff, Default image, Description,
Exchange, Exchange short name, Full time employees, Image, Industry, Ipo date, Isin,
Last div, Mkt cap, Phone, Price, Range, Sector, State, Symbol, Vol avg, Website, Zip.
[Source: Financial Modeling Prep]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
fmp_view.display_profile(self.ticker)
except Exception as e:
print(e, "\n")
def call_quote(self, other_args: List[str]):
"""Process quote command"""
fmp_view.quote(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="quote",
description="""
Prints actual information about the company which is, among other things, the day high,
market cap, open and close price and price-to-equity ratio. The following fields are
expected: Avg volume, Change, Changes percentage, Day high, Day low, Earnings
announcement, Eps, Exchange, Market cap, Name, Open, Pe, Previous close, Price, Price
avg200, Price avg50, Shares outstanding, Symbol, Timestamp, Volume, Year high, and Year
low. [Source: Financial Modeling Prep]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
fmp_view.display_quote(self.ticker)
except Exception as e:
print(e, "\n")
def call_enterprise(self, other_args: List[str]):
"""Process income command"""
fmp_view.enterprise(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="enterprise",
description="""
Prints stock price, number of shares, market capitalization and
enterprise value over time. The following fields are expected: Add total debt,
Enterprise value, Market capitalization, Minus cash and cash equivalents, Number
of shares, Stock price, and Symbol. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_enterprise(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_dcf(self, other_args: List[str]):
"""Process dcf command"""
fmp_view.discounted_cash_flow(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="dcf",
description="""
Prints the discounted cash flow of a company over time including the DCF of today. The
following fields are expected: DCF, Stock price, and Date. [Source: Financial Modeling
Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_discounted_cash_flow(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_income(self, other_args: List[str]):
"""Process income command"""
fmp_view.income_statement(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="inc",
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, Depreciation and amortization, Ebitda, Ebitdaratio, Eps, Epsdiluted, Filling
date, Final link, General and administrative expenses, Gross profit, Gross profit
ratio, Income before tax, Income before tax ratio, Income tax expense, Interest
expense, Link, Net income, Net income ratio, Operating expenses, Operating income,
Operating income ratio, Other expenses, Period, Research and development expenses,
Revenue, Selling and marketing expenses, Total other income expenses net, Weighted
average shs out, Weighted average shs out dil [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_income_statement(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_balance(self, other_args: List[str]):
"""Process balance command"""
fmp_view.balance_sheet(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="bal",
description="""
Prints a complete balance sheet statement over time. This can be
either quarterly or annually. The following fields are expected: Accepted date,
Account payables, Accumulated other comprehensive income loss, Cash and cash
equivalents, Cash and short term investments, Common stock, Deferred revenue,
Deferred revenue non current, Deferred tax liabilities non current, Filling date,
Final link, Goodwill, Goodwill and intangible assets, Intangible assets, Inventory,
Link, Long term debt, Long term investments, Net debt, Net receivables, Other assets,
Other current assets, Other current liabilities, Other liabilities, Other non current
assets, Other non current liabilities, Othertotal stockholders equity, Period, Property
plant equipment net, Retained earnings, Short term debt, Short term investments, Tax
assets, Tax payables, Total assets, Total current assets, Total current liabilities,
Total debt, Total investments, Total liabilities, Total liabilities and stockholders
equity, Total non current assets, Total non current liabilities, and Total stockholders
equity. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_balance_sheet(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_cash(self, other_args: List[str]):
"""Process cash command"""
fmp_view.cash_flow(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cash",
description="""
Prints a complete cash flow statement over time. This can be either
quarterly or annually. The following fields are expected: Accepted date, Accounts
payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at
beginning of period, Cash at end of period, Change in working capital, Common stock
issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and
amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final
link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net
cash provided by operating activities, Net cash used for investing activities, Net cash
used provided by financing activities, Net change in cash, Net income, Operating cash
flow, Other financing activities, Other investing activities, Other non cash items,
Other working capital, Period, Purchases of investments, Sales maturities of
investments, Stock based compensation. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_cash_flow(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_metrics(self, other_args: List[str]):
"""Process metrics command"""
fmp_view.key_metrics(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="metrics",
description="""
Prints a list of the key metrics of a company over time. This can be either
quarterly or annually. This includes, among other things, Return on Equity (ROE),
Working Capital, Current Ratio and Debt to Assets. The following fields are expected:
Average inventory, Average payables, Average receivables, Book value per share, Capex
per share, Capex to depreciation, Capex to operating cash flow, Capex to revenue, Cash
per share, Current ratio, Days of inventory on hand, Days payables outstanding, Days
sales outstanding, Debt to assets, Debt to equity, Dividend yield, Earnings yield,
Enterprise value, Enterprise value over EBITDA, Ev to free cash flow, Ev to operating
cash flow, Ev to sales, Free cash flow per share, Free cash flow yield, Graham net net,
Graham number, Income quality, Intangibles to total assets, Interest debt per share,
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 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]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_key_metrics(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_ratios(self, other_args: List[str]):
"""Process cash command"""
fmp_view.financial_ratios(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ratios",
description="""
Prints in-depth ratios of a company over time. This can be either quarterly or
annually. This contains, among other things, Price-to-Book Ratio, Payout Ratio and
Operating Cycle. The following fields are expected: Asset turnover, Capital expenditure
coverage ratio, Cash conversion cycle, Cash flow coverage ratios, Cash flow to debt
ratio, Cash per share, Cash ratio, Company equity multiplier, Current ratio, Days of
inventory outstanding, Days of payables outstanding, Days of sales outstanding, Debt
equity ratio, Debt ratio, Dividend paid and capex coverage ratio, Dividend payout ratio,
Dividend yield, Ebit per revenue, Ebt per ebit, Effective tax rate, Enterprise value
multiple, Fixed asset turnover, Free cash flow operating cash flow ratio, Free cash
flow per share, Gross profit margin, Inventory turnover, Long term debt to
capitalization, Net income per EBT, Net profit margin, Operating cash flow per share,
Operating cash flow sales ratio, Operating cycle, Operating profit margin, Payables
turnover, Payout ratio, Pretax profit margin, Price book value ratio, Price cash flow
ratio, Price earnings ratio, Price earnings to growth ratio, Price fair value,
Price sales ratio, Price to book ratio, Price to free cash flows ratio, Price to
operating cash flows ratio, Price to sales ratio, Quick ratio, Receivables turnover,
Return on assets, Return on capital employed, Return on equity, Short term coverage
ratios, and Total debt to capitalization. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_financial_ratios(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_growth(self, other_args: List[str]):
"""Process cash command"""
fmp_view.financial_statement_growth(other_args, self.ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="growth",
description=""" Prints the growth of several financial statement items and ratios over
time. This can be either annually and quarterly. These are, among other things, Revenue
Growth (3, 5 and 10 years), inventory growth and operating cash flow growth (3, 5 and 10
years). The following fields are expected: Asset growth, Book valueper share growth, Debt
growth, Dividendsper share growth, Ebitgrowth, Epsdiluted growth, Epsgrowth, Five y
dividendper share growth per share, Five y net income growth per share, Five y operating c
f growth per share, Five y revenue growth per share, Five y shareholders equity growth per
share, Free cash flow growth, Gross profit growth, Inventory growth, Net income growth,
Operating cash flow growth, Operating income growth, Rdexpense growth, Receivables growth,
Revenue growth, Sgaexpenses growth, Ten y dividendper share growth per share, Ten y net
income growth per share, Ten y operating c f growth per share, Ten y revenue growth per
share, Ten y shareholders equity growth per share, Three y dividendper share growth per
share, Three y net income growth per share, Three y operating c f growth per share, Three y
revenue growth per share, Three y shareholders equity growth per share, Weighted average
shares diluted growth, and Weighted average shares growth [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
)
if not ns_parser:
return
fmp_view.display_financial_statement_growth(
ticker=self.ticker,
number=ns_parser.n_num,
quarterly=ns_parser.b_quarter,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def menu(ticker: str, start: str, interval: str):

View File

@@ -0,0 +1,319 @@
""" Financial Modeling Prep Model"""
__docformat__ = "numpy"
from datetime import datetime
import FundamentalAnalysis as fa # Financial Modeling Prep
import numpy as np
import pandas as pd
import valinvest
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import long_number_format
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
def get_score(ticker: str) -> np.number:
"""Gets value score from fmp
Parameters
----------
ticker : str
Stock ticker
Returns
-------
np.number
Value score
"""
valstock = valinvest.Fundamental(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
return 100 * (valstock.fscore() / 9)
def get_profile(ticker: str) -> pd.DataFrame:
"""Get ticker profile from FMP"""
return fa.profile(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
def get_quote(ticker) -> pd.DataFrame:
"""Gets ticker quote from FMP"""
df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
clean_df_index(df_fa)
df_fa.loc["Market cap"][0] = long_number_format(df_fa.loc["Market cap"][0])
df_fa.loc["Shares outstanding"][0] = long_number_format(
df_fa.loc["Shares outstanding"][0]
)
df_fa.loc["Volume"][0] = long_number_format(df_fa.loc["Volume"][0])
# Check if there is a valid earnings announcement
if df_fa.loc["Earnings announcement"][0]:
earning_announcement = datetime.strptime(
df_fa.loc["Earnings announcement"][0][0:19], "%Y-%m-%dT%H:%M:%S"
)
df_fa.loc["Earnings announcement"][
0
] = f"{earning_announcement.date()} {earning_announcement.time()}"
return df_fa
def get_enterprise(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Financial Modeling Prep ticker enterprise
Parameters
----------
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
Returns
----------
pd.DataFrame:
Dataframe of enterprise information
"""
if quarterly:
df_fa = fa.enterprise(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.enterprise(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number, mask=False)
return df_fa
def get_dcf(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get stocks dcf from FMP
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of dcf data
"""
if quarterly:
df_fa = fa.discounted_cash_flow(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.discounted_cash_flow(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number, mask=False)
return df_fa
def get_income(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get income statements
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of income statements
"""
if quarterly:
df_fa = fa.income_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.income_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
def get_balance(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get balance sheets
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of balance sheets
"""
if quarterly:
df_fa = fa.balance_sheet_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.balance_sheet_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
def get_cash(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get cash flow
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of company cash flow
"""
if quarterly:
df_fa = fa.cash_flow_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.cash_flow_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
def get_key_metrics(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get key metrics
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of key metrics
"""
if quarterly:
df_fa = fa.key_metrics(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.key_metrics(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
def get_key_ratios(ticker: str, number: int, quarterly: bool = False) -> pd.DataFrame:
"""Get key ratios
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of key ratios
"""
if quarterly:
df_fa = fa.financial_ratios(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.financial_ratios(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
def get_financial_growth(
ticker: str, number: int, quarterly: bool = False
) -> pd.DataFrame:
"""Get financial statement growth
Parameters
----------
ticker : str
Stock ticker
number : int
Number to get
quarterly : bool, optional
Flag to get quarterly data, by default False
Returns
-------
pd.DataFrame
Dataframe of financial statement growth
"""
if quarterly:
df_fa = fa.financial_statement_growth(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.financial_statement_growth(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=number)
return df_fa
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()
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["0"])).dropna()
df_fa = df_fa.applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa.columns.name = "Fiscal Date Ending"
df_fa = df_fa.rename(
index={
"Enterprise value over e b i t d a": "Enterprise value over EBITDA",
"Net debt to e b i t d a": "Net debt to EBITDA",
"D c f": "DCF",
"Net income per e b t": "Net income per EBT",
}
)
return df_fa

View File

@@ -1,22 +1,19 @@
""" Financial Modeling Prep View """
__docformat__ = "numpy"
import argparse
from typing import List
from datetime import datetime
import os
import pandas as pd
import valinvest
import FundamentalAnalysis as fa # Financial Modeling Prep
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
from gamestonk_terminal.helper_funcs import (
long_number_format,
check_positive,
parse_known_args_and_warn,
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.fundamental_analysis.financial_modeling_prep import (
fmp_model,
)
import gamestonk_terminal.feature_flags as gtff
def valinvest_score(other_args: List[str], ticker: str):
def valinvest_score(ticker: str):
"""Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: FMP]
Parameters
@@ -26,30 +23,12 @@ def valinvest_score(other_args: List[str], ticker: str):
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="score",
description="""
Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: FMP]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
valstock = valinvest.Fundamental(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
score = 100 * (valstock.fscore() / 9)
print(f"Score: {score:.2f}".rstrip("0").rstrip(".") + " %")
print("")
except Exception as e:
print(e, "\n")
score = fmp_model.get_score(ticker)
print(f"Score: {score:.2f}".rstrip("0").rstrip(".") + " %")
print("")
def profile(other_args: List[str], ticker: str):
def display_profile(ticker: str):
"""Financial Modeling Prep ticker profile
Parameters
@@ -59,718 +38,289 @@ def profile(other_args: List[str], ticker: str):
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="profile",
description="""
Prints information about, among other things, the industry, sector exchange and company
description. The following fields are expected: Address, Beta, Ceo, Changes, Cik, City
Company name, Country, Currency, Cusip, Dcf, Dcf diff, Default image, Description,
Exchange, Exchange short name, Full time employees, Image, Industry, Ipo date, Isin,
Last div, Mkt cap, Phone, Price, Range, Sector, State, Symbol, Vol avg, Website, Zip.
[Source: Financial Modeling Prep]
""",
)
profile = fmp_model.get_profile(ticker)
if gtff.USE_TABULATE_DF:
print(
tabulate(
profile.drop(index=["description", "image"]),
headers=[],
tablefmt="fancy_grid",
)
)
else:
print(profile.drop(index=["description", "image"]).to_string(header=False))
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
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))
print(f"\nImage: {df_fa.loc['Image'][0]}")
print(f"\nDescription: {df_fa.loc['Description'][0]}")
print("")
except Exception as e:
print(e, "\n")
print(f"\nImage: {profile.loc['image'][0]}")
print(f"\nDescription: {profile.loc['description'][0]}")
print("")
def quote(other_args: List[str], ticker: str):
def display_quote(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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="quote",
description="""
Prints actual information about the company which is, among other things, the day high,
market cap, open and close price and price-to-equity ratio. The following fields are
expected: Avg volume, Change, Changes percentage, Day high, Day low, Earnings
announcement, Eps, Exchange, Market cap, Name, Open, Pe, Previous close, Price, Price
avg200, Price avg50, Shares outstanding, Symbol, Timestamp, Volume, Year high, and Year
low. [Source: Financial Modeling Prep]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
clean_df_index(df_fa)
df_fa.loc["Market cap"][0] = long_number_format(df_fa.loc["Market cap"][0])
df_fa.loc["Shares outstanding"][0] = long_number_format(
df_fa.loc["Shares outstanding"][0]
)
df_fa.loc["Volume"][0] = long_number_format(df_fa.loc["Volume"][0])
# Check if there is a valid earnings announcement
if df_fa.loc["Earnings announcement"][0]:
earning_announcement = datetime.strptime(
df_fa.loc["Earnings announcement"][0][0:19], "%Y-%m-%dT%H:%M:%S"
)
df_fa.loc["Earnings announcement"][
0
] = f"{earning_announcement.date()} {earning_announcement.time()}"
print(df_fa.to_string(header=False))
print("")
except Exception as e:
print(e, "\n")
quote = fmp_model.get_quote(ticker)
if gtff.USE_TABULATE_DF:
print(tabulate(quote, headers=[], tablefmt="fancy_grid"))
else:
print(quote.to_string(header=False))
print("")
def enterprise(other_args: List[str], ticker: str):
def display_enterprise(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker enterprise
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="enterprise",
description="""
Prints stock price, number of shares, market capitalization and
enterprise value over time. The following fields are expected: Add total debt,
Enterprise value, Market capitalization, Minus cash and cash equivalents, Number
of shares, Stock price, and Symbol. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.enterprise(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.enterprise(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num, mask=False)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
df_fa = fmp_model.get_enterprise(ticker, number, quarterly)
df_fa = df_fa[df_fa.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(tabulate(df_fa, headers=df_fa.columns, tablefmt="fancy_grid"))
else:
print(df_fa.to_string())
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "enterprise", df_fa)
def discounted_cash_flow(other_args: List[str], ticker: str):
def display_discounted_cash_flow(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker discounted cash flow
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="dcf",
description="""
Prints the discounted cash flow of a company over time including the DCF of today. The
following fields are expected: DCF, Stock price, and Date. [Source: Financial Modeling
Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
dcf = fmp_model.get_dcf(ticker, number, quarterly)
dcf = dcf[dcf.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(tabulate(dcf, headers=[], tablefmt="fancy_grid"))
else:
print(dcf.to_string())
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.discounted_cash_flow(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
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)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "dcf", dcf)
def income_statement(other_args: List[str], ticker: str):
def display_income_statement(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker income statement
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="inc",
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, Depreciation and amortization, Ebitda, Ebitdaratio, Eps, Epsdiluted, Filling
date, Final link, General and administrative expenses, Gross profit, Gross profit
ratio, Income before tax, Income before tax ratio, Income tax expense, Interest
expense, Link, Net income, Net income ratio, Operating expenses, Operating income,
Operating income ratio, Other expenses, Period, Research and development expenses,
Revenue, Selling and marketing expenses, Total other income expenses net, Weighted
average shs out, Weighted average shs out dil [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.income_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
income = fmp_model.get_income(ticker, number, quarterly)
income = income[income.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(
tabulate(
income.drop(index=["Final link", "Link"]),
headers=income.columns,
tablefmt="fancy_grid",
)
else:
df_fa = fa.income_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
else:
print(df_fa.drop(index=["Final link", "Link"]).to_string())
print(income.drop(index=["Final link", "Link"]).to_string())
pd.set_option("display.max_colwidth", None)
print("")
print(df_fa.loc["Final link"].to_frame().to_string())
print("")
print(df_fa.loc["Link"].to_frame().to_string())
print("")
except Exception as e:
print(e, "\n")
pd.set_option("display.max_colwidth", None)
print("")
print(income.loc["Final link"].to_frame().to_string())
print("")
print(income.loc["Link"].to_frame().to_string())
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "income", income)
def balance_sheet(other_args: List[str], ticker: str):
def display_balance_sheet(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker balance sheet
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="bal",
description="""
Prints a complete balance sheet statement over time. This can be
either quarterly or annually. The following fields are expected: Accepted date,
Account payables, Accumulated other comprehensive income loss, Cash and cash
equivalents, Cash and short term investments, Common stock, Deferred revenue,
Deferred revenue non current, Deferred tax liabilities non current, Filling date,
Final link, Goodwill, Goodwill and intangible assets, Intangible assets, Inventory,
Link, Long term debt, Long term investments, Net debt, Net receivables, Other assets,
Other current assets, Other current liabilities, Other liabilities, Other non current
assets, Other non current liabilities, Othertotal stockholders equity, Period, Property
plant equipment net, Retained earnings, Short term debt, Short term investments, Tax
assets, Tax payables, Total assets, Total current assets, Total current liabilities,
Total debt, Total investments, Total liabilities, Total liabilities and stockholders
equity, Total non current assets, Total non current liabilities, and Total stockholders
equity. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.balance_sheet_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.balance_sheet_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP
balance = fmp_model.get_balance(ticker, number, quarterly)
balance = balance[balance.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(
tabulate(
balance.drop(index=["Final link", "Link"]),
headers=balance.columns,
tablefmt="fancy_grid",
)
)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
else:
print(balance.drop(index=["Final link", "Link"]).to_string())
print(df_fa.drop(index=["Final link", "Link"]).to_string())
pd.set_option("display.max_colwidth", None)
print("")
print(df_fa.loc["Final link"].to_frame().to_string())
print("")
print(df_fa.loc["Link"].to_frame().to_string())
print("")
except Exception as e:
print(e, "\n")
pd.set_option("display.max_colwidth", None)
print("")
print(balance.loc["Final link"].to_frame().to_string())
print("")
print(balance.loc["Link"].to_frame().to_string())
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "balance", balance)
def cash_flow(other_args: List[str], ticker: str):
def display_cash_flow(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker cash flow
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cash",
description="""
Prints a complete cash flow statement over time. This can be either
quarterly or annually. The following fields are expected: Accepted date, Accounts
payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at
beginning of period, Cash at end of period, Change in working capital, Common stock
issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and
amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final
link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net
cash provided by operating activities, Net cash used for investing activities, Net cash
used provided by financing activities, Net change in cash, Net income, Operating cash
flow, Other financing activities, Other investing activities, Other non cash items,
Other working capital, Period, Purchases of investments, Sales maturities of
investments, Stock based compensation. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.cash_flow_statement(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
cash = fmp_model.get_cash(ticker, number, quarterly)
cash = cash[cash.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(
tabulate(
cash.drop(index=["Final link", "Link"]),
headers=cash.columns,
tablefmt="fancy_grid",
)
else:
df_fa = fa.cash_flow_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
)
else:
print(cash.drop(index=["Final link", "Link"]).to_string())
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
print(df_fa.drop(index=["Final link", "Link"]).to_string())
pd.set_option("display.max_colwidth", None)
print("")
print(df_fa.loc["Final link"].to_frame().to_string())
print("")
print(df_fa.loc["Link"].to_frame().to_string())
print("")
except Exception as e:
print(e, "\n")
pd.set_option("display.max_colwidth", None)
print("")
print(cash.loc["Final link"].to_frame().to_string())
print("")
print(cash.loc["Link"].to_frame().to_string())
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "cash", cash)
def key_metrics(other_args: List[str], ticker: str):
def display_key_metrics(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker key metrics
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="metrics",
description="""
Prints a list of the key metrics of a company over time. This can be either
quarterly or annually. This includes, among other things, Return on Equity (ROE),
Working Capital, Current Ratio and Debt to Assets. The following fields are expected:
Average inventory, Average payables, Average receivables, Book value per share, Capex
per share, Capex to depreciation, Capex to operating cash flow, Capex to revenue, Cash
per share, Current ratio, Days of inventory on hand, Days payables outstanding, Days
sales outstanding, Debt to assets, Debt to equity, Dividend yield, Earnings yield,
Enterprise value, Enterprise value over EBITDA, Ev to free cash flow, Ev to operating
cash flow, Ev to sales, Free cash flow per share, Free cash flow yield, Graham net net,
Graham number, Income quality, Intangibles to total assets, Interest debt per share,
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 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]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
key_metrics = fmp_model.get_key_metrics(ticker, number, quarterly)
key_metrics = key_metrics[key_metrics.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(tabulate(key_metrics, headers=key_metrics.columns, tablefmt="fancy_grid"))
else:
print(key_metrics.to_string())
print("")
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "metrics", key_metrics
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 50
if ns_parser.b_quarter:
df_fa = fa.key_metrics(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.key_metrics(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
def financial_ratios(other_args: List[str], ticker: str):
def display_financial_ratios(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker ratios
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ratios",
description="""
Prints in-depth ratios of a company over time. This can be either quarterly or
annually. This contains, among other things, Price-to-Book Ratio, Payout Ratio and
Operating Cycle. The following fields are expected: Asset turnover, Capital expenditure
coverage ratio, Cash conversion cycle, Cash flow coverage ratios, Cash flow to debt
ratio, Cash per share, Cash ratio, Company equity multiplier, Current ratio, Days of
inventory outstanding, Days of payables outstanding, Days of sales outstanding, Debt
equity ratio, Debt ratio, Dividend paid and capex coverage ratio, Dividend payout ratio,
Dividend yield, Ebit per revenue, Ebt per ebit, Effective tax rate, Enterprise value
multiple, Fixed asset turnover, Free cash flow operating cash flow ratio, Free cash
flow per share, Gross profit margin, Inventory turnover, Long term debt to
capitalization, Net income per EBT, Net profit margin, Operating cash flow per share,
Operating cash flow sales ratio, Operating cycle, Operating profit margin, Payables
turnover, Payout ratio, Pretax profit margin, Price book value ratio, Price cash flow
ratio, Price earnings ratio, Price earnings to growth ratio, Price fair value,
Price sales ratio, Price to book ratio, Price to free cash flows ratio, Price to
operating cash flows ratio, Price to sales ratio, Quick ratio, Receivables turnover,
Return on assets, Return on capital employed, Return on equity, Short term coverage
ratios, and Total debt to capitalization. [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
ratios = fmp_model.get_key_ratios(ticker, number, quarterly)
ratios = ratios[ratios.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(tabulate(ratios, headers=ratios.columns, tablefmt="fancy_grid"))
else:
print(ratios.to_string())
print("")
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "grratiosowth", ratios
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 40
if ns_parser.b_quarter:
df_fa = fa.financial_ratios(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.financial_ratios(ticker, cfg.API_KEY_FINANCIALMODELINGPREP)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
def financial_statement_growth(other_args: List[str], ticker: str):
def display_financial_statement_growth(
ticker: str, number: int, quarterly: bool = False, export: str = ""
):
"""Financial Modeling Prep ticker growth
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
number: int
Number to get
quarterly: bool
Flag to get quarterly data
export: str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="growth",
description=""" Prints the growth of several financial statement items and ratios over
time. This can be either annually and quarterly. These are, among other things, Revenue
Growth (3, 5 and 10 years), inventory growth and operating cash flow growth (3, 5 and 10
years). The following fields are expected: Asset growth, Book valueper share growth, Debt
growth, Dividendsper share growth, Ebitgrowth, Epsdiluted growth, Epsgrowth, Five y
dividendper share growth per share, Five y net income growth per share, Five y operating c
f growth per share, Five y revenue growth per share, Five y shareholders equity growth per
share, Free cash flow growth, Gross profit growth, Inventory growth, Net income growth,
Operating cash flow growth, Operating income growth, Rdexpense growth, Receivables growth,
Revenue growth, Sgaexpenses growth, Ten y dividendper share growth per share, Ten y net
income growth per share, Ten y operating c f growth per share, Ten y revenue growth per
share, Ten y shareholders equity growth per share, Three y dividendper share growth per
share, Three y net income growth per share, Three y operating c f growth per share, Three y
revenue growth per share, Three y shareholders equity growth per share, Weighted average
shares diluted growth, and Weighted average shares growth [Source: Financial Modeling Prep]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=1,
help="Number of latest years/quarters.",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter fundamental data flag.",
)
growth = fmp_model.get_financial_growth(ticker, number, quarterly)
growth = growth[growth.columns[::-1]]
if gtff.USE_TABULATE_DF:
print(tabulate(growth, headers=growth.columns, tablefmt="fancy_grid"))
else:
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.n_num == 1:
pd.set_option("display.max_colwidth", None)
else:
pd.options.display.max_colwidth = 50
if ns_parser.b_quarter:
df_fa = fa.financial_statement_growth(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter"
)
else:
df_fa = fa.financial_statement_growth(
ticker, cfg.API_KEY_FINANCIALMODELINGPREP
)
df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num)
print(df_fa)
print("")
except Exception as e:
print(e, "\n")
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()
df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["0"])).dropna()
df_fa = df_fa.applymap(lambda x: long_number_format(x))
clean_df_index(df_fa)
df_fa.columns.name = "Fiscal Date Ending"
df_fa = df_fa.rename(
index={
"Enterprise value over e b i t d a": "Enterprise value over EBITDA",
"Net debt to e b i t d a": "Net debt to EBITDA",
"D c f": "DCF",
"Net income per e b t": "Net income per EBT",
}
)
return df_fa
print(growth.to_string())
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "growth", growth)

View File

@@ -0,0 +1,23 @@
"""Finviz Model"""
__docformat__ = "numpy"
import finviz
import pandas as pd
def get_data(ticker: str) -> pd.DataFrame:
"""Get fundamental data from finviz
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
DataFrame of fundamental data
"""
d_finviz_stock = finviz.get_stock(ticker)
df_fa = pd.DataFrame.from_dict(d_finviz_stock, orient="index", columns=["Values"])
return df_fa[df_fa.Values != "-"]

View File

@@ -1,55 +1,31 @@
""" FinViz View """
__docformat__ = "numpy"
import argparse
from typing import List
import finviz
import pandas as pd
import os
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
from tabulate import tabulate
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.stocks.fundamental_analysis import finviz_model
def screener(other_args: List[str], ticker: str):
def display_screen_data(ticker: str, export: str = ""):
"""FinViz ticker screener
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
Stock ticker
export : str
Format to export data
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="screener",
description="""
Print several metrics about the company. The following fields are expected:
Company, Sector, Industry, Country, Index, P/E, EPS (ttm), Insider Own,
Shs Outstand, Perf Week, Market Cap, Forward P/E, EPS next Y, Insider Trans,
Shs Float, Perf Month, Income, EPS next Q, Inst Own, Short Float, Perf Quarter,
Sales, P/S, EPS this Y, Inst Trans, Short Ratio, Perf Half Y, Book/sh, P/B, ROA,
Target Price, Perf Year, Cash/sh, P/C, ROE, 52W Range, Perf YTD, P/FCF, EPS past 5Y,
ROI, 52W High, Beta, Quick Ratio, Sales past 5Y, Gross Margin, 52W Low, ATR,
Employees, Current Ratio, Sales Q/Q, Oper. Margin, RSI (14), Volatility, Optionable,
Debt/Eq, EPS Q/Q, Profit Margin, Rel Volume, Prev Close, Shortable, LT Debt/Eq,
Earnings, Payout, Avg Volume, Price, Recom, SMA20, SMA50, SMA200, Volume, Change.
[Source: Finviz]
""",
)
fund_data = finviz_model.get_data(ticker)
print("")
if gtff.USE_TABULATE_DF:
print(tabulate(fund_data, tablefmt="fancy_grid", showindex=True))
else:
print(fund_data.to_string(header=False))
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
d_finviz_stock = finviz.get_stock(ticker)
df_fa = pd.DataFrame.from_dict(
d_finviz_stock, orient="index", columns=["Values"]
)
df_fa = df_fa[df_fa.Values != "-"]
print(df_fa.to_string(header=False))
print("")
except Exception as e:
print(e, "\n")
print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "data", fund_data)

View File

@@ -1,12 +1,17 @@
""" Fundamental Analysis Market Watch Model """
__docformat__ = "numpy"
import requests
import pandas as pd
from bs4 import BeautifulSoup
import re
from typing import List, Tuple
import numpy as np
import pandas as pd
import requests
from bs4 import BeautifulSoup
from gamestonk_terminal.helper_funcs import (
clean_data_values_to_float,
get_user_agent,
int_or_round_float,
)
@@ -113,3 +118,222 @@ def prepare_df_financials(
df_financials.loc[len(df_financials)] = constructed_row
return df_financials
def get_sean_seah_warnings(
ticker: str, debug: bool = False
) -> Tuple[pd.DataFrame, List[str], List[str]]:
"""Get financial statements and prepare Sean Seah warnings
Parameters
----------
ticker : str
Ticker to look at
debug : bool, optional
[description], by default False
Returns
-------
pd.DataFrame
Dataframe of financials
List[str]
List of warnings
List[str]
List of debug messages
"""
# From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA'
url_financials = (
f"https://www.marketwatch.com/investing/stock/{ticker}/financials/income"
)
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",
)
# Define financials columns
a_financials_header = []
for financials_header in text_soup_financials.findAll(
"th", {"class": "overflow__heading"}
):
a_financials_header.append(financials_header.text.strip("\n").split("\n")[0])
df_financials = pd.DataFrame(columns=a_financials_header[0:-1])
# Add financials values
soup_financials = text_soup_financials.findAll(
lambda tag: tag.name == "tr" and tag.get("class") == ["table__row"]
)
soup_financials += text_soup_financials.findAll(
"tr", {"class": "table__row is-highlighted"}
)
for financials_info in soup_financials:
financials_row = financials_info.text.split("\n")
if len(financials_row) > 5:
for item in financials_row:
if bool(re.search(r"\d", item)):
a_financials_info = financials_info.text.split("\n")
l_financials = [a_financials_info[2]]
l_financials.extend(a_financials_info[5:-2])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials
break
l_fin = ["EPS (Basic)", "Net Income", "Interest Expense", "EBITDA"]
if not all(elem in df_financials["Item"].values for elem in l_fin):
return pd.DataFrame(), [], []
# Set item name as index
df_financials = df_financials.set_index("Item")
df_sean_seah = df_financials.loc[l_fin]
# From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt'
url_financials = (
f"https://www.marketwatch.com/investing/stock/{ticker}/financials/balance-sheet"
)
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",
)
# Define financials columns
a_financials_header = []
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"
df_financials = pd.DataFrame(
columns=a_financials_header[0 : a_financials_header.index(s_header_end_trend)]
)
# Add financials values
soup_financials = text_soup_financials.findAll(
lambda tag: tag.name == "tr" and tag.get("class") == ["table__row"]
)
soup_financials += text_soup_financials.findAll(
"tr", {"class": "table__row is-highlighted"}
)
for financials_info in soup_financials:
financials_row = financials_info.text.split("\n")
if len(financials_row) > 5:
for item in financials_row:
if bool(re.search(r"\d", item)):
a_financials_info = financials_info.text.split("\n")
l_financials = [a_financials_info[2]]
l_financials.extend(a_financials_info[5:-2])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials
break
# Set item name as index
df_financials = df_financials.set_index("Item")
# Create dataframe to compute meaningful metrics from sean seah book
df_sean_seah = df_sean_seah.append(
df_financials.loc[
[
"Total Shareholders' Equity",
"Liabilities & Shareholders' Equity",
"Long-Term Debt",
]
]
)
# Clean these metrics by parsing their values to float
df_sean_seah = df_sean_seah.applymap(lambda x: clean_data_values_to_float(x))
# Add additional necessary metrics
series = (
df_sean_seah.loc["Net Income"] / df_sean_seah.loc["Total Shareholders' Equity"]
)
series.name = "ROE"
df_sean_seah = df_sean_seah.append(series)
series = df_sean_seah.loc["EBITDA"] / df_sean_seah.loc["Interest Expense"]
series.name = "Interest Coverage Ratio"
df_sean_seah = df_sean_seah.append(series)
series = (
df_sean_seah.loc["Net Income"]
/ df_sean_seah.loc["Liabilities & Shareholders' Equity"]
)
series.name = "ROA"
df_sean_seah = df_sean_seah.append(series)
n_warnings = 0
warnings = []
debugged_warnings = []
if np.any(df_sean_seah.loc["EPS (Basic)"].diff().dropna().values < 0):
warnings.append("No consistent historical earnings per share")
n_warnings += 1
if debug:
sa_eps = np.array2string(
df_sean_seah.loc["EPS (Basic)"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
sa_growth = np.array2string(
df_sean_seah.loc["EPS (Basic)"].diff().dropna().values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
debugged_warnings.append(f"\tEPS: {sa_eps}\n\tGrowth: {sa_growth} < 0")
if np.any(df_sean_seah.loc["ROE"].values < 0.15):
warnings.append("NOT consistently high return on equity")
n_warnings += 1
if debug:
sa_roe = np.array2string(
df_sean_seah.loc["ROE"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
debugged_warnings.append(f"\tROE: {sa_roe} < 0.15")
if np.any(df_sean_seah.loc["ROA"].values < 0.07):
warnings.append("NOT consistently high return on assets")
n_warnings += 1
if debug:
sa_roa = np.array2string(
df_sean_seah.loc["ROA"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
debugged_warnings.append(f"\tROA: {sa_roa} < 0.07")
if np.any(
df_sean_seah.loc["Long-Term Debt"].values
> 5 * df_sean_seah.loc["Net Income"].values
):
warnings.append("5x Net Income < Long-Term Debt")
n_warnings += 1
if debug:
sa_5_net_income = np.array2string(
5 * df_sean_seah.loc["Net Income"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
sa_long_term_debt = np.array2string(
df_sean_seah.loc["Long-Term Debt"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
debugged_warnings.append(
f"\t5x NET Income: {sa_5_net_income}\n\tlower than Long-Term Debt: {sa_long_term_debt}"
)
if np.any(df_sean_seah.loc["Interest Coverage Ratio"].values < 3):
warnings.append("Interest coverage ratio less than 3")
n_warnings += 1
if debug:
sa_interest_coverage_ratio = np.array2string(
100 * df_sean_seah.loc["Interest Coverage Ratio"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
debugged_warnings.append(
f"\tInterest Coverage Ratio: {sa_interest_coverage_ratio} < 3"
)
print("")
return (
df_sean_seah.applymap(lambda x: int_or_round_float(x)),
warnings,
debugged_warnings,
)

View File

@@ -6,23 +6,19 @@ So this code is not being used for the time being, it may be at a later stage.
__docformat__ = "numpy"
import argparse
import re
from typing import List
import requests
import pandas as pd
from bs4 import BeautifulSoup
import numpy as np
from gamestonk_terminal.stocks.fundamental_analysis import market_watch_model as mwm
import pandas as pd
from tabulate import tabulate
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import (
get_user_agent,
financials_colored_values,
parse_known_args_and_warn,
patch_pandas_text_adjustment,
financials_colored_values,
clean_data_values_to_float,
int_or_round_float,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.stocks.fundamental_analysis import market_watch_model as mwm
# pylint: disable=too-many-branches
@@ -255,7 +251,7 @@ def cash(other_args: List[str], ticker: str):
print(e, "\n")
def sean_seah_warnings(other_args: List[str], ticker: str):
def display_sean_seah_warnings(ticker: str, debug: bool = False):
"""Display Sean Seah warnings
Parameters
@@ -265,252 +261,33 @@ def sean_seah_warnings(other_args: List[str], ticker: str):
ticker : str
Stock ticker
"""
financials, warnings, debugged_warnings = mwm.get_sean_seah_warnings(ticker, debug)
parser = argparse.ArgumentParser(
add_help=False,
prog="warnings",
description="""
Sean Seah warnings. Check: Consistent historical earnings per share;
Consistently high return on equity; Consistently high return on assets; 5x Net
Income > Long-Term Debt; and Interest coverage ratio more than 3. See
https://www.drwealth.com/gone-fishing-with-buffett-by-sean-seah/comment-page-1/
[Source: Market Watch]
""",
)
parser.add_argument(
"-i",
"--info",
action="store_true",
default=False,
dest="b_info",
help="provide more information about Sean Seah warning rules.",
)
parser.add_argument(
"-d",
"--debug",
action="store_true",
default=False,
dest="b_debug",
help="print insights into warnings calculation.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.b_info:
filepath = "fundamental_analysis/info_sean_seah.txt"
with open(filepath) as fp:
line = fp.readline()
while line:
print(f"{line.strip()}")
line = fp.readline()
print("")
# From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA'
url_financials = (
f"https://www.marketwatch.com/investing/stock/{ticker}/financials/income"
)
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",
)
# Define financials columns
a_financials_header = []
for financials_header in text_soup_financials.findAll(
"th", {"class": "overflow__heading"}
):
a_financials_header.append(
financials_header.text.strip("\n").split("\n")[0]
)
df_financials = pd.DataFrame(columns=a_financials_header[0:-1])
# Add financials values
soup_financials = text_soup_financials.findAll(
lambda tag: tag.name == "tr" and tag.get("class") == ["table__row"]
)
soup_financials += text_soup_financials.findAll(
"tr", {"class": "table__row is-highlighted"}
)
for financials_info in soup_financials:
financials_row = financials_info.text.split("\n")
if len(financials_row) > 5:
for item in financials_row:
if bool(re.search(r"\d", item)):
a_financials_info = financials_info.text.split("\n")
l_financials = [a_financials_info[2]]
l_financials.extend(a_financials_info[5:-2])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials
break
l_fin = ["EPS (Basic)", "Net Income", "Interest Expense", "EBITDA"]
if not all(elem in df_financials["Item"].values for elem in l_fin):
print("The source doesn't contain all necessary financial data")
print(url_financials, "\n")
return
# Set item name as index
df_financials = df_financials.set_index("Item")
df_sean_seah = df_financials.loc[l_fin]
# From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt'
url_financials = f"https://www.marketwatch.com/investing/stock/{ticker}/financials/balance-sheet"
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",
)
# Define financials columns
a_financials_header = []
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"
df_financials = pd.DataFrame(
columns=a_financials_header[
0 : a_financials_header.index(s_header_end_trend)
]
)
# Add financials values
soup_financials = text_soup_financials.findAll(
lambda tag: tag.name == "tr" and tag.get("class") == ["table__row"]
)
soup_financials += text_soup_financials.findAll(
"tr", {"class": "table__row is-highlighted"}
)
for financials_info in soup_financials:
financials_row = financials_info.text.split("\n")
if len(financials_row) > 5:
for item in financials_row:
if bool(re.search(r"\d", item)):
a_financials_info = financials_info.text.split("\n")
l_financials = [a_financials_info[2]]
l_financials.extend(a_financials_info[5:-2])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials
break
# Set item name as index
df_financials = df_financials.set_index("Item")
# Create dataframe to compute meaningful metrics from sean seah book
df_sean_seah = df_sean_seah.append(
df_financials.loc[
[
"Total Shareholders' Equity",
"Liabilities & Shareholders' Equity",
"Long-Term Debt",
]
]
)
# Clean these metrics by parsing their values to float
df_sean_seah = df_sean_seah.applymap(lambda x: clean_data_values_to_float(x))
# Add additional necessary metrics
series = (
df_sean_seah.loc["Net Income"]
/ df_sean_seah.loc["Total Shareholders' Equity"]
)
series.name = "ROE"
df_sean_seah = df_sean_seah.append(series)
series = df_sean_seah.loc["EBITDA"] / df_sean_seah.loc["Interest Expense"]
series.name = "Interest Coverage Ratio"
df_sean_seah = df_sean_seah.append(series)
series = (
df_sean_seah.loc["Net Income"]
/ df_sean_seah.loc["Liabilities & Shareholders' Equity"]
)
series.name = "ROA"
df_sean_seah = df_sean_seah.append(series)
print(df_sean_seah.applymap(lambda x: int_or_round_float(x)).to_string())
n_warnings = 0
print("\nWARNINGS:")
if np.any(df_sean_seah.loc["EPS (Basic)"].diff().dropna().values < 0):
print("NO consistent historical earnings per share")
n_warnings += 1
if ns_parser.b_debug:
sa_eps = np.array2string(
df_sean_seah.loc["EPS (Basic)"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" EPS: {sa_eps}")
sa_growth = np.array2string(
df_sean_seah.loc["EPS (Basic)"].diff().dropna().values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" Growth: {sa_growth} < 0")
if np.any(df_sean_seah.loc["ROE"].values < 0.15):
print("NOT consistently high return on equity")
n_warnings += 1
if ns_parser.b_debug:
sa_roe = np.array2string(
df_sean_seah.loc["ROE"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" ROE: {sa_roe} < 0.15")
if np.any(df_sean_seah.loc["ROA"].values < 0.07):
print("NOT consistently high return on assets")
n_warnings += 1
if ns_parser.b_debug:
sa_roa = np.array2string(
df_sean_seah.loc["ROA"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" ROA: {sa_roa} < 0.07")
if np.any(
df_sean_seah.loc["Long-Term Debt"].values
> 5 * df_sean_seah.loc["Net Income"].values
):
print("5x Net Income < Long-Term Debt")
n_warnings += 1
if ns_parser.b_debug:
sa_5_net_income = np.array2string(
5 * df_sean_seah.loc["Net Income"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" 5x NET Income: {sa_5_net_income}")
sa_long_term_debt = np.array2string(
df_sean_seah.loc["Long-Term Debt"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" lower than Long-Term Debt: {sa_long_term_debt}")
if np.any(df_sean_seah.loc["Interest Coverage Ratio"].values < 3):
print("Interest coverage ratio less than 3")
n_warnings += 1
if ns_parser.b_debug:
sa_interest_coverage_ratio = np.array2string(
100 * df_sean_seah.loc["Interest Coverage Ratio"].values,
formatter={"float_kind": lambda x: int_or_round_float(x)},
)
print(f" Interest Coverage Ratio: {sa_interest_coverage_ratio} < 3")
if n_warnings == 0:
print("None. Good stonk")
print("")
except Exception as e:
print(e)
print("")
if financials.empty:
print(f"No financials found for {ticker}\n")
return
if gtff.USE_TABULATE_DF:
print(
tabulate(
financials,
headers=financials.columns,
tablefmt="fancy_grid",
floatfmt=".2f",
)
)
else:
print(financials.to_string(()))
if not warnings:
print("No warnings found. Good stonk")
return
messages = (
[item for pair in zip(warnings, debugged_warnings) for item in pair]
if debug
else warnings
)
print("Warnings:\n")
print("\n".join(messages), "\n")

View File

@@ -0,0 +1,205 @@
"""Yahoo Finance Model"""
__docformat__ = "numpy"
from datetime import datetime
from typing import Tuple
import yfinance as yf
import pandas as pd
from gamestonk_terminal.helper_funcs import (
long_number_format,
)
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
def get_info(ticker: str) -> pd.DataFrame:
"""Gets ticker info
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
DataFrame of yfinance information
"""
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
df_info = df_info.set_index("Metric")
clean_df_index(df_info)
if "Last split date" in df_info.index and df_info.loc["Last split date"].values[0]:
df_info.loc["Last split date"].values[0] = datetime.fromtimestamp(
df_info.loc["Last split date"].values[0]
).strftime("%d/%m/%Y")
df_info = df_info.mask(df_info["Value"].astype(str).eq("[]")).dropna()
df_info[df_info.index != "Zip"] = df_info[df_info.index != "Zip"].applymap(
lambda x: long_number_format(x)
)
df_info = df_info.rename(
index={
"Address1": "Address",
"Average daily volume10 day": "Average daily volume 10 day",
"Average volume10days": "Average volume 10 days",
"Price to sales trailing12 months": "Price to sales trailing 12 months",
}
)
df_info.index = df_info.index.str.replace("eps", "EPS")
df_info.index = df_info.index.str.replace("p e", "PE")
df_info.index = df_info.index.str.replace("Peg", "PEG")
return df_info
def get_shareholders(ticker: str) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
"""Get shareholders from yahoo
Parameters
----------
ticker : str
Stock ticker
Returns
-------
pd.DataFrame
Major holders
pd.DataFrame
Institutuional holders
pd.DataFrame
Mutual Fund holders
"""
stock = yf.Ticker(ticker)
# Major holders
df_major_holders = stock.major_holders
df_major_holders[1] = df_major_holders[1].apply(
lambda x: x.replace("%", "Percentage")
)
# Institutional holders
df_institutional_shareholders = stock.institutional_holders
df_institutional_shareholders.columns = (
df_institutional_shareholders.columns.str.replace("% Out", "Stake")
)
df_institutional_shareholders["Shares"] = df_institutional_shareholders[
"Shares"
].apply(lambda x: long_number_format(x))
df_institutional_shareholders["Value"] = df_institutional_shareholders[
"Value"
].apply(lambda x: long_number_format(x))
df_institutional_shareholders["Stake"] = df_institutional_shareholders[
"Stake"
].apply(lambda x: str(f"{100 * x:.2f}") + " %")
# Mutualfunds holders
df_mutualfund_shareholders = stock.mutualfund_holders
df_mutualfund_shareholders.columns = df_mutualfund_shareholders.columns.str.replace(
"% Out", "Stake"
)
df_mutualfund_shareholders["Shares"] = df_mutualfund_shareholders["Shares"].apply(
lambda x: long_number_format(x)
)
df_mutualfund_shareholders["Value"] = df_mutualfund_shareholders["Value"].apply(
lambda x: long_number_format(x)
)
df_mutualfund_shareholders["Stake"] = df_mutualfund_shareholders["Stake"].apply(
lambda x: str(f"{100 * x:.2f}") + " %"
)
return df_major_holders, df_institutional_shareholders, df_mutualfund_shareholders
def get_sustainability(ticker) -> pd.DataFrame:
"""Get sustainability metrics from yahoo
Parameters
----------
ticker : [type]
Stock ticker
Returns
-------
pd.DataFrame
Dataframe of sustainability metrics
"""
stock = yf.Ticker(ticker)
pd.set_option("display.max_colwidth", None)
df_sustainability = stock.sustainability
if df_sustainability is None or df_sustainability.empty:
return pd.DataFrame()
clean_df_index(df_sustainability)
df_sustainability = df_sustainability.rename(
index={
"Controversialweapons": "Controversial Weapons",
"Socialpercentile": "Social Percentile",
"Peercount": "Peer Count",
"Governancescore": "Governance Score",
"Environmentpercentile": "Environment Percentile",
"Animaltesting": "Animal Testing",
"Highestcontroversy": "Highest Controversy",
"Environmentscore": "Environment Score",
"Governancepercentile": "Governance Percentile",
"Militarycontract": "Military Contract",
}
)
return df_sustainability
def get_calendar_earnings(ticker: str) -> pd.DataFrame:
"""Get calendar earnings for ticker
Parameters
----------
ticker : [type]
Stock ticker
Returns
-------
pd.DataFrame
Dataframe of calendar earnings
"""
stock = yf.Ticker(ticker)
df_calendar = stock.calendar
if df_calendar.empty:
return pd.DataFrame()
df_calendar.iloc[0, :] = df_calendar.iloc[0, :].apply(
lambda x: x.date().strftime("%m/%d/%Y")
)
df_calendar.iloc[1:, :] = df_calendar.iloc[1:, :].applymap(
lambda x: long_number_format(x)
)
return df_calendar
def get_website(ticker: str) -> str:
"""Gets website of company from yfinance"""
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
return df_info[df_info["Metric"] == "website"]["Value"].values[0]
def get_hq(ticker: str) -> str:
"""Gets google map url for headquarter"""
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
df_info = df_info.set_index("Metric")
maps = "https://www.google.com/maps/search/"
for field in ["address1", "address2", "city", "state", "zip", "country"]:
if field in df_info.index:
maps += (
df_info[df_info.index == field]["Value"].values[0].replace(" ", "+")
+ ","
)
return maps[:-1]

View File

@@ -1,259 +1,93 @@
""" Yahoo Finance View """
__docformat__ = "numpy"
import argparse
from typing import List
from datetime import datetime
import webbrowser
import yfinance as yf
import pandas as pd
from tabulate import tabulate
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
from gamestonk_terminal.helper_funcs import (
long_number_format,
parse_known_args_and_warn,
)
from gamestonk_terminal.stocks.fundamental_analysis import yahoo_finance_model
from gamestonk_terminal import feature_flags as gtff
def headquarters(other_args: List[str], ticker: str):
def open_headquarters_map(ticker: str):
"""Headquarters location of the company
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="hq",
description="""
Opens in Google Maps HQ location of the company. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
df_info = df_info.set_index("Metric")
maps = "https://www.google.com/maps/search/"
for field in ["address1", "address2", "city", "state", "zip", "country"]:
if field in df_info.index:
maps += (
df_info[df_info.index == field]["Value"].values[0].replace(" ", "+")
+ ","
)
webbrowser.open(maps[:-1])
print("")
except Exception as e:
print(e, "\n")
webbrowser.open(yahoo_finance_model.get_hq(ticker))
print("")
def web(other_args: List[str], ticker: str):
def open_web(ticker: str):
"""Website of the company
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="web",
description="""
Opens company's website. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
webbrowser.open(df_info[df_info["Metric"] == "website"]["Value"].values[0])
print("")
except Exception as e:
print(e, "\n")
webbrowser.open(yahoo_finance_model.get_website(ticker))
print("")
def info(other_args: List[str], ticker: str):
def display_info(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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="info",
description="""
Print information about the company. The following fields are expected:
Zip, Sector, Full time employees, Long business summary, City, Phone, State, Country,
Website, Max age, Address, Industry, Previous close, Regular market open, Two hundred
day average, Payout ratio, Regular market day high, Average daily volume 10 day,
Regular market previous close, Fifty day average, Open, Average volume 10 days, Beta,
Regular market day low, Price hint, Currency, Trailing PE, Regular market volume,
Market cap, Average volume, Price to sales trailing 12 months, Day low, Ask, Ask size,
Volume, Fifty two week high, Forward PE, Fifty two week low, Bid, Tradeable, Bid size,
Day high, Exchange, Short name, Long name, Exchange timezone name, Exchange timezone
short name, Is esg populated, Gmt off set milliseconds, Quote type, Symbol, Message
board id, Market, Enterprise to revenue, Profit margins, Enterprise to ebitda, 52 week
change, Forward EPS, Shares outstanding, Book value, Shares short, Shares percent
shares out, Last fiscal year end, Held percent institutions, Net income to common,
Trailing EPS, Sand p52 week change, Price to book, Held percent insiders, Next fiscal
year end, Most recent quarter, Short ratio, Shares short previous month date, Float
shares, Enterprise value, Last split date, Last split factor, Earnings quarterly growth,
Date short interest, PEG ratio, Short percent of float, Shares short prior month,
Regular market price, Logo_url. [Source: Yahoo Finance]
""",
)
summary = ""
df_info = yahoo_finance_model.get_info(ticker)
if "Long business summary" in df_info.index:
summary = df_info.loc["Long business summary"].values[0]
df_info = df_info.drop(index=["Long business summary"])
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if gtff.USE_TABULATE_DF:
print(tabulate(df_info, headers=[], showindex=True, tablefmt="fancy_grid"))
stock = yf.Ticker(ticker)
df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"])
df_info = df_info.set_index("Metric")
else:
print(df_info.to_string(header=False))
clean_df_index(df_info)
if summary:
print("Business Summary:")
print(summary)
if (
"Last split date" in df_info.index
and df_info.loc["Last split date"].values[0]
):
df_info.loc["Last split date"].values[0] = datetime.fromtimestamp(
df_info.loc["Last split date"].values[0]
).strftime("%d/%m/%Y")
df_info = df_info.mask(df_info["Value"].astype(str).eq("[]")).dropna()
df_info[df_info.index != "Zip"] = df_info[df_info.index != "Zip"].applymap(
lambda x: long_number_format(x)
)
df_info = df_info.rename(
index={
"Address1": "Address",
"Average daily volume10 day": "Average daily volume 10 day",
"Average volume10days": "Average volume 10 days",
"Price to sales trailing12 months": "Price to sales trailing 12 months",
}
)
df_info.index = df_info.index.str.replace("eps", "EPS")
df_info.index = df_info.index.str.replace("p e", "PE")
df_info.index = df_info.index.str.replace("Peg", "PEG")
pd.set_option("display.max_colwidth", None)
if "Long business summary" in df_info.index:
print(df_info.drop(index=["Long business summary"]).to_string(header=False))
print("")
print(df_info.loc["Long business summary"].values[0])
print("")
else:
print(df_info.to_string(header=False))
print("")
except Exception as e:
print(e, "\n")
print("")
def shareholders(other_args: List[str], ticker: str):
def display_shareholders(ticker: str):
"""Yahoo Finance ticker shareholders
Parameters
----------
other_args : List[str]
argparse other args
ticker : str
Fundamental analysis ticker symbol
"""
(
df_major_holders,
df_institutional_shareholders,
df_mutualfund_shareholders,
) = yahoo_finance_model.get_shareholders(ticker)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="shrs",
description="""Print Major, institutional and mutualfunds shareholders.
[Source: Yahoo Finance]""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
stock = yf.Ticker(ticker)
pd.set_option("display.max_colwidth", None)
# Major holders
print("Major holders")
df_major_holders = stock.major_holders
df_major_holders[1] = df_major_holders[1].apply(
lambda x: x.replace("%", "Percentage")
)
print(df_major_holders.to_string(index=False, header=False))
dfs = [df_major_holders, df_institutional_shareholders, df_mutualfund_shareholders]
titles = ["Major Holders:\n", "Institutuinal Holders:\n", "Mutual Fund Holders:\n"]
print("")
for df, title in zip(dfs, titles):
print(title)
if gtff.USE_TABULATE_DF:
print(
tabulate(df, headers=df.columns, tablefmt="fancy_grid", showindex=False)
)
else:
print(df.to_string(index=False))
print("")
# Institutional holders
print("Institutional holders")
df_institutional_shareholders = stock.institutional_holders
df_institutional_shareholders.columns = (
df_institutional_shareholders.columns.str.replace("% Out", "Stake")
)
df_institutional_shareholders["Shares"] = df_institutional_shareholders[
"Shares"
].apply(lambda x: long_number_format(x))
df_institutional_shareholders["Value"] = df_institutional_shareholders[
"Value"
].apply(lambda x: long_number_format(x))
df_institutional_shareholders["Stake"] = df_institutional_shareholders[
"Stake"
].apply(lambda x: str(f"{100 * x:.2f}") + " %")
print(df_institutional_shareholders.to_string(index=False))
print("")
# Mutualfunds holders
print("Mutualfunds holders")
df_mutualfund_shareholders = stock.mutualfund_holders
df_mutualfund_shareholders.columns = (
df_mutualfund_shareholders.columns.str.replace("% Out", "Stake")
)
df_mutualfund_shareholders["Shares"] = df_mutualfund_shareholders[
"Shares"
].apply(lambda x: long_number_format(x))
df_mutualfund_shareholders["Value"] = df_mutualfund_shareholders["Value"].apply(
lambda x: long_number_format(x)
)
df_mutualfund_shareholders["Stake"] = df_mutualfund_shareholders["Stake"].apply(
lambda x: str(f"{100 * x:.2f}") + " %"
)
print(df_mutualfund_shareholders.to_string(index=False))
print("")
except Exception as e:
print(e, "\n")
def sustainability(other_args: List[str], ticker: str):
def display_sustainability(ticker: str):
"""Yahoo Finance ticker sustainability
Parameters
@@ -263,112 +97,48 @@ def sustainability(other_args: List[str], ticker: str):
ticker : str
Fundamental analysis ticker symbol
"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sust",
description="""
Print sustainability values of the company. The following fields are expected:
Palmoil, Controversialweapons, Gambling, Socialscore, Nuclear, Furleather, Alcoholic,
Gmo, Catholic, Socialpercentile, Peercount, Governancescore, Environmentpercentile,
Animaltesting, Tobacco, Totalesg, Highestcontroversy, Esgperformance, Coal, Pesticides,
Adult, Percentile, Peergroup, Smallarms, Environmentscore, Governancepercentile,
Militarycontract. [Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
df_sustainability = yahoo_finance_model.get_sustainability(ticker)
stock = yf.Ticker(ticker)
pd.set_option("display.max_colwidth", None)
if df_sustainability.empty:
print("No sustainability data found.")
return
df_sustainability = stock.sustainability
if df_sustainability is None:
print(f"No sustainability information in Yahoo for {ticker}", "\n")
return
if df_sustainability.empty:
print(f"No sustainability information in Yahoo for {ticker}", "\n")
return
clean_df_index(df_sustainability)
df_sustainability = df_sustainability.rename(
index={
"Controversialweapons": "Controversial Weapons",
"Socialpercentile": "Social Percentile",
"Peercount": "Peer Count",
"Governancescore": "Governance Score",
"Environmentpercentile": "Environment Percentile",
"Animaltesting": "Animal Testing",
"Highestcontroversy": "Highest Controversy",
"Environmentscore": "Environment Score",
"Governancepercentile": "Governance Percentile",
"Militarycontract": "Military Contract",
}
if gtff.USE_TABULATE_DF:
print(
tabulate(
df_sustainability,
headers=[],
tablefmt="fancy_grid",
showindex=True,
)
)
print(df_sustainability.to_string(header=False))
print("")
except Exception as e:
print(e, "\n")
else:
print(df_sustainability.to_sring(index=True))
print("")
def calendar_earnings(other_args: List[str], ticker: str):
def display_calendar_earnings(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,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cal",
description="""
Calendar earnings of the company. Including revenue and earnings estimates.
[Source: Yahoo Finance]
""",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
stock = yf.Ticker(ticker)
df_calendar = stock.calendar
if df_calendar.empty:
print(f"No earnings calendar information in Yahoo for {ticker}")
print("")
return
df_calendar.iloc[0, 0] = df_calendar.iloc[0, 0].date().strftime("%d/%m/%Y")
df_calendar.iloc[:, 0] = df_calendar.iloc[:, 0].apply(
lambda x: long_number_format(x)
)
print(f"Earnings Date: {df_calendar.iloc[:, 0]['Earnings Date']}")
avg = df_calendar.iloc[:, 0]["Earnings Average"]
low = df_calendar.iloc[:, 0]["Earnings Low"]
high = df_calendar.iloc[:, 0]["Earnings High"]
print(f"Earnings Estimate Avg: {avg} [{low}, {high}]")
df_calendar = yahoo_finance_model.get_calendar_earnings(ticker).T
if df_calendar.empty:
print("No calendar events found.\n")
return
if gtff.USE_TABULATE_DF:
print(
f"Revenue Estimate Avg: {df_calendar.iloc[:, 0]['Revenue Average']} \
[{df_calendar.iloc[:, 0]['Revenue Low']}, {df_calendar.iloc[:, 0]['Revenue High']}]"
tabulate(
df_calendar,
showindex=False,
headers=df_calendar.columns,
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
else:
print(df_calendar.to_string(index=False))
print("")

View File

@@ -209,7 +209,7 @@
"outputs": [],
"source": [
"# Annual Income Statement\n",
"av.income_statement([], ticker)"
"av.display_income_statement(ticker, number=1)"
]
},
{
@@ -230,7 +230,7 @@
"outputs": [],
"source": [
"# Quarterly Income Statement\n",
"av.income_statement([\"-q\"], ticker)"
"av.display_income_statement(ticker, number = 1, quarterly=True)"
]
},
{
@@ -251,7 +251,7 @@
"outputs": [],
"source": [
"# Annual Balance Sheet\n",
"av.balance_sheet([], ticker)"
"av.display_balance_sheet(ticker, number = 1)"
]
},
{
@@ -272,7 +272,7 @@
"outputs": [],
"source": [
"# Annual cash flow\n",
"av.cash_flow([], ticker)"
"av.display_cash_flow(ticker,number=1)"
]
},
{

File diff suppressed because it is too large Load Diff

View File

@@ -69,40 +69,34 @@ class TestAVView(unittest.TestCase):
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_av_overview(self, mock_get):
# pylint: disable=unused-argument
av_view.overview([], "GME")
av_view.display_overview("GME")
@check_print(assert_in="Market capitalization")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_av_key(self, mock_get):
# pylint: disable=unused-argument
av_view.key([], "GME")
av_view.display_key("GME")
@check_print(assert_in="Gross profit")
@check_print(assert_in="netIncome")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_income_statement(self, mock_get):
# pylint: disable=unused-argument
av_view.income_statement([], "GME")
av_view.display_income_statement("GME", 1)
@check_print(assert_in="Total assets")
@check_print(assert_in="commonStockSharesOutstanding")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_balance_sheet(self, mock_get):
# pylint: disable=unused-argument
av_view.balance_sheet([], "GME")
@check_print(assert_in="Operating cashflow")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_cash_flow(self, mock_get):
# pylint: disable=unused-argument
av_view.cash_flow([], "GME")
av_view.display_balance_sheet("GME", 1)
@check_print(assert_in="Reported EPS")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_earnings(self, mock_get):
# pylint: disable=unused-argument
av_view.earnings([], "GME")
av_view.display_earnings("GME", 1)
@check_print(assert_in="Mscore Sub Stats")
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_fraud(self, mock_get):
# pylint: disable=unused-argument
av_view.fraud([], "GME")
av_view.display_fraud("GME")

View File

@@ -4,7 +4,7 @@ import unittest
import vcr
from gamestonk_terminal.stocks.fundamental_analysis.business_insider_view import (
management,
display_management,
)
from tests.helpers import check_print
@@ -16,4 +16,4 @@ class TestFaBusinessInsiderApi(unittest.TestCase):
record_mode="new_episodes",
)
def test_management(self):
management([], "PLTR")
display_management("PLTR")

View File

@@ -1,31 +1,11 @@
""" fundamental_analysis/financial_modeling_prep/fmp_view.py tests """
import sys
import unittest
# Not testing these tests further. I do not have a fmp key
from contextlib import contextmanager
import vcr
from gamestonk_terminal.stocks.fundamental_analysis.financial_modeling_prep import (
fmp_view,
)
from tests.helpers import check_print
@contextmanager
def replace_stdin(target):
orig = sys.stdin
sys.stdin = target
yield
sys.stdin = orig
class TestFMPView(unittest.TestCase):
@check_print(assert_in="Ticker should be a NASDAQ")
@vcr.use_cassette(
"tests/cassettes/test_fa/test_fa_fmp/test_fmp_valinvest.yaml",
record_mode="new_episodes",
)
def test_fmp_valinvest_score(self):
fmp_view.valinvest_score([], "GME")
self.assertRaises(ValueError, fmp_view.valinvest_score, "GME")

View File

@@ -5,9 +5,9 @@ import vcr
# pylint: disable=unused-import
from gamestonk_terminal.stocks.fundamental_analysis.yahoo_finance_view import ( # noqa: F401
calendar_earnings,
info,
sustainability,
display_calendar_earnings,
display_info,
display_sustainability,
)
from tests.helpers import check_print
@@ -19,15 +19,15 @@ class TestFaYahooFinanceApi(unittest.TestCase):
record_mode="new_episodes",
)
def test_info(self):
info([], "PLTR")
display_info("PLTR")
@check_print(assert_in="GME")
@check_print(assert_in="Military contract")
@vcr.use_cassette(
"tests/cassettes/test_fa/test_fa_yahoo/test_sustainability.yaml",
record_mode="new_episodes",
)
def test_sustainability(self):
sustainability([], "GME")
display_sustainability("AAPL")
@check_print(assert_in="Earnings Date")
@vcr.use_cassette(
@@ -35,4 +35,4 @@ class TestFaYahooFinanceApi(unittest.TestCase):
record_mode="new_episodes",
)
def test_calendar_earnings(self):
calendar_earnings([], "GME")
display_calendar_earnings("GME")