From d342da5401662bef806c2aa8096aa6a9c3bc81b0 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 27 Dec 2020 20:17:37 +0000 Subject: [PATCH] Add FMP to Fundamental Analysis income, balance and cash --- stock_market_cli.py | 9 +- stock_market_fundamental_analysis.py | 144 ++++++++++++++++++++------- stock_market_helper_funcs.py | 5 +- 3 files changed, 116 insertions(+), 42 deletions(-) diff --git a/stock_market_cli.py b/stock_market_cli.py index 482dba8d03c..69bd090f36e 100644 --- a/stock_market_cli.py +++ b/stock_market_cli.py @@ -59,10 +59,13 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): if s_ticker: print("\nFundamental Analysis:") + print("- details - ") print(" ratings company ratings from strong sell to strong buy") - print(" income income statements of the company") - print(" balance balance sheet of the company") - print(" cash cash flow of the company") + print("- financial statement -") + print(" income income statements of the company (default: AV)") + print(" balance balance sheet of the company (default: AV)") + print(" cash cash flow of the company (default: AV)") + print("- ratios -") print("\nTechnical Analysis:") print(" sma simple moving average") diff --git a/stock_market_fundamental_analysis.py b/stock_market_fundamental_analysis.py index 31dc6239c38..831f9362753 100644 --- a/stock_market_fundamental_analysis.py +++ b/stock_market_fundamental_analysis.py @@ -3,6 +3,7 @@ from alpha_vantage.fundamentaldata import FundamentalData import config_bot as cfg import argparse from stock_market_helper_funcs import * +import pandas as pd # ---------------------------------------------------- RATINGS ---------------------------------------------------- def ratings(l_args, s_ticker): @@ -33,8 +34,9 @@ def income_statement(l_args, s_ticker): parser = argparse.ArgumentParser(prog='income', description=""" """) - parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, help='Number of informations') + parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, help='Number of latest info') parser.add_argument('-q', action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data') + parser.add_argument('--fmp', action="store_true", default=False, dest="b_fmp", help='Use Financial Modeling Prep instead of Alpha Vantage') try: (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) @@ -46,26 +48,48 @@ def income_statement(l_args, s_ticker): print(f"The following args couldn't be interpreted: {l_unknown_args}") try: - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fd, d_fd_metadata = fd.get_income_statement_quarterly(symbol=s_ticker) + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) else: - df_fd, d_fd_metadata = fd.get_income_statement_annual(symbol=s_ticker) + pd.options.display.max_colwidth = 40 - df_fd = df_fd.set_index('fiscalDateEnding') - df_fd = df_fd.head(n=ns_parser.n_num).T - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fd = df_fd.applymap(lambda x: long_number_format(x)) - df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] - df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + # Use Financial Modeling Prep API + if ns_parser.b_fmp: + if ns_parser.b_quarter: + df_fd = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fd = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fd = df_fd.iloc[:, 0:ns_parser.n_num] + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" + # Use Alpha Vantage API + else: + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fd, d_fd_metadata = fd.get_income_statement_quarterly(symbol=s_ticker) + else: + df_fd, d_fd_metadata = fd.get_income_statement_annual(symbol=s_ticker) + + df_fd = df_fd.set_index('fiscalDateEnding') + df_fd = df_fd.head(n=ns_parser.n_num).T + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" + print(df_fd) print("") except: print("") return - # ---------------------------------------------------- BALANCE_SHEET ---------------------------------------------------- def balance_sheet(l_args, s_ticker): parser = argparse.ArgumentParser(prog='balance', @@ -73,6 +97,7 @@ def balance_sheet(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, help='Number of informations') parser.add_argument('-q', action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data') + parser.add_argument('--fmp', action="store_true", default=False, dest="b_fmp", help='Use Financial Modeling Prep instead of Alpha Vantage') try: (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) @@ -84,25 +109,44 @@ def balance_sheet(l_args, s_ticker): print(f"The following args couldn't be interpreted: {l_unknown_args}") try: - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fd, d_fd_metadata = fd.get_balance_sheet_quarterly(symbol=s_ticker) - else: - df_fd, d_fd_metadata = fd.get_balance_sheet_annual(symbol=s_ticker) + # Use Financial Modeling Prep API + if ns_parser.b_fmp: + if ns_parser.b_quarter: + df_fd = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fd = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fd = df_fd.iloc[:, 0:ns_parser.n_num] + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" + + # Use Alpha Vantage API + else: + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fd, d_fd_metadata = fd.get_balance_sheet_quarterly(symbol=s_ticker) + else: + df_fd, d_fd_metadata = fd.get_balance_sheet_annual(symbol=s_ticker) + + df_fd = df_fd.set_index('fiscalDateEnding') + df_fd = df_fd.head(n=ns_parser.n_num).T + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" - df_fd = df_fd.set_index('fiscalDateEnding') - df_fd = df_fd.head(n=ns_parser.n_num).T - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fd = df_fd.applymap(lambda x: long_number_format(x)) - df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] - df_fd.index = [s_val.capitalize() for s_val in df_fd.index] print(df_fd) print("") except: print("") return - + # ---------------------------------------------------- CASH_FLOW ---------------------------------------------------- def cash_flow(l_args, s_ticker): @@ -111,6 +155,7 @@ def cash_flow(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, help='Number of informations') parser.add_argument('-q', action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data') + parser.add_argument('--fmp', action="store_true", default=False, dest="b_fmp", help='Use Financial Modeling Prep instead of Alpha Vantage') try: (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) @@ -122,21 +167,44 @@ def cash_flow(l_args, s_ticker): print(f"The following args couldn't be interpreted: {l_unknown_args}") try: - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fd, d_fd_metadata = fd.get_cash_flow_quarterly(symbol=s_ticker) + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) else: - df_fd, d_fd_metadata = fd.get_cash_flow_annual(symbol=s_ticker) + pd.options.display.max_colwidth = 40 + + # Use Financial Modeling Prep API + if ns_parser.b_fmp: + if ns_parser.b_quarter: + df_fd = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fd = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fd = df_fd.iloc[:, 0:ns_parser.n_num] + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" + # Use Alpha Vantage API + else: + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fd, d_fd_metadata = fd.get_cash_flow_quarterly(symbol=s_ticker) + else: + df_fd, d_fd_metadata = fd.get_cash_flow_annual(symbol=s_ticker) + + df_fd = df_fd.set_index('fiscalDateEnding') + df_fd = df_fd.head(n=ns_parser.n_num).T + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fd = df_fd.applymap(lambda x: long_number_format(x)) + df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] + df_fd.index = [s_val.capitalize() for s_val in df_fd.index] + df_fd.columns.name = "Fiscal Date Ending" - df_fd = df_fd.set_index('fiscalDateEnding') - df_fd = df_fd.head(n=ns_parser.n_num).T - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fd = df_fd.mask(df_fd.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fd = df_fd.applymap(lambda x: long_number_format(x)) - df_fd.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fd.index.tolist()] - df_fd.index = [s_val.capitalize() for s_val in df_fd.index] print(df_fd) print("") except: print("") - return + return \ No newline at end of file diff --git a/stock_market_helper_funcs.py b/stock_market_helper_funcs.py index 8ec421263c0..4ffe3f24401 100644 --- a/stock_market_helper_funcs.py +++ b/stock_market_helper_funcs.py @@ -129,8 +129,11 @@ def b_is_stock_market_open(): # ----------------------------------------------------------------------------------------------------------------------- def long_number_format(s_num): + if not isinstance(s_num, str): + s_num = str(s_num) if s_num.lstrip("-").isdigit(): n_num = int(s_num) + n_num /= 1.0 magnitude = 0 while abs(n_num) >= 1000: magnitude += 1 @@ -138,5 +141,5 @@ def long_number_format(s_num): if n_num.is_integer(): return '%d%s' % (n_num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude]) else: - return '%.2f%s' % (n_num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude]) + return '%.3f%s' % (n_num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude]) return s_num \ No newline at end of file