I'm currently attempting to learn from this video, specifically at 8:40: EAD, PD and LGD Modeling for EL Estimation - YouTube
Here is my code so far:
suppressWarnings(suppressMessages({
library(tidytable)
library(httr)
library(jsonlite)
library(ggplot2)
library(lubridate)
library(tidyquant)
options("getSymbols.warning4.0"=FALSE)
options("getSymbols.yahoo.warning"=FALSE)
}))
options(scipen = 999)
### Get balance sheet and income statement data
api_key = '' # API for financialmodelingprep.com
stock_ticker = 'INTC' # pick AMD, NVDA, INTC, etc.
url = 'https://financialmodelingprep.com/api/v3/balance-sheet-statement/'
api = GET(paste0(url, stock_ticker, '?apikey=', api_key))
df_income_statement = fromJSON(rawToChar(api$content)) |>
select(date, totalCurrentAssets, totalCurrentLiabilities, totalNonCurrentLiabilities) |> # need totalAssets?
mutate(date = as.Date(date))
### Get stock price data
df_stock_price = getSymbols(Symbols = stock_ticker,
src= 'yahoo',
warnings = FALSE,
auto.assign = F) |>
as.data.frame() |>
tibble::rownames_to_column('date') |>
mutate(date = as.Date(date))
### Parameter values
# firm value
p_knot = df_income_statement |>
filter(date == min(date)) |>
pull(totalCurrentAssets)
p_n = df_income_statement |>
filter(date == max(date)) |>
pull(totalCurrentAssets)
n_max = df_income_statement |>
pull(date) |>
max()
n_min = df_income_statement |>
pull(date) |>
min()
n_diff = n_max - n_min
n = time_length(n_diff, 'years')
# expected return -- assuming past performance is future performance
mu = -((p_knot/p_n)^(1/n) - 1) * (p_knot/p_n)^(-1/n)
# volatility
sigma = df_stock_price |>
pull(paste0(stock_ticker, '.Close')) |>
sd()
# short term liability
STL = df_income_statement |>
filter(date == max(date)) |>
pull(totalCurrentLiabilities)
STL_max = STL |> max()
# long term liability
LTL = df_income_statement |>
filter(date == max(date)) |>
pull(totalNonCurrentLiabilities)
LTL_max = LTL |> max()
#
default_point = STL_max + (LTL_max/2)
# probability default
distance_default_numerator = log(p_n / default_point) + (mu - sigma^2 / 2) * 1 # T = 1
distance_default_denominator = sigma * 1 # T = 1
# fraction
distance_to_default = distance_default_numerator / distance_default_denominator
# PD = NORMDIST(-DD)
probability_default = pnorm(-distance_to_default)
The problem is, with all companies I tried (as well as few other columns that seem to fit the purposes), probability_default
will always result in 1, while the components of the probability_default
fraction are above 1 when (I think) they shouldn't be. This leads me to believe that I'm using the wrong data/columns. Which ones am I supposed to use? Or where can I get such data for free?