Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def get_sector_yfinance(ticker_symbol):
- """Fetch the sector for a given ticker using yfinance."""
- ticker = yf.Ticker(ticker_symbol)
- info = ticker.info
- return info.get('sector', None)
- def get_industry_yfinance(ticker_symbol):
- """Fetch the sector for a given ticker using yfinance."""
- ticker = yf.Ticker(ticker_symbol)
- info = ticker.info
- return info.get('sector', None)
- def get_stocks_from_same_industry(ticker_symbol):
- """Fetch stocks from the same industry as the provided ticker."""
- # Get the sector for the given ticker using yfinance
- sector = get_industry_yfinance(ticker_symbol)
- if not sector:
- print(f"Could not find industry for {ticker_symbol}")
- return None
- # Initialize the screener from yahooquery
- s = Screener()
- # Using sector to screen stocks
- screen_key = f"ms_{sector.lower()}"
- if screen_key not in s.available_screeners:
- print(f"No predefined screener available for sector: {sector}")
- return None
- data = s.get_screeners(screen_key)
- # Convert data to DataFrame for easier handling
- df = pd.DataFrame(data[screen_key]['quotes'])
- return df
- def calculate_rolling_beta(stock_data, market_data, window_size):
- stock_returns = stock_data['Adj Close'].pct_change().dropna()
- market_returns = market_data['Adj Close'].pct_change().dropna()
- rolling_cov = stock_returns.rolling(window=window_size).cov(market_returns)
- rolling_var = market_returns.rolling(window=window_size).var()
- rolling_beta = rolling_cov / rolling_var
- return rolling_beta.dropna()
- def get_unlevered_beta(ticker):
- stock = yf.Ticker(ticker)
- # Get levered beta
- levered_beta = stock.info['beta']
- if not levered_beta:
- return None
- # Get debt and equity values
- market_cap = stock.info['marketCap'] / 10**9
- long_term_debt = stock.balance_sheet.loc["Long Term Debt"][0] / 10**9 if "Long Term Debt" in stock.balance_sheet.index else 0
- short_term_debt = stock.balance_sheet.loc["Short Term Debt"][0] / 10**9 if "Short Term Debt" in stock.balance_sheet.index else 0
- debt_value = long_term_debt + short_term_debt
- equity_value = market_cap
- # Calculate the effective tax rate
- income_statement = stock.financials
- pretax_income = float(income_statement.loc["Pretax Income"].iloc[0])
- income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
- effective_tax_rate = income_tax_expense / pretax_income
- T = effective_tax_rate
- # Calculate unlevered beta
- return levered_beta / (1 + ((1 - T) * (debt_value / equity_value)))
- def get_pretax_cost_of_debt(ticker):
- """Compute the pre-tax cost of debt for a given ticker."""
- stock = yf.Ticker(ticker)
- income_statement = stock.financials
- balance_sheet = stock.balance_sheet
- # Interest Expense from the income statement
- interest_expense = float(income_statement.loc["Interest Expense"].iloc[0]) if "Interest Expense" in income_statement.index else 0
- # Average Total Debt calculation
- current_long_term_debt = float(balance_sheet.loc["Long Term Debt"].iloc[0]) if "Long Term Debt" in balance_sheet.index else 0
- previous_long_term_debt = float(balance_sheet.loc["Long Term Debt"].iloc[1]) if "Long Term Debt" in balance_sheet.index else 0
- current_short_term_debt = float(balance_sheet.loc["Short Term Debt"].iloc[0]) if "Short Term Debt" in balance_sheet.index else 0
- previous_short_term_debt = float(balance_sheet.loc["Short Term Debt"].iloc[1]) if "Short Term Debt" in balance_sheet.index else 0
- average_debt = (current_long_term_debt + current_short_term_debt + previous_long_term_debt + previous_short_term_debt) / 2
- # Calculate the pre-tax cost of debt
- if average_debt == 0:
- return 0
- else:
- return interest_expense / average_debt
- def get_year_cost_of_debt_converges(ticker, comparable_tickers):
- """Compute the year when the cost of debt converges to the industry average."""
- # Get the current pre-tax cost of debt for the given ticker
- DURATION = 5
- current_pretax_cost_of_debt = get_pretax_cost_of_debt(ticker)
- if not current_pretax_cost_of_debt:
- return None # No cost of debt available
- # Get the pre-tax cost of debt for each comparable ticker
- pretax_costs_of_debt = [get_pretax_cost_of_debt(ticker) for ticker in comparable_tickers]
- pretax_costs_of_debt = [cost for cost in pretax_costs_of_debt if cost is not None] # Remove None values
- # Calculate the industry average pre-tax cost of debt
- industry_average_pretax_cost_of_debt = sum(pretax_costs_of_debt) / len(pretax_costs_of_debt)
- # Estimate the terminal pre-tax cost of debt using a weighted average
- omega = 0.5 # Weight given to the company's current pre-tax cost of debt
- terminal_pretax_cost_of_debt = omega * current_pretax_cost_of_debt + (1 - omega) * industry_average_pretax_cost_of_debt
- # Assume a linear convergence from the current to the terminal cost of debt
- # Use the equation y = mx + b, where y is the cost of debt, x is the year, m is the slope, and b is the intercept
- # Solve for x when y equals the terminal cost of debt
- slope = (terminal_pretax_cost_of_debt - current_pretax_cost_of_debt) / DURATION # DURATION is the number of years for valuation
- intercept = current_pretax_cost_of_debt
- year_cost_of_debt_converges = (terminal_pretax_cost_of_debt - intercept) / slope
- return year_cost_of_debt_converges
- def get_marginal_tax_rate(ticker):
- """Compute the marginal tax rate for a given ticker using yfinance."""
- # Get the income statement from yfinance
- stock = yf.Ticker(ticker)
- income_statement = stock.financials
- # Get the income before tax and income tax expense from the income statement
- income_before_tax = float(income_statement.loc["Pretax Income"].iloc[0])
- income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
- # Calculate the marginal tax rate as the ratio of income tax expense to income before tax
- marginal_tax_rate = income_tax_expense / income_before_tax
- # Return the marginal tax rate as a percentage
- return marginal_tax_rate
- def get_ttm_total_revenue(ticker_symbol):
- ticker = yf.Ticker(ticker_symbol)
- # Fetch the total revenue for the TTM
- ttm_revenue = ticker.info['totalRevenue']
- return ttm_revenue
- def get_revenue_growth_rate_cycle1_begin(ticker):
- """Compute the revenue growth rate for cycle 1 begin for a given ticker using yfinance."""
- # Get the total revenue for the TTM
- ttm_revenue = get_ttm_total_revenue(ticker)
- if not ttm_revenue:
- return None # No revenue data available
- # Get the total revenue for the previous year
- stock = yf.Ticker(ticker)
- income_statement = stock.financials
- previous_year_revenue = float(income_statement.loc["Total Revenue"].iloc[1])
- if not previous_year_revenue:
- return None # No revenue data available
- # Calculate the revenue growth rate as the percentage change from previous year to TTM
- revenue_growth_rate = (ttm_revenue - previous_year_revenue) / previous_year_revenue
- return revenue_growth_rate
- # Define the URL for the API endpoint
- TICKER = "AAPL"
- ENDPOINT = "https://query1.finance.yahoo.com/v7/finance/download/{}"
- TICKER_SP500 = "^GSPC"
- DURATION = 10 # 10 years
- TODAY = int(datetime.now().timestamp())
- TEN_YEARS_AGO = int((datetime.now() - pd.DateOffset(years=DURATION)).timestamp())
- urlRFR = "https://query1.finance.yahoo.com/v7/finance/download/%5ETNX?period1=0&period2=9999999999&interval=1d&events=history&includeAdjustedClose=true"
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
- }
- responseRFR = requests.get(urlRFR, headers=headers)
- if responseRFR.status_code == 200:
- content = responseRFR.text
- lines = content.strip().split("\n")
- if len(lines) < 2: # Check if there's at least a header and one data line
- print("Error: Not enough data lines in the response.")
- exit()
- last_line = lines[-1]
- values = last_line.split(",")
- if len(values) < 4: # Check if there are enough values in the last line
- print("Error: Not enough values in the data line.")
- exit()
- RFR = float(values[3])
- print(f"The 10-year treasury yield in USA is {RFR}%")
- else:
- print(f"Error: The request failed with status code {responseRFR.status_code}. Response: {responseRFR.text}")
- # Fetch S&P 500 historical data
- urlSP500 = ENDPOINT.format(TICKER_SP500) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
- responseSP500 = requests.get(urlSP500, headers=headers)
- if responseSP500.status_code != 200:
- raise Exception("Error fetching S&P 500 data.")
- dataSP500 = pd.read_csv(urlSP500, parse_dates=['Date'], index_col='Date')
- urlCOMPANY = ENDPOINT.format(TICKER) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
- responseCOMPANY = requests.get(urlCOMPANY, headers=headers)
- if responseCOMPANY.status_code != 200:
- raise Exception("Error fetching company data.")
- dataCOMPANY = pd.read_csv(io.StringIO(responseCOMPANY.text), parse_dates=['Date'], index_col='Date')
- historical_beta = calculate_rolling_beta(dataCOMPANY, dataSP500, 252)
- # Calculate annualized return for S&P 500 over the given duration
- initial_value = dataSP500['Adj Close'].iloc[0]
- final_value = dataSP500['Adj Close'].iloc[-1]
- Rm = ((final_value / initial_value) ** (1/DURATION) - 1)
- risk_free_rate = RFR/100
- ERP = Rm - risk_free_rate
- print(f"Equity Risk Premium: {ERP*100:.2f}%")
- # Use yfinance to get the market capitalization
- stock = yf.Ticker(TICKER)
- market_cap = stock.info['marketCap'] / 10**9 # Convert to billions
- equity_value = market_cap
- print(f"The equity value (market cap) of {TICKER} is approximately ${market_cap:.2f} billion.")
- # Use yfinance to get the debt values
- long_term_debt = stock.balance_sheet.loc["Long Term Debt"][0] if "Long Term Debt" in stock.balance_sheet.index else 0
- short_term_debt = stock.balance_sheet.loc["Short Term Debt"][0] if "Short Term Debt" in stock.balance_sheet.index else 0
- # Calculate total debt
- debt_value = (long_term_debt + short_term_debt) / 10**9 # Convert to billions
- print(f"The total debt of {TICKER} is approximately ${debt_value:.2f} billion.")
- # Use yfinance to get the cash and non-operating asset values
- cash_and_cash_equivalents = stock.balance_sheet.loc["Cash And Cash Equivalents"][0] if "Cash And Cash Equivalents" in stock.balance_sheet.index else 0
- # Convert to billions
- cash_and_non_operating_asset = cash_and_cash_equivalents / 10**9
- print(f"Cash and non-operating assets of {TICKER} is approximately ${cash_and_non_operating_asset:.2f} billion.")
- df_result = get_stocks_from_same_industry(TICKER)
- comparable_tickers = df_result['symbol'].tolist()
- print(comparable_tickers)
- # Get unlevered betas for each comparable
- unlevered_betas = [get_unlevered_beta(ticker) for ticker in comparable_tickers]
- unlevered_betas = [beta for beta in unlevered_betas if beta is not None] # Remove None values
- # Calculate the industry average unlevered beta
- industry_average_unlevered_beta = sum(unlevered_betas) / len(unlevered_betas)
- # Estimate the terminal_unlevered_beta
- omega = 0.5 # Weight given to the company's current unlevered beta
- unlevered_beta = get_unlevered_beta(TICKER)
- terminal_unlevered_beta = omega * unlevered_beta + (1 - omega) * industry_average_unlevered_beta
- print(f"The estimated unlevered beta is: {unlevered_beta:.4f}")
- print(f"The estimated terminal unlevered beta is: {terminal_unlevered_beta:.4f}")
- # Linear regression model
- X = np.array(range(len(historical_beta))).reshape(-1, 1)
- y = historical_beta.values
- model = LinearRegression().fit(X, y)
- slope = model.coef_
- intercept = model.intercept_
- # Calculate the intersection point with terminal beta using the equation of the line
- # y = mx + c; terminal_beta = slope*x + intercept
- intersection_point = (terminal_unlevered_beta - intercept) / slope
- # Convert intersection_point to years (assuming your historical data is daily)
- intersection_in_years = intersection_point[0] / 252 # 252 trading days in a year
- print(f"Expected year to converge to terminal beta: {intersection_in_years:.2f} years")
- year_beta_begins_to_converge_to_terminal_beta = intersection_in_years
- # Calculate the effective tax rate
- income_statement = stock.financials
- pretax_income = float(income_statement.loc["Pretax Income"].iloc[0])
- income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
- tax_rate = income_tax_expense / pretax_income
- print(f"Current Effective Tax Rate: {tax_rate:.2%}")
- current_effective_tax_rate = tax_rate
- current_pretax_cost_of_debt = get_pretax_cost_of_debt(TICKER)
- print(f"Current Pretax Cost of Debt: {current_pretax_cost_of_debt:.2%}")
- # Get pre-tax cost of debt for each comparable
- pretax_costs_of_debt = [get_pretax_cost_of_debt(ticker) for ticker in comparable_tickers]
- pretax_costs_of_debt = [cost for cost in pretax_costs_of_debt if cost is not None]
- # Calculate the industry average pre-tax cost of debt
- industry_average_pretax_cost_of_debt = sum(pretax_costs_of_debt) / len(pretax_costs_of_debt)
- # Estimate the terminal_pre_tax_cost_of_debt
- omega = 0.5 # Weight given to the company's current pre-tax cost of debt
- terminal_pretax_cost_of_debt = omega * current_pretax_cost_of_debt + (1 - omega) * industry_average_pretax_cost_of_debt
- print(f"The estimated terminal pre-tax cost of debt is: {terminal_pretax_cost_of_debt:.2%}")
- year_cost_of_debt_begins_to_converge_to_terminal_cost_of_debt = get_year_cost_of_debt_converges(TICKER, comparable_tickers)
- print(f"Expected year to converge to the cost of debt: {year_cost_of_debt_begins_to_converge_to_terminal_cost_of_debt:.2f} years")
- marginal_tax_rate = get_marginal_tax_rate(TICKER)
- print(f"Current Marginal Tax Rate: {marginal_tax_rate:.2%}")
- year_effective_tax_rate_begin_to_converge_marginal_tax_rate = 1
- revenue_base = get_ttm_total_revenue(TICKER)
- print(f"The total revenue of {TICKER} is approximately ${revenue_base}")
- revenue_growth_rate_cycle1_begin = (get_revenue_growth_rate_cycle1_begin(TICKER) + ERP)/2
- print(f"The growth rate of {TICKER} cycle 1 is approximately {revenue_growth_rate_cycle1_begin}")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement