Advertisement
samipote

Untitled

Sep 23rd, 2023
736
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.13 KB | None | 0 0
  1. def get_sector_yfinance(ticker_symbol):
  2.     """Fetch the sector for a given ticker using yfinance."""
  3.     ticker = yf.Ticker(ticker_symbol)
  4.     info = ticker.info
  5.     return info.get('sector', None)
  6.  
  7. def get_industry_yfinance(ticker_symbol):
  8.     """Fetch the sector for a given ticker using yfinance."""
  9.     ticker = yf.Ticker(ticker_symbol)
  10.     info = ticker.info
  11.     return info.get('sector', None)
  12.  
  13. def get_stocks_from_same_industry(ticker_symbol):
  14.     """Fetch stocks from the same industry as the provided ticker."""
  15.     # Get the sector for the given ticker using yfinance
  16.     sector = get_industry_yfinance(ticker_symbol)
  17.  
  18.     if not sector:
  19.         print(f"Could not find industry for {ticker_symbol}")
  20.         return None
  21.  
  22.     # Initialize the screener from yahooquery
  23.     s = Screener()
  24.  
  25.     # Using sector to screen stocks
  26.     screen_key = f"ms_{sector.lower()}"
  27.    
  28.     if screen_key not in s.available_screeners:
  29.         print(f"No predefined screener available for sector: {sector}")
  30.         return None
  31.  
  32.     data = s.get_screeners(screen_key)
  33.  
  34.     # Convert data to DataFrame for easier handling
  35.     df = pd.DataFrame(data[screen_key]['quotes'])
  36.    
  37.     return df
  38.  
  39. def calculate_rolling_beta(stock_data, market_data, window_size):
  40.     stock_returns = stock_data['Adj Close'].pct_change().dropna()
  41.     market_returns = market_data['Adj Close'].pct_change().dropna()
  42.  
  43.     rolling_cov = stock_returns.rolling(window=window_size).cov(market_returns)
  44.     rolling_var = market_returns.rolling(window=window_size).var()
  45.  
  46.     rolling_beta = rolling_cov / rolling_var
  47.     return rolling_beta.dropna()
  48.  
  49. def get_unlevered_beta(ticker):
  50.     stock = yf.Ticker(ticker)
  51.  
  52.     # Get levered beta
  53.     levered_beta = stock.info['beta']
  54.     if not levered_beta:
  55.         return None
  56.  
  57.     # Get debt and equity values
  58.     market_cap = stock.info['marketCap'] / 10**9
  59.     long_term_debt = stock.balance_sheet.loc["Long Term Debt"][0] / 10**9 if "Long Term Debt" in stock.balance_sheet.index else 0
  60.     short_term_debt = stock.balance_sheet.loc["Short Term Debt"][0] / 10**9 if "Short Term Debt" in stock.balance_sheet.index else 0
  61.     debt_value = long_term_debt + short_term_debt
  62.     equity_value = market_cap
  63.  
  64.     # Calculate the effective tax rate
  65.     income_statement = stock.financials
  66.     pretax_income = float(income_statement.loc["Pretax Income"].iloc[0])
  67.     income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
  68.     effective_tax_rate = income_tax_expense / pretax_income
  69.     T = effective_tax_rate
  70.  
  71.     # Calculate unlevered beta
  72.     return levered_beta / (1 + ((1 - T) * (debt_value / equity_value)))
  73.  
  74.  
  75. def get_pretax_cost_of_debt(ticker):
  76.     """Compute the pre-tax cost of debt for a given ticker."""
  77.     stock = yf.Ticker(ticker)
  78.  
  79.     income_statement = stock.financials
  80.     balance_sheet = stock.balance_sheet
  81.  
  82.     # Interest Expense from the income statement
  83.     interest_expense = float(income_statement.loc["Interest Expense"].iloc[0]) if "Interest Expense" in income_statement.index else 0
  84.  
  85.     # Average Total Debt calculation
  86.     current_long_term_debt = float(balance_sheet.loc["Long Term Debt"].iloc[0]) if "Long Term Debt" in balance_sheet.index else 0
  87.     previous_long_term_debt = float(balance_sheet.loc["Long Term Debt"].iloc[1]) if "Long Term Debt" in balance_sheet.index else 0
  88.  
  89.     current_short_term_debt = float(balance_sheet.loc["Short Term Debt"].iloc[0]) if "Short Term Debt" in balance_sheet.index else 0
  90.     previous_short_term_debt = float(balance_sheet.loc["Short Term Debt"].iloc[1]) if "Short Term Debt" in balance_sheet.index else 0
  91.  
  92.     average_debt = (current_long_term_debt + current_short_term_debt + previous_long_term_debt + previous_short_term_debt) / 2
  93.  
  94.     # Calculate the pre-tax cost of debt
  95.     if average_debt == 0:
  96.         return 0
  97.     else:
  98.         return interest_expense / average_debt
  99.  
  100. def get_year_cost_of_debt_converges(ticker, comparable_tickers):
  101.   """Compute the year when the cost of debt converges to the industry average."""
  102.   # Get the current pre-tax cost of debt for the given ticker
  103.   DURATION = 5
  104.   current_pretax_cost_of_debt = get_pretax_cost_of_debt(ticker)
  105.   if not current_pretax_cost_of_debt:
  106.     return None # No cost of debt available
  107.  
  108.   # Get the pre-tax cost of debt for each comparable ticker
  109.   pretax_costs_of_debt = [get_pretax_cost_of_debt(ticker) for ticker in comparable_tickers]
  110.   pretax_costs_of_debt = [cost for cost in pretax_costs_of_debt if cost is not None] # Remove None values
  111.  
  112.   # Calculate the industry average pre-tax cost of debt
  113.   industry_average_pretax_cost_of_debt = sum(pretax_costs_of_debt) / len(pretax_costs_of_debt)
  114.  
  115.   # Estimate the terminal pre-tax cost of debt using a weighted average
  116.   omega = 0.5 # Weight given to the company's current pre-tax cost of debt
  117.   terminal_pretax_cost_of_debt = omega * current_pretax_cost_of_debt + (1 - omega) * industry_average_pretax_cost_of_debt
  118.  
  119.   # Assume a linear convergence from the current to the terminal cost of debt
  120.   # 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
  121.   # Solve for x when y equals the terminal cost of debt
  122.   slope = (terminal_pretax_cost_of_debt - current_pretax_cost_of_debt) / DURATION # DURATION is the number of years for valuation
  123.   intercept = current_pretax_cost_of_debt
  124.   year_cost_of_debt_converges = (terminal_pretax_cost_of_debt - intercept) / slope
  125.  
  126.   return year_cost_of_debt_converges
  127.  
  128. def get_marginal_tax_rate(ticker):
  129.     """Compute the marginal tax rate for a given ticker using yfinance."""
  130.     # Get the income statement from yfinance
  131.     stock = yf.Ticker(ticker)
  132.     income_statement = stock.financials
  133.  
  134.     # Get the income before tax and income tax expense from the income statement
  135.     income_before_tax = float(income_statement.loc["Pretax Income"].iloc[0])
  136.     income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
  137.  
  138.     # Calculate the marginal tax rate as the ratio of income tax expense to income before tax
  139.     marginal_tax_rate = income_tax_expense / income_before_tax
  140.  
  141.     # Return the marginal tax rate as a percentage
  142.     return marginal_tax_rate
  143.  
  144. def get_ttm_total_revenue(ticker_symbol):
  145.     ticker = yf.Ticker(ticker_symbol)
  146.    
  147.     # Fetch the total revenue for the TTM
  148.     ttm_revenue = ticker.info['totalRevenue']
  149.    
  150.     return ttm_revenue
  151.  
  152. # Define the URL for the API endpoint
  153. TICKER = "AAPL"
  154. ENDPOINT = "https://query1.finance.yahoo.com/v7/finance/download/{}"
  155. TICKER_SP500 = "^GSPC"
  156. DURATION = 10  # 10 years
  157. TODAY = int(datetime.now().timestamp())
  158. TEN_YEARS_AGO = int((datetime.now() - pd.DateOffset(years=DURATION)).timestamp())
  159. urlRFR = "https://query1.finance.yahoo.com/v7/finance/download/%5ETNX?period1=0&period2=9999999999&interval=1d&events=history&includeAdjustedClose=true"
  160. headers = {
  161.     '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'
  162. }
  163. responseRFR = requests.get(urlRFR, headers=headers)
  164.  
  165. if responseRFR.status_code == 200:
  166.     content = responseRFR.text
  167.     lines = content.strip().split("\n")
  168.    
  169.     if len(lines) < 2:  # Check if there's at least a header and one data line
  170.         print("Error: Not enough data lines in the response.")
  171.         exit()
  172.    
  173.     last_line = lines[-1]
  174.     values = last_line.split(",")
  175.    
  176.     if len(values) < 4:  # Check if there are enough values in the last line
  177.         print("Error: Not enough values in the data line.")
  178.         exit()
  179.  
  180.     RFR = float(values[3])
  181.     print(f"The 10-year treasury yield in USA is {RFR}%")
  182. else:
  183.     print(f"Error: The request failed with status code {responseRFR.status_code}. Response: {responseRFR.text}")
  184.  
  185.  
  186. # Fetch S&P 500 historical data
  187. urlSP500 = ENDPOINT.format(TICKER_SP500) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
  188. responseSP500 = requests.get(urlSP500, headers=headers)
  189. if responseSP500.status_code != 200:
  190.     raise Exception("Error fetching S&P 500 data.")
  191. dataSP500 = pd.read_csv(urlSP500, parse_dates=['Date'], index_col='Date')
  192.  
  193. urlCOMPANY = ENDPOINT.format(TICKER) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
  194. responseCOMPANY = requests.get(urlCOMPANY, headers=headers)
  195. if responseCOMPANY.status_code != 200:
  196.     raise Exception("Error fetching company data.")
  197. dataCOMPANY = pd.read_csv(io.StringIO(responseCOMPANY.text), parse_dates=['Date'], index_col='Date')
  198.  
  199. historical_beta = calculate_rolling_beta(dataCOMPANY, dataSP500, 252)
  200.  
  201. # Calculate annualized return for S&P 500 over the given duration
  202. initial_value = dataSP500['Adj Close'].iloc[0]
  203. final_value = dataSP500['Adj Close'].iloc[-1]
  204. Rm = ((final_value / initial_value) ** (1/DURATION) - 1)
  205. risk_free_rate = RFR/100
  206. ERP = Rm - risk_free_rate
  207. print(f"Equity Risk Premium: {ERP*100:.2f}%")
  208.  
  209. # Use yfinance to get the market capitalization
  210. stock = yf.Ticker(TICKER)
  211. market_cap = stock.info['marketCap'] / 10**9  # Convert to billions
  212.  
  213. equity_value = market_cap
  214. print(f"The equity value (market cap) of {TICKER} is approximately ${market_cap:.2f} billion.")
  215.  
  216. # Use yfinance to get the debt values
  217. long_term_debt = stock.balance_sheet.loc["Long Term Debt"][0] if "Long Term Debt" in stock.balance_sheet.index else 0
  218. short_term_debt = stock.balance_sheet.loc["Short Term Debt"][0] if "Short Term Debt" in stock.balance_sheet.index else 0
  219.  
  220. # Calculate total debt
  221. debt_value = (long_term_debt + short_term_debt) / 10**9  # Convert to billions
  222. print(f"The total debt of {TICKER} is approximately ${debt_value:.2f} billion.")
  223.  
  224. # Use yfinance to get the cash and non-operating asset values
  225. 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
  226. # Convert to billions
  227. cash_and_non_operating_asset = cash_and_cash_equivalents / 10**9
  228. print(f"Cash and non-operating assets of {TICKER} is approximately ${cash_and_non_operating_asset:.2f} billion.")
  229.  
  230.  
  231. df_result = get_stocks_from_same_industry(TICKER)
  232. comparable_tickers = df_result['symbol'].tolist()
  233.  
  234. print(comparable_tickers)
  235. # Get unlevered betas for each comparable
  236. unlevered_betas = [get_unlevered_beta(ticker) for ticker in comparable_tickers]
  237. unlevered_betas = [beta for beta in unlevered_betas if beta is not None]  # Remove None values
  238. # Calculate the industry average unlevered beta
  239. industry_average_unlevered_beta = sum(unlevered_betas) / len(unlevered_betas)
  240.  
  241. # Estimate the terminal_unlevered_beta
  242. omega = 0.5  # Weight given to the company's current unlevered beta
  243. unlevered_beta = get_unlevered_beta(TICKER)
  244. terminal_unlevered_beta = omega * unlevered_beta + (1 - omega) * industry_average_unlevered_beta
  245.  
  246. print(f"The estimated unlevered beta is: {unlevered_beta:.4f}")
  247. print(f"The estimated terminal unlevered beta is: {terminal_unlevered_beta:.4f}")
  248.  
  249. # Linear regression model
  250. X = np.array(range(len(historical_beta))).reshape(-1, 1)
  251. y = historical_beta.values
  252. model = LinearRegression().fit(X, y)
  253. slope = model.coef_
  254. intercept = model.intercept_
  255.  
  256. # Calculate the intersection point with terminal beta using the equation of the line
  257. # y = mx + c; terminal_beta = slope*x + intercept
  258. intersection_point = (terminal_unlevered_beta - intercept) / slope
  259.  
  260. # Convert intersection_point to years (assuming your historical data is daily)
  261. intersection_in_years = intersection_point[0] / 252  # 252 trading days in a year
  262.  
  263. print(f"Expected year to converge to terminal beta: {intersection_in_years:.2f} years")
  264.  
  265. year_beta_begins_to_converge_to_terminal_beta = intersection_in_years
  266.  
  267. # Calculate the effective tax rate
  268. income_statement = stock.financials
  269. pretax_income = float(income_statement.loc["Pretax Income"].iloc[0])
  270. income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
  271. tax_rate = income_tax_expense / pretax_income
  272.  
  273. print(f"Current Effective Tax Rate: {tax_rate:.2%}")
  274.  
  275. current_effective_tax_rate = tax_rate
  276.  
  277. current_pretax_cost_of_debt = get_pretax_cost_of_debt(TICKER)
  278.  
  279. print(f"Current Pretax Cost of Debt: {current_pretax_cost_of_debt:.2%}")
  280.  
  281. # Get pre-tax cost of debt for each comparable
  282. pretax_costs_of_debt = [get_pretax_cost_of_debt(ticker) for ticker in comparable_tickers]
  283. pretax_costs_of_debt = [cost for cost in pretax_costs_of_debt if cost is not None]
  284.  
  285. # Calculate the industry average pre-tax cost of debt
  286. industry_average_pretax_cost_of_debt = sum(pretax_costs_of_debt) / len(pretax_costs_of_debt)
  287.  
  288. # Estimate the terminal_pre_tax_cost_of_debt
  289. omega = 0.5  # Weight given to the company's current pre-tax cost of debt
  290. terminal_pretax_cost_of_debt = omega * current_pretax_cost_of_debt + (1 - omega) * industry_average_pretax_cost_of_debt
  291.  
  292. print(f"The estimated terminal pre-tax cost of debt is: {terminal_pretax_cost_of_debt:.2%}")
  293.  
  294. year_cost_of_debt_begins_to_converge_to_terminal_cost_of_debt = get_year_cost_of_debt_converges(TICKER, comparable_tickers)
  295.  
  296. 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")
  297.  
  298. marginal_tax_rate = get_marginal_tax_rate(TICKER)
  299.  
  300. print(f"Current Marginal Tax Rate: {marginal_tax_rate:.2%}")
  301.  
  302. year_effective_tax_rate_begin_to_converge_marginal_tax_rate = 1
  303.  
  304. revenue_base = get_ttm_total_revenue(TICKER)
  305.  
  306. print(f"The total revenue of {TICKER} is approximately ${revenue_base}")
  307.  
  308. base_case_valuation = valuator_multi_phase(
  309.             risk_free_rate,
  310.             ERP,
  311.             equity_value,
  312.             debt_value,
  313.             cash_and_non_operating_asset,
  314.             unlevered_beta,
  315.             terminal_unlevered_beta,
  316.             year_beta_begins_to_converge_to_terminal_beta,
  317.             current_pretax_cost_of_debt,
  318.             terminal_pretax_cost_of_debt,
  319.             year_cost_of_debt_begins_to_converge_to_terminal_cost_of_debt,
  320.             current_effective_tax_rate,
  321.             marginal_tax_rate,
  322.             year_effective_tax_rate_begin_to_converge_marginal_tax_rate,
  323.              revenue_base,
  324.              revenue_growth_rate_cycle1_begin = .11,
  325.              revenue_growth_rate_cycle1_end = .16,
  326.              length_of_cylcle1 = 6,
  327.              revenue_growth_rate_cycle2_begin = .14,
  328.              revenue_growth_rate_cycle2_end = .09,
  329.              length_of_cylcle2=6,
  330.              revenue_growth_rate_cycle3_begin =.08,
  331.              revenue_growth_rate_cycle3_end =.04,
  332.              length_of_cylcle3=6,
  333.             revenue_convergance_periods_cycle1= 1,
  334.             revenue_convergance_periods_cycle2=1,
  335.             revenue_convergance_periods_cycle3=1,
  336.             current_sales_to_capital_ratio = 1.7,
  337.             terminal_sales_to_capital_ratio = 1.3,
  338.             year_sales_to_capital_begins_to_converge_to_terminal_sales_to_capital = 1,
  339.             current_operating_margin = .15,
  340.             terminal_operating_margin = .175,
  341.             year_operating_margin_begins_to_converge_to_terminal_operating_margin = 1,
  342.             additional_return_on_cost_of_capital_in_perpetuity= 0.02,
  343.             asset_liquidation_during_negative_growth=0,
  344.             current_invested_capital = 6.062)
  345. point_estimate_describer(base_case_valuation)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement