## ----setup, include=FALSE----------------------------------------------------- knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE) library(cre.dcf) library(dplyr) library(tibble) library(scales) library(yaml) ## ----------------------------------------------------------------------------- cfg_path <- system.file("extdata", "preset_core.yml", package = "cre.dcf") cfg <- yaml::read_yaml(cfg_path) case <- run_case(cfg) bullet_summary <- case$comparison$summary |> filter(scenario == "debt_bullet") |> transmute( scenario, irr_project, irr_equity, min_dscr, max_ltv_forward, ops_share, tv_share ) knitr::kable( bullet_summary, digits = 3, caption = "Before-tax baseline for the stylized French core-office case" ) ## ----------------------------------------------------------------------------- tax_basis <- tax_basis_spv(case) tax_assumptions <- tibble::tribble( ~item, ~value, ~comment, "Corporate income tax", "25%", "Official French normal CIT rate as of April 1, 2026", "Land share", "20%", "Stylized non-depreciable portion", "Building share", "65%", "Stylized depreciable structure", "Fit-out share", "15%", "Stylized depreciable tenant-improvement bucket", "Building life", "30 years", "Stylized straight-line life", "Fit-out life", "10 years", "Stylized straight-line life", "Interest deductibility", "full", "Current engine scope, not full French law", "Loss carryforward", "on", "Stylized carryforward allowed", "Offset cap", "50%", "Stylized cap used to keep the rule conservative" ) knitr::kable( tax_assumptions, caption = "French-like tax assumptions used in this vignette" ) ## ----------------------------------------------------------------------------- tax_spec <- tax_spec_spv( corp_tax_rate = 0.25, depreciation_spec = depreciation_spec( acquisition_split = tibble::tribble( ~bucket, ~share, ~life_years, ~method, ~depreciable, "land", 0.20, NA, "none", FALSE, "building", 0.65, 30, "straight_line", TRUE, "fitout", 0.15, 10, "straight_line", TRUE ), capex_bucket = "fitout", start_rule = "full_year" ), interest_rule = interest_rule(mode = "full"), loss_rule = loss_rule( carryforward = TRUE, carryforward_years = Inf, offset_cap_pct = 0.50 ) ) tax_res <- tax_run_spv(tax_basis, tax_spec) ## ----------------------------------------------------------------------------- tax_view <- tax_res$tax_table |> select( year, noi, tax_depreciation, deductible_interest, taxable_income_pre_losses, loss_cf_open, loss_cf_used, cash_is, after_tax_equity_cf ) knitr::kable( tax_view, digits = 0, caption = "Stylized French SPV tax table" ) ## ----------------------------------------------------------------------------- equity_bridge <- tax_res$tax_table |> select(year, pre_tax_equity_cf, cash_is, after_tax_equity_cf) knitr::kable( equity_bridge, digits = 0, caption = "Bridge from pre-tax to after-tax equity cash flows" ) ## ----------------------------------------------------------------------------- pre_tax_equity_irr <- case$leveraged$irr_equity after_tax_equity_irr <- irr_safe(tax_res$tax_table$after_tax_equity_cf) tax_highlights <- tibble( pre_tax_equity_irr = pre_tax_equity_irr, after_tax_spv_equity_irr = after_tax_equity_irr, total_cash_is = tax_res$summary$total_cash_is, total_tax_depreciation = tax_res$summary$total_tax_depreciation, exit_year_cash_is = tax_res$tax_table$cash_is[ tax_res$tax_table$year == max(tax_res$tax_table$year) ] ) knitr::kable( tax_highlights, digits = 3, caption = "Stylized before-tax versus after-tax SPV reading" )