Advertisement
samipote

Untitled

Sep 23rd, 2023
714
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.34 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. def get_revenue_growth_rate_cycle1_begin(ticker):
  153.     """Compute the revenue growth rate for cycle 1 begin for a given ticker using yfinance."""
  154.     # Get the total revenue for the TTM
  155.     ttm_revenue = get_ttm_total_revenue(ticker)
  156.     if not ttm_revenue:
  157.         return None # No revenue data available
  158.     # Get the total revenue for the previous year
  159.     stock = yf.Ticker(ticker)
  160.     income_statement = stock.financials
  161.     previous_year_revenue = float(income_statement.loc["Total Revenue"].iloc[1])
  162.     if not previous_year_revenue:
  163.         return None # No revenue data available
  164.     # Calculate the revenue growth rate as the percentage change from previous year to TTM
  165.     revenue_growth_rate = (ttm_revenue - previous_year_revenue) / previous_year_revenue
  166.     return revenue_growth_rate
  167.  
  168. # Define the URL for the API endpoint
  169. TICKER = "AAPL"
  170. ENDPOINT = "https://query1.finance.yahoo.com/v7/finance/download/{}"
  171. TICKER_SP500 = "^GSPC"
  172. DURATION = 10  # 10 years
  173. TODAY = int(datetime.now().timestamp())
  174. TEN_YEARS_AGO = int((datetime.now() - pd.DateOffset(years=DURATION)).timestamp())
  175. urlRFR = "https://query1.finance.yahoo.com/v7/finance/download/%5ETNX?period1=0&period2=9999999999&interval=1d&events=history&includeAdjustedClose=true"
  176. headers = {
  177.     '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'
  178. }
  179. responseRFR = requests.get(urlRFR, headers=headers)
  180.  
  181. if responseRFR.status_code == 200:
  182.     content = responseRFR.text
  183.     lines = content.strip().split("\n")
  184.    
  185.     if len(lines) < 2:  # Check if there's at least a header and one data line
  186.         print("Error: Not enough data lines in the response.")
  187.         exit()
  188.    
  189.     last_line = lines[-1]
  190.     values = last_line.split(",")
  191.    
  192.     if len(values) < 4:  # Check if there are enough values in the last line
  193.         print("Error: Not enough values in the data line.")
  194.         exit()
  195.  
  196.     RFR = float(values[3])
  197.     print(f"The 10-year treasury yield in USA is {RFR}%")
  198. else:
  199.     print(f"Error: The request failed with status code {responseRFR.status_code}. Response: {responseRFR.text}")
  200.  
  201.  
  202. # Fetch S&P 500 historical data
  203. urlSP500 = ENDPOINT.format(TICKER_SP500) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
  204. responseSP500 = requests.get(urlSP500, headers=headers)
  205. if responseSP500.status_code != 200:
  206.     raise Exception("Error fetching S&P 500 data.")
  207. dataSP500 = pd.read_csv(urlSP500, parse_dates=['Date'], index_col='Date')
  208.  
  209. urlCOMPANY = ENDPOINT.format(TICKER) + f"?period1={TEN_YEARS_AGO}&period2={TODAY}&interval=1d&events=history&includeAdjustedClose=true"
  210. responseCOMPANY = requests.get(urlCOMPANY, headers=headers)
  211. if responseCOMPANY.status_code != 200:
  212.     raise Exception("Error fetching company data.")
  213. dataCOMPANY = pd.read_csv(io.StringIO(responseCOMPANY.text), parse_dates=['Date'], index_col='Date')
  214.  
  215. historical_beta = calculate_rolling_beta(dataCOMPANY, dataSP500, 252)
  216.  
  217. # Calculate annualized return for S&P 500 over the given duration
  218. initial_value = dataSP500['Adj Close'].iloc[0]
  219. final_value = dataSP500['Adj Close'].iloc[-1]
  220. Rm = ((final_value / initial_value) ** (1/DURATION) - 1)
  221. risk_free_rate = RFR/100
  222. ERP = Rm - risk_free_rate
  223. print(f"Equity Risk Premium: {ERP*100:.2f}%")
  224.  
  225. # Use yfinance to get the market capitalization
  226. stock = yf.Ticker(TICKER)
  227. market_cap = stock.info['marketCap'] / 10**9  # Convert to billions
  228.  
  229. equity_value = market_cap
  230. print(f"The equity value (market cap) of {TICKER} is approximately ${market_cap:.2f} billion.")
  231.  
  232. # Use yfinance to get the debt values
  233. long_term_debt = stock.balance_sheet.loc["Long Term Debt"][0] if "Long Term Debt" in stock.balance_sheet.index else 0
  234. short_term_debt = stock.balance_sheet.loc["Short Term Debt"][0] if "Short Term Debt" in stock.balance_sheet.index else 0
  235.  
  236. # Calculate total debt
  237. debt_value = (long_term_debt + short_term_debt) / 10**9  # Convert to billions
  238. print(f"The total debt of {TICKER} is approximately ${debt_value:.2f} billion.")
  239.  
  240. # Use yfinance to get the cash and non-operating asset values
  241. 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
  242. # Convert to billions
  243. cash_and_non_operating_asset = cash_and_cash_equivalents / 10**9
  244. print(f"Cash and non-operating assets of {TICKER} is approximately ${cash_and_non_operating_asset:.2f} billion.")
  245.  
  246.  
  247. df_result = get_stocks_from_same_industry(TICKER)
  248. comparable_tickers = df_result['symbol'].tolist()
  249.  
  250. print(comparable_tickers)
  251. # Get unlevered betas for each comparable
  252. unlevered_betas = [get_unlevered_beta(ticker) for ticker in comparable_tickers]
  253. unlevered_betas = [beta for beta in unlevered_betas if beta is not None]  # Remove None values
  254. # Calculate the industry average unlevered beta
  255. industry_average_unlevered_beta = sum(unlevered_betas) / len(unlevered_betas)
  256.  
  257. # Estimate the terminal_unlevered_beta
  258. omega = 0.5  # Weight given to the company's current unlevered beta
  259. unlevered_beta = get_unlevered_beta(TICKER)
  260. terminal_unlevered_beta = omega * unlevered_beta + (1 - omega) * industry_average_unlevered_beta
  261.  
  262. print(f"The estimated unlevered beta is: {unlevered_beta:.4f}")
  263. print(f"The estimated terminal unlevered beta is: {terminal_unlevered_beta:.4f}")
  264.  
  265. # Linear regression model
  266. X = np.array(range(len(historical_beta))).reshape(-1, 1)
  267. y = historical_beta.values
  268. model = LinearRegression().fit(X, y)
  269. slope = model.coef_
  270. intercept = model.intercept_
  271.  
  272. # Calculate the intersection point with terminal beta using the equation of the line
  273. # y = mx + c; terminal_beta = slope*x + intercept
  274. intersection_point = (terminal_unlevered_beta - intercept) / slope
  275.  
  276. # Convert intersection_point to years (assuming your historical data is daily)
  277. intersection_in_years = intersection_point[0] / 252  # 252 trading days in a year
  278.  
  279. print(f"Expected year to converge to terminal beta: {intersection_in_years:.2f} years")
  280.  
  281. year_beta_begins_to_converge_to_terminal_beta = intersection_in_years
  282.  
  283. # Calculate the effective tax rate
  284. income_statement = stock.financials
  285. pretax_income = float(income_statement.loc["Pretax Income"].iloc[0])
  286. income_tax_expense = float(income_statement.loc["Tax Provision"].iloc[0])
  287. tax_rate = income_tax_expense / pretax_income
  288.  
  289. print(f"Current Effective Tax Rate: {tax_rate:.2%}")
  290.  
  291. current_effective_tax_rate = tax_rate
  292.  
  293. current_pretax_cost_of_debt = get_pretax_cost_of_debt(TICKER)
  294.  
  295. print(f"Current Pretax Cost of Debt: {current_pretax_cost_of_debt:.2%}")
  296.  
  297. # Get pre-tax cost of debt for each comparable
  298. pretax_costs_of_debt = [get_pretax_cost_of_debt(ticker) for ticker in comparable_tickers]
  299. pretax_costs_of_debt = [cost for cost in pretax_costs_of_debt if cost is not None]
  300.  
  301. # Calculate the industry average pre-tax cost of debt
  302. industry_average_pretax_cost_of_debt = sum(pretax_costs_of_debt) / len(pretax_costs_of_debt)
  303.  
  304. # Estimate the terminal_pre_tax_cost_of_debt
  305. omega = 0.5  # Weight given to the company's current pre-tax cost of debt
  306. terminal_pretax_cost_of_debt = omega * current_pretax_cost_of_debt + (1 - omega) * industry_average_pretax_cost_of_debt
  307.  
  308. print(f"The estimated terminal pre-tax cost of debt is: {terminal_pretax_cost_of_debt:.2%}")
  309.  
  310. year_cost_of_debt_begins_to_converge_to_terminal_cost_of_debt = get_year_cost_of_debt_converges(TICKER, comparable_tickers)
  311.  
  312. 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")
  313.  
  314. marginal_tax_rate = get_marginal_tax_rate(TICKER)
  315.  
  316. print(f"Current Marginal Tax Rate: {marginal_tax_rate:.2%}")
  317.  
  318. year_effective_tax_rate_begin_to_converge_marginal_tax_rate = 1
  319.  
  320. revenue_base = get_ttm_total_revenue(TICKER)
  321.  
  322. print(f"The total revenue of {TICKER} is approximately ${revenue_base}")
  323.  
  324. revenue_growth_rate_cycle1_begin = (get_revenue_growth_rate_cycle1_begin(TICKER) + ERP)/2
  325.  
  326. 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