knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE) library(cre.dcf) library(dplyr) library(tibble)
This vignette documents the methodological choices embedded in cre.dcf.
The package is intentionally centered on a property-level, before-tax DCF. This is close to the way the core valuation chapters in Baum and Hartzell and Geltner structure the problem: identify the operating cash flows, add the terminal event, discount the resulting stream, and only then layer leverage and underwriting [@hartzellChapter5Basic; @baumChapter7Techniques2020; @geltnerChapitre11Nuts_and_Bolts_for_Real_Estate_Valuation_Cash_Flow_Proformas_and_Discount_Rates2014].
The implementation follows four principles.
GEI -> NOI -> PBTCF.Geltner labels the property pro forma bottom line as "property-before-tax cash flow (PBTCF)" [@geltnerChapitre11Nuts_and_Bolts_for_Real_Estate_Valuation_Cash_Flow_Proformas_and_Discount_Rates2014, p. 11]. The same chapter also states that a pro forma should "always include reversion cash flows in the last year" [@geltnerChapitre11Nuts_and_Bolts_for_Real_Estate_Valuation_Cash_Flow_Proformas_and_Discount_Rates2014, p. 11].
In cre.dcf, this translates into three explicit operating columns plus a separate terminal event:
dcf <- dcf_calculate( acq_price = 10e6, entry_yield = 0.055, exit_yield = 0.0575, horizon_years = 5, disc_rate = 0.075, opex = c(50000, 51000, 52020, 53060, 54121), capex = c(15000, 15000, 20000, 15000, 0) ) dcf$cashflows |> select(year, gei, noi, pbtcf, sale_proceeds, free_cash_flow)
The public preference is now:
gei: gross effective income after vacancy and rent-free effects,noi: operating income net of recurring operating expenses,pbtcf: property-before-tax cash flow, that is noi - capex.The legacy column net_operating_income is still kept for backward compatibility, but the documentation no longer treats it as the central concept.
Baum and Hartzell present unlevered feasibility as a cash-flow problem before leverage, and their worked example decomposes value between ongoing operations and sale proceeds [@baumChapter7Techniques2020, pp. 14-15]. In that example, 27.6% of value comes from operating cash flows and 72.4% from disposition proceeds [@baumChapter7Techniques2020, p. 15].
In the same spirit, Geltner emphasizes that reversion is typically capitalized off the NOI one year beyond the explicit holding period, or off a stabilized forward NOI when the next year is atypical [@geltnerChapitre11Nuts_and_Bolts_for_Real_Estate_Valuation_Cash_Flow_Proformas_and_Discount_Rates2014, pp. 25-26]. The current cre.dcf implementation therefore capitalizes a forwardized terminal NOI rather than reusing the final in-horizon NOI mechanically.
For that reason, cre.dcf now reports the present-value split between operations and terminal value:
metrics <- compute_unleveraged_metrics(dcf) tibble( pv_operations = metrics$pv_operations, pv_terminal = metrics$pv_terminal, ops_share = metrics$ops_share, tv_share = metrics$tv_share )
This is useful for two reasons.
The package does not impose a universal threshold, but a high tv_share should prompt explicit discussion of exit-yield, stabilization, and market-liquidity assumptions.
One related caution from Geltner matters for interpretation: observed market cap rates are usually NOI-based, not PBTCF-based cash yields. In other words, a quoted cap rate is useful pricing evidence, but it is not automatically identical to the discount rate applied to a full PBTCF stream. In cre.dcf, this is why the "yield_plus_growth" convention is treated as a simplified robustness check rather than as a full recovery of the opportunity cost of capital from market cap-rate evidence alone.
In Geltner's lease chapter, the rigorous version of effective rent is the "annuitized lease value (ALV)", and "the ALV of a lease is a level annuity" with the same present value as the lease cash-flow stream [@geltnerChapitre29Leases_and_Leasing_Strategy2014, p. 8]. The chapter also emphasizes that ALV can be computed from either the landlord's or tenant's perspective [@geltnerChapitre29Leases_and_Leasing_Strategy2014, pp. 8-11].
This is why the package now includes lease_effective_rent() as a generic helper:
lease_compare <- bind_rows( concession = lease_effective_rent( cashflows = c(0, 100, 100, 100, 100), discount_rate = 0.08, area = 1, timing = "arrears", perspective = "landlord" ), flat = lease_effective_rent( cashflows = c(90, 90, 90, 90, 90), discount_rate = 0.08, area = 1, timing = "arrears", perspective = "landlord" ), .id = "lease" ) lease_compare |> select(lease, pv, equivalent_annuity, effective_rent)
The function is deliberately simple in version 1.
This keeps the API scientifically clear while leaving room for richer lease-option logic later.
Hartzell and Baum state that "either the debt coverage ratio or the loan-to-value ratio will be the constraining factor" when underwriting a loan [@hartzellChapter9Commercial, p. 5]. Their chapter also sizes a maximum loan amount directly from NOI and a debt-coverage requirement [@hartzellChapter9Commercial, pp. 4-5].
That logic is now exposed in a public helper:
uw <- underwrite_loan( noi = 500000, value = 8e6, rate_annual = 0.045, maturity = 5, type = "bullet", dscr_min = 1.25, ltv_max = 0.65, debt_yield_min = 0.08 ) uw$constraints tibble( binding_constraint = uw$binding_constraint, max_loan = uw$max_loan, payment_year1 = uw$payment_year1, implied_ltv = uw$implied_ltv, implied_dscr = uw$implied_dscr, implied_debt_yield = uw$implied_debt_yield )
The methodological choice is straightforward: underwriting is presented as a deterministic property-level screen. This is narrower than the full lender-return framework developed later in Geltner, but it captures the central textbook logic with a transparent API.
Geltner's advanced valuation chapter distinguishes market value from investment value and argues that both should be analyzed with the same multiperiod DCF machinery [@geltnerChapitre12Advanced_MicroLevel_Valuation2014, pp. 2-3]. cre.dcf does not yet expose a dedicated market_value() versus investment_value() API, but the package documentation now adopts that distinction as part of its methodological framing.
Two major extensions are intentionally deferred.
In other words, the current package is intentionally strongest on the asset-level, before-tax DCF core. That core now has a clearer scientific grammar, but it is not yet the full textbook universe.
The current package design is justified by the manuals in a fairly direct way.
pbtcf is explicit because the property pro forma bottom line matters.tv_share is explicit because terminal dependence is analytically important.lease_effective_rent() exists because lease comparison should be present-value based.underwrite_loan() exists because underwriting is fundamentally a constrained sizing exercise.The result is still intentionally modest in scope, but methodologically tighter and easier to defend in academic or professional discussion.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.