# Load required libraries
library(httr)
library(highcharter)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
## Highcharts (www.highcharts.com) is a Highsoft software product which is
## not free for commercial and Governmental use
library(quantmod)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: TTR
library(scales)
library(DT)
# Set highcharter options
hcoptslang <- getOption("highcharter.lang")
hcoptslang$thousandsSep <- ","
options(highcharter.lang = hcoptslang)
# ********************************************************************************************
# Function: Get Financials (Income Statement, Cash Flow, Balance Sheet)
# ********************************************************************************************
getFins <- function(symbol, AQ, FS){
URL <- paste0('https://finviz.com/api/statement.ashx?t=', symbol, '&so=F&s=', FS, AQ)
headers <- c(
'Host' = 'finviz.com',
'User-Agent' = 'Mozilla/5.0',
'Accept' = '*/*',
'Referer' = paste0('https://finviz.com/quote.ashx?t=', symbol),
'Connection' = 'keep-alive'
)
response <- httr::GET(url = URL, add_headers(headers))
content_data <- httr::content(response)
if (is.null(content_data$data)) stop("No financial data found for ", symbol)
tbl <- unlist(content_data$data)
if (length(tbl) == 0) stop("Financial data is empty for ", symbol)
row_names <- gsub("1", "", unique(names(tbl)[seq(1, length(tbl), 8)]))
df <- matrix(tbl, ncol = 8, byrow = TRUE)
df <- data.frame(df, row.names = row_names)
colnames(df) <- df[1,]
df <- df[-1,]
df_numeric <- data.frame(apply(df, 2, function(x) as.numeric(gsub(",", "", x))), row.names = rownames(df))
colnames(df_numeric) <- colnames(df)
df_numeric <- df_numeric[rowSums(is.na(df_numeric)) != ncol(df_numeric), ]
return(df_numeric)
}
# ********************************************************************************************
# Function: Plot Financial Trends
# ********************************************************************************************
plotTrends <- function(ticker, metric, data_source) {
data_selected <- subset(data_source, row.names(data_source) == metric)
if (nrow(data_selected) == 0) stop("No data found for ", metric)
data_selected <- rev(data_selected)
data_selected <- as.data.frame(t(data_selected))
data_selected$date <- row.names(data_selected)
data_selected <- data.frame(
date = format(as.Date(data_selected$date, "%m/%d/%Y"), "%b %d '%y"),
value = data_selected[,1]
)
data_selected$pct_change <- c(NA, diff(data_selected$value) / head(data_selected$value, -1))
data_selected$yoy_change <- c(rep(NA, 4), diff(data_selected$value, lag = 4) / head(data_selected$value, -4))
data_selected %>%
hchart('column', hcaes(x = 'date', y = 'value'), name = "Value") %>%
hc_title(text = paste0(ticker, ": ", metric), align = "center") %>%
hc_yAxis_multiples(
list(title = list(text = "Value"), opposite = FALSE),
list(showLastLabel = FALSE, opposite = TRUE, title = list(text = "% Change"), min = -100, max = 100)
) %>%
hc_add_series(round(data_selected$yoy_change * 100, 2), yAxis = 1, name = "YoY % Change") %>%
hc_add_series(round(data_selected$pct_change * 100, 2), yAxis = 1, name = "QoQ % Change")
}
# ********************************************************************************************
# Function: Convert Balance Sheet to Percentages
# ********************************************************************************************
pctBS <- function(BS) {
rownames(BS)[is.na(rownames(BS))] <- paste0("Row_", seq_len(sum(is.na(rownames(BS)))))
BS <- BS[rowSums(is.na(BS)) != ncol(BS), ]
asset_index <- which(rownames(BS) == "Total Assets")
liability_index <- which(rownames(BS) == "Total Liabilities")
equity_index <- which(rownames(BS) == "Total Equity")
if (length(asset_index) == 0 | length(liability_index) == 0 | length(equity_index) == 0) {
stop("Missing key financial values (Assets, Liabilities, Equity).")
}
BS_numeric <- data.frame(lapply(BS, function(x) as.numeric(gsub(",", "", x))), row.names = rownames(BS))
asset_divisor <- as.numeric(BS_numeric[asset_index, ])
liability_divisor <- as.numeric(BS_numeric[liability_index, ])
equity_divisor <- as.numeric(BS_numeric[equity_index, ])
asset_divisor[asset_divisor == 0] <- NA
liability_divisor[liability_divisor == 0] <- NA
equity_divisor[equity_divisor == 0] <- NA
total_assets <- sweep(BS_numeric[1:asset_index, ], 2, asset_divisor, "/")
total_liabilities <- sweep(BS_numeric[(asset_index+1):liability_index, ], 2, liability_divisor, "/")
total_equity <- sweep(BS_numeric[(liability_index+1):equity_index, ], 2, equity_divisor, "/")
total_assets <- apply(total_assets, 2, scales::percent, accuracy = 0.01, na.rm = TRUE)
total_liabilities <- apply(total_liabilities, 2, scales::percent, accuracy = 0.01, na.rm = TRUE)
total_equity <- apply(total_equity, 2, scales::percent, accuracy = 0.01, na.rm = TRUE)
BS_pct <- rbind(data.frame(total_assets), data.frame(total_liabilities), data.frame(total_equity))
rownames(BS_pct) <- c(rownames(BS)[1:asset_index], rownames(BS)[(asset_index+1):liability_index], rownames(BS)[(liability_index+1):equity_index])
return(BS_pct)
}
# ********************************************************************************************
# Execution: Get AAPL Financials & Plot Trends
# ********************************************************************************************
ticker <- "AAPL"
# Fetch Financial Statements
AAPL_IS <- getFins(ticker, "A", "I") # Income Statement (Annual)
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
## Warning in FUN(newX[, i], ...): NAs introduced by coercion
AAPL_BS <- getFins(ticker, "A", "B") # Balance Sheet (Annual)
# Plot Key Financial Trends
plotTrends(ticker, "Total Revenue", AAPL_IS)
plotTrends(ticker, "Net Income", AAPL_IS)
plotTrends(ticker, "Total Liabilities", AAPL_BS)
# Convert Balance Sheet to Percentages
AAPL_BS_pct <- pctBS(AAPL_BS)
# Display Data Table
datatable(AAPL_BS_pct, options = list(pageLength = 10, autoWidth = TRUE))