Now that I’ve found the reasons to what sets Dropbox apart, I want to find the answer to “Are Dropbox shares currently undervalued?” by running relative valuations from revenue multiples and intrinsic valuation on a discounted cash flow model.
Getting Financial Data
All of the financial data is coming from S&P Capital IQ, which they get directly from the SEC filings. I downloaded them into two separate Excel Workbooks which can be done easily on Capital IQ. One workbook for annual statements and the other for quarterly, and each was loaded into R using the xlsx
package.
The end result in R was two lists, one for annual and one for quarterly. Each list contained 3 data frames for the income statement, balance sheet, and cash flow statement. See below for the code and the lists.
# Ticker
ticker <- "DBX"
# ANNUAL STATEMENTS
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Create a list and statement names
annual_dbx <- list()
statement_names <- c("income_statement","balance_sheet","cashflow")
# Read each excel sheet from the workbook into a dataframe...
for(i in 1:length(statement_names)){
annual_dbx[[i]] <- xlsx::read.xlsx("/Users/jagvill/DBX.xlsx",sheetIndex = i,startRow = 1,colClasses = c("character",rep("numeric",6)),stringsAsFactors=FALSE) %>% na.omit()
}
names(annual_dbx) <- statement_names
# QUARTERLY STATEMENTS
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Create a list and statement names
qtr_dbx <- list()
# Read each excel sheet from the workbook into a dataframe...
for(i in 1:length(statement_names)){
qtr_dbx[[i]] <- xlsx::read.xlsx("/Users/jagvill/DBX_qtr.xlsx",sheetIndex = i,startRow = 1,colClasses = c("character",rep("numeric",6)),stringsAsFactors=FALSE) %>% na.omit()
}
names(qtr_dbx) <- statement_names
# Clean up the white spacing on each of the statements line items from each list
for(i in 1:2){ # First item in the list are the annual statements, and the second is quarterly
if(i == 1){
for(i in 1:3){ # Annual
annual_dbx[[i]][,1] <- stringr::str_trim(annual_dbx[[i]][,1])
}
} else{
for(i in 1:3){ # Quarterly
qtr_dbx[[i]][,1] <- stringr::str_trim(qtr_dbx[[i]][,1])
}
}
}
head(qtr_dbx)
## $income_statement
## For.the.Fiscal.Period.Ending. Mar.31.2018 Jun.30.2018 Sep.30.2018
## 1 Revenues 316.30 339.20 360.30
## 2 Cost of Revenues -120.60 -89.50 -90.20
## 3 Sales and Marketing -157.00 -87.40 -95.00
## 4 General and Administrative -126.10 -49.80 -50.80
## 5 Research and Development -378.50 -119.70 -133.20
## 7 Other Income/expense-net 3.40 2.20 0.50
## 9 Earnings before Taxes -463.70 -3.00 -6.00
## 10 Provision for Income Tax -1.80 -1.10 0.20
## 11 Net Income (Loss) -465.50 -4.10 -5.80
## 13 Gross Profit/loss 195.70 249.70 270.10
## 14 Operating Income (Loss) -465.90 -7.20 -8.90
## 15 Basic EPS - Continuing Operations -2.13 -0.01 -0.01
## Dec.31.2018 Mar.31.2019 Jun.30.2019
## 1 375.90 385.60 401.50
## 2 -94.40 -98.40 -102.90
## 3 -100.20 -101.50 -107.30
## 4 -56.50 -57.00 -62.90
## 5 -136.80 -150.00 -162.40
## 7 0.70 4.20 10.00
## 9 -7.40 -13.40 -20.80
## 10 -2.10 5.70 -0.60
## 11 -9.50 -7.70 -21.40
## 13 281.50 287.20 298.60
## 14 -12.00 -21.30 -34.00
## 15 -0.02 -0.02 -0.05
##
## $balance_sheet
## Balance.Sheet.as.of.. X43190 X43281 X43373
## 1 Cash and Cash Equivalents 665.3 504.1 536.2
## 2 Short-term Investments 180.7 477.7 502.9
## 3 Trade and Other Receivables Net 26.2 31.2 28.6
## 4 Prepaid Expenses and Other Current Assets 57.7 86.8 96.0
## 5 Total Current Assets 929.9 1099.8 1163.7
## 6 Property and Equipment, net 345.6 330.8 295.9
## 7 Goodwill 99.0 97.8 98.0
## 8 Intangible Assets, Net 17.9 16.3 15.2
## 9 Other Assets 46.3 57.7 50.3
## 11 Total Assets 1438.7 1602.4 1623.1
## 12 Accounts Payable 29.4 24.0 27.9
## 13 Accrued Compensation and Benefits 36.2 45.1 64.2
## 14 Accrued and Other Current Liabilities 143.1 172.3 163.2
## 16 Deferred Revenue 444.6 464.8 479.3
## 19 Total Current Liabilities 746.1 793.3 815.1
## 21 Other Non-current Liabilities 36.3 31.5 8.8
## 25 Additional Paid in Capital 2104.9 2248.4 2285.0
## 26 Accumulated Deficit -1600.4 -1619.4 -1643.5
## 27 Accumulated Other Comprehensive Income (Loss) 5.7 1.9 1.9
## 28 Total Shareholders Equity 510.2 630.9 643.4
## 29 Total Liabilities & Shareholders Equity 1438.7 1602.4 1623.1
## X43465 X43555 X43646
## 1 519.3 359.2 343.6
## 2 570.0 556.0 629.2
## 3 28.6 34.1 37.6
## 4 92.3 58.3 57.3
## 5 1210.2 1007.6 1067.7
## 6 310.6 340.9 369.3
## 7 96.5 230.4 230.9
## 8 14.7 57.4 53.7
## 9 62.1 61.9 67.6
## 11 1694.1 2128.6 2364.9
## 12 33.3 27.4 31.8
## 13 80.9 36.4 57.4
## 14 164.5 148.8 149.4
## 16 485.0 508.4 517.3
## 19 837.5 865.8 903.1
## 21 8.9 9.7 10.6
## 25 2337.5 2377.8 2428.4
## 26 -1659.5 -1674.7 -1700.1
## 27 -1.2 1.8 1.9
## 28 676.8 704.9 730.2
## 29 1694.1 2128.6 2364.9
##
## $cashflow
## For.the.Fiscal.Period.Ending.
## 1 Net Income
## 2 Depreciation and Amortization
## 3 Amortization of Deferred Commissions
## 4 Stock based Compensation
## 5 Others
## 6 Other Assets
## 8 Trade and Other Receivables, Net
## 9 Accounts Payable
## 10 Deferred Revenue
## 11 Prepaid Expenses and Other Current Assets
## 12 Accrued Compensation and Benefits
## 13 Accrued and Other Current Liabilities
## 17 Cash Flow from Operating Activities
## 19 Capital Expenditures
## 23 Purchases of Short-term Investment
## 27 Cash Flow from Investing Activities
## 28 Others
## 32 Proceeds from Issuance of Common Stock, Net of Repurchases
## 34 Shares Repurchased for Tax Withholdings on Release of Restricted Stock
## 37 Cash Flow from Financing Activities
## 38 Foreign Exchange Rate Effect on Cash and Cash Equivalents
## 39 Cash Flow Net Changes in Cash
## X3.months.Mar.31.2018 X6.months.Jun.30.2018 X9.months.Sep.30.2018
## 1 -465.5 -469.6 -475.4
## 2 35.9 75.9 121.6
## 3 2.4 5.3 8.5
## 4 486.5 541.6 596.6
## 5 -0.6 -1.1 -0.9
## 6 -5.7 -17.5 -10.4
## 8 3.6 -1.9 0.4
## 9 -2.8 -8.5 -3.9
## 10 26.7 46.4 60.8
## 11 -1.5 -33.9 -47.3
## 12 -26.2 -10.9 7.2
## 13 8.8 44.5 40.6
## 17 61.8 173.7 301.7
## 19 -9.9 -19.6 -27.6
## 23 -180.8 -495.9 -664.3
## 27 -193.1 -497.6 -529.0
## 28 -2.1 -4.1 -6.1
## 32 0.8 1.0 9.8
## 34 -241.2 -282.4 -326.7
## 37 365.0 399.4 335.0
## 38 1.6 -1.4 -1.5
## 39 235.3 74.1 106.2
## X12.months.Dec.31.2018 X3.months.Mar.31.2019 X6.months.Jun.30.2019
## 1 -484.9 -7.7 -29.1
## 2 166.8 45.8 91.9
## 3 12.1 3.9 8.1
## 4 650.1 55.6 123.7
## 5 -1.9 -4.4 -7.6
## 6 -11.2 11.2 26.2
## 8 0.1 -5.1 -8.5
## 9 -1.7 -5.2 -1.8
## 10 66.4 18.6 28.0
## 11 -47.9 -14.2 -18.5
## 12 25.0 -45.9 -24.8
## 13 40.3 10.0 10.5
## 17 425.4 63.2 192.0
## 19 -63.0 -29.7 -63.4
## 23 -850.4 -153.0 -389.7
## 27 -633.8 -173.3 -270.5
## 28 -2.6 -0.2 -0.7
## 32 26.2 0.9 2.0
## 34 -351.9 -25.5 -48.1
## 37 300.8 -51.0 -97.4
## 38 -3.1 1.0 0.2
## 39 89.3 -160.1 -175.7
More Data Cleansing
Great, we got our statements loaded in pretty quickly, but it’s not 100% clean (look at the dates in the column name). Let’s do a little cleaning before we move forward.
The time origin for Excels date format is 1899-12-30
# Get quarterly dates and format correctly
dates_qtrly <- colnames(qtr_dbx[["income_statement"]])[-1]
dates_qtrly <- as.Date(dates_qtrly, "%b.%d.%Y")
# Clean the dates for each statement
for(i in 1:3){
colnames(qtr_dbx[[i]])[-1] <- as.character(dates_qtrly)
}
# Get Annual dates and format correctly
dates_annual <- colnames(annual_dbx[["balance_sheet"]])[-1]
dates_annual <- gsub(pattern = "X", replacement = "", x = dates_annual)
# Time origin for Excel date format
dates_annual <- as.Date(as.numeric(dates_annual), origin = "1899-12-30")
# Clean the dates for each statement
for(i in 1:3){
colnames(annual_dbx[[i]])[-1] <- as.character(dates_annual)
}
head(qtr_dbx)
## $income_statement
## For.the.Fiscal.Period.Ending. 2018-03-31 2018-06-30 2018-09-30
## 1 Revenues 316.30 339.20 360.30
## 2 Cost of Revenues -120.60 -89.50 -90.20
## 3 Sales and Marketing -157.00 -87.40 -95.00
## 4 General and Administrative -126.10 -49.80 -50.80
## 5 Research and Development -378.50 -119.70 -133.20
## 7 Other Income/expense-net 3.40 2.20 0.50
## 9 Earnings before Taxes -463.70 -3.00 -6.00
## 10 Provision for Income Tax -1.80 -1.10 0.20
## 11 Net Income (Loss) -465.50 -4.10 -5.80
## 13 Gross Profit/loss 195.70 249.70 270.10
## 14 Operating Income (Loss) -465.90 -7.20 -8.90
## 15 Basic EPS - Continuing Operations -2.13 -0.01 -0.01
## 2018-12-31 2019-03-31 2019-06-30
## 1 375.90 385.60 401.50
## 2 -94.40 -98.40 -102.90
## 3 -100.20 -101.50 -107.30
## 4 -56.50 -57.00 -62.90
## 5 -136.80 -150.00 -162.40
## 7 0.70 4.20 10.00
## 9 -7.40 -13.40 -20.80
## 10 -2.10 5.70 -0.60
## 11 -9.50 -7.70 -21.40
## 13 281.50 287.20 298.60
## 14 -12.00 -21.30 -34.00
## 15 -0.02 -0.02 -0.05
##
## $balance_sheet
## Balance.Sheet.as.of.. 2018-03-31 2018-06-30
## 1 Cash and Cash Equivalents 665.3 504.1
## 2 Short-term Investments 180.7 477.7
## 3 Trade and Other Receivables Net 26.2 31.2
## 4 Prepaid Expenses and Other Current Assets 57.7 86.8
## 5 Total Current Assets 929.9 1099.8
## 6 Property and Equipment, net 345.6 330.8
## 7 Goodwill 99.0 97.8
## 8 Intangible Assets, Net 17.9 16.3
## 9 Other Assets 46.3 57.7
## 11 Total Assets 1438.7 1602.4
## 12 Accounts Payable 29.4 24.0
## 13 Accrued Compensation and Benefits 36.2 45.1
## 14 Accrued and Other Current Liabilities 143.1 172.3
## 16 Deferred Revenue 444.6 464.8
## 19 Total Current Liabilities 746.1 793.3
## 21 Other Non-current Liabilities 36.3 31.5
## 25 Additional Paid in Capital 2104.9 2248.4
## 26 Accumulated Deficit -1600.4 -1619.4
## 27 Accumulated Other Comprehensive Income (Loss) 5.7 1.9
## 28 Total Shareholders Equity 510.2 630.9
## 29 Total Liabilities & Shareholders Equity 1438.7 1602.4
## 2018-09-30 2018-12-31 2019-03-31 2019-06-30
## 1 536.2 519.3 359.2 343.6
## 2 502.9 570.0 556.0 629.2
## 3 28.6 28.6 34.1 37.6
## 4 96.0 92.3 58.3 57.3
## 5 1163.7 1210.2 1007.6 1067.7
## 6 295.9 310.6 340.9 369.3
## 7 98.0 96.5 230.4 230.9
## 8 15.2 14.7 57.4 53.7
## 9 50.3 62.1 61.9 67.6
## 11 1623.1 1694.1 2128.6 2364.9
## 12 27.9 33.3 27.4 31.8
## 13 64.2 80.9 36.4 57.4
## 14 163.2 164.5 148.8 149.4
## 16 479.3 485.0 508.4 517.3
## 19 815.1 837.5 865.8 903.1
## 21 8.8 8.9 9.7 10.6
## 25 2285.0 2337.5 2377.8 2428.4
## 26 -1643.5 -1659.5 -1674.7 -1700.1
## 27 1.9 -1.2 1.8 1.9
## 28 643.4 676.8 704.9 730.2
## 29 1623.1 1694.1 2128.6 2364.9
##
## $cashflow
## For.the.Fiscal.Period.Ending.
## 1 Net Income
## 2 Depreciation and Amortization
## 3 Amortization of Deferred Commissions
## 4 Stock based Compensation
## 5 Others
## 6 Other Assets
## 8 Trade and Other Receivables, Net
## 9 Accounts Payable
## 10 Deferred Revenue
## 11 Prepaid Expenses and Other Current Assets
## 12 Accrued Compensation and Benefits
## 13 Accrued and Other Current Liabilities
## 17 Cash Flow from Operating Activities
## 19 Capital Expenditures
## 23 Purchases of Short-term Investment
## 27 Cash Flow from Investing Activities
## 28 Others
## 32 Proceeds from Issuance of Common Stock, Net of Repurchases
## 34 Shares Repurchased for Tax Withholdings on Release of Restricted Stock
## 37 Cash Flow from Financing Activities
## 38 Foreign Exchange Rate Effect on Cash and Cash Equivalents
## 39 Cash Flow Net Changes in Cash
## 2018-03-31 2018-06-30 2018-09-30 2018-12-31 2019-03-31 2019-06-30
## 1 -465.5 -469.6 -475.4 -484.9 -7.7 -29.1
## 2 35.9 75.9 121.6 166.8 45.8 91.9
## 3 2.4 5.3 8.5 12.1 3.9 8.1
## 4 486.5 541.6 596.6 650.1 55.6 123.7
## 5 -0.6 -1.1 -0.9 -1.9 -4.4 -7.6
## 6 -5.7 -17.5 -10.4 -11.2 11.2 26.2
## 8 3.6 -1.9 0.4 0.1 -5.1 -8.5
## 9 -2.8 -8.5 -3.9 -1.7 -5.2 -1.8
## 10 26.7 46.4 60.8 66.4 18.6 28.0
## 11 -1.5 -33.9 -47.3 -47.9 -14.2 -18.5
## 12 -26.2 -10.9 7.2 25.0 -45.9 -24.8
## 13 8.8 44.5 40.6 40.3 10.0 10.5
## 17 61.8 173.7 301.7 425.4 63.2 192.0
## 19 -9.9 -19.6 -27.6 -63.0 -29.7 -63.4
## 23 -180.8 -495.9 -664.3 -850.4 -153.0 -389.7
## 27 -193.1 -497.6 -529.0 -633.8 -173.3 -270.5
## 28 -2.1 -4.1 -6.1 -2.6 -0.2 -0.7
## 32 0.8 1.0 9.8 26.2 0.9 2.0
## 34 -241.2 -282.4 -326.7 -351.9 -25.5 -48.1
## 37 365.0 399.4 335.0 300.8 -51.0 -97.4
## 38 1.6 -1.4 -1.5 -3.1 1.0 0.2
## 39 235.3 74.1 106.2 89.3 -160.1 -175.7
I’ve cleaned the extra white spacing, and fix the column date formats. At this point, I can start the relative valuation and a bare bone intrinsic valuation. I’ll create functions on the fly to help calculate and replicate financial metrics / ratios.
Calculating BALLER ratios
Let’s check out the names of the statement lines so we can use the correct names when executing calculations (costs of good sold vs cost of revenues). I’ll start with calculating price-to-book, price-to-earnings, revenue multiples, and EBITDA multiples if applicable.
Price-to-Book
# Check unique labels for the lines of each statement
#unique(qtr_dbx[["income_statement"]][[1]])
# Function to calculate shares outstanding as of report date
#++++++++++++++++++++++++++++++++++++
shares_out <- function(statements){
ni <- filter(statements[["income_statement"]], For.the.Fiscal.Period.Ending. == "Net Income (Loss)")[,-1]
eps <- filter(statements[["income_statement"]], For.the.Fiscal.Period.Ending. == "Basic EPS - Continuing Operations")[,-1]
shares <- ni / eps
rownames(shares) <- "Shares Outstanding"
return(shares)
}
shares_out(qtr_dbx)
## 2018-03-31 2018-06-30 2018-09-30 2018-12-31 2019-03-31
## Shares Outstanding 218.5446 410 580 475 385
## 2019-06-30
## Shares Outstanding 428
As of the most recent quarter, the shares outstanding were 428m. As of 09/09/2019 on S&P Capital IQ, it shows shares outstanding as 413.4m which we will use for this valuation.
# Function to calculate book value per share as of report date
#++++++++++++++++++++++++++++++++++++
bk.val <- function(statements) {
shares <- shares_out(statements)
# Get Total Shareholder Equity and Calculate BVPS
shares_equity <- filter(statements[["balance_sheet"]], Balance.Sheet.as.of.. == "Total Shareholders Equity")[,-1]
bvps <- shares_equity / shares
rownames(bvps) <- "Book Val. Per Share"
return(bvps)
}
# Calculate Book Value
bk.val(qtr_dbx)
## 2018-03-31 2018-06-30 2018-09-30 2018-12-31 2019-03-31
## Book Val. Per Share 2.334535 1.53878 1.10931 1.424842 1.830909
## 2019-06-30
## Book Val. Per Share 1.706075
# Function to calculate price to book ratio as of report date
#++++++++++++++++++++++++++++++++++++
price.book <- function(symbol, bvps) {
#Price data to finish calculation
symbol_prices <- AlpacaforR::get_bars(symbol,from = "2019-09-06",to = "2019-09-06") %>% map_df(data.frame)
price_book <- Cl(symbol_prices) / last(bvps)
names(price_book) <- "Price-to-Book Ratio"
return(price_book)
}
# Calculate Price to Book
price.book("DBX",bk.val(qtr_dbx))
## Price-to-Book Ratio
## 11.11909
Price-to-Book = 💩💩💩💩💩💩
This is no surprise though. It should be expected that as a software company, it will have a high PB ratio (Mr. Buffet wouldn’t touch this type of name). According to NYU Sterns P/B ratio by Sector, the average between Software (Internet) and Software (System & Application) is 11.03x which Dropbox comes in-line with a PB ratio of ~11.12x.
Now, let’s skip price to earnings because Dropbox isn’t even turning a profit in Net Income yet. Therefore, Price-to-Earings is also 💩💩💩 but we don’t buy into growth companies for valuations, do we? Well yes, we do, but just not using these metrics. Since management doesn’t expect Dropbox to turn profits until 2021, let’s put our attention on some revenue metrics since this is where Dropbox can shine (top-line growth).
Revenue Multiples
Before I can calculate revenue multiples, I’ll need to first project revenue going out five or ten years. Since this is the quick version, I will use five years. I am using Paying Subscribers and Average Revenue Per User (ARPU) as our key drivers for projecting revenue. Since these directly affect the top-line, I think using this will give us an accurate picture of future revenue growth.
As of their most recent quarter (2Q 19’), Dropbox had 13.6 million paying subscribers which were up 1.7 million from 2Q 18’, a 14.3% YoY increase. Management forecasts FY 19’ Revenue to be between $1.646-1.648 Billion, which represents 18% YoY growth which is what I used for Year 1. I assume this comes from a modest 2.5% increase in ARPU and a small bump to 13.7 Million Paying Subscribers (only 100k more from where we are now).
In Years 2-5, I assume the growth in Paying subscribers begins to decelerate more, and growth in ARPU remains extremely modest (inline with AVG GDP growth). All in all, this has revenue growing at a decelerated rate in years 2-5 @ 15.8% 13.5% 9.6% and 6.8%. See below for the rest of projected revenue.
# Setting & plot historical + projected revenues
unique(qtr_dbx[["income_statement"]][[1]])
## [1] "Revenues"
## [2] "Cost of Revenues"
## [3] "Sales and Marketing"
## [4] "General and Administrative"
## [5] "Research and Development"
## [6] "Other Income/expense-net"
## [7] "Earnings before Taxes"
## [8] "Provision for Income Tax"
## [9] "Net Income (Loss)"
## [10] "Gross Profit/loss"
## [11] "Operating Income (Loss)"
## [12] "Basic EPS - Continuing Operations"
rev_hist <- filter(annual_dbx[["income_statement"]], For.the.Fiscal.Period.Ending. == "Revenues")[,-1]
rownames(rev_hist) <- "Revenues"
# REVENUE PROJECTIONS
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rev_g <- c(.184,.158,.135,.096,.068)
n <- 1:5
rev_proj <- rev_hist
for(i in n){
rev_proj <- cbind(rev_proj, (last(rev_proj)*(1+rev_g[i])))
}
# Add Projected dates
dates_proj <- c("Dec-31-2015","Dec-31-2016","Dec-31-2017","Dec-31-2018","Dec-31-2019","Dec-31-2020","Dec-31-2021","Dec-31-2022","Dec-31-2023")
colnames(rev_proj) <- dates_proj
Plot Revenues
# Convert to a tidy format for easier plotting
rev_proj_tidy <- tidyr::gather(rev_proj, dates, Amount) %>% mutate(type = c(rep("Historic",4),rep("Projected",5)))
# Plot away
ggplot2::ggplot(rev_proj_tidy, aes(dates,Amount,fill=type)) + geom_bar(stat = "identity") + theme(axis.text.x = element_text(angle = 90)) + geom_text(aes(label=round(Amount,1)), vjust=1.6, color="white", size=3)
Thats what I want to see!! A linear trend of top line growth, just as expected. For this type of revenue growth, we should see a premium on its revenue multiple compared to its peers. If not, then maybe the market is discounting Dropbox shares a little too much?
# My AlpacaforR package is a beast (shameless advertising here)
price <- AlpacaforR::get_bars(ticker,from = "2019-09-06",to = "2019-09-06") %>% map_df(data.frame)
#shares <- shares_out(qtr_dbx)
shares <- 413.4
mrkt_val <- Cl(price) * last(shares)
# Cash and Cash Equivalents
cash <- last(filter(qtr_dbx[["balance_sheet"]], Balance.Sheet.as.of.. == "Cash and Cash Equivalents")) + last(filter(qtr_dbx[["balance_sheet"]], Balance.Sheet.as.of.. == "Short-term Investments"))
# Total Debt
debt <- 787.20
# Enterprise Value
ent.val <- mrkt_val - cash + debt
# Projected revenue for this year
rev_19 <- rev_proj[,5]
# Current LTM revenue
ltm_rev <- qtr_dbx[["income_statement"]][1,] %>% select(-1) %>%
gather(key = Date,value = Revenue) %>%
mutate(LTM = rollapply(Revenue,4,sum,fill = 0, align="right")) %>%
select(LTM) %>% pull() %>% last()
# Calculate Multiple for Projected revenue
rev_mult19 <- ent.val / rev_19
# Calculate Multiple for LTM revenue
rev_multltm <- ent.val / ltm_rev
# Create Dataframe
ent_rev_mult <- data.frame("Multiples"=c(rev_mult19,rev_multltm))
rownames(ent_rev_mult) <- c('Est. 19\' Revenue','LTM Revenue')
# Show Projected and LTM Rev. Multiples
print(ent_rev_mult)
## Multiples
## Est. 19' Revenue 4.646635
## LTM Revenue 5.026323
Relative Valuation: Revenue Trading Multiple
According to Capital IQ, the average TEV / Total Revenue ratio for the Application Software Industry is 6.6x so we can see that Dropbox is coming in under that ratio. It looks like the market isn’t appreciating the revenue growth that Dropbox has shown therefore there is no premium compared to its peers. Being that Dropbox is a leader in this space for its size, the market is not appropriately pricing Dropbox on a revenue trading multiple front. If Dropbox was to be valued in line with its peers, we could see its stock price jump to…….
# If Dropbox had the same revenue multiple as its peers...
estimates_relval <- data.frame(Ent.Value=c(6.6 * rev_19,6.6 * ltm_rev))
estimates_relval <- estimates_relval %>% mutate(Share.Price = Ent.Value/shares)
rownames(estimates_relval) <- c("Fwd Estimate","LTM Estimate")
# Show Relative Share Price estimate
print(estimates_relval)
## Ent.Value Share.Price
## Fwd Estimate 10875.30 26.30697
## LTM Estimate 10053.78 24.31974
~$26.31 at the Estimated Full-Year Revenue Guidance for 2019 and ~$24.32 at the current LTM Revenue which is both significantly above the most recent close price of $18.97.
Now, as much as I want to calculate Ebitda multiples and run the same analysis, I don’t think it is necessary since Dropbox hasn’t been very profitable and EBITDA is the “closest” resemblance of FCF which we will be calculated next. Dropbox is undervalued in terms of relative valuation but how about Intrinsic?
Intrinsic Valuation: Quick N’ Clean DCF
There are multiple ways to calculate a companies Free Cash Flow. I usually like to be thorough when making any non-cash adjustments but since this is the “Quick N’ Clean” approach, I’ll check to see how Dropbox is calculating their FCF (a lot of these companies are in their own world so they’ll use ‘community adjusted’ free cash flows) to spare time.
From the Cash Flow Statement, Dropbox is subtracting Capital Expenditures from their Cash flow from Operating Activites to arrive at their FCF. Let’s do that and then project FCF going forward 10 years. How did I choose growth rates? I started with the guidance the management gave for the full year 2019 (see below).
We continue to expect free cash flow to be in the range of $375 million to $385 million this range includes one-time spend related to the build out of our new corporate headquarters, excluding this spend free cash flow would be $445 million to $465 million.
Notice how FCF would have been in the range of $445-465 Million if the ONE-TIME expense for new headquarters were excluded. I want to keep this in mind when projecting FCF for years 2-5. I used the industries average 3-year CAGR for free cash flow of 18.7% as a base reference when projecting future FCF growth. Once again, this historical data is coming from S&P Capital IQ.
#unique(annual_dbx[["cashflow"]][[1]])
# Create function to calculate free cash flow
#++++++++++++++++++++++++++++++++++++
fcf.value <- function(statements){
annual_cash_recent <- statements[["cashflow"]] #%>% select(1,ncol(annual_dbx[["cashflow"]]))
op_cshflw_ann <- filter(annual_cash_recent, For.the.Fiscal.Period.Ending. == "Cash Flow from Operating Activities")
capex_ann <- filter(annual_cash_recent, For.the.Fiscal.Period.Ending. == "Capital Expenditures")
fcf_current_ann <- op_cshflw_ann[,-1] + capex_ann[,-1]
rownames(fcf_current_ann) <- "Free Cash Flow"
return(fcf_current_ann)
}
# Calculate Annual Free Cash Flows
fcf_ann <- fcf.value(annual_dbx)
# Calculate Quarterly Free Cash Flows
fcf_qtr <- fcf.value(qtr_dbx)
# Show Annual FCF
print(fcf_ann)
## 2015-12-31 2016-12-31 2017-12-31 2018-12-31
## Free Cash Flow -63.9 137.4 305 362.4
Discount Rate: Capital Asset Pricing Model
Next, I’ll create a function to calculate CAPM for the discount rate. I’ll use the 10-yr yield as the risk-free rate which at the time of this writing is at a low of 1.5%. I’ll use an RF rate of 2% to adjust for the recent volatility in yields and 8.5% as the Market Premium. I expect this to be above 10% due to the risk involved with growing tech companies.
# Create function to calculate discount rate using CAPM
#++++++++++++++++++++++++++++++++++++
capm <- function(symbol, rm = .085, rf = .02){
#Calculate equity risk premium
erp <- rm - rf
#Set dates
d <- as.POSIXlt(Sys.Date())
d$year <- d$year-5
from <- as.Date(d)
to <- Sys.Date()
#Get price data for SPY then your symbol
spy.price <- getSymbols("SPY", from = from, to = to, auto.assign = FALSE)
spy.price <- to.monthly(spy.price[,4], OHLC=FALSE)
rets <- Return.calculate(spy.price)
#Your stock and combine with spy
symbol.price <- getSymbols(symbol, from = from, to = to, auto.assign = FALSE)
symbol.price <- to.monthly(symbol.price[,4], OHLC=FALSE)
rets$symbol <- Return.calculate(symbol.price)
#Rename first variable
names(rets)[1] <- "spy_ret"
#Remove NA from first obv
rets <- rets[-1,]
#Run regression to find the beta
reg <- lm(symbol ~ spy_ret, data = rets)
beta <- summary(reg)$coeff[2]
ca.pm <- rf + (beta * erp)
return(ca.pm)
}
# Calculate and show discount rate
disc <- capm(ticker)
disc
## [1] 0.1203834
Equity Value
Last, I will create a function to calculate the Equity Value of a company. In this function, we will forecast FCF, create a discount factor using the discount rate we calculated above, add the present value of those free cash flows, calculate the terminal value using a terminal value growth rate, and finally add the two together to derive the equity value of Dropbox. Finally, we will divide this value by the shares outstanding to get to our estimated share price which will hopefully be above the current price.
Not all companies are created equal and just because the peers have grown at 18.7% 3-Year CAGR doesn’t mean Dropbox will do the same. Since Dropbox is a leader and is just beginning to see some real growth in FCF, we will grow FCF a little faster than the industries historical average at 25% in year 2, peaking at 30% in year 3, 20% in year 4 and 18% in year 5. After, Dropbox sees a slowdown of 3% per year in FCF growth for years 6-8 and then shows modest growth of 5% and 3% in years 9 & 10.
# Create function to calculate Equity Value
#++++++++++++++++++++++++++++++++++++
equity.value <- function(fcf, disc, g, n = 10, tvg = .02,tv_disc_diff=.02){
#default forecast period of 5 years
#create dataframe & calculate fv of FCF and pv of the
#forecasted 5 years fv fcf and sum it all up
cf <- rep(fcf, n)
cf <- data.frame(cf)
cf$period <- seq(1,n,1)
fcf_vec <- last(fcf_ann)
for(i in g){
val <- tail(fcf_vec,1) * (1+i)
fcf_vec <- c(fcf_vec,val)
}
fcf_vec <- fcf_vec[-1]
cf$fv <- fcf_vec
cf$pv_factor <- 1 / (1 + disc)^cf$period
cf$pv <- cf$fv * cf$pv_factor
pv_cf <- sum(cf$pv)
#terminal period - default value at 2%
#calculate Terminal value and discount it to PV
tv <- cf$fv[n] * (1+tvg) / (disc - tvg)
pv_tv <- tv / (1+(disc-tv_disc_diff))^n
#add PV of forecasted values and PV of terminal value to
#get PV equity value
equity_value <- pv_cf + pv_tv
return(equity_value)
}
# FCF Growth in years 1-10
growth <- c(.05,.25,.30,.20,.18,.15,.12,.09,.05,.03)
# Calculate Equity Value
equity_value_fcf <- equity.value(fcf = last(fcf_ann), disc = disc, g = growth)
#Price per share
equity_pps <- equity_value_fcf / shares
equity_pps
## [1] 23.5093