def main(start_index: int = 0) -> None: op.print_title_panel("Value Screener Pro") all_stocks = get_all_stocks() for stock in tqdm(all_stocks[start_index:]): symbol = stock[StockListKeys.symbol.value] tqdm.write(symbol) num_retries = 0 try: if get_peg_ratio(symbol) <= 1.7: results = ivc.main(symbol, show=False) if ((results[ivc.IVCKeys.evaluation.value][ ivc.IVCKeys.market_delta_cash_flow.value] < IVC_BUFFER_VALUE or results[ivc.IVCKeys.evaluation.value][ ivc.IVCKeys.market_delta_net_income.value] < IVC_BUFFER_VALUE) or (results[ivc.IVCKeys.evaluation.value][ ivc.IVCKeys.market_delta_cash_flow.value] > IVC_BUFFER_VALUE or results[ivc.IVCKeys.evaluation.value][ ivc.IVCKeys.market_delta_net_income.value] > IVC_BUFFER_VALUE)): op.print_intrinsic_value(results, ivc.IVCKeys) except (FinvizError, DocumentError, TypeError) as e: op.log_error(e) except HTTPError: if num_retries == MAX_NETWORK_RETRIES: op.log_verbose("Network Congestion") else: num_retries += 1 time.sleep(DELAY_TIME)
def inner(*args, **kwargs): num_tries:int = 0 function_name:str = func.__name__ while num_tries < max_tries: try: return func(*args, **kwargs) except Exception: op.log_error(f"Decorator error --> {function_name}") num_tries = num_tries + 1 time.sleep(WAIT_TIME) raise exceptions.NetworkException(f"Could not retrieve data from function {function_name} " f"values with {max_tries} re-tries")
def extract_values_from_statement( statements: list, statement_attribute: StatementAttribute) -> list: float_values = [] try: for i in range(len(statements)): float_val = float( statements[i][statement_attribute.attribute_name]) float_values.append(float_val) return float_values except (ValueError, KeyError) as e: op.log_error(e) raise DocumentError
def get_company_debts(stock_symbol: str) -> (float, float): url = f"https://www.barchart.com/stocks/quotes/{stock_symbol}/balance-sheet/quarterly" rows = get_table_rows_from_url(url) rows = rows if rows is not None else list() short_term_debt = 0 long_term_debt = 0 for i in range(len(rows)): current_row = rows[i].string if current_row is not None: current_row = current_row.strip() if current_row == "Short Term Debt": try: short_term_debt = float(rows[i + 1].string.strip().replace( ',', '')) * 1e3 except ValueError as e: op.log_error(e) if current_row == "Long Term Debt $M": try: long_term_debt = float(rows[i + 1].string.strip().replace( ',', '')) * 1e3 except ValueError as e: op.log_error(e) return short_term_debt, long_term_debt
def main(stock_symbol: str, show=True) -> dict: global cash_flow_from_ops, net_incomes, total_debt, total_cash_and_short_term_investments stock_symbol = stock_symbol.upper() op.loading_message(f"Calculating Intrinsic Value for: {stock_symbol}") op.loading_message("Fetching Yearly Income Statements") income_statements_yearly = stret.get_financial_statement( stret.INCOME_STATEMENT, stock_symbol) op.loading_message("Fetching Yearly Cash Flow Statements") cash_flow_statements_yearly = stret.get_financial_statement( stret.CASH_FLOW_STATEMENT, stock_symbol) try: cash_flow_from_ops = get_cash_flows(cash_flow_statements_yearly) except DocumentError as e: op.log_error(e) op.loading_message("Parsing Net Incomes") try: net_incomes = get_net_incomes(income_statements_yearly) except DocumentError as e: op.log_error(e) # cash flow from ops # use net income if cash flow from ops not increasing # if net income not increasing as well skip try: op.loading_message("Parsing Cash Flows from Operations") # total debt (short term + long) latest quarter op.loading_message("Fetching Quarterly Balance Sheets") balance_sheets_quarterly = stret.get_financial_statement( stret.BALANCE_SHEET, stock_symbol, quarterly=True) op.loading_message("Calculating Total Debt") total_debt = get_total_debt(stock_symbol) op.loading_message("Calculating Total Cash on Hand") total_cash_and_short_term_investments = get_total_cash_on_hand( balance_sheets_quarterly) except ValueError as e: op.log_error(e) try: projected_growth_5_y = finviz.get_eps_growth(stock_symbol) projected_growth_after_5_y = projected_growth_5_y / 2 if projected_growth_5_y is not None else 0 projected_growth_5_y = projected_growth_5_y / 100 if projected_growth_5_y is not None else 0 projected_growth_after_5_y = projected_growth_after_5_y / 100 current_year_cash_flow = cash_flow_from_ops[0] current_year_net_income = net_incomes[0] op.loading_message("Calculating Projected Cash Flows") projected_growths_cash_flow = get_projected_cash_flow( current_year_cash_flow, projected_growth_5_y, projected_growth_after_5_y) op.loading_message("Calculating Projected Net Incomes") projected_growths_net_income = get_projected_cash_flow( current_year_net_income, projected_growth_5_y, projected_growth_after_5_y) op.loading_message("Fetching Number of Outstanding Shares from Finviz") no_outstanding_shares = finviz.get_no_shares(stock_symbol) op.loading_message("Fetching Beta Value from Finviz") beta_value = finviz.get_beta(stock_symbol) except FinvizError as e: op.log_error(e) return dict() discounted_rates = calculate_discount_rates( get_discount_from_beta(beta_value)) op.loading_message("Calculating Discounted Projected Cash Flows") projected_cash_flow_discounted = calculate_discounted_values( projected_growths_cash_flow, discounted_rates) op.loading_message("Calculating Intrinsic Value from Cash Flow") intrinsic_value_cash_flow = calculate_intrinsic_value( sum(projected_cash_flow_discounted), no_outstanding_shares, total_debt, total_cash_and_short_term_investments) op.loading_message("Calculating Discounted Projected Cash Flows") projected_net_income_discounted = calculate_discounted_values( projected_growths_net_income, discounted_rates) op.loading_message("Calculating Intrinsic Value from Net Income") intrinsic_value_net_income = calculate_intrinsic_value( sum(projected_net_income_discounted), no_outstanding_shares, total_debt, total_cash_and_short_term_investments) market_price = float( get_last_price_data(stock_symbol)[PricePayloadKeys.price.value]) intrinsic_value_cash_flow_final = intrinsic_value_cash_flow[ IVCKeys.intrinsic_value.value] intrinsic_value_net_income_final = intrinsic_value_net_income[ IVCKeys.intrinsic_value.value] try: peg_ratio = finviz.get_peg_ratio(stock_symbol) except FinvizError as e: peg_ratio = None op.log_error(e) results = { IVCKeys.company_name.value: finviz.get_company_name(stock_symbol), IVCKeys.symbol.value: stock_symbol, IVCKeys.total_debt.value: total_debt, IVCKeys.total_cash.value: total_cash_and_short_term_investments, IVCKeys.eps_5Y.value: projected_growth_5_y, IVCKeys.projected_growth.value: projected_growth_after_5_y, IVCKeys.no_shares.value: no_outstanding_shares, IVCKeys.cash_from_ops_calcs.value: { IVCKeys.cash_from_ops.value: current_year_cash_flow, IVCKeys.discount_rates.value: discounted_rates, IVCKeys.pv_of_cash.value: projected_cash_flow_discounted, IVCKeys.intrinsic_value.value: intrinsic_value_cash_flow, IVCKeys.debt_per_share.value: intrinsic_value_cash_flow[IVCKeys.debt_per_share.value], IVCKeys.cash_per_share.value: intrinsic_value_cash_flow[IVCKeys.cash_per_share.value] }, IVCKeys.net_income_calcs.value: { IVCKeys.net_income.value: current_year_net_income, IVCKeys.pv_of_cash.value: projected_growths_net_income, IVCKeys.discount_rates.value: discounted_rates, IVCKeys.projected_growth_discounted.value: projected_net_income_discounted, IVCKeys.intrinsic_value.value: intrinsic_value_net_income, IVCKeys.debt_per_share.value: intrinsic_value_net_income[IVCKeys.debt_per_share.value], IVCKeys.cash_per_share.value: intrinsic_value_net_income[IVCKeys.cash_per_share.value] }, IVCKeys.evaluation.value: { IVCKeys.peg.value: peg_ratio, IVCKeys.market_price.value: market_price, IVCKeys.market_delta_cash_flow.value: market_price - intrinsic_value_cash_flow_final, IVCKeys.market_delta_net_income.value: market_price - intrinsic_value_net_income_final, IVCKeys.cash_from_ops.value: fuzzy_increase(stret.CASH_FLOW_FROM_OPERATIONS_ATTR, cash_flow_from_ops[:5][::-1]), IVCKeys.net_income.value: fuzzy_increase(stret.NET_INCOME_ATTR, net_incomes[:5][::-1]) } } if show: op.print_intrinsic_value(results, IVCKeys) return results
def main(stock: str) -> None: cash_from_investments = sys.maxsize cash_from_financing = sys.maxsize cash_flow_from_ops = sys.maxsize eps_diluted = sys.maxsize gross_margin = sys.maxsize net_profit_margins = sys.maxsize net_incomes = sys.maxsize interest_expense = sys.maxsize free_cash_flows = sys.maxsize revenues = sys.maxsize total_shareholders_equity = sys.maxsize total_liabilities = sys.maxsize total_current_liabilities = sys.maxsize total_current_assets = sys.maxsize stock = stock.upper() try: op.loading_message("Fetching Yearly Income Statements") income_statements_yearly = stret.get_financial_statement( stret.INCOME_STATEMENT, stock)[stret.StatementKeys.financials.value][::-1][-5:] op.loading_message("Fetching Quarterly Balance Sheets") balance_sheets_quarterly = stret.get_financial_statement( stret.BALANCE_SHEET, stock, quarterly=True)[stret.StatementKeys.financials.value][::-1][-5:] op.loading_message("Fetching Yearly Cash Flow Statements") cash_flow_statements_yearly = stret.get_financial_statement( stret.CASH_FLOW_STATEMENT, stock)[stret.StatementKeys.financials.value][::-1][-5:] except KeyError as e: op.log_error(e) return except HTTPError as e2: print(f"--{stock} was not found--") op.log_error(e2) raise e2 op.loading_message("Parsing Years") years = [] for i in range(len(income_statements_yearly)): years.append(income_statements_yearly[i]['date']) years = [year.split('-')[0] for year in years] quarters = [] for i in range(len(balance_sheets_quarterly)): quarters.append(balance_sheets_quarterly[i]['date']) try: op.loading_message("Parsing Net Incomes") net_incomes = extract_values_from_statement(income_statements_yearly, stret.NET_INCOME_ATTR) op.loading_message("Parsing Revenues") revenues = extract_values_from_statement(income_statements_yearly, stret.REVENUE_ATTR) op.loading_message("Parsing EPS Diluted") eps_diluted = extract_values_from_statement(income_statements_yearly, stret.EPS_DILUTED_ATTR) op.loading_message("Parsing Cash Flow from Operations") cash_flow_from_ops = extract_values_from_statement( cash_flow_statements_yearly, stret.CASH_FLOW_FROM_OPERATIONS_ATTR) op.loading_message("Parsing Total Current Assets") total_current_assets = extract_values_from_statement( balance_sheets_quarterly, stret.TOTAL_CURRENT_ASSETS_ATTR) op.loading_message("Parsing Total Liabilities") total_liabilities = extract_values_from_statement( balance_sheets_quarterly, stret.TOTAL_LIABILITIES_ATTR) op.loading_message("Parsing Total Current Liabilities") total_current_liabilities = extract_values_from_statement( balance_sheets_quarterly, stret.TOTAL_CURRENT_LIABILITIES_ATTR) op.loading_message("Parsing Total Shareholder Equity") total_shareholders_equity = extract_values_from_statement( balance_sheets_quarterly, stret.TOTAL_SHAREHOLDER_EQUITY_ATTR) op.loading_message("Parsing Free Cash Flows") free_cash_flows = extract_values_from_statement( cash_flow_statements_yearly, stret.FREE_CASH_FLOWS_ATTR) op.loading_message("Parsing Cash From Financing") cash_from_financing = extract_values_from_statement( cash_flow_statements_yearly, stret.CASH_FROM_FINANCING_ATTR) op.loading_message("Parsing Cash From Investments") cash_from_investments = extract_values_from_statement( cash_flow_statements_yearly, stret.CASH_FROM_INVESTMENTS_ATTR) op.loading_message("Parsing Interest Expense") interest_expense = extract_values_from_statement( income_statements_yearly, stret.INTEREST_EXPENSE_ATTR) op.loading_message("Parsing Gross Margin") gross_margin = extract_values_from_statement(income_statements_yearly, stret.GROSS_MARGIN_ATTR) op.loading_message("Parsing Net Margin") net_profit_margins = extract_values_from_statement( income_statements_yearly, stret.NET_PROFIT_MARGIN_ATTR) except DocumentError as e: op.log_error(e) op.loading_message("Calculating Current Ratio") current_ratio = calculate_ttm_ratio(total_current_assets, total_current_liabilities) current_ratio_check = current_ratio >= 1 op.loading_message("Calculating Debt to Equity Ratio") de_ratios = calculate_ratios(total_liabilities, total_shareholders_equity) op.loading_message("Calculating Debt Servicing Ratio") debt_servicing_ratios_fcf = calculate_ratios(interest_expense, free_cash_flows) op.loading_message("Calculating Free Cash Flow (Revenues)") fcf_revenues = calculate_ratios(free_cash_flows, revenues) op.loading_message("Calculating Return on Equity (FCF)") return_on_equity_fcf = calculate_ratios(free_cash_flows, total_shareholders_equity) op.loading_message("Calculating Return on Equity (Net Income)") return_on_equity_net_income = calculate_ratios(net_incomes, total_shareholders_equity) op.loading_message("Fetching PEG Ratio") try: peg_ratio = get_peg_ratio(stock) except FinvizError as e: peg_ratio = None op.log_error(e) try: eps_current = get_eps_growth(stock, 0) except FinvizError as e: eps_current = None op.log_error(e) try: eps_1yr = get_eps_growth(stock, 1) except FinvizError as e: eps_1yr = None op.log_error(e) try: eps_5yr = get_eps_growth(stock) except FinvizError as e: eps_5yr = None op.log_error(e) company_npm, industry_npm, roe_company, roe_industry, debt_to_equity_company, debt_to_equity_industry = externals. \ get_industry_comparisons(stock) results = { VIKeys.company_name.value: get_company_name(stock), VIKeys.symbol.value: stock, VIKeys.current_ratio.value: current_ratio, VIKeys.current_ratio_check.value: current_ratio_check, VIKeys.cash_flow_from_financing.value: calculate_flow_graph(cash_from_investments, CASH_FLOW_FROM_FINANCING_THRESHOLD), VIKeys.cash_flow_from_investing.value: calculate_flow_graph(cash_from_financing, CASH_FLOW_FROM_INVESTING_THRESHOLD), VIKeys.free_cash_flow.value: free_cash_flows, VIKeys.free_cash_flow_trend.value: fuzzy_increase(stret.FREE_CASH_FLOWS_ATTR, free_cash_flows), VIKeys.debt_to_equity_ratio.value: de_ratios, VIKeys.debt_to_equity_ratio_trend.value: fuzzy_increase(stret.DEBT_TO_EQUITY_RATIO_ATTR, de_ratios), VIKeys.debt_servicing_ratio_free_cash_flow.value: debt_servicing_ratios_fcf, VIKeys.debt_servicing_ratio_free_cash_flow_decision.value: evaluate_debt_servicing_ratios(debt_servicing_ratios_fcf), VIKeys.cash_flow_from_ops.value: cash_flow_from_ops, VIKeys.cash_flow_from_ops_trend.value: fuzzy_increase(stret.CASH_FLOW_FROM_OPERATIONS_ATTR, cash_flow_from_ops), VIKeys.eps.value: eps_diluted, VIKeys.eps_trend.value: fuzzy_increase(stret.EPS_DILUTED_ATTR, eps_diluted), VIKeys.net_incomes.value: net_incomes, VIKeys.net_incomes_trend.value: fuzzy_increase(stret.NET_INCOME_ATTR, net_incomes), VIKeys.revenues.value: revenues, VIKeys.revenues_trend.value: fuzzy_increase(stret.REVENUE_ATTR, revenues), VIKeys.gross_margin.value: gross_margin, VIKeys.gross_margin_trend.value: fuzzy_increase(stret.GROSS_MARGIN_ATTR, gross_margin), VIKeys.net_profit_margin.value: net_profit_margins, VIKeys.net_profit_margin_trend.value: fuzzy_increase(stret.NET_PROFIT_MARGIN_ATTR, net_profit_margins), VIKeys.peg_ratio.value: peg_ratio, VIKeys.peg_ratio_check.value: evaluate_peg_ratio(peg_ratio), VIKeys.years.value: years, VIKeys.free_cash_flow_revenue.value: fcf_revenues, VIKeys.return_on_equity_fcf.value: return_on_equity_fcf, VIKeys.return_on_equity_fcf_list_evaluate.value: evaluate_roes(return_on_equity_fcf), VIKeys.return_on_equity_net_income.value: return_on_equity_net_income, VIKeys.return_on_equity_net_income_list_evaluate.value: evaluate_roes(return_on_equity_net_income), VIKeys.quarters.value: quarters, VIKeys.eps_current.value: eps_current, VIKeys.eps_1yr.value: eps_1yr, VIKeys.eps_5yr.value: eps_5yr, VIKeys.eps_5yr_check.value: evaluate_eps(eps_5yr), VIKeys.company_npm.value: company_npm, VIKeys.industry_npm.value: industry_npm, VIKeys.net_profit_margin_evaluate.value: compare_to_industry(company_npm, industry_npm), VIKeys.roe_company.value: roe_company, VIKeys.roe_industry.value: roe_industry, VIKeys.return_on_equity_evaluate.value: compare_to_industry(roe_company, roe_industry), VIKeys.dtoe_company.value: debt_to_equity_company, VIKeys.dtoe_industry.value: debt_to_equity_industry, VIKeys.debt_to_equity_ratio_evaluate.value: compare_to_industry(debt_to_equity_industry, debt_to_equity_company) } op.print_value_investing_report(results, VIKeys)
#!/usr/bin/env python3 import configparser import exceptions import output as op import os config_file = "config.ini" if os.path.exists(config_file): config = configparser.ConfigParser() config.read(config_file) SWING_API_KEY = config['keys']['swing_api_key'] CURRENT_CAPITAL = float(config['account']['current_capital']) COMMISSION_COST = float(config['account']['commission_cost']) VERBOSITY = int(config['app']['verbosity']) WRITE_TO_FILE = True if config['app']['write_to_file'] == "true" else False else: op.log_error(exceptions.DocumentError)
# -*- coding: utf-8 -*- """ My personal swing trading entry formula """ import argparse import datetime import config_loader as cl import output as op from pricing import get_last_price_data, PricePayloadKeys from stock import Stock from trade import Trade try: import holidays except ModuleNotFoundError as e: op.log_error("Holidays module not loaded") # TODO: Add break for large candles def get_price_padding(closing_price: float) -> float: """ Calculate how far above and below to place your entry/stop """ if closing_price < 5: return 0.01 elif 5 <= closing_price < 10: return 0.02 elif 10 <= closing_price < 50: return 0.03 elif 50 <= closing_price < 100: return 0.05