3
\$\begingroup\$

A while ago I created a program for fundamental analysis of stocks. Back then, I used to enter all the values by hand, which took a lot of time and was very annoying if a value was entered incorrectly. Now the script takes care of most of that on its own. Sometimes, when the API is incomplete, the script throws a KeyError, which I haven't found a good way around yet without doing a try/except for every value.

I'm sure however, that this script can be improved a lot and would appreciate any feedback. Thank you and have a great day :)

from time import strftime
from pyfiglet import figlet_format
import json, locale, requests


# Reference: https://rapidapi.com/apidojo/api/yahoo-finance1?endpoint=apiendpoint_2e0b16d4-a66b-469e-bc18-b60cec60661b
# https://finance.yahoo.com/quote/AMRN/financials?p=AMRN

print(figlet_format("Stock Fundamental Analysis\n"))
print("Note: The Stock's numbers will be interpreted as Euro for all but american stocks")

print("Ticker symbol:")
ticker = input("> ")

url_base = "https://apidojo-yahoo-finance-v1.p.rapidapi.com/stock/v2/"
url_summary = url_base + "get-summary"
url_financials = url_base + "get-financials"

date = strftime("%Y-%m-%d")
time = strftime(" %H:%M:%S")


def get_json(url):
    """
    :param url: url to the API endpoint
    :return: json_data
    """
    querystring = {f"symbol": {ticker}}
    headers = {
        'x-rapidapi-key': "API-KEY",
        'x-rapidapi-host': "apidojo-yahoo-finance-v1.p.rapidapi.com"
    }

    response = requests.request("GET", url, headers=headers, params=querystring)
    j_data = json.loads(response.text)

    return j_data


def get_currency(currency):
    if currency == "USD":
        locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
    else:
        locale.setlocale(locale.LC_ALL, '')


def ask_yes_no(prompt):
    """
    :param prompt: The question to be asked
    :return: Value to check
    """
    while True:
        answer = input(prompt + " (y/n): ")

        if answer == "y":
            return True
        elif answer == "n":
            return False

        print("Please only enter y or n.")


def check_partners_trends():
    # Check Partners
    if ask_yes_no("Does it have big partners?"):
        partners = input("Who? ")
    else:
        partners = "none"

    # Check Trend
    if ask_yes_no("Does it participate in any current trends?"):
        trends = input("Which? ")
    else:
        trends = "none"

    return partners, trends


def check_age_forecast_commodity():
    # Check age
    if ask_yes_no("Is the company older than 10 years?"):
        old = True
    else:
        old = False

    # Check forecast
    if ask_yes_no("Do you still see the company around in 10 years?"):
        future = True
    else:
        future = False

    # Check commodity reliance
    if ask_yes_no("Is the company distinguishable from others/ Does it have an economic moat?"):
        distinguish = True
    else:
        distinguish = False

    return old, future, distinguish


partner, trend = check_partners_trends()
category = input("Category according to Peter Lynch: ")
age, forecast, moat = check_age_forecast_commodity()


print("Receiving data from Yahoo...")
###############################
""" --- Get-Summary --- """  ##
###############################

json_data = get_json(url_summary)

defaultKeyStatistics = json_data['defaultKeyStatistics']

profit_margin = defaultKeyStatistics['profitMargins']['fmt']
eps = defaultKeyStatistics['forwardEps']['raw']
book_value = defaultKeyStatistics['bookValue']['raw']
try:
    price_to_book = round(defaultKeyStatistics['priceToBook']['raw'], 2)
except KeyError:
    price_to_book = 0
peg_ratio = defaultKeyStatistics['pegRatio']['fmt']
shares_outstanding = defaultKeyStatistics['sharesOutstanding']['raw']
shares_short = defaultKeyStatistics['sharesShort']['raw']
short_ratio = defaultKeyStatistics['shortRatio']['fmt'] + "%"


summary_profile = json_data['summaryProfile']

sector = summary_profile['sector']
country = summary_profile['country']
city = summary_profile['city']
website = summary_profile['website']
industry = summary_profile['industry']


price = json_data['price']

market_cap = price['marketCap']['raw']
current_price = price['regularMarketPrice']['raw']
name = price['longName']


holders = json_data['majorHoldersBreakdown']

insiders_percentage = holders['insidersPercentHeld']['fmt']
institutions_percentage = holders['institutionsPercentHeld']['fmt']
institutions_float_percentage = holders['institutionsFloatPercentHeld']['fmt']
institutions_count = holders['institutionsCount']['fmt']


financialData = json_data['financialData']
currency = financialData['financialCurrency']
get_currency(currency)
gross_margin = financialData['grossMargins']['raw']
revenue_growth = financialData['revenueGrowth']['fmt']
operating_margins = financialData['operatingMargins']['fmt']
ebitda = financialData['ebitda']['fmt']
current_ratio = financialData['currentRatio']['raw']
return_on_assets = financialData['returnOnAssets']['raw']
debt_to_equity = financialData['debtToEquity']['fmt']
return_on_equity = financialData['returnOnEquity']['fmt']
total_cash_per_share = financialData['totalCashPerShare']['fmt']
quick_ratio = financialData['quickRatio']['fmt']
total_debt = financialData['totalDebt']['fmt']

##################################
""" --- Get-Financials --- """  ##
##################################

json_data = get_json(url_financials)


# Income Statement
def special_income():
    try:
        research = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['researchDevelopment']['fmt']
    except KeyError:
        research = 0

    return research


income = json_data['incomeStatementHistory']['incomeStatementHistory']

total_rev = income[0]['totalRevenue']['raw']
last_rev = income[1]['totalRevenue']['raw']
gross_profit = income[0]['grossProfit']['raw']
last_profit = income[1]['grossProfit']['raw']
operating_income = income[0]['operatingIncome']['raw']
operating_expenses = income[0]['totalOperatingExpenses']['raw']
interest_expenses = income[0]['interestExpense']['fmt']
cost_of_revenue = income[0]['costOfRevenue']['raw']
net_income = income[0]['netIncome']['raw']
last_income = income[1]['netIncome']['raw']
ebit = income[0]['ebit']['raw']
research = special_income()


# Balance Sheet
def special_balance():
    try:
        intangible_assets = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['intangibleAssets']['fmt']
    except KeyError:
        intangible_assets = 0
    try:
        capital_surplus = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['capitalSurplus']['fmt']
    except KeyError:
        capital_surplus = 0

    return intangible_assets, capital_surplus

balance = json_data['balanceSheetHistory']['balanceSheetStatements']

total_liablities = balance[0]['totalLiab']['raw']
last_liabilities = balance[1]['totalLiab']['raw']
current_liabilities = balance[0]['totalCurrentLiabilities']['raw']
stockholders_equity = balance[0]['totalStockholderEquity']['raw']
last_stockholders = balance[1]['totalStockholderEquity']['raw']
total_assets = balance[0]['totalAssets']['raw']
last_assets = balance[1]['totalAssets']['raw']
current_assets = balance[0]['totalCurrentAssets']['raw']
long_term_debt = balance[0]['longTermDebt']['raw']
last_long_term = balance[1]['longTermDebt']['raw']
short_term_debt = balance[0]['shortLongTermDebt']['raw']
cash = balance[0]['cash']['raw']
inventory = balance[0]['inventory']['fmt']
net_ppe = balance[0]['propertyPlantEquipment']['fmt']
intangible_assets, capital_surplus = special_balance()


# Cash Flow Statement
def special_cash():
    try:
        repurchase_stock = json_data['cashflowStatementHistory']['cashflowStatements'][0]['repurchaseOfStock']['fmt']
    except KeyError:
        repurchase_stock = 0
    try:
        capital_expenditure = json_data['cashflowStatementHistory']['cashflowStatements'][0]['capitalExpenditures']['raw']
    except KeyError:
        capital_expenditure = 0
    return repurchase_stock, capital_expenditure


cashflow = json_data['cashflowStatementHistory']['cashflowStatements']

investing_cash = cashflow[0]['totalCashflowsFromInvestingActivities']['fmt']
financing_cash = cashflow[0]['totalCashFromFinancingActivities']['fmt']
operating_cash = cashflow[0]['totalCashFromOperatingActivities']['raw']
shares_issued = cashflow[0]['issuanceOfStock']['raw']
last_shares = cashflow[1]['issuanceOfStock']['raw']
depreciation = cashflow[0]['depreciation']['raw']
change_cash = cashflow[0]['changeInCash']['raw']
repurchase_stock, capital_expenditure = special_cash()

shares_increased = True if (shares_issued > last_shares) else False
more_cash = True if (cash > long_term_debt) else False
debt_decrease = True if (long_term_debt < last_long_term) else False
asset_increase = True if (total_assets > last_assets) else False
liabilities_increase = True if (total_liablities > last_liabilities) else False
income_increase = True if (net_income > last_income) else False
last_margin = (last_profit / last_rev * 100)
gross_increase = True if (gross_margin > last_margin) else False

net_cash = operating_cash - capital_expenditure
working_capital = current_assets - current_liabilities
return_on_capital_employed = ebit / (total_assets - current_liabilities)
rcoe_to_price = return_on_capital_employed * current_price
company_valuation = round((market_cap / total_rev), 2)
last_current = last_assets / last_liabilities
last_return_on_assets = last_income / last_assets
total_debt_to_total_assets = '{0:.2f}%'.format((current_liabilities + long_term_debt) / total_assets)

print("Analyzing data...")


def analyze():
    # Income analysis
    income_red_list = ["\n[+] Income statement red flags: \n"]
    income_green_list = ["\n[+] Income statement green flags: \n"]
    income_red = 0

    if income_increase: income_green_list.append("\n[->] Income increased year over year.\n")
    if gross_increase: income_green_list.append(['\n[->] The gross margin increased year over year.\n'])

    if net_income < last_income:
        income_red += 1
        income_red_list.append("\n[!] Smaller net income than last year!")
    if operating_income < 0:
        income_red += 1
        income_red_list.append(
            "\n[!] The company doesn't generate cash from operations! Negative operative income.")
    if operating_expenses > total_rev:
        income_red += 1
        income_red_list.append(
            "\n[!] Operating expenses are more expensive than the produced revenue!")
    if cost_of_revenue > gross_profit:
        income_red += 1
        income_red_list.append(
            "\n[!] Cost of revenue higher than gross profit! The product costs more than it produces.")

    # Balance analysis
    balance_list = ["[+] Balance sheet red flags: \n"]
    balance_red = 0
    if not asset_increase:
        balance_red += 1
        balance_list.append("\n[!] Assets are decreasing!")
    if not debt_decrease:
        balance_red += 1
        balance_list.append("\n[!] Long term debt is increasing!")
    if not more_cash:
        balance_red += 1
        balance_list.append("\n[!] The company has less cash than debt!")
    if liabilities_increase:
        balance_red += 1
        balance_list.append("\n[!] The liabilities are increasing!")
    if shares_increased:
        balance_red += 1
        balance_list.append("\n[!] Number of issued shares increased! Company may finance itself via public offerings.")
    if stockholders_equity < 0:
        balance_red += 1
        balance_list.append("\n[!] Stockholders equity is negative! Liabilities are growing faster than assets.")

    # Cash flow analysis
    cash_list = ["[+] Cash flow red flags: \n"]
    cash_red = 0
    if net_cash < 0:
        cash_red += 1
        cash_list.append("\n[!] Negative Net Cash Position.")
    if operating_cash < 0:
        cash_red += 1
        cash_list.append("\n[!] Negative operating cash flow.")
    if working_capital < 0:
        cash_red += 1
        cash_list.append(
            "\n[!] Working capital negative! The company took on more debt or sold something to generate more money")
    if change_cash < 0:
        cash_red += 1
        cash_list.append(
            "\n[!] Negative net change in cash! Find out why, did the company buy something big?")
    if operating_cash < 0:
        cash_red += 1
        cash_list.append(
            "\n[!] Negative operating cash flow! Company is operating at a loss.")

    # Intrinsic value
    intrinsic_value = 0
    total_red = income_red + balance_red + cash_red

    if price_to_book < 1.5: intrinsic_value += 1
    if book_value > 0: intrinsic_value += 1
    if age: intrinsic_value += 1
    if forecast: intrinsic_value += 1
    if moat: intrinsic_value += 1
    if (net_income / stockholders_equity * 100) > 0.1: intrinsic_value += 1
    if (total_liablities / stockholders_equity * 100) < 1: intrinsic_value += 1
    if net_cash > 0: intrinsic_value += 1
    if total_red < 1: intrinsic_value += 1

    # Piotroski-F score -> max 8
    piotroski = 0

    # Profitability criteria
    if int(return_on_assets) > 0: piotroski += 1
    if operating_cash > 0: piotroski += 1
    if return_on_assets > last_return_on_assets: piotroski += 1
    if operating_cash > return_on_assets: piotroski += 1

    # Leverage, Luquidity and Source of Funds Criteria
    if debt_decrease: piotroski += 1
    if current_ratio > last_current: piotroski += 1
    if not shares_increased: piotroski += 1
    if stockholders_equity > last_stockholders: piotroski += 1

    # Operating efficiency criteria
    if gross_increase: piotroski += 1

    return income_red, income_red_list, income_green_list, balance_list, balance_red, cash_list, cash_red, total_red, intrinsic_value, piotroski


income_red, income_red_list, income_green_list, balance_list, balance_red, cash_list, cash_red, total_red, intrinsic_value, piotroski = analyze()
print("Creating report...")


def create_report():
    def convert_numbers():
        json_data = get_json(url_financials)
        mc = json_data['summaryDetail']['marketCap']['fmt']
        tr = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['totalRevenue']['fmt']
        cr = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['costOfRevenue']['fmt']
        ni = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['netIncome']['fmt']
        gp = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['grossProfit']['fmt']
        oi = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['operatingIncome']['fmt']
        oe = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['totalOperatingExpenses']['fmt']
        ebi = json_data['incomeStatementHistory']['incomeStatementHistory'][0]['ebit']['fmt']
        ta = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['totalAssets']['fmt']
        ca = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['totalCurrentAssets']['fmt']
        dep = json_data['cashflowStatementHistory']['cashflowStatements'][0]['depreciation']['fmt']
        tl = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['totalLiab']['fmt']
        cl = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['totalCurrentLiabilities']['fmt']
        ltd = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['longTermDebt']['fmt']
        oc = json_data['cashflowStatementHistory']['cashflowStatements'][0]['totalCashFromOperatingActivities']['fmt']
        se = json_data['balanceSheetHistory']['balanceSheetStatements'][0]['totalStockholderEquity']['fmt']
        ce = json_data['cashflowStatementHistory']['cashflowStatements'][0]['capitalExpenditures']['fmt']


        return mc, tr, cr, ni, gp, oi, oe, ebi, ta, ca, dep, tl, cl, ltd, oc, se, ce

    market_cap, total_rev, cost_of_revenue, net_income, gross_profit, \
    operating_income, operating_expenses, ebit, total_assets, current_assets, \
    depreciation, total_liablities, current_liabilities, long_term_debt, \
    operating_cash, stockholders_equity, capital_expenditure = convert_numbers()

    with open(f"{name}.txt", "a") as file:
        file.write(figlet_format(name) + "\n\n")
        file.write(f"Date of evaluation: {date}\nTime: {time}\n")
        file.write("\n\n________________________________________\n\t\t######################\n\t\t## General Overview ##\n\t\t######################\n________________________________________\n\n")

        def general_overview():
            file.write("# General information\n\n")
            file.write(
                f"{name} is situated in: {country} in {city}\n- Sector: {sector}\n- Industry: {industry}\n- Company website: {website}\n- Company partners: {partner}\n- Participating in the trend: {trend}\n\n")

            file.write("# Valuation\n")
            file.write(f"- Current price: %s\n- EPS: {eps}\t\t- PE/G: {peg_ratio}\n" % locale.currency(current_price,
                                                                                                       grouping=True))
            file.write(
                f"- Market capitalization: {market_cap}\n- [+] Valued at: %sx of the total revenue\n\n" % company_valuation)

            file.write("# Stockholders\n")
            file.write(
                f"- Insiders holding: {insiders_percentage}\n- Institutions holding: {institutions_percentage}\n- Float owned by institutions: {institutions_float_percentage}\n- Number of holding institutions: {institutions_count}\n- Shares held short: {short_ratio}\n\n")

            file.write("# Financial Data\n")
            file.write(f"- Profit margin: {profit_margin}\n")
            file.write(f"- Book value: %s\n- Price to book value: {price_to_book}\n" % locale.currency(book_value,
                                                                                                       grouping=True))
            file.write("- Gross margin: " + '{0:.2f}%'.format(gross_margin) + "\n")
            file.write(f"- Revenue growth: {revenue_growth}\n- Operating margins: {operating_margins}\n")
            file.write("- Return on assets: " + '{0:.2f}%'.format(return_on_assets) + "\n")
            file.write(f"- Return on equity: {return_on_equity}\n- Debt to equity ratio: {debt_to_equity}" + "%\n")
            file.write(f"- Total debt to total assets ratio: {total_debt_to_total_assets}\n- Total cash per share: {total_cash_per_share} {currency}\n")
            file.write(f"- Quick ratio: {quick_ratio}\n")
            file.write("- Return on capital employed: " + '{0:.2f}%'.format(return_on_capital_employed) + "\n")
            file.write("- Return on capital employed to price: %s\n" % locale.currency(rcoe_to_price, grouping=True))

        def income_statement():
            file.write(
                "\n\n________________________________________\n\t\t######################\n\t\t## Income Statement ##\n\t\t######################\n________________________________________\n\n")
            file.write(
                f"- Total revenue: {total_rev}\t\t- Cost of revenue: {cost_of_revenue}\n- Net income: {net_income}\t\t\t- Gross profit: {gross_profit}\n")
            file.write(f"- Operating income: {operating_income}\t\t- Operating expenses: {operating_expenses}\n")
            file.write(f"- EBIT: {ebit}\t\t\t\t\t- EBITDA: {ebitda}\n")
            file.write(f"- Money spent on research: {research}\n- Interest expenses: {interest_expenses}\n\n\n")

            file.write("# Income analysis")
            for item in income_green_list:
                file.write(item)
            for item in income_red_list:
                file.write(item)
            file.write(f"\n\n[+] Total income red flags: {income_red}\n\n\n")

        def balance_sheet():
            file.write(
                "_____________________________________\n\t\t#####################\n\t\t### Balance sheet ###\n\t\t#####################\n_____________________________________\n\n")
            file.write("# Assets that be liquidated within one year\n")
            file.write(
                f"- Total assets: {total_assets}\n- Current assets: {current_assets}\n- Inventory value: {inventory}\n\n")

            file.write("# Non-current assets -> require more time for liquidation\n")
            file.write(
                f"- Net PPE: {net_ppe}\n- Depreciation: {depreciation}\n- Intangible assets: {intangible_assets}\n\n")

            file.write("# Liabilities\n")
            file.write(
                f"- Total liabilities: {total_liablities}\n- Current liabilities/short term debt: {current_liabilities}\n- Long term debt: {long_term_debt}\n- Short long term debt: {short_term_debt}\n- Total debt: {total_debt}\n\n")

            file.write("# Additional information\n")
            file.write(f"- Stockholders equity: {stockholders_equity}\n- Current ratio: {current_ratio}\n\n")

            file.write("# Balance analysis\n")
            for item in balance_list:
                file.write(item)
            file.write(f"\n\n[+] Total balance red flags: {balance_red}\n\n\n")

        def cash_flow():
            file.write("_____________________________________\n\t\t###################\n\t\t#### Cash flow ####\n\t\t###################\n_____________________________________\n\n")
            file.write(f"- Operating cash flow: {operating_cash}\n- Investing cash flow: {investing_cash}\n- Financing cash flow: {financing_cash}\n")
            file.write(f"- Free cash: %s\n- Capital expenditure: {capital_expenditure}\n- Stock repurchased: {repurchase_stock}\n\n" % locale.currency(net_cash, grouping=True))

            file.write("# Cash analysis\n")
            for item in cash_list:
                file.write(item)
            file.write(f"\n\n[+] Total cash red flags: {cash_red}\n\n\n")

        def evaluation():
            file.write(
                "_____________________________________\n\t\t####################\n\t\t# Final Evaluation #\n\t\t####################\n_____________________________________\n\n")
            file.write("# Intrinsic value\n")
            file.write(f"- Total red flags: {total_red}\n- Intrinsic value score: {intrinsic_value}/8\n- Piotroski score: {piotroski}/8\n")

        def analysis():
            if intrinsic_value <= 3:
                file.write(
                    "\n\n[+] Fundamental Analysis: High risk!\n\t[=>] Be careful investing into this company and make sure to check the "
                    "financial statements and\n\t\tcompany story again properly. Further research recommended!")
            elif intrinsic_value == 4 or 5 or 6:
                file.write(
                    "\n\n[+] Fundamental Analysis: Medium risk.\n\t[=>] This company could be turning a profit but for safety reasons, "
                    "please check the financial statements,\n\t\tred flags and other facts again, to be sure that nothing is "
                    "inadvertently overlooked")
            elif intrinsic_value >= 7:
                file.write(
                    "\n\n[+] Fundamental Analysis: Low risk.\n\t[=>] It's unlikely that the company will go bankrupt in the foreseeable "
                    "future.")

        def glossary():
            file.write("\n\n\n_____________________________________\n\t\t###################\n\t\t#### Glossary ####\n\t\t###################\n_____________________________________\n")
            file.write("[+] EPS:\n- indicates how much money a company makes for each share of its stock, and is a widely used metric to estimate corporate value\n- A higher EPS indicates greater value because investors will pay more for a company's shares if they think the company has higher profits relative to its share price\n\n")
            file.write("[+] PE/G:\n- considered to be an indicator of a stock's true value, and similar to the P/E ratio, a lower PEG may indicate that a stock is undervalued.\n\n")
            file.write("[+] Market capitalization:\n- defined as the total market value of all outstanding shares.\n Companies are typically divided according to market capitalization: large-cap ($10 billion or more), mid-cap ($2 billion to $10 billion), and small-cap ($300 million to $2 billion.\n\n")
            file.write("[+] Holdings:\n- Who owns the company. The more insiders are holding shares of their own company, the more interested they are in a good performance.\n\n")
            file.write("[+] Profit margin:\n- indicates how many cents of profit has been generated for each dollar of sale.\n- As typical profit margins vary by industry sector, care should be taken when comparing the figures for different businesses.\n\n")
            file.write("[+] Book value:\n- the difference in value between that company's total assets and total liabilities on its balance sheet.\n- Traditionally, a P/B less than 1.0 is considered a good value, but it can be difficult to pinpoint a 'good' P/B ratio since it can vary by industry and any particular company may have underlying financial troubles.\n\n")
            file.write("[+] Price to book value:\n- Investors use the price-to-book value to gauge whether a company's stock price is valued properly.\n- A price-to-book ratio of one means that the stock price is trading in line with the book value of the company.\n- A P/B ratio with lower values, particularly those below one, are a signal to investors that a stock may be undervalued.\n\n")
            file.write("[+] Gross margins:\n- shows the amount of profit made before deducting selling, general, and administrative costs.\n\n")
            file.write("[+] Revenue growth:\n- measures the increase in a firm's sales from one year to another.\nFor an accurate picture of growth, investors should look at the growth of several quarters and how consistent it is.\n\n")
            file.write("[+] Operating margins:\n- the profit a company makes on a dollar of sales after paying for variable costs but before paying any interest or taxes.\n- Operating margin is a profitability ratio that shows how much profit a company makes from its core operations in relation to the total revenues it brings in.\n- An increasing operating margin over a period of time indicates a company whose profitability is improving.\n\n")
            file.write("[+] Return on assets:\n- an indicator of how well a company utilizes its assets, by determining how profitable a company is relative to its total assets.\n- best used when comparing similar companies or comparing a company to its previous performance.\n- takes a company's debt into account.\n\n")
            file.write("[+] Return on equity:\n- measures how the profitability of a corporation in relation to stockholders’ equity.\n- As a shortcut, investors can consider an ROE near the long-term average of the S&P 500 (14%) as an acceptable ratio and anything less than 10% as poor.\n\n")
            file.write("[+] Debt to equity ratio:\n- compares a company’s total liabilities to its shareholder equity and can be used to evaluate how much leverage a company is using.\n- Higher leverage ratios tend to indicate a company or stock with higher risk to shareholders.\n\n")
            file.write("[+] Total debt to total assets ratio:\n- shows the degree to which a company has used debt to finance its assets.\n- If a company has a total-debt-to-total-assets ratio of 0.4, 40% of its assets are financed by creditors, and 60% are financed by owners (shareholders) equity.\n\n")
            file.write("[+] Total cash per share:\n- tells us the percentage of a company’s share price available to spend on strengthening the business, paying down debt, returning money to shareholders, and other positive campaigns.\n- Paradoxically, too much cash per share can be a negative indicator of a company's health, because it may suggest an unwillingness by management to nurture forward-thinking measures.\n\n")
            file.write("[+] Quick ratio:\n- indicates a company's capacity to pay its current liabilities without needing to sell its inventory or get additional financing.\n- The higher the ratio result, the better a company's liquidity and financial health; the lower the ratio, the more likely the company will struggle with paying debts.\n\n")
            file.write("[+] Return on capital employed:\n- measures a company’s profitability in terms of all of its capital.\n- can be used when analyzing a company’s financials for profitability performance.\n- reflects a company's ability to earn a return on all of the capital it employs.\n\n")
            file.write("[+] Return on capital employed to price:\n- Amount of money the company is generating per one share at the current price.\n\n")
            file.write("[+] EBIT:\n- earnings before interest and taxes\n- a company's net income before income tax expense and interest expenses are deducted.\n- used to analyze the performance of a company's core operations without the costs of the capital structure and tax expenses impacting profit.\n- takes a company's cost of manufacturing including raw materials and total operating expenses, which include employee wages, into consideration.\n\n")
            file.write("[+] EBITDA:\n- a good measure of core profit trends because it eliminates some extraneous factors and allows a more 'apples-to-apples' comparisons.\n- can be used as a shortcut to estimate the cash flow available to pay the debt of long-term assets.\n\n")
            file.write("[+] Net PPE:\n- Property, plant, and equipment are also called fixed assets, meaning they are physical assets that a company cannot easily liquidate.\n-  long-term assets vital to business operations and the long-term financial health of a company.\n- Purchases of PP&E are a signal that management has faith in the long-term outlook and profitability of its company.\n\n")
            file.write("[+] Depreciation:\n- Wear and Tear on the assets.\n- represents how much of an asset's value has been used up.\n- Depreciating assets helps companies earn revenue from an asset while expensing a portion of its cost each year the asset is in use.\n\n")
            file.write("[+] Intangible assets:\n- an asset that is not physical in nature. Goodwill, brand recognition and intellectual property, such as patents, trademarks, and copyrights.\n- Intangible assets exist in opposition to tangible assets, which include land, vehicles, equipment, and inventory.\n\n")
            file.write("[+] Long term debt:\n- A loan that the company took to finance its operations.\n- debt that matures in more than one year and is often treated differently from short-term debt.\n- Entities choose to issue long-term debt with various considerations, primarily focusing on the timeframe for repayment and interest to be paid.\n\n")
            file.write("[+] Stockholder's Equity:\n- refers to the assets remaining in a business once all liabilities have been settled.\n- A negative stockholders' equity may indicate an impending bankruptcy.\n\n")
            file.write("[+] Current ratio:\n- compares all of a company’s current assets to its current liabilities. These are usually defined as assets that are cash or will be turned into cash in a year or less, and liabilities that will be paid in a year or less.\n- sometimes referred to as the “working capital” ratio and helps investors understand more about a company’s ability to cover its short-term debt with its current assets.\n- A ratio under 1 indicates that the company’s debts due in a year or less are greater than its assets \n\n")
            file.write("[+] Free Cash Flow:\n- the money a company has left over after paying its operating expenses and capital expenditures.\n- The more free cash flow a company has, the more it can allocate to dividends, paying down debt, and growth opportunities.\n- If a company has a decreasing free cash flow, that is not necessarily bad if the company is investing in its growth.\n\n")
            file.write("[+] Capital expenditure:\n- funds used by a company to acquire, upgrade, and maintain physical assets such as property, plants, buildings, technology, or equipment.\n- can include repairing a roof, purchasing a piece of equipment, or building a new factory.\n\n")

            file.write("[+] Intrinsic value:\n- Evaluates some key fundamental data to determine the company's health.\n")
            file.write("[+] Piotroski Score:\n- incorporates eight factors that speak to a firm's financial strength.\n- aspects are based on accounting results over a number of years; a point is awarded each time a standard is met, resulting in an overall score.\n- A favorite metric used to judge value stocks.\n- Used to determine the strength of a firms financial position\n\n")

        general_overview()
        income_statement()
        balance_sheet()
        cash_flow()
        evaluation()
        analysis()
        glossary()


create_report()

print("Done.\n")
print("The intrinsic value score is: " + str(intrinsic_value) + "/9\n")
print("The Piotroski F score is: " + str(piotroski) + "/8\n")
print("A report has been generated. Please check the same directory this program is located in\nThank you for using the Stock analysis tool.")

Edit: I tried solving the KeyError using a for loop:

item_list = ['forwardEPS', 'bookValue']

for item in item_list:
    try:
        item = defaultKeyStatistics[item]['raw']
    except KeyError:
        item = 0

But I can't figure out how to return the variable with the respective value (e.g. forwardEps = 10, bookValue = 5) as it always returns the last item, with item as variable name (e.g. item = 5)

\$\endgroup\$
3
\$\begingroup\$

Just some quick notes:

  • Are you sure this is correct: querystring = {f"symbol": {ticker}}? It looks like you either wanted querystring = {"symbol": ticker} or querystring = f"symbol={ticker}", but not this combination of the two.

  • get_currency can be simplified using a ternary expression:

    def get_currency(currency):
        locale.setlocale(locale.LC_ALL, 'en_US.UTF-8' if currency == "USD" else '')
    
  • Your check_* functions can be simplified by using the boolean result directly:

    def check_age_forecast_commodity():
        # Check age
        old = ask_yes_no("Is the company older than 10 years?")
    
        # Check forecast
        future = ask_yes_no("Do you still see the company around in 10 years?")
    
        # Check commodity reliance
        distinguish = ask_yes_no("Is the company distinguishable from others/ Does it have an economic moat?")
    
        return old, future, distinguish
    
  • Similarly, you don't need ternary expressions here, you can directly use the boolean results:

    shares_increased = shares_issued > last_shares
    
  • Python has an official style-guide, PEP8. It recommends always putting code on a new line when starting a new block, so not to use this:

    if price_to_book < 1.5: intrinsic_value += 1
    

    But this:

    if price_to_book < 1.5:
        intrinsic_value += 1
    
  • Instead of having many file.write calls, consider building a list (or any iterable, really) of lines first and then just use file.writelines(lines) instead. Note that the lines still need a final \n, otherwise they will not actually become multiple lines. This also allows you to separate getting the content from actually writing the file, allowing you to print it to the terminal instead, send it via email or do whatever else you might want to do with it in the future.

\$\endgroup\$
0
0
\$\begingroup\$

I managed to handle the second part of my question, regarding the try/except part:

item_list = ['forwardEps', 'bookValue']

def get_data(value, url, query_data):
    """
    Query the items of query_data, avoiding KeyErrors
    -> returns a dictionary, e.g.: {'forwardEps': 5.42, 'bookValue': 23.37}
    """

    json_data = get_json(url)
    value = json_data['defaultKeyStatistics']

    results = {}

    for item in query_data:
        try:
            results[item] = value[item]['raw']
        except KeyError:
            results[item] = 0

    return results


results = get_data("defaultKeyStatistics", url_summary, item_list)

eps = results['forwardEps']
book_value = results['bookValue']
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.