Extended Dupont (#1475)

* Added dupont, fixed fraud

* Added dupont to scripts

* Added better handling

* Added test fixes

Co-authored-by: jmaslek <jmaslek11@gmail.com>
This commit is contained in:
Colin Delahunty
2022-03-12 14:28:25 -05:00
committed by GitHub
parent dbaa3ecb41
commit 3d5cbcb2ae
14 changed files with 403 additions and 16 deletions

View File

@@ -2,7 +2,7 @@
__docformat__ = "numpy"
import logging
from typing import Dict, List, Optional, Tuple
from typing import Dict, List
import numpy as np
import pandas as pd
@@ -12,6 +12,7 @@ from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.helper_funcs import lambda_long_number_format
from gamestonk_terminal.rich_config import console
from gamestonk_terminal.stocks.stocks_helper import clean_fraction
from gamestonk_terminal.stocks.fundamental_analysis.fa_helper import clean_df_index
logger = logging.getLogger(__name__)
@@ -368,7 +369,9 @@ def get_earnings(ticker: str, quarterly: bool = False) -> pd.DataFrame:
@log_start_end(log=logger)
def df_values(df: pd.DataFrame, item: str, index: Optional[int] = None) -> List[int]:
def df_values(
df: pd.DataFrame, item: str, index: int = 0, length: int = 2
) -> List[int]:
"""Clean the values from the df
Parameters
@@ -377,6 +380,10 @@ def df_values(df: pd.DataFrame, item: str, index: Optional[int] = None) -> List[
The Dataframe to use
item : str
The item to select
index : int
The number of row to display
length : int
The number of rows to return
Returns
-------
@@ -384,16 +391,16 @@ def df_values(df: pd.DataFrame, item: str, index: Optional[int] = None) -> List[
The values for the dataframe
"""
if index:
df = df.iloc[index : index + 2]
df = df.iloc[index : index + length]
selection = df[item]
values = selection.apply(lambda x: int(x) if x else 0).values
values = selection.apply(
lambda x: "N/A" if (not x or x == "None") else int(x)
).values
return values.tolist()
@log_start_end(log=logger)
def get_fraud_ratios(
ticker: str,
) -> Tuple[Optional[Dict[str, float]], Optional[float], Optional[float]]:
def get_fraud_ratios(ticker: str) -> pd.DataFrame:
"""Get fraud ratios based on fundamentals
Parameters
@@ -403,10 +410,8 @@ def get_fraud_ratios(
Returns
-------
Dict[float]:
Dictionary of fraud metrics
float:
Z score for fraud metrics
metrics : pd.DataFrame
The fraud ratios
"""
try:
@@ -486,4 +491,61 @@ def get_fraud_ratios(
if fraud_years.empty:
fraud_years.index = ratios.keys()
fraud_years[df_cf.index[i]] = ratios.values()
fraud_years = fraud_years[sorted(fraud_years)]
return fraud_years
@log_start_end(log=logger)
def get_dupont(ticker: str) -> pd.DataFrame:
"""Get dupont ratios
Parameters
----------
ticker : str
Stock ticker
Returns
-------
dupont : pd.DataFrame
The dupont ratio breakdown
"""
try:
fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas")
# pylint: disable=unbalanced-tuple-unpacking
df_bs, _ = fd.get_balance_sheet_annual(symbol=ticker)
df_is, _ = fd.get_income_statement_annual(symbol=ticker)
except Exception as e:
console.print(e)
return pd.DataFrame()
# pylint: disable=no-member
df_bs = df_bs.set_index("fiscalDateEnding")
df_is = df_is.set_index("fiscalDateEnding")
dupont_years = pd.DataFrame()
for i in range(len(df_bs)):
ni = df_values(df_is, "netIncome", i, 1)
pretax = df_values(df_is, "incomeBeforeTax", i, 1)
ebit = df_values(df_is, "ebit", i, 1)
sales = df_values(df_is, "totalRevenue", i, 1)
assets = df_values(df_bs, "totalAssets", i, 1)
equity = df_values(df_bs, "totalShareholderEquity", i, 1)
ratios: Dict = {}
try:
ratios["Tax Burden"] = clean_fraction(ni[0], pretax[0])
ratios["Interest Burden"] = clean_fraction(pretax[0], ebit[0])
ratios["EBIT Margin"] = clean_fraction(ebit[0], sales[0])
ratios["Asset Turnover"] = clean_fraction(sales[0], assets[0])
ratios["Finance Leverage"] = clean_fraction(assets[0], equity[0])
ratios["ROI"] = clean_fraction(ni[0], equity[0])
except IndexError:
pass
if dupont_years.empty:
dupont_years.index = ratios.keys()
dupont_years[df_bs.index[i]] = ratios.values()
dupont_years = dupont_years[sorted(dupont_years)]
return dupont_years

View File

@@ -231,3 +231,22 @@ A mckee less than 0.5 indicates a high risk of fraud.
if help_text:
console.print(help_message)
@log_start_end(log=logger)
@check_api_key(["API_KEY_ALPHAVANTAGE"])
def display_dupont(ticker: str):
"""Shows the extended dupont ratio
Parameters
----------
ticker : str
Fundamental analysis ticker symbol
"""
df = av_model.get_dupont(ticker)
if df.empty:
console.print("[red]Invalid response from AlphaVantage[/red]\n")
else:
print_rich_table(
df, headers=list(df.columns), show_index=True, title="Extended Dupont"
)

View File

@@ -71,6 +71,7 @@ class FundamentalAnalysisController(StockBaseController):
"fraud",
"dcf",
"mktcap",
"dupont",
]
CHOICES_MENUS = [
@@ -130,7 +131,8 @@ Ticker: [/param] {self.ticker} [cmds]
balance balance sheet of the company
cash cash flow of the company
earnings earnings dates and reported EPS
fraud key fraud ratios[/cmds]
fraud key fraud ratios
dupont detailed breakdown for return on equity[/cmds]
[info]Other Sources:[/info][menu]
> fmp profile,quote,enterprise,dcf,income,ratios,growth from FMP[/menu]
"""
@@ -741,6 +743,21 @@ Ticker: [/param] {self.ticker} [cmds]
if ns_parser:
av_view.display_fraud(self.ticker, ns_parser.exp)
@log_start_end(log=logger)
def call_dupont(self, other_args: List[str]):
"""Process dupont command."""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.RawTextHelpFormatter,
prog="dupont",
description="The extended dupont deconstructs return on equity to allow investors to understand it better",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
av_view.display_dupont(self.ticker)
@log_start_end(log=logger)
def call_dcf(self, other_args: List[str]):
"""Process dcf command."""

View File

@@ -878,3 +878,24 @@ def additional_info_about_ticker(ticker: str) -> str:
extra_info += "\n[param]Currency: [/param]"
return extra_info + "\n"
def clean_fraction(num, denom):
"""Returns the decimal value or NA if the operation cannot be performed
Parameters
----------
num : Any
The numerator for the fraction
denom : Any
The denominator for the fraction
Returns
----------
val : Any
The value of the fraction
"""
try:
return num / denom
except TypeError:
return "N/A"

View File

@@ -72,4 +72,5 @@ cash
dcf
splits
mktcap
exit
dupont
exit

View File

@@ -0,0 +1,218 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.alphavantage.co/query?apikey=MOCK_API_KEY&function=BALANCE_SHEET&symbol=TSLA
response:
body:
string: !!binary |
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
urYAAA==
headers:
Allow:
- GET, HEAD, OPTIONS
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 6ea918b5edc28140-ORD
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Sat, 12 Mar 2022 02:28:27 GMT
Expect-CT:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server:
- cloudflare
Transfer-Encoding:
- chunked
Vary:
- Cookie
Via:
- 1.1 vegur
X-Frame-Options:
- SAMEORIGIN
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.alphavantage.co/query?apikey=MOCK_API_KEY&function=INCOME_STATEMENT&symbol=TSLA
response:
body:
string: !!binary |
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
headers:
Allow:
- GET, HEAD, OPTIONS
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 6ea918b7adf22a15-ORD
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Sat, 12 Mar 2022 02:28:27 GMT
Expect-CT:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server:
- cloudflare
Transfer-Encoding:
- chunked
Vary:
- Cookie
Via:
- 1.1 vegur
X-Frame-Options:
- SAMEORIGIN
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,7 @@
,2017-12-31,2018-12-31,2019-12-31,2020-12-31,2021-12-31
Tax Burden,1.0165803108808291,1.0631808278867103,1.1462765957446808,0.7117472852912142,0.8875844322933419
Interest Burden,1.3228238519533928,3.6,11.223880597014926,0.5752413401476434,0.943694035513735
EBIT Margin,-0.12407517646058339,-0.011882018545268162,-0.002726015135487021,0.05584094368340944,0.12241978336398937
Asset Turnover,0.41035935600487056,0.7216207128446537,0.7163717974875398,0.6047403543760067,0.8662825320693374
Finance Leverage,6.762741424728633,6.041031891123299,5.184194620731339,2.3463667041619796,2.0580675080327273
ROI,-0.46303704154730835,-0.19825309770465163,-0.13025083106678756,0.03244094488188976,0.1828149325913412
1 2017-12-31 2018-12-31 2019-12-31 2020-12-31 2021-12-31
2 Tax Burden 1.0165803108808291 1.0631808278867103 1.1462765957446808 0.7117472852912142 0.8875844322933419
3 Interest Burden 1.3228238519533928 3.6 11.223880597014926 0.5752413401476434 0.943694035513735
4 EBIT Margin -0.12407517646058339 -0.011882018545268162 -0.002726015135487021 0.05584094368340944 0.12241978336398937
5 Asset Turnover 0.41035935600487056 0.7216207128446537 0.7163717974875398 0.6047403543760067 0.8662825320693374
6 Finance Leverage 6.762741424728633 6.041031891123299 5.184194620731339 2.3463667041619796 2.0580675080327273
7 ROI -0.46303704154730835 -0.19825309770465163 -0.13025083106678756 0.03244094488188976 0.1828149325913412

View File

@@ -65,6 +65,13 @@ def test_check_output(func, kwargs_dict, recorder):
@pytest.mark.vcr
def test_get_fraud_ratios(recorder):
result_tuple = av_model.get_fraud_ratios(ticker="TSLA")
result_df = av_model.get_fraud_ratios(ticker="TSLA")
recorder.capture(result_tuple)
recorder.capture(result_df)
@pytest.mark.vcr
def test_get_dupont(recorder):
result_df = av_model.get_dupont(ticker="TSLA")
recorder.capture(result_df)

View File

@@ -120,3 +120,19 @@ def test_display_fraud(mocker, df):
return_value=(df),
)
av_view.display_fraud(ticker="TSLA")
@pytest.mark.vcr(record_mode="none")
@pytest.mark.record_stdout
@pytest.mark.parametrize(
"df",
[
(pd.DataFrame()),
],
)
def test_dupont(mocker, df):
mocker.patch(
"gamestonk_terminal.stocks.fundamental_analysis.av_view.av_model.get_dupont",
return_value=(df),
)
av_view.display_dupont(ticker="TSLA")

View File

@@ -264,6 +264,12 @@ def test_call_func_expect_queue(expected_queue, queue, func):
[],
{"TSLA"},
),
(
"call_dupont",
"av_view.display_dupont",
[],
{"TSLA"},
),
(
"call_cal",
"yahoo_finance_view.display_calendar_earnings",

View File

@@ -0,0 +1,2 @@
[red]Invalid response from AlphaVantage[/red]

View File

@@ -25,6 +25,7 @@ Ticker: TSLA
cash cash flow of the company
earnings earnings dates and reported EPS
fraud key fraud ratios
dupont detailed breakdown for return on equity
Other Sources:
> fmp profile,quote,enterprise,dcf,income,ratios,growth from FMP

View File

@@ -0,0 +1,10 @@
```
usage: dupont [-h] [--export {csv,json,xlsx}]
```
The dupont ratio is a breakdown of the various components of return on equity. This breakdown gives investors a more complete picutre of how a company generates profit from its assets.
```
optional arguments:
-h, --help show this help message
--export {csv,json,xlsx}
Export raw data into csv, json, xlsx

View File

@@ -1,5 +1,5 @@
```
usage: fraud [-h] [--export {csv,json,xlsx}]
usage: fraud [-h] [-e] [--export {csv,json,xlsx}]
```
```