Session 16 of 26 Part VI: Relative Valuation — Chapter 15 of 18
Part VI: Relative Valuation Chapter 15 of 18 Session 16 Python

Price Multiples: P/E, P/B & PEG Ratios

Value companies by comparison — compute and interpret price multiples, identify genuine peers with statistical filters, and understand the fundamental drivers behind every multiple.

Learning Objectives

15.1 The Philosophy of Relative Valuation

Relative valuation values an asset by comparing it to how similar assets are priced in the market. Instead of asking "what are this company's future cash flows worth?" (the DCF question), it asks "what are investors paying for comparable companies right now?"

Relative valuation dominates practice. A survey of equity research reports found that over 85% use multiples as either the primary or secondary valuation method. Investment bankers price IPOs on multiples. Private equity firms make buyout decisions on multiples. The reasons are practical:

Strengths of Relative Valuation

  • Simple, fast, and intuitive
  • Reflects current market mood and sector sentiment
  • Requires far fewer explicit assumptions than a DCF
  • Easy to communicate: "Trades at 12x vs peers at 15x"
  • Provides a market-based reality check on DCF results

Weaknesses of Relative Valuation

  • If the peer group is mispriced, your valuation is wrong
  • No two companies are truly identical — the "comparable" is always approximate
  • Multiples ignore company-specific differences in growth, risk, and quality
  • Market-wide overvaluation or undervaluation contaminates all multiples
  • Easy to manipulate by cherry-picking peers
🌎
Real World: In the 2021 IPO boom, several Indian tech startups (Zomato, Nykaa, Paytm) were valued at 40–60x revenue using relative valuation — because global peers traded at those multiples. Within 12 months, many had fallen 50–70% as the peer group multiples compressed. Relative valuation told you what the market was paying; it did not tell you whether the market was right. This is why a DCF cross-check is essential — if your DCF intrinsic value is Rs. 600 and the peer group implies Rs. 1,200, one of them is wrong. Usually, it is the peer group during a bubble.

15.2 The P/E Ratio: The Ubiquitous Multiple

The Price-to-Earnings (P/E) ratio is the most widely used valuation multiple in the world. It is reported on every financial website, cited in every earnings call, and embedded in the collective consciousness of investors. But its ubiquity masks important subtleties.

P/E = Market Price per Share / Earnings per Share (EPS)
P/E = Market Capitalization / Net Income

15.2.1 Which Earnings? Trailing vs Forward

VariantEarnings UsedUse Case
Trailing P/ELast 4 quarters (TTM) or last fiscal yearBased on actual reported earnings — factual, but backward-looking
Forward P/EConsensus analyst estimate for next 12 monthsForward-looking, but depends on analyst accuracy. Forward P/E is typically lower than trailing for growing companies.
Normalized P/EAverage earnings over 3–5 years or through-the-cycle earningsAdjusts for cyclicality. Essential for cyclicals (metals, autos) where current earnings may be at a peak or trough.

15.2.2 The Fundamental Drivers of P/E

P/E is not an independent number. It is determined by the same value drivers we studied throughout this course. The P/E ratio implied by a DCF is:

P/E = (Payout Ratio) / (Ke − g)
P/E = 1 / Ke × [1 + (ROE − Ke) / (Ke − g) × Retention Ratio]

This tells us P/E increases with: higher growth (g), higher ROE, lower risk (Ke). A company with a P/E of 30 is not "overvalued" if it has 25% ROE and 15% growth. A company with a P/E of 8 is not "cheap" if it has 5% ROE and 0% growth. The P/E must be interpreted relative to its fundamental drivers.

15.2.3 P/E in Python

import yfinance as yf
import pandas as pd
import numpy as np

def fetch_pe_and_drivers(ticker_symbol):
    """Fetch P/E ratio and its fundamental drivers for a company."""
    ticker = yf.Ticker(ticker_symbol)
    info = ticker.info

    pe_trailing = info.get('trailingPE')
    pe_forward = info.get('forwardPE')
    eps_ttm = info.get('trailingEps')
    growth = info.get('revenueGrowth', 0) * 100
    roe = info.get('returnOnEquity', 0) * 100 if info.get('returnOnEquity') else None
    beta = info.get('beta')
    market_cap = info.get('marketCap', 0) / 1e7

    return {
        'ticker': ticker_symbol.replace('.NS', ''),
        'company': info.get('longName', ticker_symbol),
        'trailing_pe': pe_trailing,
        'forward_pe': pe_forward,
        'eps_ttm': eps_ttm,
        'revenue_growth_pct': round(growth, 1),
        'roe_pct': round(roe, 1) if roe else None,
        'beta': round(beta, 2) if beta else None,
        'market_cap_cr': round(market_cap, 0),
    }


# --- Fetch P/E for a set of Indian companies ---
tickers = ['TCS.NS', 'INFY.NS', 'WIPRO.NS', 'HCLTECH.NS', 'TECHM.NS',
           'ASIANPAINT.NS', 'TITAN.NS', 'RELIANCE.NS']
pe_data = []
for t in tickers:
    try:
        pe_data.append(fetch_pe_and_drivers(t))
    except Exception as e:
        print(f"Error for {t}: {e}")

pe_df = pd.DataFrame(pe_data).set_index('ticker')
print("=== P/E RATIOS — SELECT INDIAN COMPANIES ===")
print(pe_df.to_string())

15.2.4 P/E Interpretation Guide

SectorTypical Trailing P/E Range (India)What Drives It
IT Services20–35xHigh ROE (30–45%), moderate growth (8–15%), zero debt
Consumer Staples40–70xExceptional ROE (40–100% due to negative working capital), stable growth, low beta
Private Banks15–25xModerate ROE (12–18%), GDP-plus loan growth
Automotive15–30xCyclical earnings; use normalized P/E. Maruti trades at premium to Tata Motors.
Pharma20–40xR&D-driven growth, patent cliff risk, US FDA regulatory risk
Metals & Mining5–15xCommodity cycle; P/E is low at cycle peak (high E), high at trough (low E). Normalized P/E essential.
PSU / Utilities8–15xRegulated returns, low growth, government ownership discount
P/E Red Flags: (1) A P/E below 5 — either the company is in distress, or earnings are unsustainably high. (2) A P/E above 100 — either extraordinary growth is priced in, or earnings are near zero. (3) A negative P/E — the company is losing money; P/E is meaningless. Use EV/EBITDA or Price/Sales instead. (4) A P/E that diverges sharply from historical range without a clear fundamental reason — investigate for earnings manipulation or structural change.

15.3 The P/B Ratio: Value in Assets

The Price-to-Book (P/B) ratio compares market value to the accounting book value of equity. It is most useful for financial institutions and asset-heavy companies where book value is a meaningful measure of economic worth — and least useful for asset-light, brand-driven companies where most value is intangible.

P/B = Market Price per Share / Book Value per Share
P/B = Market Capitalization / Shareholders' Equity

15.3.1 The Fundamental Driver of P/B

P/B = (ROE − g) / (Ke − g)

A company trades above book value (P/B > 1) only if it earns a return on equity (ROE) that exceeds its cost of equity (Ke). The higher the ROE relative to Ke, the higher the P/B. This is why Titan (ROE ~30%, P/B ~76x) commands a vastly higher P/B than a PSU bank (ROE ~8%, P/B ~0.8x).

15.3.2 When P/B Works (and When It Does Not)

P/B Works Well ForP/B Fails For
Banks, NBFCs, insurance companies — assets and liabilities are mostly financial and marked-to-market or near-marketTechnology companies — most value is in intellectual property and human capital, which does not appear on the balance sheet
Asset-heavy industrials (cement, steel) — book value is a reasonable floor for liquidation valueConsumer brands (Titan, Nestle, Asian Paints) — brand value is largely absent from book value
REITs, infrastructure holding companiesPharma — patent portfolios and R&D pipelines are not on the books
Companies where ROE is stable and mean-revertingCompanies with significant goodwill from acquisitions — book value is inflated by purchase accounting

15.3.3 P/B in Python

def fetch_pb_and_roe(ticker_symbol):
    """Fetch P/B ratio and ROE to validate the P/B = f(ROE) relationship."""
    ticker = yf.Ticker(ticker_symbol)
    info = ticker.info

    pb = info.get('priceToBook')
    roe = info.get('returnOnEquity', 0) * 100 if info.get('returnOnEquity') else None

    return {'ticker': ticker_symbol.replace('.NS', ''),
            'pb_ratio': round(pb, 1) if pb else None,
            'roe_pct': round(roe, 1) if roe else None}


# --- Compare P/B vs ROE across sectors ---
stocks_for_pb = ['HDFCBANK.NS', 'ICICIBANK.NS', 'SBIN.NS',  # Banks
                 'TCS.NS', 'ASIANPAINT.NS', 'TATASTEEL.NS',  # IT, Consumer, Metals
                 'NTPC.NS', 'TITAN.NS']
pb_data = []
for t in stocks_for_pb:
    try:
        pb_data.append(fetch_pb_and_roe(t))
    except Exception as e:
        print(f"Error: {t}: {e}")

pb_df = pd.DataFrame(pb_data).set_index('ticker')
print("=== P/B vs ROE ===")
print(pb_df)
print(f"\nCorrelation (ROE, P/B): {pb_df['roe_pct'].corr(pb_df['pb_ratio']):.2f}")
print("→ P/B is driven by ROE. Higher ROE → Higher P/B.")

15.4 The PEG Ratio: Growth-Adjusted Valuation

The PEG ratio (Price/Earnings-to-Growth) divides the P/E ratio by the earnings growth rate. It addresses the most common objection to P/E-based comparisons: "Company A deserves a higher P/E because it is growing faster." PEG normalizes for growth.

PEG = (P/E Ratio) / (Earnings Growth Rate %)

A PEG of 1.0 is the traditional "fair value" benchmark — the company's P/E equals its growth rate. PEG < 1.0 suggests undervaluation; PEG > 1.0 suggests overvaluation. But this rule of thumb is crude. The true fair PEG depends on the company's risk and return profile — a high-ROE, low-risk company deserves a PEG > 1.0.

15.4.1 PEG in Python

def compute_peg(ticker_symbol):
    """Compute the PEG ratio = Trailing P/E / Earnings Growth Rate (%)."""
    ticker = yf.Ticker(ticker_symbol)
    info = ticker.info

    pe = info.get('trailingPE')
    # Earnings growth: use the average of historical and forward where available
    earnings_growth = info.get('earningsGrowth', 0) * 100
    if earnings_growth == 0:
        earnings_growth = info.get('earningsQuarterlyGrowth', 0) * 100

    peg = pe / earnings_growth if earnings_growth and earnings_growth > 0 else None

    return {
        'ticker': ticker_symbol.replace('.NS', ''),
        'pe': round(pe, 1) if pe else None,
        'earnings_growth_pct': round(earnings_growth, 1),
        'peg': round(peg, 2) if peg else None,
    }


# --- Compare PEG across companies ---
peg_tickers = ['TCS.NS', 'INFY.NS', 'ASIANPAINT.NS', 'TITAN.NS',
               'RELIANCE.NS', 'TATASTEEL.NS']
peg_data = [compute_peg(t) for t in peg_tickers]
peg_df = pd.DataFrame(peg_data).set_index('ticker')
print("=== PEG RATIOS ===")
print(peg_df)
print(f"\nMedian PEG: {peg_df['peg'].median():.2f}")
print("PEG < 1.0 may indicate undervaluation relative to growth.")
print("PEG > 2.0 may indicate the market is pricing in even higher future growth.")
📝
The PEG Trap: PEG uses one year of earnings growth, which can be highly volatile. A company with 5% earnings growth that had a one-time 40% earnings jump will show a deceptively low PEG. Always use a normalized or sustainable growth rate — the 3–5 year average or the long-run implied growth from reinvestment rate × ROIC (Chapter 12). Never compute PEG on a single year of anomalous growth.

15.5 Finding Comparable Companies with Statistical Filters

The single most important step in relative valuation is selecting the right peer group. Cherry-picking peers is the easiest way to manipulate a multiples-based valuation. A disciplined approach uses objective, quantifiable filters that can be defended.

15.5.1 The Five-Filter Framework

FilterWhat It ScreensExample for TCS
1. Sector/IndustrySame 2-digit or 3-digit NIC code, or same GICS sectorIT Services (NIC 62)
2. SizeRevenue or Market Cap within 0.2x–5x of targetRevenue Rs. 30,000–2,50,000 Cr
3. GrowthRevenue growth within ±10% of target's 3Y CAGR8–18% revenue growth
4. ProfitabilityOperating margin within ±10% or ROE within ±15%Operating margin 18–30%
5. LeverageD/E within 0–0.5 (for non-financials)D/E < 0.3 (asset-light IT)

15.5.2 Peer Selection in Python

def find_comparable_companies(target_ticker, candidate_tickers,
                                sector_filter=True, size_filter=True,
                                growth_filter=True, profitability_filter=True,
                                leverage_filter=True):
    """
    Identify truly comparable companies using statistical filters.

    Returns the filtered peer group with their key metrics.
    """
    # Fetch target company data
    target = yf.Ticker(target_ticker)
    target_info = target.info
    target_sector = target_info.get('sector', '')
    target_industry = target_info.get('industry', '')
    target_mcap = target_info.get('marketCap', 0) / 1e7
    target_rev_growth = target_info.get('revenueGrowth', 0) * 100
    target_op_margin = (target_info.get('operatingMargins', 0) * 100
                        if target_info.get('operatingMargins') else None)

    print(f"Target: {target_info.get('longName', target_ticker)}")
    print(f"  Sector: {target_sector} | MCap: Rs.{target_mcap:,.0f}Cr | "
          f"Rev Growth: {target_rev_growth:.1f}%")

    # Fetch all candidates
    peers = []
    for tkr in candidate_tickers:
        try:
            t = yf.Ticker(tkr)
            info = t.info
            mcap = info.get('marketCap', 0) / 1e7
            rev_g = info.get('revenueGrowth', 0) * 100
            op_m = (info.get('operatingMargins', 0) * 100
                    if info.get('operatingMargins') else None)
            de = info.get('debtToEquity', 0) / 100 if info.get('debtToEquity') else 0
            pe = info.get('trailingPE')
            pb = info.get('priceToBook')

            # Apply filters
            passes = True
            reasons = []

            if sector_filter:
                if info.get('sector') != target_sector:
                    passes = False
                    reasons.append('Sector mismatch')

            if size_filter and mcap > 0:
                if not (target_mcap * 0.2 <= mcap <= target_mcap * 5):
                    passes = False
                    reasons.append(f'Size out of range')

            if growth_filter and rev_g:
                if abs(rev_g - target_rev_growth) > 10:
                    passes = False
                    reasons.append(f'Growth diff > 10%')

            if profitability_filter and op_m and target_op_margin:
                if abs(op_m - target_op_margin) > 10:
                    passes = False
                    reasons.append(f'Margin diff > 10%')

            if leverage_filter and de:
                if de > 1.5:  # Exclude highly leveraged
                    passes = False
                    reasons.append(f'High leverage (D/E={de:.1f})')

            peers.append({
                'Ticker': tkr.replace('.NS', ''),
                'Company': info.get('longName', tkr),
                'Sector': info.get('sector', ''),
                'MCap (Cr)': round(mcap, 0),
                'Rev Growth %': round(rev_g, 1),
                'Op Margin %': round(op_m, 1) if op_m else None,
                'D/E': round(de, 2),
                'Trailing P/E': round(pe, 1) if pe else None,
                'P/B': round(pb, 1) if pb else None,
                'Passes': passes,
                'Reject Reason': '; '.join(reasons) if not passes else '✓'
            })
        except Exception as e:
            print(f"  Error fetching {tkr}: {e}")

    peer_df = pd.DataFrame(peers)
    filtered = peer_df[peer_df['Passes']]

    print(f"\n  Total candidates: {len(candidates)}")
    print(f"  Passed all filters: {len(filtered)}")
    print(f"  Rejected: {len(peer_df) - len(filtered)}")
    print(f"\n  === COMPARABLE PEERS ===")
    print(filtered[['Ticker', 'Trailing P/E', 'P/B', 'Rev Growth %', 'Op Margin %']].to_string(index=False))
    print(f"\n  Median Trailing P/E: {filtered['Trailing P/E'].median():.1f}x")
    print(f"  Median P/B: {filtered['P/B'].median():.1f}x")

    return filtered, peer_df


# --- Example: Find peers for Infosys ---
it_candidates = ['TCS.NS', 'INFY.NS', 'WIPRO.NS', 'HCLTECH.NS', 'TECHM.NS',
                 'LTIM.NS', 'PERSISTENT.NS', 'COFORGE.NS', 'MPHASIS.NS',
                 'SONATSOFTW.NS', 'ZENSARTECH.NS', 'TANLA.NS']
filtered_peers, all_peers = find_comparable_companies('INFY.NS', it_candidates)

15.6 From Peer Multiples to Target Price

With a validated peer group, the relative valuation is straightforward: apply the peer group's median multiple to the target company's corresponding fundamental.

Target Price (P/E method) = Peer Median P/E × Target EPS
Target Price (P/B method) = Peer Median P/B × Target BV/Share
def relative_valuation(target_ticker, peer_tickers):
    """
    Perform a complete relative valuation.

    1. Find comparable peers using statistical filters
    2. Compute peer group median multiples
    3. Apply to target company fundamentals
    4. Derive target price and compare to DCF
    """
    target = yf.Ticker(target_ticker)
    t_info = target.info
    t_name = t_info.get('longName', target_ticker)
    t_price = t_info.get('currentPrice') or t_info.get('previousClose')
    t_eps = t_info.get('trailingEps')
    t_bv = t_info.get('bookValue')

    # Find peers
    filtered, _ = find_comparable_companies(target_ticker, peer_tickers)

    # Peer multiples
    median_pe = filtered['Trailing P/E'].median()
    median_pb = filtered['P/B'].median()

    # Target values
    pe_target = median_pe * t_eps if t_eps and median_pe else None
    pb_target = median_pb * t_bv if t_bv and median_pb else None
    avg_target = np.nanmean([pe_target, pb_target]) if pe_target and pb_target else (pe_target or pb_target)

    print(f"\n{'='*50}")
    print(f"  RELATIVE VALUATION: {t_name}")
    print(f"{'='*50}")
    print(f"\n  Peer Group: {len(filtered)} companies")
    print(f"  Median P/E: {median_pe:.1f}x")
    print(f"  Median P/B: {median_pb:.1f}x")
    print(f"\n  Target Fundamentals:")
    print(f"    EPS (TTM):  Rs. {t_eps:.2f}" if t_eps else "    EPS: N/A")
    print(f"    BV/Share:   Rs. {t_bv:.2f}" if t_bv else "    BV/Share: N/A")
    print(f"\n  Implied Target Prices:")
    if pe_target:
        print(f"    P/E Method:  Rs. {pe_target:,.0f} "
              f"({'↑' if pe_target > t_price else '↓'} "
              f"{(pe_target/t_price - 1)*100:+.1f}% vs market)")
    if pb_target:
        print(f"    P/B Method:  Rs. {pb_target:,.0f} "
              f"({'↑' if pb_target > t_price else '↓'} "
              f"{(pb_target/t_price - 1)*100:+.1f}% vs market)")
    if avg_target:
        print(f"    Average:     Rs. {avg_target:,.0f}")

    print(f"\n  Current Price: Rs. {t_price:,.0f}")
    print(f"\n  NOTE: Relative valuation reflects market sentiment.")
    print(f"  Cross-check with DCF intrinsic value from Chapter 14.")

    return {
        'target': target_ticker,
        'peers_used': len(filtered),
        'median_pe': median_pe,
        'median_pb': median_pb,
        'pe_target_price': pe_target,
        'pb_target_price': pb_target,
        'avg_target_price': avg_target,
        'current_price': t_price,
    }


# --- Run relative valuation for Infosys ---
rel_val = relative_valuation('INFY.NS', it_candidates)

15.7 Common Multiples Traps and How to Avoid Them

Trap 1: Using the simple average instead of the median. The mean is distorted by outliers. One peer with a P/E of 500x can pull the average up by 20%. Always use the median or harmonic mean for peer group multiples.
Trap 2: Ignoring differences in capital structure. P/E and P/B are equity multiples — they are affected by leverage. Two identical companies with different D/E ratios will have different P/E ratios even if their enterprise values are the same. Use EV-based multiples (EV/EBITDA, EV/EBIT) for companies with different leverage. We cover these in Chapter 16.
Trap 3: Comparing multiples across sectors. A P/E of 12 is cheap for a consumer staple company but expensive for a steel company. Every sector has its own multiple regime. Never say "Company A is cheaper than Company B" unless they are in the same sector with similar growth and risk profiles.
Trap 4: Using a single year's earnings for cyclical companies. At the bottom of the cycle, earnings are depressed — P/E looks high (the denominator is small). At the peak, earnings are inflated — P/E looks low. For cyclicals, use normalized earnings (5-year average) or through-the-cycle estimates. Otherwise, you will systematically buy at the peak and sell at the trough.
Trap 5: The "peer group" of one. Selecting only the 2–3 companies that support your desired valuation is manipulation, not analysis. Define your filters before you see the results. Disclose which companies were excluded and why. If challenged, be prepared to defend every inclusion and exclusion with data.

Hands-On Project: Relative Valuation for Your Capstone Company

Perform a complete relative valuation of your capstone company using P/E, P/B, and PEG multiples. Identify a defensible peer group using the five statistical filters, compute the implied target price from peer multiples, and compare the result to your DCF intrinsic value from Chapter 14.

Steps

  1. Identify 10–15 candidate peers in the same sector as your capstone company. Use Screener.in or Yahoo Finance to build the list.
  2. Apply the five statistical filters from Section 15.5. Document which companies passed and which were rejected, with reasons.
  3. Compute peer median P/E and P/B. Use trailing P/E (TTM) for consistency. If the peer group has fewer than 4 companies after filtering, relax the filters incrementally and document why.
  4. Derive the implied target price from P/E and P/B. Average the two if both are available.
  5. Compute the PEG ratio for each peer and your target. Is your target's PEG above or below the peer median?
  6. Compare to DCF: Plot a bar chart showing: (a) Current market price, (b) DCF intrinsic value (from Ch14), (c) Relative valuation target (P/E method), (d) Relative valuation target (P/B method). Which method suggests the stock is most undervalued? Which is most conservative?
  7. Write a 200-word reconciliation: If the DCF and relative valuation give different answers, why? What assumption differences explain the gap? Which method do you trust more for this company and why?
View Solution / Walkthrough

Relative Valuation — Infosys (Illustrative)

# ================================================================
# COMPLETE RELATIVE VALUATION — Infosys
# ================================================================

# DCF value from Chapter 14 (hypothetical)
dcf_iv = 1850  # Rs. per share

# Run relative valuation
rel_val = relative_valuation('INFY.NS', it_candidates)

# Comparison chart
fig, ax = plt.subplots(figsize=(10, 6))
methods = ['Market\nPrice', 'DCF\n(Ch14)', 'P/E\nMethod', 'P/B\nMethod']
values = [
    rel_val['current_price'],
    dcf_iv,
    rel_val['pe_target_price'],
    rel_val['pb_target_price']
]
colors = ['gray', '#6c8cff', '#00c9a7', '#f0a040']
bars = ax.bar(methods, values, color=colors, edgecolor='white', linewidth=1.5)
for bar, val in zip(bars, values):
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + max(values)*0.01,
            f'Rs.{val:,.0f}', ha='center', fontweight='bold', fontsize=11)
    if val != rel_val['current_price']:
        pct = (val / rel_val['current_price'] - 1) * 100
        ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() * 0.5,
                f'{pct:+.0f}%', ha='center', color='white', fontweight='bold', fontsize=10)

ax.set_ylabel('Value Per Share (Rs.)')
ax.set_title('Valuation Method Comparison — Infosys', fontweight='bold', fontsize=14)
ax.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()

# Reconciliation
print(f"""
=== DCF vs RELATIVE VALUATION RECONCILIATION ===

DCF Intrinsic Value:       Rs. {dcf_iv:,.0f}
Relative Valuation (Avg):  Rs. {rel_val['avg_target_price']:,.0f}
Difference:                Rs. {rel_val['avg_target_price'] - dcf_iv:,.0f}

Possible explanations for the gap:
1. The market (relative valuation) may be pricing in higher near-term
   growth than my DCF terminal growth assumes.
2. The DCF's WACC of 10.6% may be conservative vs the market-implied
   discount rate embedded in current peer multiples.
3. Peer multiples may incorporate an acquisition premium or scarcity
   premium not captured in the DCF.
4. If DCF > Relative: the market may be undervaluing the company's
   long-term competitive advantages that are captured in my DCF.

For Infosys, I place more weight on the DCF because:
• The IT services sector's multiples are sensitive to global tech
  spending cycles and can be volatile.
• Infosys's value is primarily driven by long-term cash flow generation
  (captured in DCF), not by asset value (P/B is less relevant for IT).
• The DCF forces explicit thinking about the sustainability of Infosys's
  margins and growth, while multiples embed market sentiment.
""")

Key Takeaways

1

Multiples are driven by fundamentals. P/E is driven by growth, risk, and ROE. P/B is driven by ROE relative to Ke. Never compare multiples without comparing the fundamentals that explain them.

2

The peer group is the model. Statistical filters (sector, size, growth, profitability, leverage) produce a defensible peer set. Cherry-picking peers to hit a target price is manipulation.

3

PEG adjusts P/E for growth — but use normalized growth. A single year's earnings spike produces a misleadingly low PEG. Use 3–5 year average growth or the implied sustainable growth rate.

4

P/B works for banks and asset-heavy companies; it fails for asset-light, brand-driven businesses. Titan's P/B of 76x is not "overvalued" — it reflects that most of Titan's value is not on the balance sheet.

5

Relative valuation and DCF are complementary, not competing. When they agree, you have confirmation. When they disagree, investigate why — the gap reveals what the market believes that your DCF does not (or vice versa).

Test Your Understanding

1. A company has a P/E of 25, an ROE of 30%, and earnings growth of 20%. Its peer has a P/E of 15, ROE of 10%, and growth of 5%. Is the first company overvalued relative to the peer?

2. Why is the P/B ratio usually inappropriate for technology companies?

3. You need to value a cyclical steel company. Its current P/E is 6 (near a 10-year low). What is the most appropriate action?

4. In peer group selection, why is the median multiple preferred over the mean (simple average)?

5. Your DCF gives an intrinsic value of Rs. 1,200/share. Relative valuation (peer median P/E) gives Rs. 1,600/share. The current market price is Rs. 1,400. Which interpretation is most reasonable?