Session 5 of 26 Part II: Financial Analysis & Value Drivers — Chapter 5 of 18
Part II: Financial Analysis & Value Drivers Chapter 5 of 18 Session 5 Python Excel

ROIC, Economic Profit & Value Creation

The single most important number in corporate valuation — how to compute it, decompose it, and use it to separate value creators from value destroyers.

Learning Objectives

📋
Two Paths, One Destination — Choose Your Tool

This session builds the ROIC engine: NOPAT → Invested Capital → ROIC → Economic Profit. The Python path (marked Python) automates it; the Excel path (green Excel Path boxes) computes the identical chain with formulas — and has a genuine edge here: Screener.in prints ROCE (Return on Capital Employed) for every company, which is a close cousin of ROIC. Compute your ROIC in Excel, compare with the site's ROCE, and you have a built-in answer key: broadly matching numbers mean your NOPAT and Invested Capital rows are right.

Python: compute_roic() pipeline Excel: formula chain + ROCE cross-check

🔍 Opening Challenge — The Growth Illusion

You have Rs. 1 lakh to invest. Company X grows revenue 20% a year. Company Y grows only 6% a year. Both are in the same industry, both are profitable. A friend tells you: "Easy — pick X. Growth is what makes money."
Your Task: Do you agree? Take a 30-second personal vote (agree / disagree / unsure). Then turn to a partner: what information is missing before you can choose? List at least 2 things. You have 2 minutes.

5.1 Why ROIC Is the Central Metric in Valuation

In Chapter 1, we established a fundamental truth: growth creates value only when the return on invested capital exceeds the cost of that capital. ROIC is the metric that makes this truth operational. It answers the question every investor should ask: for every rupee the company invests, how much profit does it generate?

Consider three companies with identical 15% revenue growth:

Company ACompany BCompany C
Revenue Growth15%15%15%
ROIC35%12%6%
WACC10%10%10%
ROIC − WACC Spread+25%+2%−4%
Value CreationStrong creatorMarginalDestroyer

Company A is a compounding machine. Every rupee reinvested generates 35 paise of after-tax profit — far above the 10% cost. Company C, despite growing at the same rate, is burning value. Its 6% ROIC means each rupee invested earns less than what that capital costs. The 15% growth only accelerates the destruction.

🌎
Real World: Between 2010 and 2020, the Indian telecom sector grew revenue at 8–10% annually — but the industry's aggregate ROIC fell below 5%, far beneath the 10–12% WACC. Billions of dollars of capital were invested in spectrum and infrastructure that produced returns below the cost of capital. The result: a sector-wide destruction of shareholder value, culminating in consolidation (Vodafone-Idea merger) and bankruptcy (RCom, Aircel). Growth without adequate ROIC is a wealth-destruction machine.
Your Turn — Back to the Opening Hook ⏱ 2 min

Now complete the hook with the missing number. Company X: revenue growth 20%, ROIC 7%, WACC 11%. Company Y: growth 6%, ROIC 28%, WACC 11%.

  1. Compute each company's ROIC − WACC spread.
  2. Which company actually creates value with every rupee it reinvests?
  3. Was your opening vote right? What does X's 20% growth actually do to shareholder value?
Reveal answers

X: 7% − 11% = −4% — every rupee reinvested at 20% growth destroys 4 paise of value; faster growth = faster destruction. Y: 28% − 11% = +17% — a compounding machine even at 6% growth. Y wins. The missing number from the hook was ROIC (vs WACC) — which is exactly what this session teaches you to compute.

5.2 Computing NOPAT: The Numerator

NOPAT (Net Operating Profit After Tax) is the profit generated by the company's core operations, after tax, but before financing costs. It represents the earnings available to all capital providers — both debt and equity holders. It is the numerator in the ROIC equation.

NOPAT = EBIT × (1 − Effective Tax Rate)

The simplicity of this formula is deceptive. The adjustment work lies in ensuring EBIT truly reflects operating earnings. Here is the step-by-step approach:

  • Start with Reported EBIT (or Operating Income) from the income statement.
  • Strip out non-operating income embedded in EBIT. This includes: interest income on excess cash, dividend income, rental income from non-core property, gains/losses on asset sales. These are not generated by the company's operations.
  • Add back operating lease expense (if material and not already capitalized under Ind AS 116). The lease payment is partly a financing cost, not an operating cost.
  • Add back non-recurring charges that distort sustainable earnings — restructuring costs, impairment charges, large legal settlements. But be honest: if "restructuring" happens every year, it is a recurring operating cost.
  • Apply the effective tax rate (not the statutory rate). The effective rate = Total Tax Expense / PBT. Use a normalized rate (typically 25% for Indian companies under the new tax regime) if the current year's effective rate is distorted by one-time tax items.
  • 💡
    Pro Tip: Many analysts shortcut NOPAT as EBIT × (1 − 25%). For preliminary screening, this is acceptable. For a final valuation, you must use the company's actual effective tax rate and adjust EBIT for non-operating items. The difference in ROIC from these adjustments can be 200–500 basis points — enough to flip a company from "value creator" to "value destroyer."
    Your Turn — Compute NOPAT with Adjustments ⏱ 3 min

    Reported figures (Rs. Cr): Operating Income (EBIT) = 900 · Other Income (all non-operating: interest + dividend) = 150 · One-time gain on property sale = 100 · Effective tax rate = 25%.

    Compute:

    1. Adjusted Operating EBIT (strip both non-operating items)
    2. NOPAT

    Then answer: by what percentage would you have overstated NOPAT if you had used reported EBIT directly?

    Reveal answers

    Adjusted EBIT = 900 − 150 − 100 = 650. NOPAT = 650 × 0.75 = 487.5. Unadjusted NOPAT would be 900 × 0.75 = 675 — overstated by 38.5%. On a 11% WACC, that error alone flips the ROIC conclusion for many companies.

    5.2.1 NOPAT in Python

    def compute_nopat(income_stmt, tax_rate=0.25, non_operating_income_fields=None):
        """
        Compute NOPAT from an income statement DataFrame.
    
        Parameters
        ----------
        income_stmt : pd.DataFrame (yfinance .financials format)
        tax_rate : float — effective or statutory tax rate (default 0.25)
        non_operating_income_fields : list of str — income statement line items
            that are non-operating and should be excluded from operating EBIT.
    
        Returns
        -------
        pd.Series of NOPAT by fiscal year.
        """
        def safe_get(df, candidates):
            for c in ([candidates] if isinstance(candidates, str) else candidates):
                if c in df.index:
                    return df.loc[c]
            return None
    
        ebit = safe_get(income_stmt, ['Operating Income', 'EBIT'])
    
        if ebit is None:
            # Try to construct EBIT from components
            rev = safe_get(income_stmt, ['Total Revenue', 'Revenue'])
            total_exp = safe_get(income_stmt, ['Total Expenses'])
            if rev is not None and total_exp is not None:
                ebit = rev - total_exp
            else:
                raise ValueError("Cannot find or construct EBIT from income statement.")
    
        # Strip non-operating income if fields are provided
        if non_operating_income_fields:
            for field in non_operating_income_fields:
                non_op = safe_get(income_stmt, field)
                if non_op is not None:
                    ebit = ebit - non_op
    
        nopat = ebit * (1 - tax_rate)
        return nopat
    
    # Usage
    import yfinance as yf
    ticker = yf.Ticker("ASIANPAINT.NS")
    nopat = compute_nopat(ticker.financials)
    print("NOPAT by Fiscal Year (Rs. Cr):")
    print((nopat / 1e7).round(2))  # Convert to crores
    X Excel Path — NOPAT, and the "One Input Cell" Rule Excel

    On each company's Drivers sheet, first set up an Inputs block — this is the single most important Excel modeling habit of the whole course:

    ' Cell B1 — the ONE place the tax rate lives:
    B1: 25% ' ← label "Tax Rate" in A1
    B2: 10% ' ← label "WACC assumption" in A2 (used in 5.6)

    Then (Operating Profit row 3, Other Income row 23, one-time gains row 24 — adjust rows to your sheet):

    ' Adjusted Operating EBIT (row 47):
    = C3 - C23 - C24
    ' NOPAT (row 48) — note the $B$1 ABSOLUTE reference:
    = C47 * (1 - $B$1)

    Why $B$1 matters: the dollar signs "lock" the tax rate cell so it does not shift when you drag the formula across years — every NOPAT cell reads the same single input. Next year, or in a scenario, you change one cell and the entire workbook updates. This is Excel's version of a function parameter, and it is how professional models are built.

    Screener.in cross-check: Screener's P&L shows "Other Income" as a separate line already excluded from its OPM calculation — so your row 47 and Screener's "Operating Profit" should agree closely. Screener's "Tax %" line gives you the effective tax rate to put in B1 (better than a flat 25%).

    5.3 Computing Invested Capital: The Denominator

    Invested Capital represents the total capital that has been deployed in the company's operations — the capital provided by both debt and equity holders, net of non-operating assets. It is the denominator of ROIC.

    5.3.1 The Operating Approach

    Invested Capital = Operating Current Assets − Operating Current Liabilities + Net PPE + Other Operating Long-Term Assets

    This builds invested capital from the asset side. Operating current assets include receivables, inventory, and the minimum cash needed for operations — but exclude excess cash. Operating current liabilities include payables and accruals — but exclude interest-bearing short-term debt.

    5.3.2 The Financing Approach (Easier from yfinance)

    Invested Capital = Total Shareholders' Equity + Total Debt − Cash & Equivalents − Non-Operating Investments

    This builds invested capital from the financing side — equity plus debt, minus assets that are not employed in the business. We subtract cash because it is not an operating asset (it generates interest income, not operating profit). We subtract non-operating investments (minority stakes in other companies) for the same reason.

    👥 Think-Pair-Share — The Cash Paradox ⏱ 3 min

    Think: TCS holds roughly Rs. 50,000 Cr of cash. Suppose we did NOT subtract cash from invested capital. Would TCS's ROIC go up or down? Would that be fair to the business?

    Pair: Work through the logic with your partner: cash sits in the denominator but generates almost none of the numerator (interest income is excluded from NOPAT).

    Share: Two pairs explain. Key insight: idle cash dilutes ROIC — including it punishes efficient businesses for holding reserves, which is why we remove it and value cash separately.

    5.3.3 Critical Adjustments

    AdjustmentRationaleHow
    Subtract excess cash Cash beyond what is needed for day-to-day operations is a non-operating asset. Including it inflates invested capital and depresses ROIC. Estimate operating cash as 2–5% of revenue (varies by industry). Subtract the remainder from invested capital.
    Subtract non-consolidated investments Minority stakes generate dividend/associate income, not operating profit. They should be valued separately. Identify "Investments" on the balance sheet (non-current and current). Exclude unless they are operating subsidiaries.
    Add capitalized operating leases Under Ind AS 116, most leases are already on the balance sheet. For companies exempt or pre-2019 data, leases were off-balance-sheet. Multiply annual lease expense by 6–8x to estimate the off-balance-sheet debt equivalent. Add to both debt and fixed assets.
    Add back goodwill impairment Goodwill impairment is a non-cash charge that reduces equity but does not reflect current operating reality. Add cumulative impairment charges back to equity and invested capital. This prevents ROIC from being artificially inflated by write-downs.
    Treat provisions as debt equivalents Large restructuring or legal provisions are essentially debt — they represent future cash outflows. Add material long-term provisions to invested capital. Judge materiality case by case.

    5.3.4 Invested Capital in Python

    def compute_invested_capital(balance_sheet, excess_cash_pct=0.0):
        """
        Compute invested capital from balance sheet data.
    
        By default, treats ALL cash as non-operating (conservative).
        Set excess_cash_pct to ~0.02 (2% of revenue) to treat some cash
        as operating when you have revenue data.
        """
        def safe_get(df, candidates):
            for c in ([candidates] if isinstance(candidates, str) else candidates):
                if c in df.index:
                    return df.loc[c]
            return None
    
        equity = safe_get(balance_sheet, [
            'Total Equity Gross Minority Interest',
            'Stockholders Equity', 'Total Equity'])
        total_debt = safe_get(balance_sheet, [
            'Total Debt', 'Long Term Debt'])
        cash = safe_get(balance_sheet, [
            'Cash And Cash Equivalents',
            'Cash Cash Equivalents And Short Term Investments'])
        lt_investments = safe_get(balance_sheet, [
            'Long Term Investments', 'Investments And Advances'])
    
        if equity is None:
            # Build from: Total Assets − Total Liabilities
            assets = safe_get(balance_sheet, ['Total Assets'])
            liabilities = safe_get(balance_sheet, ['Total Liabilities Net Minority Interest'])
            if assets is not None and liabilities is not None:
                equity = assets - liabilities
            else:
                raise ValueError("Cannot determine equity from balance sheet.")
    
        # If there's no separate debt line, use the difference approach
        if total_debt is None:
            total_debt = 0  # In some yfinance outputs, debt is embedded in liabilities
    
        invested_capital = equity + total_debt
    
        if cash is not None:
            invested_capital = invested_capital - cash
    
        if lt_investments is not None:
            # Only subtract if these are truly non-operating
            invested_capital = invested_capital - lt_investments
    
        return invested_capital
    
    
    # Usage
    ic = compute_invested_capital(ticker.balance_sheet)
    print("Invested Capital by Fiscal Year (Rs. Cr):")
    print((ic / 1e7).round(2))
    Your Turn — Compute Invested Capital Both Ways ⏱ 4 min

    Balance sheet snapshot (Rs. Cr): Equity 4,000 · Total Debt 1,500 · Cash 800 · Non-operating investments 300 · Operating Current Assets 2,200 · Operating Current Liabilities 1,400 · Net PPE 3,800.

    Compute IC twice and check they agree:

    1. Financing approach: Equity + Debt − Cash − Non-op investments = ?
    2. Operating approach: (Op. Current Assets − Op. Current Liabilities) + Net PPE = ?

    If your two answers differ, one of your classifications is wrong — find it.

    Reveal answers

    Financing: 4,000 + 1,500 − 800 − 300 = 4,400. Operating: (2,200 − 1,400) + 3,800 = 4,600. They differ by 200 — the non-operating investments of 300 don't fully reconcile with the working capital split (200 of the investments sit inside "operating" current assets here). This is exactly the kind of classification judgment Section 5.3.3's adjustment table addresses: the two approaches only match when every asset is correctly tagged operating vs non-operating.

    X Excel Path — Invested Capital, with the Adjustments as Visible Rows Excel

    Build IC as a staircase of rows — one row per component, so every adjustment from the table above is visible and auditable (rows continue from the Session 4 workbook; Equity row 7, Debt row 5, Cash row 6, Investments row 28):

    ' Total capital (row 49):
    = C7 + C5
    ' (−) Cash (row 50):
    = -C6
    ' (−) Non-operating investments (row 51):
    = -C28
    ' Invested Capital (row 52) — sum the staircase:
    = SUM(C49:C51)
    ' Optional refinement — keep only EXCESS cash in row 50 instead:
    = -(C6 - 0.02*C2) ' subtracts cash beyond 2% of revenue

    Then ROIC is one formula (NOPAT row 48 from the previous Excel Path):

    ' ROIC % (row 53):
    = IFERROR(C48 / C52 * 100, "n/a")

    Apply conditional formatting to row 53: green above your WACC cell ($B$2, set to 10%), red below. Drag all rows right across the years — you now have the full ROIC trend, color-coded, exactly like the Python pipeline's output.

    The ROCE answer key: Screener.in prints ROCE on every company page. ROCE = Operating Profit × (1−tax isn't applied) / (Debt + Equity) — slightly different numerator and it does not net out cash. So expect your ROIC to be near ROCE but not identical (usually a bit higher for cash-rich firms because you subtract cash). If your number is wildly different (say, off by 15+ percentage points), you have a formula bug — check rows 49–52 before anything else.

    5.4 Putting It Together: Computing ROIC

    With NOPAT and Invested Capital computed, ROIC follows directly. But the analysis does not stop at a single number — we must examine ROIC trends, compare against WACC, and decompose the drivers.

    5.4.1 The Core ROIC Function

    def compute_roic(income_stmt, balance_sheet, tax_rate=0.25):
        """
        Compute NOPAT, Invested Capital, and ROIC.
    
        Returns a DataFrame with all three components by fiscal year.
        """
        nopat = compute_nopat(income_stmt, tax_rate)
        ic = compute_invested_capital(balance_sheet)
    
        # Align indices (they should match by fiscal year, but verify)
        common_years = nopat.index.intersection(ic.index)
        nopat = nopat[common_years]
        ic = ic[common_years]
    
        roic = (nopat / ic) * 100
    
        result = pd.DataFrame({
            'NOPAT (Cr)': nopat / 1e7,
            'Invested Capital (Cr)': ic / 1e7,
            'ROIC (%)': roic.round(2)
        })
    
        return result
    
    
    def compare_roic_across_companies(tickers, labels=None, tax_rate=0.25):
        """
        Compute and compare ROIC for multiple companies.
    
        Returns a DataFrame with each company's latest ROIC and components.
        """
        if labels is None:
            labels = [t.replace('.NS', '').replace('.BO', '') for t in tickers]
    
        results = {}
        for tkr, lbl in zip(tickers, labels):
            try:
                ticker = yf.Ticker(tkr)
                roic_df = compute_roic(ticker.financials, ticker.balance_sheet, tax_rate)
                latest = roic_df.iloc[:, 0]  # Most recent fiscal year
                results[lbl] = latest
                print(f"✓ {lbl}: ROIC = {latest['ROIC (%)']:.1f}%")
            except Exception as e:
                print(f"✗ {lbl}: {e}")
            time.sleep(1.5)
    
        comparison = pd.DataFrame(results).T
        return comparison
    
    
    # --- Compare Indian consumer leaders ---
    consumer_tickers = ['ASIANPAINT.NS', 'TITAN.NS', 'NESTLEIND.NS',
                        'BRITANNIA.NS', 'HINDUNILVR.NS']
    consumer_labels = ['Asian Paints', 'Titan', 'Nestle India', 'Britannia', 'HUL']
    
    roic_comparison = compare_roic_across_companies(consumer_tickers, consumer_labels)
    print("\n=== ROIC Comparison — Indian Consumer Sector ===")
    print(roic_comparison)

    5.4.2 Interpreting ROIC Levels

    ROIC RangeAssessmentTypical Examples (India)
    > 30%Exceptional — wide and durable competitive moatAsian Paints, Titan, TCS, Nestle India, Pidilite
    20–30%Strong — clear competitive advantagesInfosys, HUL, Dr. Reddy's, Maruti Suzuki
    10–20%Adequate — earning returns above typical cost of capitalLarsen & Toubro, Sun Pharma, Ultratech Cement
    5–10%Marginal — returns barely exceed or equal cost of capitalTata Motors, Hindalco (cyclical; check multi-year averages)
    < 5%Weak — likely destroying value; growth is harmfulTelecom companies (pre-consolidation), highly leveraged infra firms
    Important: ROIC must be interpreted relative to WACC, not in absolute terms. A 12% ROIC looks decent in absolute terms — unless the company's WACC is 14%, in which case it is destroying value. We will compute WACC in Chapters 10–11. For now, use 10–12% as a rough benchmark for Indian companies.

    🔗 Before You Move On — 3 Quick Checks

    True or False: A company with ROE of 22% and a D/E of 2.5 must be creating value for shareholders.

    Reveal
    NOT NECESSARILY — leverage inflates ROE (Session 4's DuPont). What matters is ROIC vs WACC: if the business earns 9% on capital costing 11%, equity leverage shows a pretty ROE while value is being destroyed.

    True or False: Subtracting cash from invested capital lowers ROIC.

    Reveal
    FALSE — subtracting cash shrinks the denominator, which raises ROIC. That is the point: idle cash shouldn't dilute the measured return on the capital actually working in the business.

    True or False: NOPAT uses the same numerator as net income — they only differ in the tax rate applied.

    Reveal
    FALSE — NOPAT starts from operating EBIT (non-operating income stripped out) and ignores interest entirely; net income is after interest and includes non-operating items. Same company, different questions: NOPAT = return to ALL capital; net income = return to equity only.

    5.5 Decomposing ROIC: The Value Driver Formula

    A single ROIC number is useful for comparison. But to understand why one company earns 35% while its competitor earns 12%, we must decompose ROIC into its drivers. McKinsey's value driver formula expresses ROIC as the product of operating margin and capital turnover:

    ROIC = (NOPAT / Revenue) × (Revenue / Invested Capital)
    ROIC = Operating Margin × Capital Turnover

    This decomposition reveals that there are exactly two ways to earn a high ROIC:

    Strategy 1: High Margins

    Earn a large spread between selling price and cost. This requires pricing power — a strong brand, differentiated product, or monopoly position.

    Examples: Asian Paints (brand), Titan (brand + design), TCS (service quality), Nestle (brand portfolio).

    Margin driver: NOPAT / Revenue

    Strategy 2: High Capital Efficiency

    Generate a lot of revenue from a small capital base. This requires asset-light operations — minimal PPE, fast inventory turns, tight receivables.

    Examples: DMart (inventory turns), Indigo (aircraft utilization), Infosys (asset-light IT).

    Turnover driver: Revenue / Invested Capital

    The very best companies — Titan, TCS, Asian Paints — score well on both dimensions. They earn high margins AND turn over capital efficiently. This is the hallmark of a genuinely exceptional business.

    Your Turn — The Decomposition Puzzle ⏱ 3 min

    Four companies, all with ROIC = 24%. Fill in the blanks:

    NOPAT MarginCapital TurnoverBusiness type
    Luxury Brands Ltd24%______
    HyperMart Ltd3%______
    Software Ltd___1.5x___
    Steel Co___0.8x___

    For each: compute the missing value (remember ROIC = Margin × Turnover) and name a real Indian company with roughly that profile.

    Reveal answers

    Luxury: 24% × 1.0x (Titan-style pricing power) · HyperMart: 3% × 8.0x (DMart-style volume machine) · Software: 16% × 1.5x (Infosys — margin-led) · Steel: 30% × 0.8x (Tata Steel at a cyclical peak — the margin is not durable!). Same ROIC, four totally different risk profiles — which is why you decompose before you forecast.

    👥 Think-Pair-Share — Which Moat Is Stronger? ⏱ 3 min

    Think: Company P earns its ROIC through margins (a beloved brand). Company Q earns the same ROIC through capital turnover (brilliant operations, thin margins). If a well-funded competitor attacks both in 5 years, whose ROIC is more likely to survive?

    Pair: Take opposite sides with your partner — one defends the brand (P), one defends the operations (Q). Two rounds, 1 minute each.

    Share: We'll hear the best argument for each side. Note for your capstone: this judgment becomes your terminal ROIC assumption in Session 15.

    5.5.1 Python: ROIC Decomposition

    def decompose_roic(income_stmt, balance_sheet, tax_rate=0.25):
        """
        Decompose ROIC into Operating Margin and Capital Turnover.
        """
        def safe_get(df, candidates):
            for c in ([candidates] if isinstance(candidates, str) else candidates):
                if c in df.index:
                    return df.loc[c]
            return None
    
        revenue = safe_get(income_stmt, ['Total Revenue', 'Revenue'])
        nopat = compute_nopat(income_stmt, tax_rate)
        ic = compute_invested_capital(balance_sheet)
    
        common = nopat.index.intersection(ic.index).intersection(revenue.index)
        nopat = nopat[common]
        ic = ic[common]
        revenue = revenue[common]
    
        op_margin = (nopat / revenue) * 100
        capital_turnover = revenue / ic
        roic = (nopat / ic) * 100
    
        decomposition = pd.DataFrame({
            'NOPAT Margin (%)': op_margin.round(2),
            'Capital Turnover (x)': capital_turnover.round(2),
            'ROIC (%)': roic.round(2)
        })
    
        return decomposition
    
    
    def plot_roic_decomposition(tickers, labels):
        """
        Scatter plot: Operating Margin vs Capital Turnover,
        with ROIC as isoquants. Each company is a point.
        """
        import matplotlib.pyplot as plt
        import numpy as np
    
        fig, ax = plt.subplots(figsize=(12, 8))
    
        for tkr, lbl in zip(tickers, labels):
            try:
                ticker = yf.Ticker(tkr)
                dec = decompose_roic(ticker.financials, ticker.balance_sheet)
                latest = dec.iloc[:, 0]  # Most recent year
                ax.scatter(latest['Capital Turnover (x)'],
                          latest['NOPAT Margin (%)'],
                          s=300, edgecolors='white', linewidth=2, zorder=5)
                ax.annotate(f"{lbl}\nROIC: {latest['ROIC (%)']:.0f}%",
                           (latest['Capital Turnover (x)'],
                            latest['NOPAT Margin (%)']),
                           textcoords="offset points", xytext=(10, 5), fontsize=9)
            except Exception as e:
                print(f"✗ {lbl}: {e}")
            time.sleep(1.5)
    
        # Add ROIC isoquants
        x_range = np.linspace(0.1, ax.get_xlim()[1] * 1.2, 100)
        for roic_level in [10, 20, 30, 50, 75]:
            y = roic_level / x_range
            ax.plot(x_range, y, '--', color='gray', alpha=0.3, linewidth=0.8)
            ax.annotate(f'{roic_level}% ROIC',
                       (x_range[-1], y[-1]),
                       fontsize=7, color='gray', alpha=0.7,
                       textcoords="offset points", xytext=(5, 0))
    
        ax.set_xlabel('Capital Turnover (Revenue / Invested Capital)')
        ax.set_ylabel('NOPAT Margin (%)')
        ax.set_title('ROIC Decomposition: How Do Companies Earn Their Returns?',
                     fontsize=13, fontweight='bold')
        ax.grid(True, alpha=0.3)
        plt.tight_layout()
        plt.show()
    
    
    # Usage
    consumer_tickers = ['ASIANPAINT.NS', 'TITAN.NS', 'NESTLEIND.NS',
                        'BRITANNIA.NS', 'HINDUNILVR.NS']
    consumer_labels = ['Asian Paints', 'Titan', 'Nestle India', 'Britannia', 'HUL']
    plot_roic_decomposition(consumer_tickers, consumer_labels)
    X Excel Path — Decomposition as Two Visible Rows + the Scatter Excel

    Two more rows and the decomposition is laid bare (continuing row numbers: Sales row 2, NOPAT row 48, IC row 52):

    ' NOPAT Margin % (row 54):
    = C48 / C2 * 100
    ' Capital Turnover x (row 55):
    = C2 / C52
    ' Consistency check — should equal ROIC row 53:
    = C54 * C55

    The margin-vs-turnover scatter (the Python isoquant chart, Excel edition): on your Summary sheet, ensure every company's latest Margin (row 54) and Turnover (row 55) are pulled across, then select the two rows → Insert → Scatter → add data labels with company names. The Python version draws curved "ROIC isoquant" lines; in Excel, simply add a third series manually — a column of turnover values (0.5, 1, 2, 4, 8) against a computed =24/turnover formula gives you the 24% ROIC frontier as a line. Companies sitting above the frontier out-earn 24%; below it, they don't.

    5.6 Economic Profit: The True Measure of Value Creation

    Economic Profit (also called Economic Value Added or EVA) measures the absolute amount of value created in a given period — not just the rate of return. While ROIC tells you the efficiency of capital use, Economic Profit tells you the magnitude of value creation.

    Economic Profit = (ROIC − WACC) × Invested Capital
    Economic Profit = NOPAT − (WACC × Invested Capital)

    Economic Profit has a powerful property: it is directly linked to the excess returns in a DCF valuation. The present value of all future Economic Profits, plus the current invested capital, equals the enterprise value from a DCF model. This is the economic profit valuation model — an alternative to the traditional DCF that separates the value of existing capital from the value of future value creation.

    5.6.1 Why Net Income Fails to Measure Value Creation

    Net income is the most commonly cited profit metric. But it fails as a value creation measure for three reasons:

    Flaw in Net IncomeWhy It MattersHow Economic Profit Fixes It
    Ignores the cost of equity capital A company can report positive net income while destroying shareholder value because it earns less than the equity cost of capital. Economic Profit charges for ALL capital — debt AND equity — at the WACC.
    Includes non-operating items Gains on asset sales, investment income, and one-time items inflate net income without reflecting operating performance. Economic Profit starts from NOPAT, which strips out non-operating items.
    Penalizes investment Under GAAP/Ind AS, R&D and capex are expensed or depreciated, reducing net income even when they create value. Investments that earn above WACC increase Economic Profit over time, even if they reduce near-term earnings.
    🌎
    Real World — Amazon vs a profitable but value-destroying utility: For years, Amazon reported thin or negative net income while investing massively in infrastructure. A traditional analysis would call it "unprofitable." But Amazon's ROIC consistently exceeded its WACC — its investments were creating value, just not in the form of current net income. Conversely, many regulated Indian power utilities report positive net income due to accounting conventions, but their ROIC has been below WACC for decades, making them chronic value destroyers despite "profitability."
    Your Turn — Profitable but Destroying Value? ⏱ 3 min

    Two companies, both reporting healthy net income (Rs. Cr):

    Steady Power LtdNimbus Software
    Net Income500480
    NOPAT620540
    Invested Capital7,0002,400
    WACC10%11%

    Compute for each: (a) ROIC, (b) capital charge, (c) Economic Profit. Which company would you rather own — and why does the answer differ from what net income suggests?

    Reveal answers

    Steady Power: ROIC = 620/7,000 = 8.9% < 10% WACC → charge 700 → EP = −80 Cr (destroying value despite Rs. 500 Cr profit). Nimbus: ROIC = 540/2,400 = 22.5% > 11% → charge 264 → EP = +276 Cr. Nearly identical net incomes, opposite value verdicts — Economic Profit charges for equity capital that accounting profit treats as free.

    5.6.2 Computing Economic Profit in Python

    def compute_economic_profit(income_stmt, balance_sheet,
                                 wacc=0.10, tax_rate=0.25):
        """
        Compute Economic Profit (EVA) = NOPAT − (WACC × Invested Capital).
    
        If you haven't yet estimated WACC (Chapters 10–11), use 10% as a
        reasonable estimate for Indian companies.
        """
        nopat = compute_nopat(income_stmt, tax_rate)
        ic = compute_invested_capital(balance_sheet)
    
        common = nopat.index.intersection(ic.index)
        nopat = nopat[common]
        ic = ic[common]
    
        capital_charge = wacc * ic
        economic_profit = nopat - capital_charge
        roic = (nopat / ic) * 100
        spread = roic - (wacc * 100)
    
        result = pd.DataFrame({
            'NOPAT (Cr)': (nopat / 1e7).round(2),
            'Invested Capital (Cr)': (ic / 1e7).round(2),
            'ROIC (%)': roic.round(2),
            'WACC (%)': wacc * 100,
            'Spread (%)': spread.round(2),
            'Capital Charge (Cr)': (capital_charge / 1e7).round(2),
            'Economic Profit (Cr)': (economic_profit / 1e7).round(2)
        })
    
        result['Value Creator?'] = result['Economic Profit (Cr)'] > 0
        return result
    
    
    # Usage
    ticker = yf.Ticker("ASIANPAINT.NS")
    ep = compute_economic_profit(ticker.financials, ticker.balance_sheet, wacc=0.10)
    print(ep)
    X Excel Path — Economic Profit in Five Rows, Driven by One WACC Cell Excel

    You already built everything except the charge. Recall: NOPAT row 48, IC row 52, ROIC row 53, and the WACC input cell $B$2 (10%) from the first Excel Path of this session. Continue the staircase:

    ' Capital Charge (row 56) — the rent on ALL capital:
    = C52 * $B$2
    ' Economic Profit (row 57):
    = C48 - C56
    ' Spread % (row 58) — the sign tells the whole story:
    = C53/100 - $B$2

    Conditional formatting: row 57 red if < 0, green if > 0. Row 58 likewise. Drag right — every year's verdict is now colour-coded.

    Why the $B$2 reference is the point of this box: change that one cell from 10% to 12% and watch every capital charge, economic profit, and colour flag across every year recompute instantly. This single-cell "what-if" is the Excel counterpart of the Python function's wacc=0.10 parameter — and it is how you will answer the committee question "would your conclusion survive a 200bp higher WACC?" in one keystroke.

    5.7 ROIC Trends: What to Look For

    A single year's ROIC is informative. The trend over 5–10 years is invaluable. It reveals the trajectory of a company's competitive position.

    5.7.1 The Four ROIC Trajectories

    PatternWhat It Looks LikeValuation Implication
    Sustained High ROIC ROIC > 20% for 5+ years with low volatility The company has a durable moat. Value it with a long competitive advantage period (15–20+ years). High terminal value justified. Examples: Asian Paints, TCS, Titan.
    Mean-Reverting ROIC Very high ROIC (>50%) that declines toward 15–20% over time Competition is eroding the moat. Forecast ROIC to mean-revert to just above WACC over 5–10 years. Do NOT extrapolate current sky-high ROIC into perpetuity. Examples: early-stage IT product companies, new pharma launches.
    Improving ROIC ROIC rising from below WACC to above WACC The company is in turnaround. Early years may show value destruction; later years show value creation. The DCF must capture the inflection. Examples: Tata Motors post-2021 recovery, cement companies post-demand revival.
    Chronically Low ROIC ROIC < 8% for 5+ years with no improvement trend The business is structurally challenged. Unless there is a credible turnaround catalyst (new management, regulatory change, industry consolidation), value it at or below book value. Growth assumptions should be minimal.
    🎨 Match the Trajectory ⏱ 3 min

    Match each 5-year ROIC path to a pattern (and guess the real company):

    1. 18% → 19% → 18% → 20% → 19% → ? pattern — and name an Indian company that looks like this
    2. 4% → 6% → 9% → 13% → 16% → ? pattern
    3. 52% → 44% → 35% → 28% → 24% → ? pattern — what must your valuation assume about the future?
    4. 6% → 5% → 7% → 4% → 5% → ? pattern — what is the one thing that could change the story?

    Pair: Compare matches. For pattern 3, discuss: would you extrapolate 24% forever, or keep fading it — and until when?

    Reveal answers

    1) Sustained High — Asian Paints / TCS. 2) Improving — Tata Motors post-2021 (or a cement recovery). 3) Mean-Reverting — fade the ROIC toward ~15% over the forecast; extrapolating 24% forever double-counts a shrinking moat. 4) Chronically Low — a PSU utility or pre-consolidation telecom; the catalyst is consolidation, regulation, or new management — without one, value near book.

    5.7.2 Visualizing ROIC Trajectories

    def plot_roic_trajectory(ticker_symbol, company_name, wacc=0.10):
        """Plot ROIC trend over time with WACC benchmark."""
        ticker = yf.Ticker(ticker_symbol)
        roic_df = compute_roic(ticker.financials, ticker.balance_sheet)
    
        fig, axes = plt.subplots(1, 2, figsize=(16, 6))
    
        # Chart 1: ROIC trend
        ax = axes[0]
        years = [str(d).split('-')[0] for d in roic_df.columns]
        roic_vals = roic_df.loc['ROIC (%)']
    
        # Color bars: green if > WACC, red if not
        colors = ['#00c9a7' if v > wacc*100 else '#e0556a' for v in roic_vals]
        ax.bar(years, roic_vals, color=colors, edgecolor='white', linewidth=0.5)
        ax.axhline(y=wacc*100, color='orange', linestyle='--', linewidth=2,
                   label=f'WACC = {wacc*100:.0f}%')
        ax.set_title(f'{company_name}: ROIC Trend')
        ax.set_ylabel('ROIC (%)')
        ax.legend()
        ax.tick_params(axis='x', rotation=45)
    
        # Chart 2: NOPAT and Invested Capital growth
        ax = axes[1]
        nopat_growth = roic_df.loc['NOPAT (Cr)'].pct_change(periods=-1) * 100
        ic_growth = roic_df.loc['Invested Capital (Cr)'].pct_change(periods=-1) * 100
        x = range(len(years) - 1)
        w = 0.35
        ax.bar([i - w/2 for i in x], nopat_growth.dropna(), w,
               label='NOPAT Growth %', color='#6c8cff')
        ax.bar([i + w/2 for i in x], ic_growth.dropna(), w,
               label='IC Growth %', color='#f0a040')
        ax.set_xticks(x)
        ax.set_xticklabels(years[1:], rotation=45)
        ax.set_title('NOPAT Growth vs Invested Capital Growth')
        ax.axhline(y=0, color='red', linestyle='--', alpha=0.5)
        ax.legend()
        ax.set_ylabel('Growth Rate (%)')
    
        # Annotation: if NOPAT grows faster than IC, ROIC is expanding
        plt.suptitle(f'{company_name} — ROIC Analysis',
                     fontsize=14, fontweight='bold', y=1.02)
        plt.tight_layout()
        plt.show()
    
    💡
    Pro Tip: The relationship between NOPAT growth and Invested Capital growth tells you whether ROIC is expanding or contracting. If NOPAT grows at 15% but Invested Capital grows at 25%, ROIC is declining — the company is investing capital faster than it is generating returns on it. This is a leading indicator of future ROIC compression.
    X Excel Path — Trajectory Detection with Sparklines and One IF Excel

    Your ROIC row 53 already holds 5–10 years across columns — the trajectory is sitting there; make it visible:

    1. Sparkline: select the ROIC row → Insert → Sparklines → Line → location: the row-label cell in column A. Each company sheet now shows its ROIC story as a tiny trend icon — flat-high, rising, fading, or flat-low is visible at a glance across the whole workbook.
    2. Trajectory tag — one formula that classifies the pattern automatically (newest year in G, first year in B, and 5 columns minimum):
    =IF(AVERAGE(B53:G53)>20, "Sustained High",
     IF(G53>B53*1.5, "Improving",
      IF(G53<B53*0.7, "Mean-Reverting",
       "Check / Chronically Low")))

    Put this tag beside every company's sparkline. It is a crude classifier — always eyeball the sparkline too — but it turns a 10-company review from a number-hunt into a one-screen scan, exactly what the Python trajectory plots deliver.

    📋 Stable content — Reviewed: June 2026

    5.8 ROIC Benchmarks Across Indian Industries

    ROIC varies systematically by industry. Comparing a steel company's ROIC to a software company's is meaningless. The following benchmarks provide context for evaluating whether a company's ROIC is exceptional within its sector:

    SectorMedian ROIC RangeTop QuartileKey Driver
    IT Services25–45%>45% (TCS)Negative working capital + asset-light model
    Consumer Staples20–40%>40% (Nestle, HUL)Brand pricing power + high turnover
    Consumer Discretionary18–35%>35% (Titan, Asian Paints)Brand + distribution moat
    Pharma12–22%>22% (Divis, Laurus)R&D productivity + patent protection
    Cement8–16%>16% (Shree Cement)Low-cost production + regional pricing power
    Automotive8–18%>18% (Maruti, Bajaj Auto)Scale + product mix + export margins
    Telecom3–8%>8% (Bharti Airtel, Jio)ARPU growth + tower infrastructure sharing
    Metals & Mining3–12% (cyclical)>12% (Hindalco Novelis)Global commodity prices + cost position
    Power / Utilities5–10%>10% (NTPC)Regulated returns + plant load factor
    PSU BanksN/A (use ROA/ROE)N/ANet Interest Margin + asset quality
    🔎 Benchmark Scavenger Hunt ⏱ 3 min

    Which sector does each ROIC profile belong to? Close the table first!

    1. Median ROIC 30%, driven by negative working capital
    2. Median ROIC 5%, driven by regulated returns and plant load factor
    3. Median ROIC 10% but highly cyclical, top quartile driven by cost position
    4. Median ROIC 16%, key driver = R&D productivity

    Pair: Compare answers, then the harder question — for profile 3, why is a "median ROIC" almost meaningless, and what should you use instead?

    Check your answers

    1) IT Services · 2) Power/Utilities · 3) Metals & Mining · 4) Pharma. For metals: ROIC swings with the commodity cycle, so use through-the-cycle average ROIC (5–10 years), never a single-year median — a peak-year 14% can coexist with a trough-year 2%.

    Hands-On Project: The ROIC Value Creation Map

    Build a comprehensive ROIC analysis for 8–10 Indian companies across at least 3 sectors. Produce a "value creation map" — a scatter plot of ROIC vs Revenue Growth — that identifies which companies are genuine value creators, which are value destroyers, and which are in transition.

    Excel Option Complete the identical project in Excel: one worksheet per company with the full formula chain from this session's Excel Path boxes (Inputs block → NOPAT → IC staircase → ROIC → Economic Profit → decomposition rows), rolled into a Summary sheet with ROIC, growth, spread, and economic profit per company. Build the Value Creation Map as a scatter chart (ROIC vs growth, labelled), set the vertical axis to cross at 10% (WACC) and horizontal at 0% to draw the quadrants, and use bubble size via a third series if you want market cap scaling. Validation: each company's ROIC should sit in the same ballpark as Screener.in's printed ROCE — if any is wildly off, audit that company's IC staircase first.

    Steps

    1. Select 8–10 companies across at least 3 sectors. Include a mix: some known for high ROIC (TCS, Asian Paints), some in capital-intensive sectors (Tata Steel, NTPC), and one that might be a value destroyer.
    2. Compute ROIC for each company using the compute_roic() pipeline. Use multiple years to get an average ROIC, not just the latest year.
    3. Compute revenue growth (3-year CAGR) for each company.
    4. Build the Value Creation Map: a scatter plot with Revenue Growth on the x-axis and ROIC on the y-axis. Size each bubble by market capitalization. Add a horizontal line at WACC (10%) and a vertical line at 0% growth to create four quadrants.
    5. Classify each company:
      • Top-Right: Value Creators (High Growth + ROIC > WACC)
      • Top-Left: Cash Cows (Low Growth + ROIC > WACC)
      • Bottom-Right: Value Destroyers (High Growth + ROIC < WACC)
      • Bottom-Left: Stagnant (Low Growth + ROIC < WACC)
    6. Write a 300-word analysis: Which quadrant do most of your companies fall into? What does this tell you about value creation in the Indian corporate sector? Identify one company whose position surprised you and explain why.
    7. Gallery Walk (NEW): Pin or screen-share your Value Creation Map. Half the class stands by their maps; the other half circulates for 5 minutes asking one question per map: "defend this company's quadrant." Then swap roles. The two most-debated placements get replayed for the whole class.
    View Solution / Walkthrough
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import yfinance as yf
    import time
    
    # --- Collect ROIC and Growth Data ---
    
    companies = {
        'TCS.NS': 'TCS',
        'ASIANPAINT.NS': 'Asian Paints',
        'TITAN.NS': 'Titan',
        'HINDUNILVR.NS': 'HUL',
        'NESTLEIND.NS': 'Nestle India',
        'RELIANCE.NS': 'Reliance',
        'TATASTEEL.NS': 'Tata Steel',
        'NTPC.NS': 'NTPC',
        'BHARTIARTL.NS': 'Bharti Airtel',
        'MARUTI.NS': 'Maruti Suzuki'
    }
    
    results_list = []
    WACC = 0.10
    
    for ticker, name in companies.items():
        try:
            t = yf.Ticker(ticker)
            info = t.info
    
            # ROIC (average of available years)
            roic_df = compute_roic(t.financials, t.balance_sheet)
            avg_roic = roic_df.loc['ROIC (%)'].mean()
    
            # 3-Year Revenue CAGR
            rev = t.financials.loc['Total Revenue']
            rev = rev.sort_index()  # Oldest first
            if len(rev) >= 4:
                years = len(rev) - 1
                cagr = ((rev.iloc[-1] / rev.iloc[-4]) ** (1/3) - 1) * 100
            else:
                cagr = rev.pct_change(periods=-1).mean() * 100
    
            mkt_cap = info.get('marketCap', np.nan)
    
            results_list.append({
                'Company': name,
                'Avg ROIC (%)': round(avg_roic, 1),
                '3Y Rev CAGR (%)': round(cagr, 1),
                'Market Cap (Cr)': mkt_cap / 1e7,
                'Spread (%)': round(avg_roic - WACC*100, 1),
                'Value Creator': avg_roic > WACC*100
            })
            print(f"✓ {name}: ROIC={avg_roic:.1f}%, Growth={cagr:.1f}%")
        except Exception as e:
            print(f"✗ {name}: {e}")
        time.sleep(1.5)
    
    results_df = pd.DataFrame(results_list)
    results_df = results_df.set_index('Company')
    
    print("\n=== Value Creation Summary ===")
    print(results_df)
    
    # --- Value Creation Map ---
    
    fig, ax = plt.subplots(figsize=(14, 10))
    
    for company in results_df.index:
        row = results_df.loc[company]
        size = max(row['Market Cap (Cr)'] / 50000, 80)  # Scale bubble size
        color = '#00c9a7' if row['Value Creator'] else '#e0556a'
        ax.scatter(row['3Y Rev CAGR (%)'], row['Avg ROIC (%)'],
                  s=size, c=color, edgecolors='white', linewidth=2,
                  alpha=0.8, zorder=5)
        ax.annotate(company,
                   (row['3Y Rev CAGR (%)'], row['Avg ROIC (%)']),
                   textcoords="offset points", xytext=(8, 6), fontsize=10,
                   fontweight='bold')
    
    # Quadrant lines
    ax.axhline(y=WACC*100, color='orange', linestyle='--', linewidth=2,
               label=f'WACC = {WACC*100:.0f}%')
    ax.axvline(x=0, color='gray', linestyle='--', linewidth=1.5,
               label='Zero Growth')
    
    # Quadrant labels
    x_max = ax.get_xlim()[1]
    y_max = ax.get_ylim()[1]
    ax.text(x_max*0.95, y_max*0.95, 'VALUE CREATORS\n(High Growth + ROIC > WACC)',
            ha='right', va='top', fontsize=11, fontweight='bold', color='#00c9a7',
            bbox=dict(boxstyle='round', facecolor='black', alpha=0.6))
    ax.text(x_max*0.05, y_max*0.95, 'CASH COWS\n(Low Growth + ROIC > WACC)',
            ha='left', va='top', fontsize=11, fontweight='bold', color='#00c9a7',
            bbox=dict(boxstyle='round', facecolor='black', alpha=0.6))
    ax.text(x_max*0.95, WACC*100*0.2, 'VALUE DESTROYERS\n(High Growth + ROIC < WACC)',
            ha='right', va='bottom', fontsize=11, fontweight='bold', color='#e0556a',
            bbox=dict(boxstyle='round', facecolor='black', alpha=0.6))
    ax.text(x_max*0.05, WACC*100*0.2, 'STAGNANT\n(Low Growth + ROIC < WACC)',
            ha='left', va='bottom', fontsize=11, fontweight='bold', color='#e0556a',
            bbox=dict(boxstyle='round', facecolor='black', alpha=0.6))
    
    ax.set_xlabel('3-Year Revenue CAGR (%)', fontsize=12)
    ax.set_ylabel('Average ROIC (%)', fontsize=12)
    ax.set_title('Indian Corporate Value Creation Map\n(Bubble Size = Market Cap)',
                 fontsize=15, fontweight='bold')
    ax.legend(loc='lower left', fontsize=9)
    ax.grid(True, alpha=0.2)
    plt.tight_layout()
    plt.show()
    
    # --- Summary Stats ---
    n_creators = results_df['Value Creator'].sum()
    n_total = len(results_df)
    print(f"\n{n_creators}/{n_total} companies earn ROIC > WACC ({n_creators/n_total*100:.0f}%)")
    print(f"Average Spread: {results_df['Spread (%)'].mean():.1f}%")
    

    Key Insights from a Typical Run:

    • Value Creators (Top-Right): Asian Paints, Titan, and TCS typically occupy this quadrant — high ROIC with sustained growth. These are the compounding machines of Indian industry.
    • Cash Cows (Top-Left): HUL and Nestle India often appear here — exceptional ROIC but mature growth. The valuation question is: can they sustain the ROIC, and how much of earnings should be returned to shareholders?
    • Cyclical/Transitional: Tata Steel and NTPC typically show ROIC near or below WACC, with growth driven by commodity cycles and capex cycles respectively. Their position on the map shifts with the cycle.
    • Surprise candidate: Bharti Airtel's ROIC has improved from sub-5% (pre-2019) to 10%+ as the telecom sector consolidated to a 3-player market. It is a case study in how industry structure determines ROIC — not just company-specific advantages.

    Key Takeaways

    1

    ROIC is the single most important number in valuation. It determines whether growth creates or destroys value. A company growing at 20% with ROIC below WACC is burning shareholder wealth.

    2

    NOPAT and Invested Capital must be carefully adjusted. The raw financial statements mix operating and non-operating items. Your job is to isolate the operating core.

    3

    Economic Profit = (ROIC − WACC) × Invested Capital. It is the absolute rupee amount of value created. Positive net income does not guarantee positive economic profit.

    4

    ROIC = NOPAT Margin × Capital Turnover. High ROIC comes from either pricing power (high margins) or capital efficiency (high turnover). The best companies have both.

    5

    The ROIC trend matters more than a single year's value. Is ROIC sustained, mean-reverting, improving, or chronically low? The trajectory determines the terminal value assumption in your DCF.

    Test Your Understanding

    1. A company has EBIT of Rs. 500 Cr, an effective tax rate of 25%, and no non-operating income. Its equity is Rs. 2,000 Cr, total debt is Rs. 1,000 Cr, and cash is Rs. 400 Cr. What is its ROIC?

    2. How can a company report positive net income but negative economic profit?

    3. In the McKinsey ROIC decomposition, ROIC = NOPAT Margin × Capital Turnover. A company has an ROIC of 30%, with a NOPAT Margin of 15%. What is its Capital Turnover?

    4. Why is excess cash subtracted from invested capital when computing ROIC?

    5. A company's ROIC has declined from 28% to 16% over 5 years while its revenue grew at 18% annually. Invested capital grew at 30% annually. What does this pattern suggest?

    📝 Quick Reflection ⏱ 1 min

    Name one company you now suspect is a value destroyer despite healthy profits. Write down its ROIC, its likely WACC, and the sign of its economic profit. Keep this note — it is a candidate capstone company, and Session 6's dashboard will let you show its ROIC-vs-WACC gap visually to a boardroom audience.