From 4a9a00d4ec9b9e9ee3a4ea1df165fb8f27a10d39 Mon Sep 17 00:00:00 2001 From: eggmasonvalue Date: Mon, 31 Aug 2026 23:24:22 +0530 Subject: [PATCH] refactor: sharpen bottom-up analyst skill --- context/MAP.md | 11 +- skills/README.md | 8 +- skills/bottom-up-analyst/README.md | 119 ++-- skills/bottom-up-analyst/SKILL.md | 462 +++++-------- .../references/archetypes/compounder.md | 123 ++-- .../references/archetypes/cyclical.md | 115 ++-- .../references/archetypes/deep_value.md | 129 ++-- .../references/archetypes/hypergrowth.md | 127 ++-- .../archetypes/special_situation.md | 126 ++-- .../references/archetypes/turnaround.md | 131 ++-- .../references/guide_competitive.md | 238 ++++--- .../references/guide_normalization.md | 296 +++++---- .../references/guide_ownership_signals.md | 173 +++-- .../references/guide_valuation.md | 403 +++++------ .../references/memo_template.md | 309 ++++----- skills/bottom-up-analyst/scripts/dcf.py | 624 +++++++++++------- skills/bottom-up-analyst/scripts/epv.py | 244 +++---- 17 files changed, 1844 insertions(+), 1794 deletions(-) diff --git a/context/MAP.md b/context/MAP.md index f5e08be..f8130f8 100644 --- a/context/MAP.md +++ b/context/MAP.md @@ -16,7 +16,7 @@ skills/ Skill collection and skill-level documentation signal-sweep/ Discovery — scan the universe, surface tickers sec-edgar-skill/ Data — SEC EDGAR filings, ownership, 13F holders market-scout/ Data — price, peers, transcripts (Yahoo Finance) - bottom-up-analyst/ Analysis — one ticker → auditable memo (the conductor) + bottom-up-analyst/ Analysis — one operating company → scoped answer or memo pitch-like-lou/ Voice — finished thesis → VIC-style pitch context/ Agent-maintained project documentation ``` @@ -64,14 +64,14 @@ sessions, and unrelated settings remain profile-local and untouched. ```mermaid flowchart TD - SS[signal-sweep
surfaces tickers] --> BUA[bottom-up-analyst
deep dive + memo] + SS[signal-sweep
surfaces tickers] --> BUA[bottom-up-analyst
analysis + optional memo] BUA --> SEC[sec-edgar-skill
filings] BUA --> MS[market-scout
price / peers / transcripts] BUA --> PLL[pitch-like-lou
renders pitch] ``` -- `bottom-up-analyst` is the brain and conductor: it decides what to pull, reasons over it, - and writes the memo. The data skills never decide what matters. +- `bottom-up-analyst` selects evidence, reasons over it, and produces the requested analysis or + full memo. Retrieval contracts and source semantics remain in the data skills. - The two filing/market data skills know nothing of each other and are swappable. - `signal-sweep` and SEC-facing `sec-edgar-skill` commands read `EDGAR_IDENTITY` and use on-disk cache contracts defined in their `_common.py` modules. The SEC skill's routine 13F @@ -80,7 +80,8 @@ flowchart TD ## Production order -`signal-sweep` → `bottom-up-analyst` → memo → optionally `pitch-like-lou`. +For a full thesis: `signal-sweep` → `bottom-up-analyst` → memo → optionally +`pitch-like-lou`. For the package installation and isolated-profile workflow, start at the root [`README.md`](../README.md). For the collection overview, start at diff --git a/skills/README.md b/skills/README.md index 12396a3..0bcfb8f 100644 --- a/skills/README.md +++ b/skills/README.md @@ -11,7 +11,7 @@ they form a research pipeline. | **Discovery** | [`signal-sweep`](signal-sweep/) | Scan SEC filings and market data to surface new investment ideas. | | **Data** | [`sec-edgar-skill`](sec-edgar-skill/) | Retrieve and extract SEC filings, ownership, and 13F holder data. | | **Data** | [`market-scout`](market-scout/) | Pull prices, returns, peers, sector screens, and transcripts. | -| **Analysis** | [`bottom-up-analyst`](bottom-up-analyst/) | Turn one ticker into an auditable investment memo. | +| **Analysis** | [`bottom-up-analyst`](bottom-up-analyst/) | Turn one operating company into scoped analysis or an auditable investment memo. | | **Voice** | [`pitch-like-lou`](pitch-like-lou/) | Render a finished thesis as a VIC-style pitch. | ## Data flow @@ -28,7 +28,8 @@ they form a research pipeline. ``` `bottom-up-analyst` is the conductor. It decides what to pull, reasons over the evidence, -values the business, and writes the memo. The data skills never decide what matters. +values the business, and produces the requested analysis or full memo. The data skills supply +the underlying evidence. `signal-sweep` and `sec-edgar-skill` are independent data sources. `market-scout` is also swappable: the analyst can use a different market-data provider without changing its @@ -36,7 +37,8 @@ reasoning workflow. The voice skill renders from a finished thesis; it is not an idea generator. -**Production order:** signal-sweep → bottom-up-analyst → memo → optionally pitch-like-lou. +**Production order for a full thesis:** signal-sweep → bottom-up-analyst → memo → optionally +pitch-like-lou. ## Progressive disclosure diff --git a/skills/bottom-up-analyst/README.md b/skills/bottom-up-analyst/README.md index 95091e3..b779437 100644 --- a/skills/bottom-up-analyst/README.md +++ b/skills/bottom-up-analyst/README.md @@ -1,64 +1,55 @@ -# Bottom-Up Analyst - -An [agent skill](SKILL.md) that turns **one company** into an **earned investment thesis**, -written up as a detailed, auditable due-diligence memo. It is the analytical engine of a -bottom-up research stack: given a ticker or a name, it drives SEC-filing and market-data -tools for grounding, reasons over the evidence, classifies the business into an archetype, -triangulates an intrinsic-value range, tries to kill its own thesis, and writes the memo. - -## Where it sits - -The **analyst** in a three-layer stack: the [data skills](../sec-edgar-skill/) ground it, and -[`pitch-like-lou`](../pitch-like-lou/) renders a pitch from its memo. The analyst is the missing -middle — it decides what to pull, reasons to a verdict, values the business, and writes the memo; -the data skills decide nothing and Lou assumes the work is already done. See the -[stack overview](../README.md) for how the four compose. **Production order:** analyst → memo → -(optionally) Lou pitches from it; the definition of done is a **pitch-ready memo**. - -## What it does - -- **Classifies** the company into one of six archetypes and loads the matching playbook — - *compounder, hypergrowth, cyclical, turnaround/inflection, special-situation, deep-value* — - so the right questions get the weight. (Lou's three value-investing shapes are a subset; - the rest extend past where he worked. "Anything else" falls back to the core method.) -- **Normalizes** GAAP into owner earnings — maintenance vs. growth capex, stock comp, deferred - revenue, one-offs — and shows capital allocation as a year-by-year trend. -- **Analyzes competitive position** filings-first (including *peers'* filings for management - commentary), using the web only for what filings genuinely can't give — and labels it. -- **Values** by triangulation, weighted by archetype, with a **reverse-DCF** ("what's priced - in?") as a first-class lens alongside forward DCF, EPV, and multiples. -- **Stress-tests** every thesis against the archetype's disqualifiers and a borrowed - discipline: separate what you *know* from what you *believe*, concede the weak points, never - let conviction outrun the evidence. - -## Layout - -- `SKILL.md` — the skill itself (the entry point an agent loads): the loop, archetype routing, - how it drives the tools, and the valuation tooling. -- `references/` — lazily-loaded guides: the memo template, normalization, competitive analysis, - valuation, ownership signals, and one playbook per archetype (`references/archetypes/`). -- `scripts/` — thin, self-documenting valuation tools: - - `dcf.py` — two-stage DCF, **forward** (assumptions → intrinsic value) and **reverse** - (price → implied growth), with a bear/base/bull sensitivity table. - - `epv.py` — Earnings Power Value, the no-growth floor. - -## Setup - -The valuation scripts are pure-Python (standard library only) — no install needed: - -```bash -python scripts/dcf.py --help -python scripts/epv.py --help -``` - -For the data layer, install and configure [`sec-edgar-skill`](../sec-edgar-skill/) (it needs an -`EDGAR_IDENTITY`) and, for market data, [`market-scout`](../market-scout/); this skill drives -those tools but does not re-document them. - -## A note on scope - -This skill produces analysis, not advice. It is a tool for doing research rigorously and -honestly; it does not know your circumstances and nothing it writes is a recommendation to buy -or sell a security. Its entire design — the honesty markup, the pre-mortem, the -verified-vs-assumed tagging — exists to keep an LLM's fluent prose tethered to evidence, so -that a human can audit every claim and reach their own judgment. +# Bottom-Up Analyst + +An [agent skill](SKILL.md) for substantive, long-only fundamental research on one +non-financial operating company. It turns filing, market, industry, and ownership evidence +into a scoped answer or a full, auditable due-diligence memo. + +The framework is designed for companies whose operating economics and cash flows can be +underwritten. It is not the primary framework for banks, insurers, REITs, funds, or +predominantly binary-asset companies. + +## What it does + +- Scales the work to the question instead of forcing every request into a full memo. +- Selects one or more optional analytical lenses: compounder, hypergrowth, cyclical, + turnaround, special situation, or deep value. +- Reconciles reported results to normalized economics without double-counting stock + compensation, leases, working capital, or enterprise-to-equity adjustments. +- Underwrites competitive position, management incentives, ownership, and governance when + they are material to value. +- Chooses valuation methods for the business rather than mechanically running every method. +- Separates verified evidence, estimates, assumptions, and external evidence, with citations. +- Builds the strongest countercase and lets conviction fall when evidence is incomplete. + +## Layout + +- `SKILL.md` — workflow, evidence discipline, resource routing, and script examples. +- `references/memo_template.md` — adaptable full-memo skeleton. +- `references/guide_*.md` — normalization, competition, valuation, and + ownership/governance guidance. +- `references/archetypes/` — optional playbooks for six common thesis shapes. +- `scripts/dcf.py` — forward, explicit-forecast, and reverse enterprise DCF. +- `scripts/epv.py` — no-growth Earnings Power Value arithmetic. + +## Setup + +The valuation scripts use only the Python standard library: + +```bash +python scripts/dcf.py --help +python scripts/epv.py --help +``` + +They require material assumptions explicitly. `dcf.py` accepts free cash flow to the firm +(FCFF), discounts it at WACC, and bridges enterprise value to equity using net claims: debt and +other senior claims less non-operating assets. + +Install and configure [`sec-edgar-skill`](../sec-edgar-skill/) for SEC evidence and +[`market-scout`](../market-scout/) for market data and transcripts. Each data skill owns its +runtime, cache, and source instructions. + +## Scope and judgment + +This skill supports research, not personalized investment advice. Its memo is an auditable +argument rather than a recommendation tailored to a person's circumstances. A human remains +responsible for checking the evidence, assumptions, suitability, and decision. diff --git a/skills/bottom-up-analyst/SKILL.md b/skills/bottom-up-analyst/SKILL.md index 4158480..d66ce1c 100644 --- a/skills/bottom-up-analyst/SKILL.md +++ b/skills/bottom-up-analyst/SKILL.md @@ -1,279 +1,183 @@ ---- -name: bottom-up-analyst -description: >- - Run a rigorous bottom-up fundamental deep dive on a single company and produce a - pitch-ready investment memo. Use this skill whenever the user hands you one stock — a - ticker or a name — and wants real due diligence: an investment thesis, a long/short - case, "is this a buy?", a valuation, a bull/bear teardown, an earnings-quality check, or - a full research write-up. Reach for it any time the task is "research this company", - "should I own this", "what do you think of X", or "do a deep dive on Y" — even if - neither "memo" nor "valuation" is said out loud. ---- - -# Bottom-Up Analyst - -This skill is the **analyst** in a three-layer research stack. It turns *one name* into an -*earned thesis*, written up as a detailed, auditable investment memo that a reader can act -on. It does the work that sits between raw data and a finished pitch - the work of actually -deciding what the numbers mean. - -## Where this sits - the seam with the other two skills - -A bottom-up stack has three jobs, and they are deliberately kept separate: - -- **The hands** - `sec-edgar-skill` (SEC filings and 13F institutional holder data) and - `market-scout` (price, returns, the peer set, and earnings call transcripts): - unopinionated data/tools layers. They fetch and extract token-efficiently; they *never* - decide what matters. -- **The analyst - this skill.** It is both **the brain and the conductor.** It decides - *what* to pull and *why*, reasons over it, values the business, stress-tests the - conclusion, and writes the memo. The agent that chooses the evidence and the agent that - judges it are the same agent - that is how real analysts work, and why this layer drives - the tools rather than waiting to be handed numbers. -- **The voice** - `pitch-like-lou`: renders a *pitch* from a finished thesis. Short, - compelling, "a pitch with conditions." A reader hooked by the pitch drops into **this - skill's memo** for the full due diligence behind it. - -So the production order is: **analyst → memo → (optionally) Lou pitches from it.** You -produce the substance. You do not need to invoke the voice skill yourself; your job is to -make the memo *pitch-ready* - complete and honest enough that a pitch can stand on it -without inventing anything. - -## The prime directive: conviction must be earned, never manufactured - -Every conclusion in the memo must trace to something you actually verified in a document -or computed yourself. This is not a style note - it is the whole point. A confident memo -built on an unchecked assumption is worse than no memo, because it *launders a guess into a -recommendation*. - -The quality gate that prevents this is **Lou's honesty gate** - separate what you *know* -from what you *believe*, concede the weak points out loud, tag second-hand claims as -second-hand, and demand a margin of safety that survives the bad parts (governance, -dilution, cyclical risk). It is a **necessary condition on every memo regardless of company -type**. The gate lives in one place - `pitch-like-lou`, "the one inviolable rule" (with the -MCI QUIPS cautionary tale of a thesis nearly sunk by an unverified third-hand claim). Read -it there; apply it to every memo here. - -Lou's gate is *necessary but not sufficient.* It does **not** dictate the analysis - this -skill researches companies Lou never touched (hypergrowth tech, regulatory-tailwind -inflections, turnarounds). The *method* below supplies the sufficiency; Lou's temperament -supplies the honesty. - -## The loop - -Work through these phases in order, but let the **archetype** decide where the weight goes - -a hypergrowth name lives in phases 3 and 6; a cyclical in 4; a special-situation in 5 and 7. - -1. **Orient and scope - filings first, always, before any web search.** Run - `sec-edgar-skill`'s `scripts/orient.py` as the **very first tool call** - before web - search, before `market-scout`, before anything else. This is non-negotiable even when the - user describes breaking news ("just reported," "a few hours ago," "announced today"). - orient.py takes seconds and immediately shows you what was filed today; a web search for - the same information is slower, less authoritative, and often wrong about the company. - - **Breaking-news pattern:** if the user mentions a same-day event, orient.py will show the - 8-K filed today. Pull it and its press-release exhibit (Exhibit 99.1) via `sec-edgar-skill`, - which documents the exact breaking-news fetch sequence. That exhibit is the primary - source; read it rather than web-searching for what it contains. - - After orient, read the latest **annual report** (10-K, or 20-F for an FPI) - its business - section and MD&A - and skim the most recent **interim/current** reports (10-Q/8-K, or 6-K - for an FPI) to learn, in the company's own words, *how it makes money.* You cannot value a - business you cannot explain in one plain sentence. Pull the market snapshot (price, market - cap, **the peer set**, sector) from `market-scout` to frame size and comps - orientation, - not evidence. - - **Pull the latest earnings call transcript** via `market-scout`, then read or grep it. - The transcript is a **primary source** — management's own words on guidance, strategy, - and tone. The Q&A section is especially valuable: analyst questions often target exactly - the weak points you need to stress-test in phase 6. - -2. **Classify the archetype.** Almost every company is dominated by one shape, and the - shape decides which DD emphases, metrics, disqualifiers, and valuation method carry the - weight. Pick one primary archetype (a secondary is fine) and **load that playbook** from - `references/archetypes/`. See the routing table below. When nothing fits cleanly, the - core spine here is the fallback - reason from first principles. - -3. **Reconstruct the normalized economics.** GAAP rarely shows the real earning power. - Drive `sec-edgar-skill` to pull the statements (XBRL → CSV), then *un-distort* them: - separate maintenance from growth capex, pull deferred revenue back into the picture, undo - one-offs, treat stock-comp and leases honestly, build owner earnings / FCF. Show capital - allocation as a **year-by-year table** (share count, debt, reinvestment, returns on it) - - a trend persuades where a single number cannot. See `references/guide_normalization.md`. - - **When the thesis depends on a new revenue stream** - a pre-revenue JV, a partnership - product, a market entry unlocked by regulation, a post-restructuring margin profile - - build a **unit-economics bridge** from per-unit inputs (price, cost, volume) to the - stream's FCF contribution. A management TAM estimate plugged into a DCF growth rate is - not a model; it launders a guess into a valuation. The bridge makes the assumption - auditable: a reader who disagrees with your per-unit fee or customer count can re-run - the math. See `references/guide_normalization.md` § "When the thesis depends on a new - revenue stream." - -4. **Read the competitive and industry position.** A number is only as good as the moat - under it. Establish industry structure, the company's place in it, and - the hard part - - *relative* competitive advantage. **SEC filings are the default and the grounding**: the - 10-K's competition and risk-factor sections, and crucially the **peers' own filings** - (their 8-Ks, 10-Qs, 10-Ks) for management commentary, pricing, and sentiment you can - cite. **Peers' earnings call transcripts** are equally valuable primary sources - a - competitor's CEO discussing pricing pressure, capacity additions, or market-share wins - on their own call is citable competitive intelligence - pull peer transcripts via - `market-scout` and grep the cached file for the subject company's name, the product - category, or pricing language. Use **web research only for what filings and transcripts genuinely - cannot give you** - relative positioning, market-share dynamics, channel/customer - checks - and label every web claim as such. See `references/guide_competitive.md`. - - **Quantify impact, don't just list forces.** Every competitive strength, threat, and - moat mechanism must be *sized* - how big, how fast it's moving, and the dollar impact - on this company. A force you can't size is one you haven't understood. See - `guide_competitive.md` § "Quantify impact" for the full framework and examples. - -5. **Value it - by triangulation, weighted by archetype.** Never a single point estimate. - Converge on an intrinsic-value *range* from independent lenses, weighted by what the - archetype makes trustworthy: a **reverse-DCF** ("what growth/margin does today's price - already imply, and is that achievable?") is first-class - especially for hypergrowth, - where it is often the *only* honest lens - alongside a forward DCF, an EPV no-growth - floor, and peer multiples. End with an explicit **margin of safety**. Use the bundled - `scripts/` and `references/guide_valuation.md`. - - **Discount rate: reason it, don't default it.** Derive the discount rate from the - business's actual risk profile - never default to 10% or 12%. The memo's valuation - section **must** include a "Discount Rate Derivation" subsection. See - `references/guide_valuation.md` § "Discount rate" for the full methodology. - -6. **Try to kill it - pre-mortem.** Assume it's a year later and the thesis failed; write - down why. Run the **archetype's disqualifiers** (each playbook lists them) *and* Lou's - honesty gate (above). Most candidates should die here or get marked down - that is the - system working, not failing. Re-tag every surviving claim as verified vs. assumed. - - Before finalising the risk assessment, read the **ownership signal**: pull institutional - (13F) and insider (Form 4) data via `sec-edgar-skill`, then interpret it against the - thesis. This is where adverse selection surfaces - a concentrated holder base that can - crater the float, smart money accumulating or quietly exiting, insiders buying with their - own capital or selling into your long. Account for every cluster buy and every - discretionary senior-officer sale; a signal you skip is a risk you took blind. See - `references/guide_ownership_signals.md` for how to read each pattern (13F reports stale - quarter-end prices, so use the **share counts** and divide by shares outstanding from the - `market-scout` snapshot for ownership %). - -7. **Reach a verdict at the conviction the work supports.** State the call - **Long / - Short / Pass / Watch** - with an honest conviction level, the **variant perception** - (what you believe that the market doesn't, and why you're right), the catalysts or - monitorables that would confirm or break it, and the margin of safety. If the digging was - thin, say so and dial conviction down; a hedged verdict is still a verdict. - -8. **Write the memo.** Render everything into the standard-DD structure in - `references/memo_template.md`. The memo *is* the deliverable; pitch-ready is the - definition of done. - -## Archetype routing - -Classify in phase 2, then load exactly one playbook (Lou's three shapes are the -value-investing subset; the rest extend past where he worked). Read only the one in play - -each is loaded lazily so you carry just the lens you need. - -| If the company is primarily... | Tell by... | Load | -| :-- | :-- | :-- | -| A **quality compounder** - high ROIC, long reinvestment runway | durable returns on capital well above cost, pricing power, low capital intensity | `references/archetypes/compounder.md` | -| A **hypergrowth** name - fast top-line, profits immature | >25-30% growth, heavy S&M, GAAP losses or thin margins, large TAM claim | `references/archetypes/hypergrowth.md` | -| A **cyclical** - earnings swing with a cycle | commodity/industrial/financial exposure, margins that breathe with demand | `references/archetypes/cyclical.md` | -| A **turnaround / inflection** - economics bending on a catalyst | margin or demand inflecting on a regulatory, sectoral, or self-help change | `references/archetypes/turnaround.md` | -| A **special situation** - a structural or legal fact drives it | spin-off, post-bankruptcy, merger/arb, seniority waterfall, squeeze-out | `references/archetypes/special_situation.md` | -| A **deep-value / asset play** - price below tangible value | net cash, net-net, hidden assets, liquidation/sum-of-parts angle | `references/archetypes/deep_value.md` | -| **None fits cleanly** ("anything") | - | Stay on the core spine above; reason from first principles. | - -## Driving the tools - the conductor's job - -You are the one deciding what the hands fetch. Be deliberate and frugal: - -- **Reuse the cache.** `sec-edgar-skill` writes filings to `./sec-cache/{TICKER}/` with - deterministic, accession-keyed names. `market-scout` caches transcripts to - `./transcript-cache/{TICKER}/transcripts/`. Before fetching, glob the cache; re-use - what's there rather than re-hitting the source. -- **Pull by section, not whole filings.** Use item codes (10-K Item 1/1A/7/8) and - heading maps; grep the cached Markdown and read only the lines that matter. A 10-K can - exceed 100k words - loading one whole buries the signal. -- **Transcripts are greppable too.** Once cached, grep a transcript for "guidance", - "margin", a competitor's name, or a specific metric - you don't need to read the whole - 45-minute call to find the passage that matters. -- **Ownership data is cached like everything else.** `sec-edgar-skill` writes 13F and - insider output to the same `sec-cache/{TICKER}/` tree under scope-keyed filenames. Glob - the cache before re-fetching — if the window you need is already on disk, grep and read - it rather than re-hitting the source. -- **Spend tokens where the archetype says the value hides.** Don't fetch a proxy's - compensation tables for a hypergrowth TAM question, or a deferred-revenue footnote for a - liquidation. Let the playbook route you. -- **For foreign private issuers** there is no 10-K/10-Q/DEF 14A - it's 20-F and 6-K, and the - financials are IFRS. `sec-edgar-skill`'s guides cover the mechanics. - -If a tool detail is unclear, defer to `sec-edgar-skill`'s and `market-scout`'s own guides -and `--help`; do not re-document the hands here. Keep the tools unopinionated; keep the -opinion in this skill. - -## Web research - grounding first, web for the gaps - -Filings are the spine of the memo because they are auditable and primary. Reach for the web -only when no filing can answer the question - chiefly *relative* competitive advantage, -real-time market share, pricing dynamics, and channel or customer checks. When you do: -**attribute and date every web claim**, prefer primary sources (company IR, regulators, -trade bodies) over aggregators, and never let a web assertion silently outrank a filing. -Mark web-sourced claims distinctly in the memo so the reader can weight them. - -**Do not fire any web search until orient.py has returned and you have read at least one -filing section.** This applies even for breaking news: orient.py will surface the 8-K -filed today, and the 8-K's Exhibit 99.1 is the press release - the primary source that -any web article is merely summarising. Fetch the exhibit; don't search for the summary. - -**When a tool errors, recover - don't escape to the web.** A failed `sec-edgar-skill` call -is a fixable usage detail, not a signal to pivot to web search. Re-run `orient.py`, read the -relevant guide, or query `.docs`, then retry. The web is a *supplement for what filings -cannot cover* - never a fallback for filings you failed to fetch. - -## Valuation tooling - -Run the bundled scripts rather than hand-rolling a DCF per memo. `--help` is the -authoritative flag reference; canonical invocations: - -```bash -# Forward DCF (bear/base/bull sensitivity via comma-separated growth) -python scripts/dcf.py --fcf0 1200 --growth 8,12,16 --years 10 --terminal-growth 3 \ - --discount 10 --shares 500 --net-debt 200 - -# Three-stage DCF (add --growth2/--years2 when the trajectory bends) -python scripts/dcf.py --fcf0 5 --growth 25,35,50 --years 3 \ - --growth2 5,8 --years2 7 --terminal-growth 2.5 --discount 12 \ - --shares 30 --net-debt 66 --price 2.75 - -# Reverse DCF (what growth does today's price imply?) -python scripts/dcf.py --mode reverse --price 150 --fcf0 1200 --years 10 \ - --terminal-growth 3 --discount 10 --shares 500 --net-debt 200 - -# EPV (no-growth floor) -python scripts/epv.py --ebit 600 --tax 21 --wacc 9 --shares 500 --net-debt 200 -``` - -`references/guide_valuation.md` explains which lens to weight for which archetype, when to -use three-stage vs two-stage, and how to set the discount rate and terminal value honestly. - -## Bundled resources - -| Resource | When to read / run | -| :-- | :-- | -| `references/memo_template.md` | The required output structure. Read before writing the memo. | -| `references/guide_normalization.md` | Phase 3 - un-distorting the financials into owner earnings. | -| `references/guide_competitive.md` | Phase 4 - SEC-first competitive work; when to go to the web. | -| `references/guide_valuation.md` | Phase 5 - triangulation, reverse-DCF, discount/terminal discipline. | -| `references/guide_ownership_signals.md` | Phase 6 - reading the 13F and insider ownership signal. | -| `references/archetypes/*.md` | Phase 2 - load the one matching the company's shape. | -| `scripts/dcf.py`, `scripts/epv.py` | Phase 5 - the valuation arithmetic. `--help` for flags. | - -## Definition of done: pitch-ready - -The memo ships when it passes **Lou's honesty gate** end to end - concretely: - -1. every claim is verified in a document or computed yourself, and everything unverified is - marked as such; and -2. you have been as honest and specific about what is wrong with the thesis as about what - is right. - -Both true - the memo is pitch-ready. +--- +name: bottom-up-analyst +description: >- + Conduct substantive, long-only bottom-up research on one non-financial operating company. + Use for an investment thesis, buy/pass/watch decision, valuation, earnings-quality review, + bull/bear assessment, or full due-diligence memo when the user wants analysis rather than a + quote or filing lookup. The framework suits businesses whose operating, asset, or transaction + economics can be underwritten from public evidence, including cash-burning growth companies + with observable unit economics. Do not use it as the primary framework for banks, insurers, + REITs, funds, or clinical-stage and other predominantly binary-asset companies. +--- + +# Bottom-Up Analyst + +Turn evidence about one company into a long-only investment judgment. Scale the work to the +question: answer a scoped valuation or earnings-quality request directly; produce the full memo +only for a deep dive or when the user asks for one. + +This is the analysis layer of SecStack. Use `sec-edgar-skill` for filing evidence and +`market-scout` for market data and transcripts. A finished memo may later feed +`pitch-like-lou`, but this skill owns the research method and does not depend on that voice. + +## Evidence discipline + +Facts, estimates, assumptions, and external evidence must remain distinguishable. Use this +markup on load-bearing claims and tables, not on headings or connective prose: + +- **[V] Verified:** checked against a cited filing, regulator, issuer document, or other + authoritative primary record. Identify the form/document, period, section or accession, and + date where available. +- **[E] Estimate:** calculated or modeled. Show the formula, inputs, units, and source dates. +- **[A] Assumption:** not established by available evidence. State what would validate it and + how the conclusion changes if it is wrong. +- **[W] External evidence:** a web, trade, channel, expert, or secondary source. Name and date + it. `[W]` describes provenance, not truth; assess incentives and corroboration. + +Do not tag an inference `[V]` merely because its premises are verified. State the inference and +cite its premises. An issuer filing verifies what the issuer disclosed, not that management's +interpretation is neutral. Vendor-produced call transcripts are useful records of a call but +can contain transcription errors; verify a load-bearing quotation against issuer materials or +recording when practical. + +Prefer the source authoritative for the claim. SEC filings lead for filed financials, capital +structure, contracts, ownership, and governance. Issuer IR may lead for a release not yet filed; +a regulator or court may lead for a rule or case; industry data may lead for market structure. +Report material conflicts instead of silently choosing one source. + +## Workflow + +### 1. Frame the decision + +Identify the security, listing, as-of date, investor question, and requested depth. Resolve +ambiguous tickers or share classes before research. For a full deep dive, define the current +market expectation you need to test. For a scoped request, investigate only the evidence needed +to answer it and disclose what was not reviewed. + +### 2. Build the evidence set + +Use `sec-edgar-skill` orientation only when the relevant form or accession is unknown. Skip it +when an accession, cached artifact, or non-SEC source is already the precise route. Read the +latest annual filing and subsequent material updates for a full company review; choose narrower +sources for a narrower question. + +Timestamp current market data. Check recent EDGAR and issuer IR for new disclosures, but do not +assume a same-day event has already been filed. Use call transcripts for management statements +and Q&A leads, with speaker attribution and the transcript caveat above. + +Keep large documents on disk and retrieve only relevant sections. Follow each data skill's own +current guide and `--help`; do not guess flags, cache behavior, or field semantics here. + +### 3. Select the analytical lenses + +Choose an archetype only when it sharpens the work. Load the closest playbook from +`references/archetypes/`; use a primary and secondary lens when the economics genuinely span +both. Do not force a company into the taxonomy. If no playbook fits, reason from the business +model and the decision at hand. + +| Lens | Use when the thesis turns on | +| :-- | :-- | +| `compounder.md` | returns on incremental capital and reinvestment runway | +| `hypergrowth.md` | immature profits, unit economics, and a path to positive cash flow | +| `cyclical.md` | normalized cycle earnings, cost position, and balance-sheet survival | +| `turnaround.md` | a specific mechanism changing margins, demand, or capital structure | +| `special_situation.md` | a transaction, legal document, security, or forced flow | +| `deep_value.md` | conservatively realizable assets and a path to realization | + +### 4. Reconstruct the economics + +Reconcile reported earnings to the cash-flow measure appropriate to the valuation. Separate +recurring operations from one-offs, acquisition effects, working-capital timing, stock +compensation, leases, and maintenance versus growth investment without double-counting any +adjustment. Use a multi-period view long enough for the business and cycle. Read +`references/guide_normalization.md`. + +When a material part of value comes from a new stream or future margin structure, build a +bottom-up bridge from operational drivers to revenue, margins, reinvestment, and cash flow. +Treat an unsupported TAM share or margin target as `[A]`, not as a forecast. + +### 5. Underwrite the business and stewards + +Explain how the company makes money, why customers choose it, where industry profits accrue, +and what could change. Select peers by business model and economics rather than accepting an +automated industry list uncritically. Quantify material forces where reliable evidence permits; +otherwise use a bounded range or identify the unresolved variable. Do not invent precision to +fill a template. Read `references/guide_competitive.md`. + +Review management incentives, dilution, capital allocation, controlling holders, related-party +transactions, and governance when they can affect value. Use 13F and Form 4 data as limited, +lagged evidence rather than a verdict. Read `references/guide_ownership_signals.md`. + +### 6. Value the security + +Use the lenses that match the cash-flow and asset economics; triangulation does not mean running +an inapplicable method. Reverse DCF is useful only when a positive base FCFF and the model shape +make implied growth interpretable. EPV is a no-growth operating case, not a guaranteed floor. +Special situations and asset plays usually need scenario payoffs or sum-of-parts work outside +the bundled scripts. + +State the valuation date, cash-flow basis, enterprise-to-equity bridge, diluted share count, +discount rate, terminal assumptions, and scenario logic. Vary the assumptions that actually +drive value, not growth alone by habit. Read `references/guide_valuation.md` before running the +scripts. + +### 7. Try to disprove the thesis + +Write the strongest contrary explanation, run the relevant playbook's disqualifiers, and test +load-bearing assumptions. Distinguish permanent impairment from volatility. Describe what +would falsify the thesis, the expected timing, financing or dilution risk, and any evidence gap +that limits conviction. A pass or watch decision is a valid result. + +### 8. Deliver at the requested depth + +Use `references/memo_template.md` for a full deep dive. Adapt its sections and metrics to the +company and thesis; it is a decision-oriented skeleton, not a form. For a scoped answer, give +the conclusion, decisive evidence, calculations, countercase, missing work, and sources without +padding it into a full memo. + +## Valuation scripts + +Resolve script paths relative to this `SKILL.md` and invoke them by absolute path while keeping +the shell working directory at the user's research workspace. Every material assumption is +explicit; `--help` is the flag reference. + +```bash +# Positive-FCFF forward sensitivity +python "/scripts/dcf.py" forward --fcff0 1200 --growth 8,12,16 \ + --years 10 --terminal-growth 3 --wacc 10 --shares 500 --net-claims 200 --price 75 + +# Explicit annual FCFF, including an initial loss or inflection +python "/scripts/dcf.py" forecast --fcff=-20,10,45,80,110 \ + --terminal-growth 2.5 --wacc 12 --shares 30 --net-claims 66 --price 8 + +# Growth implied by price +python "/scripts/dcf.py" reverse --price 75 --fcff0 1200 --years 10 \ + --terminal-growth 3 --wacc 10 --shares 500 --net-claims 200 + +# No-growth operating earnings case +python "/scripts/epv.py" --ebit 600 --tax 21 --wacc 9 \ + --shares 500 --net-claims 200 --price 10 +``` + +The DCF is an enterprise model: pass normalized **FCFF**, discount at WACC, then subtract +`--net-claims` (debt and other senior claims less non-operating assets). Do not pass +after-interest owner earnings or FCFE and subtract debt again. + +## Resources + +| Resource | Read or run when | +| :-- | :-- | +| `references/memo_template.md` | writing a full due-diligence memo | +| `references/guide_normalization.md` | reconstructing normalized cash economics | +| `references/guide_competitive.md` | underwriting industry and competitive position | +| `references/guide_valuation.md` | choosing and implementing valuation lenses | +| `references/guide_ownership_signals.md` | assessing ownership, insiders, incentives, and governance | +| `references/archetypes/*.md` | one or two lenses materially sharpen the case | +| `scripts/dcf.py`, `scripts/epv.py` | reproducible enterprise-valuation arithmetic | + +## Completion check + +Before answering, ensure the work supports its own confidence: current security and source +periods are clear; material facts are cited; calculations reconcile; assumptions and inferences +are visible; the strongest countercase is addressed; valuation uses a consistent cash-flow +basis; and omitted work is disclosed. Do not manufacture a verdict stronger than the evidence. diff --git a/skills/bottom-up-analyst/references/archetypes/compounder.md b/skills/bottom-up-analyst/references/archetypes/compounder.md index d6e0c07..462a7f5 100644 --- a/skills/bottom-up-analyst/references/archetypes/compounder.md +++ b/skills/bottom-up-analyst/references/archetypes/compounder.md @@ -1,66 +1,57 @@ -# Archetype: Quality Compounder - -A business that earns **high returns on capital** and can **reinvest** a large share of its -earnings at similar returns for years. The thesis is rarely "it's cheap" — it's "the market -under-appreciates the *duration* and *reinvestment runway* of the compounding." Time is the -ally; you are underwriting a machine, then trying to buy it at a fair price. (One of Lou's -three value-investing shapes — see NVR, Sportsman's Guide in the `pitch-like-lou` corpus.) - -## Tell it by - -Durable ROIC/ROE well above the cost of capital (sustained, not a single year), pricing -power, low incremental capital intensity, expanding or stable margins, and a reinvestment -runway (new units, geographies, share gains) that isn't nearly exhausted. - -## Where the value hides - -- **Duration the market won't extrapolate.** Screens see a high multiple and stop; the edge - is judging that the high return *persists* far longer than consensus assumes. -- **Reinvestment math.** Value = return on incremental capital × the fraction reinvested. A - 35% ROIC business reinvesting 70% of earnings compounds intrinsic value ~24%/yr before any - multiple change — that engine, not the entry multiple, is the thesis. -- **Under-distorted economics** — GAAP often *understates* a compounder (expensed growth - investment, deferred revenue, conservative depreciation). - -## Pull these (drive sec-edgar) - -- 10-K Item 7 (MD&A) and Item 1 (Business) — the unit economics and the runway in management's - words. -- The cash-flow statement and the revenue / deferred-revenue / lease footnotes — for the - normalization that reveals true returns. -- A multi-year financial history (`sec-edgar-skill`'s `parse_financials.py` across years) — to prove ROIC is - *durable*, not a one-year flatter. -- The proxy (DEF 14A) — capital-allocation incentives; is management paid to compound or to - empire-build? - -## Key metrics - -ROIC and **return on incremental invested capital** (the forward-looking one), reinvestment -rate, organic revenue growth, gross-margin stability, FCF conversion, same-store / cohort / -unit economics where disclosed. - -## Normalize / adjust - -- Split maintenance vs. growth capex carefully — a compounder's value is highly sensitive to - it (see `guide_normalization.md`). -- Pull deferred revenue back into earning power; undo conservative-accounting drag. -- Expense stock comp and bake dilution into the share count. - -## Valuation lens - -Lead with a **forward two-stage DCF** that gives the long reinvestment runway room, then -**reality-check with a reverse-DCF** (is the priced-in growth sane?) and floor it with EPV. -The key question isn't today's multiple — it's whether the runway justifies it. - -## Disqualifiers — kill it (or mark it down) if… - -- High ROIC is an **accounting mirage** — goodwill-light denominators, off-balance-sheet - leverage, or returns that evaporate once you capitalize the real investment. -- **Growth needs ever more capital at falling returns** — incremental ROIC is decaying toward - the cost of capital; the compounding is already ending. -- The **reinvestment runway is nearly full** — you're paying a compounder multiple for what's - about to become a no-growth cash cow. -- **Buybacks only when the stock is dear**, or capital allocation that destroys the very - compounding you're paying for. -- Margins propped by a **temporary** advantage (a subsidy, a fad, one big customer) rather - than a structural moat. +# Archetype: quality compounder + +Use this lens when value depends on a business reinvesting substantial cash at attractive +incremental returns for a long time. The analytical edge is usually duration and reinvestment, +not merely calling the company “high quality.” + +## Establish the shape + +Look for persistent economic returns above the opportunity cost of capital, a demonstrated +ability to reinvest, durable customer value, and room to deploy more capital. Do not use a fixed +ROIC or growth threshold. Adjust accounting and compare through a cycle where relevant. + +Distinguish: + +- average ROIC from return on **incremental** invested capital; +- organic reinvestment from acquisitions and financial leverage; +- pricing power from temporary price/cost timing; +- a long runway from a large but inaccessible TAM; and +- per-share compounding from enterprise growth offset by dilution. + +A useful approximation is sustainable operating growth = reinvestment rate × return on new +capital. It is not an identity for shareholder return or intrinsic-value growth; taxes, +distributions, financing, fade, and valuation still matter. + +## Evidence to pull + +- segment economics, unit growth, pricing, retention, and customer concentration; +- capex, working capital, acquisitions, and other reinvestment by period; +- gross margin, incremental margin, ROIC, and FCFF across enough years to test durability; +- diluted share count, repurchases, stock compensation, and acquisition consideration; +- incentives and capital-allocation record from proxies and filings; and +- peers with similar customers and business models, not merely the same sector label. + +## Valuation + +Connect the explicit forecast to reinvestment capacity and incremental returns. Test what growth +duration and fade the current price implies. A forward enterprise DCF may be useful when FCFF is +positive and predictable; an explicit forecast is better when margins or reinvestment change. +EPV can show how much value comes from future reinvestment but is not a hard downside floor. + +Do not justify a terminal premium by repeating the word “quality.” Normalize returns and +reinvestment in the terminal state. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- reported ROIC is an accounting artifact or omits required assets and obligations; +- incremental returns are falling toward or below the cost of capital; +- growth requires acquisitions or spending that the model excludes; +- the reachable runway is nearly exhausted or competitors can copy the expansion; +- customer concentration, regulation, or a temporary shortage explains the apparent moat; +- buybacks occur above defensible value or only offset dilution; or +- enterprise growth fails to produce per-share value. + +The memo should state the operating measure that will reveal runway or return decay before the +headline growth rate does. diff --git a/skills/bottom-up-analyst/references/archetypes/cyclical.md b/skills/bottom-up-analyst/references/archetypes/cyclical.md index 5fb5b63..59c3bec 100644 --- a/skills/bottom-up-analyst/references/archetypes/cyclical.md +++ b/skills/bottom-up-analyst/references/archetypes/cyclical.md @@ -1,66 +1,49 @@ -# Archetype: Cyclical - -A business whose earnings swing with a **cycle** — commodity prices, the industrial economy, -housing, credit, shipping rates. The cardinal sin is valuing it on its current earnings: -peak earnings on a low multiple is the classic value trap, and trough losses on a "no -multiple" basis is where the bargains hide. The whole game is **normalizing to mid-cycle** -and knowing *where in the cycle you are*. - -## Tell it by - -Revenue and margins that breathe with an external driver, history of boom/bust EPS, exposure -to a commodity or a capital-spending cycle, operating leverage that amplifies both -directions, and a balance sheet that matters more than usual (leverage kills cyclicals at the -trough). - -## Where the value hides - -- **Mid-cycle earning power**, not the printed number — what the business makes *on average* - across a full cycle. -- **Cycle position.** Buying near the trough (ugly trailing numbers, washed-out sentiment) and - selling near the peak (record earnings, optimistic multiples) is most of the return. The - tape and the headlines will tell you the opposite of what to do. -- **The low-cost producer** survives the trough and takes share; cost-curve position is the - durable edge in a commodity business. - -## Pull these (drive sec-edgar) - -- 10-K Item 7 (MD&A) across **multiple years spanning a full cycle** — pull a long history so - you can see peak-to-trough, not one phase. -- The balance sheet and debt maturities — can it survive the next trough without a dilutive - raise? Leverage is the cyclical killer. -- Segment data and the cost structure — fixed vs. variable, the operating leverage, the - position on the industry cost curve. -- Industry data (often web/trade sources [W]) — capacity utilization, inventory, the - supply/demand balance that sets where the cycle goes next. - -## Key metrics - -Mid-cycle revenue and EBIT margin, peak-to-trough earnings range, capacity utilization, -incremental/decremental margins (operating leverage), net debt / mid-cycle EBITDA, cost-curve -position, returns on capital *averaged across the cycle*. - -## Normalize / adjust - -- **Mid-cycle earnings:** average margins (or volumes × normalized price) across a full cycle, - then apply to current capacity — don't anchor on the latest year either way. -- Adjust for capacity added/retired since the last comparable cycle phase. -- Stress the balance sheet at trough cash flows; a covenant breach changes everything. - -## Valuation lens - -**EPV on mid-cycle EBIT** is the natural anchor (no growth credit on top of an already-rich -mid-cycle number), cross-checked with a **normalized P/E** and the multiple the stock has -historically commanded at this cycle phase. Beware: a *low* trailing P/E on peak earnings is a -sell signal, not a buy. - -## Disqualifiers — kill it (or mark it down) if… - -- **It's a peak, not a trough** — current earnings are cycle-high and you'd be paying a - "cheap" multiple on a number about to fall. -- **The balance sheet won't survive the trough** — too much debt, near-term maturities, or - covenant risk; cyclicality + leverage is how permanent losses happen. -- **It's a high-cost producer** — first to bleed in the downturn, no share gains in recovery. -- **The cycle is structurally impaired** — secular demand decline (not just cyclical), so - "mid-cycle" never returns. -- You can't actually tell where in the cycle you are — then you're guessing, not investing. +# Archetype: cyclical + +Use this lens when an external cycle drives material variation in price, volume, credit, +utilization, or margins. The central tasks are estimating normalized economics, locating the +current cycle with humility, and testing whether the balance sheet survives a worse path. + +## Establish the shape + +Identify the actual cycle driver and transmission mechanism. Separate cyclical variation from a +secular change in demand, technology, regulation, or cost position. The latest earnings and +trailing multiple are often poor anchors at both peaks and troughs. + +Study more than one comparable cycle where the history exists. Adjust for changes in capacity, +product mix, geography, accounting, acquisitions, and capital structure before averaging old +results. + +## Evidence to pull + +- price, volume, mix, utilization, backlog, inventory, and capacity across a full cycle; +- fixed and variable costs, incremental and decremental margins, and cash conversion; +- sustaining capex, working-capital swings, and closure or restart costs; +- debt maturities, covenants, liquidity, collateral, and refinancing requirements; +- cost-curve or asset-quality evidence relative to competitors; and +- authoritative industry supply, demand, inventory, and capacity data. + +## Normalization and valuation + +Estimate mid-cycle earnings from operating drivers, not a blind arithmetic average. Show a +trough, normalized, and strong environment with the associated FCFF, liquidity, and share count. +Include any dilution or asset sale needed to survive the trough. + +EPV on defensible mid-cycle operating earnings can be useful, alongside asset or unit values and +historical transaction evidence. A spot P/E or EV/EBITDA on peak results is not evidence of +cheapness. An explicit DCF should model the transition to normalized conditions rather than +assuming a peak or trough persists. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- normalized earnings are anchored to an unusually favorable period; +- the balance sheet, covenants, or liquidity cannot withstand the downside path; +- the company sits high on the cost curve or owns impaired assets; +- new capacity, substitution, or secular decline prevents the prior cycle from returning; +- management adds capacity or leverage near peaks and issues equity near troughs; or +- the thesis requires precise cycle timing unsupported by observable supply and demand. + +The memo should state the cycle indicators, what phase they suggest, alternative explanations, +and what evidence would prove the “mid-cycle” estimate too high. diff --git a/skills/bottom-up-analyst/references/archetypes/deep_value.md b/skills/bottom-up-analyst/references/archetypes/deep_value.md index a846a6c..da6ef10 100644 --- a/skills/bottom-up-analyst/references/archetypes/deep_value.md +++ b/skills/bottom-up-analyst/references/archetypes/deep_value.md @@ -1,69 +1,60 @@ -# Archetype: Deep Value / Asset Play - -The price is below a conservative reckoning of **what the company owns** — net cash, net-net -working capital, hidden or understated assets, or a sum-of-the-parts/liquidation value well -above the market cap. The thesis is *margin of safety in the assets*, not earnings growth. -The two things that kill it are a **catch** (debt or cash burn eating the assets) and the -**absence of a catalyst** (cheap forever isn't a return). (Lou's cigar-butt shape — see Winmill -in the `pitch-like-lou` corpus.) - -## Tell it by - -Market cap near or below net cash / net current assets / tangible book; assets carried below -market value (real estate at historical cost, a stake marked conservatively, a hidden -subsidiary); a discount to a credible liquidation or break-up value. - -## Where the value hides - -- **On the balance sheet, not the income statement.** Net cash minus *all* liabilities; - current assets minus *all* liabilities (net-net); assets carried below fair value. -- **In what's hidden or mismarked** — land at 1950s cost, an equity stake at the lower of - cost, an over-funded pension, a non-consolidated JV. -- **Behind a catalyst.** The discount only becomes a return when something closes it — a - buyback, a sale, a liquidation, an activist, a return of capital. Asset value *plus* a - realization path is the complete thesis. - -## Pull these (drive sec-edgar) - -- The **balance sheet and every liability footnote** — including off-balance-sheet and - contingent claims (the hidden liabilities that turn a "net cash" story into a trap). -- The cash-flow statement — is operating burn *depleting* the asset pile? A melting ice cube - isn't a bargain. -- Recent 8-Ks — asset sales, buybacks, special dividends, activist involvement (the catalyst). -- The proxy (DEF 14A) — controlling holder, founder age/estate, insider ownership and pay; who - decides whether value gets realized, and are they aligned or extracting? - -## Key metrics - -Net cash per share, net-net working capital per share, tangible book, discount to liquidation / -sum-of-the-parts, cash burn rate and **months of runway**, insider ownership %, the size of -the discount vs. the annual governance "leakage." - -## Normalize / adjust - -- Subtract **all** liabilities, not just debt — pensions, leases, contingencies, preferred. -- **Haircut** assets to realizable value (receivables, inventory, "investments"); mark hidden - assets *up* to fair value with evidence. -- Back non-recurring items out of operating cash flow to see the true burn (or generation). -- Price the cost of value-destructive governance (option grants, related-party deals) and - subtract it — the discount has to survive that. - -## Valuation lens - -**Asset value / liquidation value** is the anchor (conservative, haircut), with an **EPV floor** -on any ongoing operations and a **reverse-DCF or scenario on the catalyst** to gauge the return -*if and when* the gap closes. The return is (asset value − price) × probability-of-realization -÷ time — so the catalyst's likelihood and timing are part of the valuation, not an afterthought. - -## Disqualifiers — kill it (or mark it down) if… - -- **There's a catch** — funded debt senior to you, or operating cash burn that eats the asset - pile faster than you can realize it. -- **No catalyst and no path to one** — a controller content to sit on the discount forever; a - perpetual value trap. -- **The discount is smaller than the governance theft** — insiders extract more per year than - the gap you'd capture. -- **The assets aren't what they're carried at** — receivables uncollectable, inventory stale, - "investments" impaired, real estate encumbered. -- **Hidden liabilities** — pension shortfalls, litigation, guarantees that erase the net-asset - cushion. +# Archetype: deep value or asset play + +Use this lens when the case depends on conservatively realizable assets or a sum of parts rather +than forecast growth. A balance-sheet discount is only the start; liabilities, cash burn, +control, tax, timing, and a credible realization path determine whether it becomes a return. + +## Establish the shape + +Identify the exact asset claim per diluted share and why carrying value differs from realizable +value. Distinguish cash available to common shareholders from restricted, regulated, pledged, +subsidiary, or operating cash. Determine who can authorize realization and whether incentives +support it. + +## Evidence to pull + +- balance sheet and footnotes for debt, leases, pensions, guarantees, contingencies, preferred + claims, minority interests, and restrictions; +- asset-level detail for receivables, inventory, property, investments, tax basis, liens, and + disposal costs; +- operating cash flow and commitments to estimate how quickly the asset cushion changes; +- buybacks, tenders, sales, liquidation plans, spin-offs, or other realization actions; +- proxy, 13D/13G, voting rights, related parties, compensation, and insider ownership; and +- market or transaction evidence for asset haircuts and sale timelines. + +## Valuation + +Build a transparent realizable-value bridge: + +```text +cash and investments, adjusted for restrictions ++ recoverable receivables and inventory ++ appraised or transaction-supported asset values +− all debt and senior claims +− operating losses through realization +− tax, transaction, closure, and corporate costs += value available to common equity +``` + +Use ranges for recovery rates and timing. Value ongoing operations separately with EPV only when +earnings are durable and required maintenance is included. Do not call book value or EPV a hard +floor. + +Model realization outcomes and annualized returns rather than multiplying the headline discount +by probability and dividing by time. Expected value must include the downside payoff, interim +burn or distributions, taxes, and time value. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- restricted cash, senior claims, liens, or contingencies consume the apparent cushion; +- operating losses or required investment erode value before realization; +- receivables, inventory, property, or investments cannot realize the assumed amount; +- a controller can delay or divert value and minority protections are weak; +- annual compensation, related-party leakage, or dilution overwhelms expected convergence; +- tax and transaction costs eliminate the headline discount; or +- no observable path or decision-maker can close the gap within an underwritable period. + +The memo should state who controls realization, what action is required, the expected value under +non-realization, and the monitorable that shows the asset cushion is melting. diff --git a/skills/bottom-up-analyst/references/archetypes/hypergrowth.md b/skills/bottom-up-analyst/references/archetypes/hypergrowth.md index 1878dbc..5c3e30a 100644 --- a/skills/bottom-up-analyst/references/archetypes/hypergrowth.md +++ b/skills/bottom-up-analyst/references/archetypes/hypergrowth.md @@ -1,68 +1,59 @@ -# Archetype: Hypergrowth - -A company growing the top line fast (often >25–30%/yr) where **profits are immature or -absent** — earnings are being deliberately deferred into customer acquisition, R&D, or land -grab. This is the shape Lou never invested in, and it needs analysis his playbook doesn't -contain: the question isn't "what does it earn today" but "**what will the unit economics -look like at scale, how durable is the growth, and is that future already in the price?**" - -## Tell it by - -Rapid revenue growth with GAAP losses or thin margins, heavy S&M and/or R&D as a % of -revenue, a large TAM claim, negative or marginal FCF reinvested into growth, frequent equity -issuance, and metrics management steers you to (ARR, net revenue retention, GMV, MAUs). - -## Where the value (and the trap) hides - -- **Unit economics at maturity.** Strip the growth spend and look at a *cohort* or a mature - segment: are the underlying customers profitable once you stop acquiring more? A business - that's "unprofitable because it's investing" is wonderful; one that's unprofitable because - the unit economics don't work is a value trap with a story. -- **Durability of growth.** TAM size, share gains vs. market growth, competitive intensity, - and whether growth is *organic* or bought with discounts and incentives. -- **The dilution tax.** Stock comp and secondary raises can quietly transfer most of the - upside to employees and new shareholders — per-*share* value is what matters. - -## Pull these (drive sec-edgar) - -- 10-K/10-Q MD&A and the latest earnings 8-K (Exhibit 99.1) — growth drivers, cohort/retention - disclosure, the metrics management reports and how their definitions change. -- The cash-flow statement and stock-comp footnote — real cash burn and the dilution rate. -- The S-1 / early 10-Ks if recently public — original unit-economics and TAM framing to test - against what actually happened. -- Peers' filings — to separate company-specific share gains from a rising-tide market. - -## Key metrics - -Revenue growth (organic), gross margin and its *trajectory*, net revenue retention / cohort -retention, CAC payback and LTV/CAC, contribution margin, **Rule of 40** (and its trend), -FCF burn and **runway**, fully-diluted share-count growth. - -## Normalize / adjust - -- Treat stock-based comp as the real expense it is and fold dilution into shares — *the* swing - factor between "profitable at scale" and not. -- Distinguish **growth** opex/capex from **maintenance**: model the steady-state margin by - scaling S&M down to a renewal level, not zero. -- Watch metric definitions — "adjusted EBITDA" that addbacks stock comp and "non-recurring" - growth costs can manufacture profitability that doesn't exist. - -## Valuation lens - -**Reverse-DCF is the lead lens** — solve for the growth/margin the price implies and judge -whether it's achievable, because forecasting a hyper-growth decade forward is mostly -self-deception. Cross-check with a scenario forward DCF on *mature-state* margins (bear/base/ -bull) and with forward multiples. Anchor on per-share, post-dilution. - -## Disqualifiers — kill it (or mark it down) if… - -- **Unit economics don't work at scale** — mature cohorts/segments still don't generate cash; - growth is buying revenue at a structural loss. -- **The priced-in growth is fantasy** — reverse-DCF requires a decade above what the company - (or anyone in the category) has ever sustained. -- **Growth is decelerating** while the valuation still assumes acceleration. -- **Dilution eats the upside** — share count compounds so fast that per-share value barely - moves even if the business wins. -- **The TAM is a mirage** — top-down "1% of a huge market" with no bottom-up path, or a market - that shrinks as the product commoditizes. -- **Runway is short** and the next raise will be dilutive or unavailable. +# Archetype: cash-burning or high-growth operating company + +Use this lens when current profit understates or fails to show the economics management expects +at scale, but the company has observable customers, revenue, and operating drivers. Do not use it +for a predominantly binary clinical, exploration, or legal asset. + +## Establish the shape + +Growth rates alone do not define the archetype. Look for deliberate investment ahead of revenue, +immature margins, evolving product-market fit, meaningful stock compensation or external +financing, and operating metrics that can connect customers or units to cash flow. + +Separate: + +- growth caused by customer value from growth purchased with discounts or uneconomic spend; +- mature-cohort economics from blended company economics; +- organic growth from acquisitions; +- gross retention from expansion revenue; +- addressable demand from management's TAM; and +- company growth from per-share value after dilution. + +Metrics such as retention, CAC payback, LTV/CAC, active users, GMV, ARR, or Rule of 40 apply only +when they match the business model and are defined consistently. Reconcile non-GAAP measures to +reported results and track definition changes. + +## Evidence to pull + +- cohort, retention, pricing, usage, backlog, and contribution-margin disclosures; +- gross margin and sales, marketing, R&D, support, capex, and working capital by period; +- cash, burn, debt, covenants, funding needs, and runway under a downside case; +- stock compensation, grants, issuance, repurchases, and diluted share history; +- early public filings and prior targets, to compare the original model with outcomes; and +- peers or substitutes that reveal acquisition cost, churn, price, and mature margins. + +## Valuation + +Do not grow a negative FCFF base with the constant-growth DCF route. Build explicit annual +revenue, margin, tax, reinvestment, and FCFF scenarios, then use `dcf.py forecast` once the annual +FCFF sequence is defensible. Reconcile the current price to combinations of scale, mature margin, +capital intensity, and dilution rather than presenting one implied growth rate as unique. + +Forward revenue multiples are shorthand for future margin, growth, and reinvestment assumptions; +make that bridge explicit. Include financing and dilution before the company reaches positive +cash flow. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- mature cohorts or units remain uneconomic; +- growth depends on rising incentives, falling price, or worsening acquisition efficiency; +- retention, backlog quality, or metric definitions deteriorate; +- a plausible scale and margin path still cannot reconcile to the price; +- the reachable market is not supported by bottom-up customers or units; +- funding runs out before operating break-even or creates unacceptable dilution; or +- the model assumes costs disappear rather than scale with service obligations. + +The memo should identify the metric that distinguishes temporary investment from structurally +poor unit economics and the date by which evidence should emerge. diff --git a/skills/bottom-up-analyst/references/archetypes/special_situation.md b/skills/bottom-up-analyst/references/archetypes/special_situation.md index d93318b..feec365 100644 --- a/skills/bottom-up-analyst/references/archetypes/special_situation.md +++ b/skills/bottom-up-analyst/references/archetypes/special_situation.md @@ -1,72 +1,54 @@ -# Archetype: Special Situation - -A situation where a **structural, legal, or transactional fact** — not the ongoing business — -drives the outcome: a spin-off, post-bankruptcy equity, a merger/arb spread, a seniority -waterfall, a put/call formula, a squeeze-out or minority-protection statute, a recapitalization. -The edge is *forensic*: you read the actual document, compute the formula yourself, and rebuild -the capital structure — and you reach a conclusion that nearly *has* to resolve a certain way. -(Lou's richest value-investing shape — see Quilmes, MCI, NII Holdings, Telemig in the -`pitch-like-lou` corpus.) - -## Tell it by - -The thesis hinges on an event or a legal/structural mechanism rather than earnings growth: -corporate actions (spin, merger, tender, reorg), unusual securities (pink-sheet preferreds, -stubs, post-reorg equity), or a binding formula/statute that forces value to a class of -holders. - -## Where the value hides - -- **In the document itself.** The put/call formula in an exhibit, the seniority of a security - in the waterfall, the squeeze-out price mechanism in foreign company law. The market prices - the *headline*; the edge is reading the *fine print* and computing the consequence. -- **In forced/neglected selling.** Spin-offs dumped by index funds, post-bankruptcy equity - held by creditors who want out, complex securities no analyst covers — structural sellers - create mispricing unrelated to value. -- **In the binding-ness.** The whole thesis rests on whether the legal fact *actually binds*. - That is the one thing you must verify yourself, not relay second-hand. - -## Pull these (drive sec-edgar) - -- **The primary document** — the merger agreement, indenture, plan of reorganization, 13D - exhibit, Form 10 spin filing, or the foreign-law statute. Read the *exhibit*, not the - summary. `sec-edgar-skill` can pull attachments/exhibits directly. -- 8-Ks for the triggering event (Item 1.01, 1.03, 2.01, 5.01) and the timeline. -- 13D/G for the activist or controlling holder and — critically — - `item4_purpose_of_transaction` (the *why*). -- For foreign private issuers: 20-F and 6-K, and the local regulator's filings; reconcile to a - comparable basis. -- Capital-structure detail to rebuild the **post-event** balance sheet and the waterfall. - -## Key metrics / objects - -The payoff under each outcome (deal closes / breaks; put exercised / not), the **probability -and timing** of each, the position in the capital structure, the spread vs. downside, the -sum-of-the-parts value, the formula output you computed yourself. - -## Normalize / adjust - -- **Compute the formula yourself** from the document — do not trust a summary or a third-hand - characterization (`pitch-like-lou`'s inviolable rule, the MCI lesson). -- Rebuild the **pro-forma** capital structure as it exists *after* the event. -- For foreign issuers, reconcile foreign-GAAP/IFRS to a comparable basis before valuing. - -## Valuation lens - -**Event payoff / sum-of-the-parts**, probability-weighted across outcomes, with the spread -measured against a hard downside. For spins, value the pieces separately on **multiples**; for -arb, it's payoff × probability vs. break risk; for structural/legal, it's the formula output -discounted for time and the (small) chance the fact doesn't bind. - -## Disqualifiers — kill it (or mark it down) if… - -- **The legal/structural fact doesn't actually bind** — the formula has an out, the statute - doesn't apply, the seniority is subordinated by a clause you missed. -- **Minorities have no protection** — a controller can take the value without sharing it - (no fair-price statute, no independent committee, coercive terms). -- **The timeline is open-ended** — no forcing event or date; "eventually" is not a catalyst and - time decay eats arb returns. -- **You're relying on something you didn't verify** — any load-bearing claim taken second-hand - is an unpriced risk; check it or mark the conviction down hard. -- **The downside isn't bounded** — if the deal breaks or the put isn't exercised, the residual - business is worth far less than the spread implies. +# Archetype: special situation + +Use this lens when a transaction, security term, legal document, reorganization, spin-off, +tender, recapitalization, or forced flow drives value more than ordinary operating growth. The +edge is accurate document reading, a complete capital structure, and scenario arithmetic. + +## Establish the shape + +Identify the binding event or term, the security being valued, conditions and consents, seniority, +timeline, and who controls each decision. Read the operative agreement, plan, indenture, exhibit, +court order, or statute rather than relying on a summary. + +A primary document verifies its text, not the analyst's legal interpretation. Mark uncertain +interpretation as `[A]`, use qualified legal analysis where material, and do not describe an +outcome as inevitable merely because the language appears favorable. + +## Evidence to pull + +- operative transaction and security documents, including definitions, schedules, and exhibits; +- SEC current reports, registration or information statements, tender materials, and amendments; +- court, regulator, exchange, and home-jurisdiction records where applicable; +- voting agreements, financing commitments, termination rights, fees, and outside dates; +- 13D/13G purpose, control relationships, and minority protections; +- the fully diluted pre- and post-event capital structure and claim waterfall; and +- operating information needed to value each residual outcome. + +## Scenario arithmetic + +For each material outcome, show: + +- payoff to the exact security and share class; +- interim distributions, financing, taxes, fees, and dilution; +- probability basis and dependencies; +- expected timing and annualized return; and +- break, delay, or residual value supported independently of the deal price. + +Use sum-of-parts for separable businesses and a waterfall for layered claims. Rebuild the +post-event balance sheet rather than subtracting today's net debt mechanically. Preserve +currency, exchange-ratio, proration, and conversion assumptions. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- a condition, definition, consent, financing out, or senior claim defeats the apparent term; +- minority protections or enforcement are weaker than assumed; +- the timeline is open-ended and carrying costs erase the expected return; +- break value depends on the unaffected price without re-underwriting the business; +- probability is asserted without a base rate or case-specific evidence; +- taxes, fees, proration, dilution, tradability, or liquidity materially change the security payoff; or +- a load-bearing legal interpretation has not been independently checked. + +The memo should separate document facts, legal interpretation, probability judgment, and payoff +calculation so a reader can disagree with one without losing the entire audit trail. diff --git a/skills/bottom-up-analyst/references/archetypes/turnaround.md b/skills/bottom-up-analyst/references/archetypes/turnaround.md index 7dc4e66..91ce218 100644 --- a/skills/bottom-up-analyst/references/archetypes/turnaround.md +++ b/skills/bottom-up-analyst/references/archetypes/turnaround.md @@ -1,74 +1,57 @@ -# Archetype: Turnaround / Inflection - -A business whose **economics are bending** — a money-loser or no-grower whose unit economics, -margins, or growth are inflecting because of a *specific, identifiable* change: a regulatory -or sectoral tailwind, a new management team, a divested loss-maker, a pricing reset, a -product cycle, a cost-structure overhaul. This is the "shitco with inflecting economics" -case. The thesis is **discontinuity** — the future will not look like the trailing financials, -and you must prove *why* with a mechanism, not a hope. - -## Tell it by - -Poor or deteriorating trailing numbers but an identifiable catalyst for change; a new CEO -with a credible plan; a regulatory/sectoral shift that alters the company's economics; early -evidence of margin or demand inflection in the most recent quarters; a market still pricing -the *old* trajectory. - -## Where the value hides - -- **The gap between trailing and forward.** The market extrapolates the recent past; the edge - is identifying a *real* break in trend before the financials confirm it. -- **The mechanism.** A turnaround thesis lives or dies on a concrete cause — "new management - cut 300bps of structural cost," "regulation X forces a price the company couldn't charge - before," "the loss-making segment was sold." Vague "things will get better" is not a thesis. -- **Asymmetry.** Done right, the downside is anchored by current/asset value while the upside - is the inflected earning power — but only if the balance sheet buys enough time. - -## Pull these (drive sec-edgar) - -- The **most recent** 8-Ks, 10-Qs, and earnings call/exhibit — this is where early inflection - evidence shows up first; weight recency heavily. -- 10-K MD&A and segment data — to locate exactly *where* the losses/drag sit and whether the - fix targets it. -- 8-Ks for the catalyst itself — management change (Item 5.02), divestiture/restructuring, - strategic shift; read the actual filing, not the press summary. -- Balance sheet and liquidity — does it have the runway to reach the inflection? A right thesis - with a wrong balance sheet still goes to zero. -- For regulatory/sectoral tailwinds: the rule/regulator filings and peers' filings, plus web - [W] for the policy context filings won't carry. - -## Key metrics - -Sequential (QoQ) margin and revenue trend (not just YoY), the specific cost/revenue line that's -inflecting, incremental margins on the recovery, cash runway and burn, leverage and maturities, -the size of the addressable improvement vs. the current loss. - -## Normalize / adjust - -- Model **post-inflection** steady-state economics explicitly — and separately keep a - **downside case where the inflection fails**. -- Strip the segment/cost being fixed to see the "good company" underneath. -- Be conservative on timing; inflections usually take longer than the bull case assumes. - -## Valuation lens - -**Scenario DCF** on post-inflection margins (bear = inflection stalls; base = partial; bull = -full), with **EPV/asset value today as the downside floor**. A turnaround’s FCF trajectory -almost always has a structural bend — near-term acceleration from cost-outs, margin -expansion, or debt paydown, followed by a different normalized growth rate. The **three-stage -DCF** (`--growth2`, `--years2`) exists for exactly this shape; prefer it over forcing a -single stage-1 rate to average across two distinct phases. The thesis is attractive only if -the EPV floor limits the loss while the inflection delivers the upside — quantify both ends. - -## Disqualifiers — kill it (or mark it down) if… - -- **No concrete mechanism** — the case rests on hope, sentiment, or "it's too cheap to go - lower" rather than a specific, traceable cause of change. -- **The balance sheet runs out before the inflection lands** — insufficient runway; the next - raise is dilutive or unavailable. -- **The inflection is already in the price** — the market has re-rated ahead of proof and the - asymmetry is gone. -- **It's a value trap** — the "temporary" problems are structural/secular (dying end-market, - broken model), so the inflection never comes. -- **No evidence yet** *and* no near-dated way to get it — an untestable turnaround is a bet, - not a thesis. +# Archetype: turnaround or inflection + +Use this lens when a specific change may make future economics differ materially from trailing +results: restructuring, new management, pricing, divestiture, product transition, regulation, +demand recovery, or capital-structure repair. Cheapness and management targets are not mechanisms. + +## Establish the shape + +Write the causal bridge: + +```text +identified change +→ operating line affected +→ magnitude and timing +→ cash cost and funding +→ observable evidence so far +→ normalized FCFF if it works +``` + +Separate self-help the company controls from external recovery it does not. Distinguish early +evidence from a target, and identify the old problem that could persist. + +## Evidence to pull + +- recent quarterly and current reports, exhibits, and calls for sequential evidence; +- segment results and cost lines that locate the drag and proposed improvement; +- restructuring charges, cash payments, stranded costs, dis-synergies, and transition capex; +- pricing, volume, backlog, churn, or utilization measures tied to the mechanism; +- management's prior targets and delivery record; +- liquidity, covenants, maturities, and financing needs through the transition; and +- the primary regulatory, contractual, or transaction document when it drives the change. + +## Valuation + +Build explicit annual failure, partial-success, and stronger-success cases. Use +`dcf.py forecast` when FCFF changes sign or margins step through a transition. Do not give the +company its target margin immediately; model implementation cost, timing, taxes, working capital, +reinvestment, financing, and dilution. + +EPV or asset value may provide a comparison for current operations, but neither is a floor when +cash burn, liabilities, or deterioration continue. Value any disposed or retained pieces on the +post-transaction capital structure. + +## Disqualifiers and counterevidence + +Mark down or reject the case when: + +- no specific mechanism connects actions to cash flow; +- reported progress relies on exclusions while cash economics do not improve; +- the balance sheet runs out before evidence should arrive; +- savings are offset by lost revenue, reinvestment, or stranded costs; +- the apparent inflection is an ordinary cycle rebound or temporary comparison; +- management has repeatedly missed similar plans; or +- price already requires successful execution with little downside protection. + +The memo should specify milestones, dates, cash runway, and the evidence that would distinguish a +delay from a broken mechanism. diff --git a/skills/bottom-up-analyst/references/guide_competitive.md b/skills/bottom-up-analyst/references/guide_competitive.md index 4a5eaf2..87186d8 100644 --- a/skills/bottom-up-analyst/references/guide_competitive.md +++ b/skills/bottom-up-analyst/references/guide_competitive.md @@ -1,123 +1,115 @@ -# Competitive & industry analysis - filings first, web for the gaps - -Phase 4 of the loop. A normalized earnings number is only as trustworthy as the moat under -it: durable returns require a durable *reason*. This phase establishes industry structure, -the company's place in it, and - the hard, decisive part - its **relative** competitive -advantage. Assert nothing; explain the moat *mechanically* or concede there isn't one. - -The governing rule of the stack applies here with full force: **SEC filings are the default -and the grounding; the web fills only what filings genuinely cannot.** Filings are primary, -auditable, and citable; the web is a labeled supplement that must never silently outrank a -filing. - -## What filings give you - more than people expect - -Before touching the web, exhaust the documents. A surprising amount of "qualitative" insight -is sitting in EDGAR, already auditable: - -- **The subject's 10-K.** Item 1 (Business) describes competition, customers, suppliers, and - segments in the company's own words. Item 1A (Risk Factors) is a candid map of what - management fears - read it as a competitive document, not boilerplate. The MD&A (Item 7) - explains *why* the numbers moved. -- **Peers' own filings - the high-leverage move.** `market-scout` hands you the **peer - set**. Pull each peer's recent **8-Ks, 10-Qs, and 10-K** and read - their management commentary: pricing actions, demand color, capacity, who's winning share. - Triangulating the same quarter across three competitors' filings is primary-source - competitive intelligence you can cite [V] - often sharper than any third-party take. -- **Industry structure from the numbers.** Compare gross and operating margins, returns on - capital, capital intensity, and growth across the peer set. Persistent margin or ROIC - gaps are the *quantitative fingerprint* of a moat (or its absence) - pricing power, scale - economics, switching costs show up here before anyone writes them down. - -## What only the web can give - and how to use it - -Some questions no filing answers, and these are exactly where competitive theses are won or -lost. Go to the web for: - -- **Relative positioning and market share** - who's actually winning, and the trend. -- **Pricing dynamics and channel checks** - real-world price moves, distribution, customer - satisfaction, churn anecdotes. -- **Industry tailwinds/headwinds** - regulation, technology shifts, end-market demand. -- **Management quality and track record** - beyond the proxy's bare facts. - -When you do, observe the discipline that keeps the memo trustworthy: - -- **Attribute and date every web claim**, and prefer **primary** sources - company IR decks, - regulators, standards bodies, trade associations - over aggregators and secondary - commentary. -- **Mark it [W]** in the memo so the reader can weight it differently from a filed fact. -- **Never let a web assertion override a filing** without saying so explicitly and explaining - why you believe the web over the document. -- **Separate fact from sentiment.** "Revenue grew 30%" (checkable) is not "analysts love the - story" (mood). Both can matter; don't let the second masquerade as the first. - -## The output of this phase - -A clear verdict on competitive position you can defend: - -1. **Industry structure** - concentration, rivalry, where the profit pools sit, the - secular direction of travel. -2. **The company's position** - leader/challenger/niche, and the *evidence* (the margin/ROIC - gap vs. peers, share trend, customer captivity). -3. **The moat, named and tested** - which specific mechanism (scale, network, switching - costs, brand/share-of-mind, low-cost production, regulatory) and *why it persists*. State - what would erode it; a moat you can't imagine breaching is a moat you haven't examined. - -Feed this straight into valuation: the strength and *durability* of the moat is what justifies -the growth runway and the discount rate you'll defend in phase 5. - -## Quantify impact, don't just list forces - -The most common failure in competitive analysis is **cataloguing without quantifying.** -Listing five barriers to entry or four competitive threats is not analysis - it is -inventory. The reader needs to understand *how much each force matters* to the thesis. -For every competitive strength, weakness, threat, or moat mechanism, answer three -questions: - -1. **How big is it?** Attach a number, a share, a dollar figure, or a rate. "High - switching costs" is a label; "multi-year contracts with 95%+ renewal rates and - 12-18 month migration timelines" is evidence. "Competition is intensifying" is mood; - "Motorola's Command Center division grew 14% last year and now holds ~30% of the - call-handling market" is a fact you can reason from. - -2. **How fast is it moving?** A static snapshot is not enough. Is the competitor - gaining share, losing it, or flat? Is the technology threat emerging (R&D stage), - arriving (first deployments), or mature (already displacing incumbents)? A threat - that is five years away at current pace is a different input to the thesis than one - that is already taking share. Cite the trajectory, not just the position. - -3. **What is the dollar impact on *this company* if it plays out?** Translate the - competitive force into revenue, margin, or FCF impact on the subject. "Cloud-native - architectures could lower barriers" becomes "if a cloud-native entrant captured 10% - of the addressable NG9-1-1 market over 5 years, that's ~$12M/yr of revenue at risk - for Allerium, or ~5% of current revenue." Now the reader can weigh it. A risk you - can't size is a risk you haven't understood. - -### Applying this to strengths and moats - -The same discipline applies to the bull case. "Strong installed base" is a label; -"4,200 PSAPs on the platform with an average contract life of 7 years and a historical -churn rate below 3%" is a moat you can underwrite. "Switching costs are high" is an -assertion; "the Kentucky statewide migration took 8 months of planning and 4 months of -execution for 12 PSAPs, and the state has 120 total" tells you *how* high. - -When you can't find the number, say so - mark it [A] and flag it as a gap the reader -should investigate. An honest "I couldn't quantify this" is more useful than a -confident-sounding assertion that melts under scrutiny. - -### Applying this to risks and threats - -Every risk factor in the memo should pass a **"so what" test**: if this risk -materializes, what happens to revenue, margins, or FCF - and over what timeframe? -A risk without an impact estimate is a worry, not an analysis. The pre-mortem -(phase 6) is where you stress-test the risks against the thesis; the competitive -section is where you *size* them so the pre-mortem has something to work with. - -Examples of the shift from listing to quantifying: - -| Listing (weak) | Quantifying (strong) | -| :-- | :-- | -| "Competition from larger players" | "Competitor X's revenue in the segment grew 14% YoY to ~$X00M; their new platform has been deployed in N states, directly overlapping with the subject's TAM" | -| "Technology disruption risk" | "Cloud-native entrants have raised $X00M in VC funding and signed pilot contracts with N customers; at current adoption rates, they could reach ~5% market penetration by 2028" | -| "Customer concentration" | "Top customer is ~25% of segment revenue (~$56M); the contract runs through 2029, but loss at renewal would cut segment EBITDA by ~$15M" | -| "High switching costs" | "A statewide migration took 8 months planning + 4 months execution for 12 of 120 sites; full cutover expected to take 3+ years, creating de facto lock-in" | +# Competitive and industry analysis + +Use this guide to determine whether the economics in the model can persist. The goal is not a +list of moat labels or risk factors; it is a causal account of where industry profits come from, +why this company captures its share, and what evidence would show that position changing. + +## Start with the question, then choose sources + +Use the source authoritative for each claim rather than imposing one universal source order. + +- **Issuer filings and exhibits:** reported segments, customer concentration, contracts, + capacity, risk disclosures, and management's explanation of results. They are primary records + of the issuer's disclosure, not independent proof of market position. +- **Peer filings and calls:** competitors' reported demand, pricing, capacity, strategy, and + financial outcomes. Select a few economically relevant peers; an automated industry list is a + candidate set, not ground truth. +- **Regulators, courts, standards bodies, and government data:** rules, licenses, enforcement, + market statistics, and legal status. +- **Customers, suppliers, product documentation, procurement records, and trade data:** buying + criteria, switching friction, price, reliability, channel behavior, and adoption. +- **Independent research and reporting:** useful for discovery and triangulation. Assess source + access, method, date, incentives, and whether the claim can be checked directly. + +Cite and date material evidence. Use `[V]` for facts checked in an authoritative primary record +and `[W]` for external or secondary evidence. When sources disagree, preserve the disagreement +and explain which assumption the valuation uses. + +## Map the industry economics + +Answer the questions that determine profit durability: + +1. **Value chain:** who supplies, distributes, pays, uses, and captures gross profit? +2. **Market definition:** what product, customer, geography, and time period does a share or TAM + figure actually cover? +3. **Structure:** concentration, capacity, entry and exit, substitutes, regulation, bargaining + power, and capital intensity. +4. **Buying decision:** which attributes decide a purchase, who bears switching cost, and how + often a customer can reconsider? +5. **Rate of change:** technology, regulation, supply, customer behavior, and new business + models that could alter the profit pool. + +Avoid top-down market labels that mix unlike products or geographies. Reconcile market-size and +share estimates to company revenue where possible. + +## Select and compare peers + +Choose peers based on the economic question: product overlap, customer set, cost structure, +geography, maturity, or capital intensity. Different questions may need different peer sets. +Document why each peer belongs. + +Compare a multi-period set of relevant measures, which may include organic growth, unit volume, +price/mix, gross margin, incremental margin, retention, capital intensity, ROIC, and customer +concentration. Persistent differences are clues, not automatic proof of a moat. Test alternative +explanations such as accounting policy, mix, geography, underinvestment, leverage, or a temporary +cycle position. + +## Explain advantage as a mechanism + +For each claimed advantage, complete the chain: + +```text +asset, capability, or structural position +→ customer or cost consequence +→ observable operating evidence +→ economic outcome +→ reason competitors cannot quickly copy or neutralize it +``` + +Examples of mechanisms include scale economies, network effects, switching costs, scarce assets, +regulatory position, process advantage, brand, distribution, and counter-positioning. The label +alone does no analytical work. State what would erode the mechanism and which metric would show +that first. + +## Quantify without inventing precision + +Size forces when reliable data permit. Useful forms include: + +- exposure: affected revenue, customers, units, capacity, or gross profit; +- sensitivity: effect of a price, volume, churn, utilization, or cost change; +- trajectory: direction, rate, and time to materiality; and +- scenario range: a bounded impact under explicit assumptions. + +Some risks are discontinuous, legal, behavioral, or poorly disclosed. Do not fabricate a point +estimate merely because a template asks for one. Use a range, break-even calculation, observable +leading indicator, or `[A]` gap. Explain whether the unknown is capable of changing the decision. + +## Separate evidence from inference + +A contract term can be `[V]`; “therefore customers are captive” is an inference. A peer's claim +that it gained share verifies the claim was made, not the share gain. Tie inferences to multiple +observable premises when possible: + +- renewal or churn history; +- realized price versus input cost; +- win/loss or backlog conversion; +- gross-margin and incremental-margin persistence; +- customer concentration and cohort behavior; +- replacement cycle or migration effort; and +- competitor investment and capacity response. + +Treat management tone and analyst questions as leads, not measurements. + +## Output + +Conclude with a compact underwriting view: + +1. market and profit-pool definition; +2. the company's position and relevant peers; +3. two or three mechanisms that matter, with evidence and erosion tests; +4. material threats and their best-supported ranges or indicators; +5. implications for growth, margins, reinvestment, and valuation; and +6. unresolved evidence gaps. + +The section earns its place only if it changes an assumption, probability, risk assessment, or +monitorable in the thesis. diff --git a/skills/bottom-up-analyst/references/guide_normalization.md b/skills/bottom-up-analyst/references/guide_normalization.md index 905a3ff..ecbeb0f 100644 --- a/skills/bottom-up-analyst/references/guide_normalization.md +++ b/skills/bottom-up-analyst/references/guide_normalization.md @@ -1,137 +1,159 @@ -# Normalization — from GAAP to owner earnings - -Phase 3 of the loop. The goal is the business's *real, repeatable* earning power — what an -owner would actually pocket — not the accounting surface. GAAP is a starting point, not the -answer: it mixes one-offs with the run-rate, expenses real investment as if it were waste -(and vice-versa), and hides economics in the footnotes. Your job is to un-distort it, and — -per the prime directive — to **name every adjustment** so a reader can undo it. An -unexplained "adjusted" number is exactly the kind of laundered guess this skill exists to -avoid. - -Drive `sec-edgar-skill` to pull the statements (`sec-edgar-skill`'s `parse_financials.py` → CSV) and the -relevant footnotes (grep the cached 10-K); do the reasoning here. - -## Owner earnings — the target number - -Start from the Buffett definition and adjust toward cash an owner could remove without -harming the business: - -```text -Owner earnings = net income - + depreciation & amortization - + other non-cash charges - − maintenance capex (NOT total capex — see below) - ± normalized working-capital change - − real stock-based compensation cost -``` - -The art is in three places, and each is a judgment you must show your work on: - -### 1. Maintenance vs. growth capex - -Total capex on the cash-flow statement bundles "keep the lights on" with "build the future." -Only **maintenance** capex belongs in owner earnings; growth capex is optional spending you -can value separately. Estimate maintenance capex from D&A as a floor, from management's own -split if they disclose one [V], from unit economics (capex per store/rig/MW at steady -state), or from history (capex in no-growth years). State which method and why — a -compounder's value swings hard on this number. - -### 2. Working capital — separate structural from one-off - -A growing business consumes working capital; a shrinking or seasonal one releases it. Pull -the *normalized* draw, not a single year's swing, and watch for channel-stuffing or a -one-time release flattering operating cash flow. - -### 3. Stock-based comp is a real expense - -It is non-cash but not free — it transfers ownership. Subtract it, and fold the resulting -dilution into the share count (treasury-stock method) rather than admiring a "cash" number -that quietly grows the shares 4% a year. For hypergrowth names this is often *the* swing -factor between "profitable" and not. - -## Common distortions to undo - -- **Deferred / subscription revenue.** Cash collected up front can make GAAP *understate* - real earnings (a healthy subscription book) or overstate durability — read the deferred - revenue footnote and decide which. -- **Leases.** Post-ASC 842, operating leases are on the balance sheet; treat lease - obligations as the debt-like commitments they are when you compute net debt and TEV. -- **One-offs and "non-recurring" items that recur.** Restructuring every year is an - operating cost, not a special item. Back out the genuinely one-time; keep the rest. -- **Acquired growth vs. organic.** Strip the contribution of acquisitions to see the - organic engine; a roll-up's "growth" can be capital consumption in disguise. -- **Non-operating noise.** Pension mark-to-market, FX, fair-value swings on securities — - separate from operating earning power. - -## Show the trend, not a snapshot - -A single normalized year can be cherry-picked or flattered. Build the **year-by-year -capital-allocation table** — it is the most persuasive object in the memo because the trend -argues for itself: - -```text - Shares(M) Net debt($M) Reinvested($M) ROIC(%) FCF/share -FY-4 15.2 420 … … … -FY-3 13.6 360 -FY-2 11.1 300 -FY-1 10.4 210 -FY0 9.2 120 -``` - -Falling share count, falling debt, rising returns on retained capital — that picture tells -the reader how management actually behaves, which no single ratio can. - -## When the thesis depends on a new revenue stream: model the unit economics - -Normalization looks backward — it un-distorts what the business *has* earned. But many -theses (turnarounds, inflections, hypergrowth pivots, special situations) depend on a -revenue stream or business model that **doesn’t yet exist in the trailing financials.** -When the valuation’s base or bull case rests on a new stream, the memo must model its -unit economics explicitly — not just cite a management TAM estimate and plug a growth -rate into the DCF. - -### What “model the unit economics” means - -Build a **bottom-up revenue bridge** from the new stream’s inputs to its contribution -to FCF. The bridge should answer: - -1. **What is the unit of sale?** A per-device chip fee, a per-store contribution, a - per-seat SaaS subscription, a per-unit margin on hardware — name it. -2. **What does one unit cost to deliver?** COGS, fulfillment, support, platform costs. - If the company hasn’t disclosed this, benchmark against the closest analog and mark - it [A]. -3. **How many units does the scenario assume?** Tie this to something observable — - the number of customers in the pipeline, the addressable installed base, the - contract backlog — not just a top-down TAM percentage. -4. **What is the resulting gross margin and contribution margin?** Show the math. -5. **How does this flow through to FCF?** After incremental SG&A, R&D, capex, and - working capital required to support the new stream. - -The bridge makes the assumption *auditable*. A reader who disagrees with your per-unit -fee or your customer count can re-run the math; a reader who sees only “$5–20M in -annual SaaS revenue per customer [A]” cannot. The bridge also forces *you* to confront -whether the numbers are internally consistent: if the per-device fee implies a price -point higher than the competitor’s whole product, the thesis has a problem you’d rather -find now. - -### When to do this - -Any time the valuation’s base or bull case assigns material value to a revenue stream -that is pre-revenue, in pilot, or represents a business model change from the trailing -financials. Examples: - -- A regulatory catalyst opens a new market the company hasn’t yet entered (ISPR’s IKE - age-gating chip in the flavored ENDS market) -- A partnership or JV creates a new product category (WRBY’s Google smart-glasses) -- A divestiture or restructuring changes the margin profile (CMTL’s Allerium post-S&S) -- A platform or marketplace layer is being built on top of an existing product - -If the new stream is immaterial to the thesis (“a small adjacent opportunity”), a -sentence suffices. If it’s load-bearing, the bridge is mandatory. - -## The honesty check - -Every normalized figure is an [E]stimate built on an [A]ssumption. Mark them as such in the -memo, state the assumption inline, and make sure the thesis survives the *conservative* end -of each. If owner earnings only works on your aggressive maintenance-capex number, that's not -a thesis — that's a hope with a spreadsheet. +# Normalization — reported results to economic cash flow + +Use this guide when reported earnings do not represent the repeatable cash economics relevant +to the thesis. Normalization is a reconciliation, not permission to remove unpleasant costs. +Show each adjustment, source period, rationale, tax treatment, and effect so the reader can +reverse it. + +## Choose the cash-flow basis first + +Do not mix enterprise and equity cash flows. + +### Free cash flow to the firm (FCFF) + +Use FCFF for the bundled DCF and EPV scripts: + +```text +FCFF = EBIT × (1 − normalized cash tax rate) + + D&A and other justified non-cash add-backs + − capital expenditure + − increase in operating working capital +``` + +Do not use “non-cash” alone as justification to add back a recurring economic cost such as stock +compensation. FCFF is before interest and net borrowing. Discount it at WACC to value operations, +then bridge from enterprise value to common equity by adding non-operating assets and subtracting net debt, +preferred stock, minority interests, pension deficits, and other senior claims as appropriate. +Do not hide those items inside a label called net debt; show the bridge in the memo. + +### Owner earnings or free cash flow to equity (FCFE) + +A cash flow starting from net income or cash from operations is after interest under US GAAP and +is generally an equity cash flow. IFRS presentation can classify interest differently, so +reconcile it explicitly. Discount FCFE at the cost of equity and do not subtract debt again. The +bundled DCF does not model FCFE. + +Whichever basis you use, reconcile it to the statements. Label units, currency, fiscal period, +and whether each figure is reported `[V]`, estimated `[E]`, or assumed `[A]`. + +## Recurring versus non-recurring + +Use a multi-period history and ask what a steady owner must expect to recur. + +- Remove a gain or loss only when the underlying event is genuinely non-operating or unlikely + to recur. Repeated restructuring, litigation, acquisition, or “one-time” costs belong in + normalized economics unless the operating mechanism has demonstrably changed. +- Normalize taxes using the expected cash burden, including jurisdiction mix, credits, NOLs, + and expiry. Do not adopt a headline statutory rate by default. +- Separate acquired growth from organic growth and include the acquisition spending required + to sustain a roll-up's apparent growth. +- Distinguish temporary commodity, foreign-exchange, pension, fair-value, and working-capital + effects from a changed run rate. + +Present reported-to-normalized bridges for the periods that matter. A single adjusted year is +usually too easy to cherry-pick. + +## Maintenance and growth investment + +Total capex combines replacement, compliance, capacity, and expansion. Estimate maintenance +capex by triangulating evidence such as: + +- management's disclosed split, treated as an issuer estimate rather than objective fact; +- physical units, replacement cycles, utilization, and current replacement cost; +- capex during periods with little capacity growth; +- depreciation by asset class, useful life, asset age, and inflation; and +- peer asset intensity and sustaining-capex disclosures. + +D&A is a reference point, not a universal floor or ceiling. Old assets and inflation can make +replacement cost exceed depreciation; overbuilt capacity or accelerated depreciation can do the +opposite. If the split is uncertain, use a range and show how valuation changes. + +A growth project is not economically free because it is excluded from “maintenance” capex. +Connect growth investment to incremental revenue, margins, and returns on incremental capital. + +## Working capital and deferred revenue + +Use operating working capital and preserve signs: an increase is a use of cash; a decrease is a +source. Normalize seasonal or event-driven swings with comparable dates and multiple periods. +Investigate receivable growth, inventory aging, payables extension, factoring, and channel +loading before treating a cash release as repeatable. + +Deferred revenue is customer financing and a timing difference, not extra revenue to add back +mechanically. Its change already affects operating cash flow. Analyze billings, remaining +performance obligations, refund obligations, churn, and the future delivery cost; then model the +cash timing consistently without counting the same inflow twice. + +## Stock-based compensation and dilution + +Stock compensation is an economic cost, but common starting points treat it differently: + +- GAAP EBIT and net income already expense it. Do not subtract the same expense again from an + EBIT-based FCFF unless you first added it back. +- Cash from operations adds the non-cash expense back. A CFO-minus-capex measure therefore needs + an explicit treatment: retain the GAAP expense in a reconstructed FCFF, subtract an estimate + of ongoing grants, or model the cash needed to offset dilution. +- Reflect outstanding in-the-money instruments in diluted shares or value them separately. + Model future grants consistently with operating margins. Do not charge the full compensation + expense and an unrelated full dilution penalty without reconciling the overlap. + +Show basic and diluted share-count history, grants, exercises, repurchases, and net issuance. +Repurchases that merely offset compensation are not a return of capital. + +## Leases + +Lease treatment must match the cash flow, capital structure, and comparison metric. + +- If rent remains an operating expense and cash outflow, do not also add the full lease + liability to debt without adjusting the earnings and cash-flow basis. +- If leases are capitalized as financing, add back the financing component consistently, + capitalize the obligation, and use lease-adjusted peer metrics. + +Either convention can be useful; mixing them double-counts the lease burden. + +## A useful operating history + +Choose rows and years for the business rather than forcing a fixed table. A typical operating +company history may include: + +| Period | Revenue | Organic growth | EBIT margin | FCFF | Diluted shares | Net debt | ROIC | +| :-- | --: | --: | --: | --: | --: | --: | --: | +| [FY-2] | | | | | | | | +| [FY-1] | | | | | | | | +| [FY0] | | | | | | | | + +For a cyclical, span a full cycle. For a turnaround, add quarterly bridge metrics. For a unit +model, show mature cohorts or stores. Explain denominator choices for ROIC and compute return on +incremental capital only across periods where the comparison is meaningful. + +## New streams and changed economics + +When a material scenario depends on a stream not represented in trailing results, bridge from +observable drivers rather than applying a TAM percentage: + +```text +addressable units +× adoption or penetration +× price per unit += revenue +× contribution margin +− incremental fixed cost +− capex and working-capital needs += incremental FCFF +``` + +Use the actual economic unit: customer, seat, location, device, transaction, capacity unit, or +contract. Source price, volume, churn, utilization, cost to serve, and timing separately. Use +ranges when inputs are sparse. Reconcile the stream to consolidated revenue and costs so shared +expenses and cannibalization are not omitted. + +## Final check + +For each adjustment, ask: + +1. Is it already reflected elsewhere in the cash flow, share count, or enterprise bridge? +2. Does it recur economically even if accounting labels it unusual? +3. Are tax and sign conventions correct? +4. Is the estimate supported by more than management's preferred presentation? +5. Does a conservative alternative materially change the decision? + +An unexplained adjusted number is an assumption, not a fact. diff --git a/skills/bottom-up-analyst/references/guide_ownership_signals.md b/skills/bottom-up-analyst/references/guide_ownership_signals.md index 39895b1..9f4539f 100644 --- a/skills/bottom-up-analyst/references/guide_ownership_signals.md +++ b/skills/bottom-up-analyst/references/guide_ownership_signals.md @@ -1,58 +1,115 @@ -# Reading the ownership signal — 13F and insider data - -Phase 6 support. Pull the data via `sec-edgar-skill` (institutional 13F holders and Form 4 -insider transactions), then read it against the thesis. This guide is *how to interpret* -each pattern; the fetch mechanics and flags live in `sec-edgar-skill` (`--help` is -authoritative). - -13F output reports **share counts**, not dollar values (13F values are stale quarter-end -prices). Convert to ownership percentages by dividing by shares outstanding from the -`market-scout` snapshot or the latest 10-Q. - -## Institutional ownership (13F) - -Who is positioned and how the holder base has shifted — signals that feed the risk and -catalyst assessment: - -- **Concentration risk:** if 3–5 holders own >30% of the float, a single redemption cycle - can crater the stock independent of fundamentals. -- **Smart-money conviction:** are high-conviction value managers (Royce, Needham, Baupost) - building or trimming? A rising share count from a known deep-diver is a confirming signal; - a quiet exit is a warning. -- **Activist presence:** a 13D/13G filer in the holder list may signal an upcoming catalyst - (board fight, strategic review, buyback demand). -- **Passive vs. active mix:** a stock dominated by index funds (Vanguard, BlackRock, State - Street) has different liquidity and governance dynamics than one held by concentrated - active managers. -- **Ownership trend vs. price:** rising institutional ownership into a falling price - suggests accumulation; the reverse suggests distribution. Cross-reference with the holder - history. - -## Insider activity (Form 4) - -Insider transactions are a direct, auditable read on whether the people running the business -are aligned with outside shareholders — or quietly heading for the exits. Read them for -adverse-selection risk: - -- **Open-market purchases by officers/directors** are the strongest signal — voluntary, with - the insider's own capital, filed publicly. A CEO or CFO buying $500K+ at current prices is - putting money where their mouth is; multiple insiders buying in the same window (a "cluster - buy") is stronger still. -- **Selling context matters.** Discretionary sales by senior officers outside a pre-announced - 10b5-1 plan — especially into strength or ahead of a known risk — are a red flag; routine - 10b5-1, diversification, and tax-driven exercises are not. Read the pattern: clockwork - quarterly selling is a plan; three executives dumping the week after an earnings beat is - discretionary. -- **Ownership level vs. compensation.** Cross-reference insider holdings (the "Remaining - Shares" column) against the proxy's compensation tables. Holdings 10x+ annual salary is - real skin in the game; holdings that round to zero against cash comp are not. -- **Buy/sell ratio and trend.** A ratio well above 1x (net buying) over the past 6–12 months - is confirming; well below 1x (net selling) into a long you are building is a direct - adverse-selection warning — the best-informed people are reducing exposure. -- **Activity at inflection points.** The most informative trades cluster around events. An - insider buying after a 40% drawdown thinks the market overreacted; an insider selling ahead - of a product launch they have been hyping is telling you the opposite. -- **Foreign private issuers (FPIs):** FPIs are exempt from Section 16 and do not file Forms - 3/4/5 on EDGAR. Insider data will be unavailable — note the gap in the memo, and check the - home-jurisdiction regulator (e.g. SEDAR+ for Canadian filers) if the thesis depends on - insider alignment. +# Ownership, insider activity, incentives, and governance + +Use ownership evidence when it can change alignment, liquidity, control, dilution, governance, +or the path to value. It is supporting evidence, not a substitute for operating work. Pull the +underlying records through `sec-edgar-skill` and follow that skill's current guides for retrieval +and form semantics. + +## 13F — limited institutional position evidence + +Form 13F is a delayed quarter-end disclosure by qualifying investment managers for reportable +securities over which they exercise investment discretion. It is not a complete cap table or a +record of all institutional trading. + +Before interpreting a result, record: + +- quarter-end date, filing date, and amendments; +- issuer, security class, CUSIP, shares or principal amount, and option indicator; +- whether the same exposure may appear under multiple managers or classes; and +- a period-matched share denominator if calculating ownership percentage. + +Important limits: + +- reports can arrive up to the filing deadline after quarter end; +- short positions and investment rationale are absent; +- non-reportable securities, smaller managers, and some confidential positions are absent; +- a quarter-end comparison does not show when or why a position changed; and +- shares outstanding from a later date can distort an ownership percentage. + +Use manager position history to describe reported quarter-end changes. Do not call a change +“accumulation into weakness” or “distribution” without compatible dates and additional evidence. +A well-known manager's name does not validate the thesis; the position may be hedged, passive, +small within its portfolio, or held for an unknown mandate. + +Potentially useful questions include: + +- Is reported ownership concentrated enough that a holder's exit could affect liquidity? +- Are changes broad across independently selected active holders or driven by passive flows? +- Do amendments, class changes, mergers, splits, or CUSIP changes explain the movement? + +Label computed percentages `[E]` and state the denominator and dates. Never present the sum of +available 13F rows as definitive institutional ownership or float ownership. + +## 13D, 13G, and the proxy — beneficial ownership and control + +Schedules 13D/13G and proxy beneficial-ownership tables answer different questions from 13F. +Use them directly when the thesis concerns a blockholder, activist purpose, voting control, or +insider ownership. + +Check: + +- beneficial owner, group status, class, shares, percentage, and measurement date; +- voting and dispositive power, direct versus indirect ownership, and footnotes; +- amendments and changes in purpose; +- Item 4 plans or proposals in Schedule 13D; and +- dual-class rights, agreements, pledges, and related entities. + +Do not infer activism merely because a manager also appears in a 13F list. Schedule 13G is not a +synonym for passive in every case; use the filing category and disclosed facts. + +## Form 4 — transaction evidence, not mind reading + +Read transaction code, price, shares, direct/indirect ownership, footnotes, derivative table, +10b5-1 indicator, transaction date, filing date, and post-transaction amount together. + +- **P** is an open-market or private purchase and is usually the cleanest voluntary cash signal. +- **S** is a sale, but motive requires context from footnotes, plan disclosure, ownership, size, + history, and compensation. +- **M** is an option exercise, **F** commonly covers tax withholding, **A** is a grant or award, + and **G** is a gift. Do not mix these mechanically into a buy/sell ratio. + +Use the reported 10b5-1 checkbox and adoption date where available. Do not infer plan status +solely from a regular trading cadence. Likewise, timing near an event does not establish intent. +Phrase suspicious patterns as questions or risks unless direct evidence supports more. + +“Remaining shares” is a post-transaction amount for the reported ownership line. It may omit +other direct, indirect, or derivative holdings and should not be treated automatically as the +person's aggregate beneficial ownership. Use the proxy and all relevant ownership rows for an +alignment calculation. + +Useful interpretation compares transaction size with prior holdings, compensation, liquidity, +and the insider's history. Avoid universal dollar thresholds: materiality differs by person and +company. Cluster purchases can be notable, but check whether they were voluntary, independently +decided, and economically meaningful. + +## Incentives and governance + +For a full memo, review the proxy and related filings when these items can change value: + +- performance metrics and whether compensation rewards per-share value, growth at any price, or + a manipulable adjusted measure; +- option and equity grants, dilution, repricing, and share-count history; +- insider ownership, pledging, hedging, and change-of-control arrangements; +- board independence, tenure, relevant expertise, and controller rights; +- related-party transactions and conflicts; +- capital-allocation record versus stated policy; and +- voting structure, proposals, and minority protections. + +Compensation metrics are inputs to an incentive analysis, not proof of behavior. Compare what +management was paid to do with what it actually did and the per-share outcome. + +Foreign private issuers may not file Forms 3/4/5 and may use home-country governance documents. +State the gap and use the relevant regulator or issuer record when material. + +## Memo output + +Include only decision-relevant ownership and governance evidence. A compact section may contain: + +1. control and beneficial ownership; +2. material 13F position changes with period caveats; +3. voluntary insider purchases and material sales with transaction-code context; +4. dilution and incentive alignment; and +5. the resulting implication for liquidity, control, capital allocation, or thesis risk. + +Cite the filings and dates. If the data are unavailable, stale, or ambiguous, say so rather than +turning absence into a positive or negative signal. diff --git a/skills/bottom-up-analyst/references/guide_valuation.md b/skills/bottom-up-analyst/references/guide_valuation.md index b70a4ab..c0f5287 100644 --- a/skills/bottom-up-analyst/references/guide_valuation.md +++ b/skills/bottom-up-analyst/references/guide_valuation.md @@ -1,197 +1,206 @@ -# Valuation — triangulation, weighted by archetype - -Phase 5 of the loop. Value is a *range*, reached from independent lenses, never a single -false-precision point. Each lens has failure modes; the archetype tells you which to trust. -The discipline is to make every assumption explicit and conservative enough that the thesis -survives the *low* end — an intrinsic value that only works on heroic inputs is a hope, not a -valuation. - -Run the arithmetic with the bundled scripts (`scripts/dcf.py`, `scripts/epv.py`) rather than -re-deriving it each time; `--help` is the flag reference. Reason about the *inputs* here. - -## The four lenses - -### 1. Reverse-DCF — "what's already priced in" (first-class) - -Instead of forecasting, **invert**: solve for the stage-1 growth (or margin) the *current -price* requires, then ask one question — *is that achievable?* This is the most honest lens -when the future is uncertain, and for **hypergrowth** names it is often the *only* defensible -one: rather than pretend you can forecast a hyper-growth decade, you judge whether the -market's embedded expectation is too high, about right, or too low. Run it on every name as a -reality check, even when another lens leads. - -```bash -python scripts/dcf.py --mode reverse --price 150 --fcf0 1200 --years 10 \ - --terminal-growth 3 --discount 10 --shares 500 --net-debt 200 -``` - -Read the result against reality: if the price implies 22% FCF growth for a decade and the -company has never exceeded 12%, the bar is too high regardless of how good the story sounds. - -### 2. Forward DCF — intrinsic value under your assumptions - -A two-stage discounted cash flow on normalized owner earnings (phase 3). Best for businesses -with *predictable* cash flows — compounders, stable cash generators. Drive it with -**bear/base/bull** growth cases (the script accepts comma-separated growth for a quick -sensitivity table) so the output is a range, not a point. - -```bash -python scripts/dcf.py --fcf0 1200 --growth 8,12,16 --years 10 --terminal-growth 3 \ - --discount 10 --shares 500 --net-debt 200 -``` - -When the FCF trajectory has a **structural bend** — the near-term growth rate differs -materially from the long-run rate — a single stage-1 rate is a forced average that -misrepresents both phases. Use the **three-stage model** by adding `--growth2` and -`--years2`. Stage 1 captures the distinct near-term phase, stage 2 captures the subsequent -normalized phase, then the terminal value. The output is a stage-1 × stage-2 sensitivity -matrix. Reach for it whenever the business has an identifiable reason for the growth rate -to change — not just turnarounds, but any shape where one rate doesn’t fit: - -- **Turnaround / inflection:** cost-outs, margin expansion, or debt paydown free up FCF - faster than revenue grows (stage 1), then revenue-driven growth takes over (stage 2). -- **Hypergrowth investing phase:** heavy S&M/R&D depresses FCF now; once the business - scales past the investment hump, FCF inflects sharply (stage 1), then grows at a - mature-compounder rate (stage 2). -- **Cyclical recovery:** earnings snap back from trough to mid-cycle (stage 1), then grow - at trend (stage 2). -- **Regulatory / deployment wave:** a defined tailwind (NG9-1-1 rollout, 5G buildout) - drives elevated growth for a bounded period (stage 1), then steady-state (stage 2). -- **Post-acquisition synergies:** integration savings land over 2–3 years (stage 1), - then organic growth resumes (stage 2). - -```bash -python scripts/dcf.py --fcf0 5 --growth 25,35,50 --years 3 \ - --growth2 5,8 --years2 7 --terminal-growth 2.5 --discount 12 \ - --shares 30 --net-debt 66 --price 2.75 -``` - -### 3. EPV — the no-growth floor - -Earnings Power Value capitalizes *current normalized* operating earnings with **no growth -credit** — a conservative floor that answers "what's it worth if the growth never shows up?" -Especially clarifying for cyclicals (use mid-cycle EBIT), deep-value, and any case where you -don't want to pay for a future you can't underwrite. - -```bash -python scripts/epv.py --ebit 600 --tax 21 --wacc 9 --shares 500 --net-debt 200 -``` - -### 4. Relative multiples — the sanity check - -P/E, EV/EBIT, EV/Sales, P/FCF against the peer set (`market-scout` gives you the peers). -Never a thesis on its own — "cheap vs. peers" can mean the whole group is -mispriced or the company deserves its discount — but a vital cross-check on the absolute -lenses, and the right primary lens for some special situations and asset plays. - -## Setting the inputs honestly - -The output is only as good as three judgment calls — show your work on each: - -- **Discount rate.** See the dedicated section below — this is the input most analysts get - wrong, and it deserves its own reasoning process. -- **Terminal value.** This is usually most of a DCF's value, so it's where false precision - hides. Keep terminal growth at or below long-run GDP; sanity-check the implied terminal - multiple — if it bakes in a permanent premium multiple, you've smuggled optimism into the - tail. -- **The base cash flow.** Use *normalized* owner earnings (phase 3), not a peak or trough - year. Garbage in, garbage out — most valuation errors are bad inputs, not bad arithmetic. - -## Discount rate — reason it, don't default it - -The discount rate is the single most levered input in a DCF: a 300bps change can move -intrinsic value by 30–50%. Yet it is the input most often set by reflex (“10% for -equity”) rather than by reasoning. **Every memo must derive and justify its discount rate -in a dedicated subsection of the valuation section.** A number without a rationale is an -assumption the reader cannot audit — and cannot trust. - -### The reasoning process (do this every time) - -1. **Start with the business, not the stock.** Ask: *what is the risk profile of the - underlying cash flows?* A government-contracted, recurring-revenue oligopoly with - mandated demand has fundamentally different cash-flow risk than a single-product - biotech or a commodity cyclical. The business risk should drive the unlevered cost of - capital — the stock’s trading volatility and capital structure are layered on top. - -2. **Anchor to peers, not defaults.** Pull betas for 2–4 closest business-model peers - from `market-scout` (yfinance’s `.info["beta"]`). Unlever each using Hamada: - `beta_u = beta_l / (1 + (1 - tax_rate) * D/E)`. Average the unlevered betas — this - is the *business risk* of the peer group, stripped of each company’s financing - choices. - -3. **Re-lever for the subject’s capital structure.** Use the company’s *pro-forma or - target* D/E (not necessarily today’s, if the capital structure is in transition): - `beta_l = beta_u * (1 + (1 - tax_rate) * D/E)`. Then CAPM: - `Ke = Rf + beta_l * ERP`. Use the current 10-year Treasury yield for Rf and a - long-run ERP of 5–6% (Damodaran’s implied ERP is the standard reference). - -4. **Compute WACC if doing an enterprise DCF.** Weight cost of equity and after-tax - cost of debt by their shares of total capital. If there is preferred equity or - mezzanine debt, include it as a separate tranche at its own cost. - -5. **Sanity-check against the business description.** Before using the number, ask: - *does this rate make sense for what this business actually is?* A few guideposts: - - | Business type | Typical WACC range | Why | - | :-- | :-- | :-- | - | Regulated utility / infrastructure concession | 6–8% | Contracted, inflation-linked, near-monopoly | - | Mission-critical gov-contracted recurring revenue | 8–10% | Mandated demand, high switching costs, oligopoly | - | Stable consumer/enterprise compounder | 9–11% | Durable moat, predictable FCF | - | Cyclical industrial / commodity | 10–13% | Earnings volatility, capital intensity | - | Growth-stage / unproven unit economics | 12–15% | Execution risk, cash burn, TAM uncertainty | - | Distressed / binary outcome | 15%+ | Survival risk, option-like payoff | - - If your derived WACC lands far outside the range for the business type, re-examine - your inputs — the beta sample, the D/E assumption, or the ERP. The guideposts are - not rules, but a derived rate that contradicts the business description is a red flag. - -6. **Separate business risk from financial risk.** When the capital structure is - distressed or in transition (turnarounds, post-divestiture, over-leveraged), the - *business* may deserve a low discount rate while the *equity* deserves a high one. - Make this explicit: run the DCF at the business-appropriate WACC to value the - enterprise, then subtract net debt and senior claims to get equity value. Do not - double-count by using a high WACC *and* subtracting the debt — that penalizes the - cash flows for leverage risk and then penalizes the equity again. - -7. **State it in the memo.** The valuation section must include a subsection titled - “**Discount Rate Derivation**” (or similar) that shows: the peer set used, their - betas and unlevered betas, the re-levered beta, the CAPM cost of equity, the WACC, - and the sanity check against the business description. A reader should be able to - disagree with your rate and re-run the DCF with their own — that’s the point. - -### Common mistakes - -- **Defaulting to 10% or 12%.** These are not reasoned rates; they are habits. 10% was - a reasonable equity return assumption when the risk-free rate was 4–5% and the ERP was - 5–6%, but it says nothing about *this specific business*. Always derive. -- **Using the stock’s own beta.** A distressed, thinly-traded small-cap will have a - high beta driven by liquidity and sentiment, not business risk. Use peer unlevered - betas to isolate the business risk, then re-lever. -- **Double-counting leverage risk.** If you use a high WACC because the company is - leveraged, and then also subtract a large net-debt figure, you’re penalizing leverage - twice. The WACC already reflects the cost of the debt; subtracting net debt converts - enterprise value to equity value. Don’t inflate both. -- **Ignoring capital structure transitions.** A turnaround that will be nearly debt-free - in 18 months should not be discounted at today’s levered cost of capital for a - 10-year DCF. Use the *target* or *normalized* capital structure for the WACC, and - reflect the transition costs in the near-term cash flows instead. - -## Weighting by archetype - -Lean on the lens the business actually fits; report the others as cross-checks. - -| Archetype | Lead lens | Cross-check with | -| :-- | :-- | :-- | -| Compounder | Forward DCF (long stage-1 runway) | Reverse-DCF reality check; EPV floor | -| Hypergrowth | **Reverse-DCF** (what's priced in) | Multiples; scenario forward DCF | -| Cyclical | EPV on **mid-cycle** earnings | Normalized P/E; mid-cycle multiples | -| Turnaround / inflection | Scenario DCF (post-inflection margins) | EPV today as downside floor | -| Special situation | Event payoff / sum-of-parts | Multiples on the resulting pieces | -| Deep value | Asset value / liquidation; EPV floor | Multiples; reverse-DCF for the catalyst | - -## The output - -A defensible **intrinsic-value range** (low–high, anchored to bear–bull), the **margin of -safety** at today's price, and a plain statement of the *one or two assumptions the value is -most sensitive to* — because that's where the next reader (and reality) will push hardest. -Carry these straight into the verdict. +# Valuation — match the method to the economics + +Valuation is a set of conditional claims, not a ritual. Choose methods that fit the business, +state what each method assumes, and reconcile them to the same security, date, currency, share +count, and capital structure. Multiple inapplicable methods do not create triangulation. + +The bundled scripts cover enterprise DCF and EPV for non-financial operating companies. They do +not replace a segment model, asset appraisal, transaction waterfall, or probability tree. + +## Build the enterprise-to-equity bridge + +Before comparing per-share values, show the bridge: + +```text +value of operating assets ++ excess cash and non-operating assets +− funded debt +− preferred and minority interests +− pension deficits and other senior claims +− value attributable to outstanding options or similar instruments, if not in shares += value of common equity +÷ consistent diluted share count += value per share +``` + +Avoid burying all adjustments in “net debt.” Match the bridge date to the base cash flow and +adjust for material subsequent transactions. Reconcile basic, reported diluted, and modeled +future shares. + +## Enterprise DCF + +### Cash-flow basis + +The DCF script accepts free cash flow to the firm (FCFF): after-tax operating cash flow before +interest and net borrowing. Discount FCFF at WACC to obtain enterprise value, then subtract net +debt and other senior claims. Do not pass owner earnings or FCFE that already includes interest +and then subtract debt again. + +Read `guide_normalization.md` for the reconciliation. A growing terminal state must include the +reinvestment needed to support that growth; terminal FCFF cannot assume growth while silently +removing its capital needs. + +### Choose the route + +Use the script path resolved from the installed skill. + +**Forward growth sensitivity** works for a positive, normalized FCFF base when a constant rate +is a tolerable abstraction: + +```bash +python "/scripts/dcf.py" forward --fcff0 1200 --growth 8,12,16 \ + --years 10 --terminal-growth 3 --wacc 10 --shares 500 --net-claims 200 --price 75 +``` + +Comma-separated growth values vary growth while holding every other input fixed. They are a +sensitivity, not complete bear/base/bull scenarios. Run separate commands when margins, +reinvestment, WACC, dilution, or the capital structure also differ. + +**Explicit forecast** is preferable when FCFF begins negative or changes shape. Forecast each +year from revenue, margin, tax, reinvestment, and working-capital drivers: + +```bash +python "/scripts/dcf.py" forecast --fcff=-20,10,45,80,110 \ + --terminal-growth 2.5 --wacc 12 --shares 30 --net-claims 66 --price 8 +``` + +The final explicit FCFF must be positive because it anchors a Gordon terminal value. Make the +transition to stable economics plausible rather than jumping from an immature margin directly +to perpetuity. + +**Reverse growth DCF** asks which constant positive-FCFF growth rate equates the model to price: + +```bash +python "/scripts/dcf.py" reverse --price 75 --fcff0 1200 --years 10 \ + --terminal-growth 3 --wacc 10 --shares 500 --net-claims 200 +``` + +The answer is conditional on every other input. It is informative only when positive base FCFF +and the model shape represent the business. It does not solve for revenue growth, margin, or +dilution, and it should not be presented as “the market's” unique forecast. For an immature +business, construct an operating model and test combinations of scale, margin, reinvestment, +and dilution that reconcile to price instead. + +### Terminal value + +A terminal state should be economically mature: + +- terminal growth is consistent with the currency and long-run market opportunity; +- return on new capital and reinvestment support the growth rate; +- margins and competitive position have faded or stabilized plausibly; +- capital intensity, taxes, and dilution are normalized; and +- WACC exceeds terminal growth. + +Report the terminal value as a percentage of enterprise value and cross-check its implied +terminal multiple. A high percentage is not automatically wrong, but it identifies where the +model is least anchored by near-term evidence. + +## Earnings Power Value + +EPV capitalizes normalized no-growth operating earnings at WACC. Without the optional +maintenance-capex refinement, it assumes D&A and maintenance capex offset: + +```text +normalized after-tax EBIT = EBIT × (1 − normalized cash tax rate) +operating cash earnings = after-tax EBIT + D&A − maintenance capex +EPV of operations = operating cash earnings ÷ WACC +``` + +Use the D&A refinement only when both D&A and maintenance capex are estimated on a consistent +basis: + +```bash +python "/scripts/epv.py" --ebit 600 --tax 21 --wacc 9 \ + --shares 500 --net-claims 200 --da 100 --maint-capex 85 --price 10 +``` + +EPV is a no-growth operating case, not a guaranteed floor. It can overstate value when earnings +are cyclical, assets are deteriorating, maintenance investment is understated, customers are +leaving, or liabilities sit outside the model. For cyclicals, use defensible mid-cycle earnings +and separately test trough liquidity. + +## Relative and transaction evidence + +Use multiples only when numerator, denominator, growth, accounting, leases, and capital +structure are comparable. Match enterprise multiples with pre-interest measures and equity +multiples with post-interest measures. Explain why a peer deserves the same or a different +multiple; an automated peer table is only a candidate list. + +Useful anchors may include EV/EBIT, EV/FCFF, P/E, P/FCFE, unit value, replacement cost, and +precedent transactions. Sales multiples require an explicit margin and reinvestment bridge. +Historical multiples are evidence about prior expectations and rates, not intrinsic value. + +Asset plays and special situations generally require their own arithmetic: + +- sum-of-parts with segment-specific methods and corporate-cost allocation; +- liquidation or realizable NAV with asset haircuts, liabilities, tax, and timing; +- transaction outcomes with payoff, probability, timing, break value, and interim cash flows; + and +- annualized expected return rather than an unadjusted spread. + +Do not turn uncertain legal interpretation into a precise probability without qualified support. + +## Discount rate + +No fixed WACC or required-return table is timeless or company-specific. Derive a rate from +current inputs, document the date and sources, and sensitize it. + +For an enterprise DCF: + +```text +cost of equity = risk-free rate + beta × equity risk premium +WACC = E/(D+E) × cost of equity + D/(D+E) × pre-tax cost of debt × (1 − tax rate) +``` + +Add country or other risk components only when they are not already captured elsewhere. Use +market-value capital weights where observable. Estimate debt cost from current borrowing terms, +yield, or a defensible default spread rather than the historical coupon. + +A bottom-up beta can be useful: choose operationally comparable firms, unlever their equity +betas using consistent market D/E and tax assumptions, take a robust central estimate, and +re-lever for a defensible current or target capital structure. But beta is a noisy model input, +not a fact. A thin or poor peer set may justify broader industry data, an alternative required +return, or wider sensitivity rather than false precision. + +Using WACC for FCFF and then subtracting debt is not double-counting. WACC discounts operating +cash flow using financing costs; the debt subtraction allocates enterprise value to common +equity. Double-counting occurs when the same expected loss, lease burden, pension contribution, +or distress effect is embedded in both cash flow and an additional adjustment without +reconciliation. + +If leverage or survival changes across scenarios, reflect financing costs, refinancing, +dilution, and default risk explicitly. A single normalized WACC can conceal the path dependency +of a distressed equity. + +The memo should show enough of the derivation for a reader to replace the rate, but it need not +force a ceremonial subsection or peer-beta table when another method is better supported. + +## Scenario design and margin of safety + +Name scenarios for the mechanism that differs, not merely bear/base/bull. At minimum disclose: + +- revenue or unit path; +- operating margin and reinvestment; +- taxes and working capital; +- financing, dilution, and enterprise bridge; +- discount and terminal assumptions; and +- evidence supporting the scenario weight, if probabilities are used. + +Use sensitivity around the two or three variables that dominate value. Report value per share +and the price discount or premium to each relevant outcome. Margin of safety is a conclusion +about downside, uncertainty, and required return; no universal percentage substitutes for the +quality of the inputs. + +## Method selection by thesis shape + +| Thesis shape | Usually useful | Common misuse | +| :-- | :-- | :-- | +| Compounder | operating DCF, reinvestment/runway cases, reverse check | extrapolating current ROIC forever | +| Cash-burning growth | explicit operating forecast, price-reconciliation scenarios | growing a negative FCFF base | +| Cyclical | mid-cycle EPV/DCF, trough balance sheet, asset or unit values | valuing peak earnings at a spot multiple | +| Turnaround | explicit transition cases, failure case, financing path | applying target margins immediately | +| Special situation | payoff tree, waterfall, SOTP, annualized return | DCF obscuring the binding event terms | +| Deep value | realizable NAV/liquidation, burn and timing, EPV where durable | calling EPV or book value a hard floor | + +End with the range supported by the evidence, the assumptions that dominate it, and the +conditions under which the range ceases to be useful. diff --git a/skills/bottom-up-analyst/references/memo_template.md b/skills/bottom-up-analyst/references/memo_template.md index aecee28..c4b6990 100644 --- a/skills/bottom-up-analyst/references/memo_template.md +++ b/skills/bottom-up-analyst/references/memo_template.md @@ -1,151 +1,158 @@ -# The memo — standard due-diligence structure - -This is the deliverable. The memo *is* the product of the whole loop, and "pitch-ready" -is the definition of done: complete and honest enough that a `pitch-like-lou` pitch could -stand on it without inventing anything. - -A memo is an argument, not a form. Use this structure as a skeleton, but let the -**archetype** decide where the weight goes — a compounder earns its keep in the economics -and moat sections; a special-situation in the structural fact and the payoff; a hypergrowth -name in the reverse-DCF and unit economics. Weight each section to the archetype; a tight -six-page memo beats a padded twenty. - -## The honesty markup (use it throughout) - -The single most important habit: let the reader audit your confidence. Adopt a consistent -convention and use it in every section — for example: - -- **[V]** verified — you read it in a named filing (give the form + accession or section). -- **[E]** estimate — you computed or modeled it; state the assumption. -- **[A]** assumption — you're taking it on faith; flag it for the reader to challenge. -- **[W]** web — sourced from outside filings; attribute and date it. - -The markup is not bureaucracy. It is what separates a memo from propaganda: a reader can see -at a glance which load-bearing claims are solid and which are your judgment. - -## Structure - -### 0. Stat header - -A compact, text-aligned block that orients the reader in five seconds. Compute, don't -guess; name any adjustment. - -```text -Ticker / Name Price: [px] Archetype: [one of the six] -Market Cap ($M): [mc] EPS (cur/fwd): [ ] Verdict: [Long/Short/Pass/Watch] -Net Debt ($M): [nd] P/E: [x] Conviction: [Low/Med/High] -TEV ($M): [tev] P/FCF: [x] IV range: [low–high] -Shares (M, dil): [sh] TEV/EBIT: [x] Margin of safety: [%] -``` - -*Calc discipline:* Net Debt = total debt − cash & marketable securities. TEV = market cap + -net debt + cost of option dilution (treasury-stock method — bake it in, don't footnote it). -FCF = operating cash flow − capex, with any normalization named. - -### 1. Thesis & variant perception - -Three to five sentences, punchline first. The core disconnect, then the **variant -perception**: what do you believe that the market doesn't, and *why are you the one who's -right*? If you can't name a variant perception, you have a description, not a thesis. - -### 2. Business overview - -How the company actually makes money — segments, unit of sale, who pays and why, revenue -model, key economics — in plain language. If you can't explain it in one clean sentence, -you're not ready to value it. - -### 3. Archetype & why it's the right lens - -Name the primary (and any secondary) archetype and justify it from the financials and -business model. This tells the reader which questions the rest of the memo prioritizes. - -### 4. Financial analysis — the normalized economics - -The un-distorted earning power (see `guide_normalization.md`), not raw GAAP. Owner earnings -/ FCF, returns on capital, margins and their drivers, working-capital behavior. Include the -**capital-allocation track record as a year-by-year table** — share count, debt, -reinvestment and the return on it — because the trend is the argument. - -**When the thesis depends on a new revenue stream** (pre-revenue JV, partnership product, -market entry enabled by a regulatory change, post-restructuring margin profile), include a -**unit-economics bridge** that builds from per-unit inputs (price, cost, volume) to the -stream’s contribution to FCF. A management TAM estimate plugged into a DCF growth rate is -not a model — it is a hope with a discount rate. See `guide_normalization.md` § “When the -thesis depends on a new revenue stream.” - -### 5. Competitive position & industry - -Industry structure, the company's place in it, and *relative* competitive advantage — -moat (or its absence) explained mechanically, not asserted. Ground in filings (incl. peers' -filings); use web only for what filings can't give, and mark it [W]. - -**Quantify, don't catalogue.** Every competitive strength, moat mechanism, and threat must -be sized — how big, how fast it's moving, and what the dollar impact on *this company* -would be if it plays out. “High switching costs” is a label; “3-year migration timelines -and 95%+ renewal rates” is evidence. “Competition is intensifying” is mood; “Competitor X -grew Y% last year and now holds Z% of the addressable market” is a fact the reader can -reason from. A competitive force you can’t size is one you haven’t understood — mark it -[A] and flag the gap. See `guide_competitive.md` § “Quantify impact.” - -### 6. Valuation - -Triangulated, never a single point (see `guide_valuation.md`). Show each lens, weighted by -archetype, including a **reverse-DCF of what today's price implies**. Lay out -**bear / base / bull** scenarios with their key assumptions, converge on an **intrinsic-value -range**, and state the **margin of safety** at the current price. - -This section **must** include a **"Discount Rate Derivation"** subsection showing how the -rate was reasoned - peer betas, the re-levered beta, the CAPM cost of equity, the WACC, and -the sanity check against the business type (methodology in `guide_valuation.md` § "Discount -rate"). A rate without a derivation is unauditable - the reader cannot disagree with it, so -cannot trust it. - -### 7. Ownership — institutional holders and insider activity - -Who owns this stock, inside and out, and what the picture says about alignment and adverse -selection. Pull 13F and Form 4 data via `sec-edgar-skill`, then read each pattern against -`guide_ownership_signals.md`. Include: - -- **Institutional (13F):** top 10–15 holders (passive index vs. active/concentrated), the - ownership trend vs. price (accumulation or distribution), any notable - deep-value/activist/specialist holders, and concentration/forced-selling risk. -- **Insider (Form 4):** a table of open-market buys/sells over the past 6–12 months - (distinguish voluntary P/S from routine M/F), the net buy/sell ratio, the key - buyers/sellers by name and role, aggregate insider ownership vs. compensation, and the FPI - Section-16 gap where it applies. - -Keep it to a table or two plus a paragraph of interpretation; it grounds the catalyst and -risk sections. If the best-informed people are not aligned with your thesis, that fact -belongs in the risk section. - -### 8. Risks & pre-mortem - -The bear case, in your own words and as strong as you can make it. Run the archetype's -disqualifiers explicitly. Assume it's a year out and the thesis failed — what broke? -Re-tag the load-bearing claims as verified vs. assumed; the assumed ones are your risks. - -**Every risk must pass the “so what” test.** State the *impact* — what happens to -revenue, margins, or FCF if this risk materializes, and over what timeframe? A risk -without a sized impact is a worry, not an analysis. Where possible, assign a probability -(High/Medium/Low) and cite the evidence behind it. The pre-mortem narrative should -reference the sized risks from the competitive section, not re-invent them as vague -fears. - -### 9. Catalysts & monitorables - -Specific, ideally dated events or metrics that would confirm or break the thesis — a -buyback, an uplisting, a margin-inflection quarter, a cohort metric, a regulatory date. -"Re-rating" is not a catalyst; a mechanism or a date is. List what you'll watch to know if -you're wrong early. - -### 10. Verdict & conviction - -The call — **Long / Short / Pass / Watch** — at the conviction the work supports, with a -one-line rationale tying back to the variant perception and the margin of safety. If the -digging was thin in places, say where; an honest hedge is part of the verdict. - -### 11. Appendix — sources - -The audit trail. Every filing used (form + accession number + section) and every web source -(URL + date). This is what makes the memo checkable — and what a downstream pitch leans on -when a skeptic pushes back. +# Full due-diligence memo + +Use this skeleton for a requested deep dive. It is not a questionnaire: combine, reorder, or omit +sections when that improves the argument, and add a section when the company's economics demand +it. A special situation, cyclical, and compounder should not produce identical memos. + +## Evidence notation + +Use the notation consistently on load-bearing factual and model claims: + +- **[V]** checked against a cited authoritative primary record; +- **[E]** calculated or modeled, with inputs and units; +- **[A]** unresolved assumption, with its decision impact; and +- **[W]** external, trade, channel, expert, or secondary evidence, named and dated. + +The tag does not replace a citation. Do not label an analytical inference `[V]` merely because +its inputs are verified; state that it is an inference. Ordinary connective prose does not need +a tag. + +## Header + +```markdown +# [Company] ([Ticker / share class]) — investment memo +**As of:** [date, time zone where relevant] +**Question:** [decision being evaluated] +**Decision:** [Long / Watch / Pass] +**Conviction:** [plain-language level and why] +``` + +## Decision snapshot + +Select the small set of current metrics that orient this specific case. Do not reproduce a +fixed stat block inherited from another pitch or fill irrelevant cells. Possibilities include: +price and market value, enterprise value, diluted shares, net debt, normalized FCFF, valuation +range, cycle position, unit metric, asset value, liquidity runway, or event spread. Label dates, +periods, currencies, and adjustments. + +Then state in a few sentences: + +- what the market price appears to require; +- the variant view, if one exists; +- the decisive evidence; +- what could make the view wrong; and +- why the current price does or does not compensate for that uncertainty. + +If no differentiated view is established, say so. A clear pass is better than an invented +variant perception. + +## Business and economic model + +Explain in plain language: + +- product or service, customer, payer, and unit of sale; +- segments and where gross profit and cash flow arise; +- pricing, volume, retention, cyclicality, and capital needs; and +- the few operating variables that govern value. + +Name the analytical lens or lenses only if they sharpen the decision. Do not force the company +into an archetype. + +## Reported-to-normalized economics + +Reconcile reported results to the cash-flow basis used in valuation. Include the periods and +metrics that reveal the economics rather than a mandatory table. Show: + +- recurring versus non-recurring items; +- organic versus acquired growth; +- maintenance and growth investment; +- working-capital and deferred-revenue timing; +- stock compensation and diluted shares; +- lease treatment; and +- capital allocation and return on incremental capital where meaningful. + +Use `guide_normalization.md`. If a new stream or future margin structure carries material value, +include a driver bridge from volume and price through costs, reinvestment, and FCFF. + +## Competitive and industry underwriting + +Define the relevant market and profit pool, identify economically comparable peers, and explain +the company's position through mechanisms and evidence. Connect material advantages and threats +to an operating assumption, scenario, or monitorable. + +Quantify where evidence supports it. Where it does not, use a range, break-even calculation, +leading indicator, or explicit `[A]` gap rather than invented precision. Use +`guide_competitive.md`. + +## Management, ownership, and governance + +Include this section when control, incentives, dilution, capital allocation, insider activity, +or holder concentration can affect the outcome. Distinguish: + +- beneficial ownership and voting control from 13F positions; +- voluntary Form 4 purchases and sales from grants, exercises, tax withholding, and gifts; +- reported quarter-end 13F changes from inferred trading intent; and +- compensation design from demonstrated capital-allocation behavior. + +Use `guide_ownership_signals.md`. Keep immaterial holder lists out of the memo. + +## Valuation and expectations + +Use methods that fit the business and reconcile each to common equity. State: + +- valuation date, currency, and current price; +- reported-to-normalized cash-flow bridge; +- enterprise-to-equity bridge and diluted shares; +- explicit operating scenarios and their evidence; +- discount-rate and terminal assumptions; +- value per share or payoff under relevant outcomes; and +- price discount/premium, downside, and required return. + +A reverse DCF is useful only if its positive-FCFF model describes the company. EPV is a no-growth +case, not a hard floor. Growth sensitivity alone is not a bear/base/bull analysis when margins, +capital needs, dilution, or financing also change. Use `guide_valuation.md`. + +Summarize the assumptions that dominate the result and show the sensitivity that matters. Do +not require a ceremonial peer-beta table if another discount-rate method is better supported. + +## Countercase and pre-mortem + +Make the strongest good-faith case against owning the security. Run the relevant archetype +disqualifiers, then answer: + +- Which fact, inference, or assumption is most likely wrong? +- What permanent impairment path exists? +- What financing, dilution, control, or liquidity event could intervene? +- Which downside estimate is genuinely anchored, and which is not? +- If the thesis has failed one year from now, what probably happened? + +Size material effects when the evidence supports it. For discontinuous or poorly disclosed +risks, describe the mechanism, exposure, leading indicator, and decision impact instead of +inventing a probability. + +## Catalysts, falsifiers, and monitorables + +List observable developments that change probability or value. For each, state the expected +time window, source to check, and what outcome confirms or weakens the thesis. A catalyst needs a +mechanism; “re-rating” alone is an outcome. + +Separate a catalyst from a falsifier. The latter is the evidence that should make the investor +exit or revisit the work even if price has not cooperated. + +## Verdict + +Conclude **Long**, **Watch**, or **Pass** at the confidence supported by the research. Tie the +verdict to valuation, the variant view, and the countercase. State unresolved work and the price +or evidence that would change the decision. + +## Sources and calculation notes + +Provide an audit trail for material claims: + +- SEC form, filing date, accession, and item or section; +- issuer, regulator, court, or industry document title and date; +- external URL, publisher, publication date, and access date where relevant; and +- calculation inputs, units, periods, and formulas. + +Do not dump every document opened. Include the sources on which the argument actually relies and +preserve conflicting evidence. diff --git a/skills/bottom-up-analyst/scripts/dcf.py b/skills/bottom-up-analyst/scripts/dcf.py index 16bc21e..c94537b 100644 --- a/skills/bottom-up-analyst/scripts/dcf.py +++ b/skills/bottom-up-analyst/scripts/dcf.py @@ -1,29 +1,26 @@ -"""Two-or-three-stage DCF — forward (assumptions -> intrinsic value) and reverse (price -> implied growth). +"""Enterprise DCF for explicit FCFF assumptions. -Part of the bottom-up-analyst skill's valuation tooling. The judgment — which lens to weight, -how to set the inputs honestly — lives in ``references/guide_valuation.md``; this script just -does the arithmetic the same way every time so memos are comparable. Output is a compact -Markdown summary to stdout. Run ``--help`` for all flags. +The model has three routes: -Conventions: monetary inputs (``--fcf0``, ``--net-debt``) share one unit (e.g. $millions); -``--shares`` is in the matching count unit (e.g. millions) so per-share output is in dollars. -Rates (``--growth``, ``--terminal-growth``, ``--discount``) are percentages. +``forward`` + Grow a positive base FCFF at one or two explicit rates. +``forecast`` + Discount an explicit annual FCFF sequence. This route can represent an + initial loss and is preferable when margins or cash flow inflect. +``reverse`` + Solve for the first-stage FCFF growth rate implied by the share price. -Two-stage model (default): FCF grows at ``--growth`` for ``--years``, then a Gordon terminal -value captures perpetual growth at ``--terminal-growth``. - -Three-stage model (add ``--growth2`` and ``--years2``): FCF grows at ``--growth`` for -``--years`` (stage 1), then at ``--growth2`` for ``--years2`` (stage 2), then a Gordon -terminal value. Use it whenever the FCF trajectory has a structural bend — the near-term -rate differs materially from the long-run rate. Examples: turnaround cost-out then -normalized growth, hypergrowth investment phase then harvest, cyclical recovery then -trend, regulatory deployment wave then steady-state. - -Enterprise value -> less net debt -> equity value -> per share. +All cash flows are free cash flow to the firm (FCFF), so they are discounted at +WACC to obtain enterprise value. Net claims are then subtracted to obtain equity +value. Net claims equal debt and other senior claims less excess cash and other +non-operating assets; use a negative number when additions exceed claims. +Monetary inputs must use one common unit; shares must use the matching count +unit. Rates are percentages. """ import argparse import sys +from collections.abc import Sequence if sys.platform.startswith("win"): try: @@ -32,280 +29,411 @@ pass -def two_stage_value(fcf0, g1, years, g_term, disc): - """Return (enterprise_value, pv_stage1, pv_terminal) for a two-stage DCF.""" - if disc <= g_term: - raise ValueError( - f"discount rate ({disc:.1%}) must exceed terminal growth ({g_term:.1%}); " - "the Gordon terminal value is undefined otherwise." - ) - pv_stage1 = 0.0 - fcf = fcf0 - for t in range(1, years + 1): - fcf = fcf * (1 + g1) - pv_stage1 += fcf / (1 + disc) ** t - fcf_terminal = fcf * (1 + g_term) - tv = fcf_terminal / (disc - g_term) - pv_terminal = tv / (1 + disc) ** years - return pv_stage1 + pv_terminal, pv_stage1, pv_terminal - - -def three_stage_value(fcf0, g1, years1, g2, years2, g_term, disc): - """Return (enterprise_value, pv_stage1, pv_stage2, pv_terminal) for a three-stage DCF. - - Stage 1: FCF grows at g1 for years1 (acceleration / inflection). - Stage 2: FCF grows at g2 for years2 (normalized growth). - Terminal: Gordon perpetuity at g_term after both stages. - """ - if disc <= g_term: - raise ValueError( - f"discount rate ({disc:.1%}) must exceed terminal growth ({g_term:.1%}); " - "the Gordon terminal value is undefined otherwise." - ) +def _percent_list(value: str) -> list[float]: + try: + values = [float(item.strip()) for item in value.split(",") if item.strip()] + except ValueError as exc: + raise argparse.ArgumentTypeError("expected comma-separated percentages") from exc + if not values: + raise argparse.ArgumentTypeError("provide at least one percentage") + return values + + +def _number_list(value: str) -> list[float]: + try: + values = [float(item.strip()) for item in value.split(",") if item.strip()] + except ValueError as exc: + raise argparse.ArgumentTypeError("expected comma-separated numbers") from exc + if not values: + raise argparse.ArgumentTypeError("provide at least one cash flow") + return values + + +def _validate_common(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + if args.wacc <= 0: + parser.error("--wacc must be positive") + if args.terminal_growth <= -100: + parser.error("--terminal-growth must exceed -100%") + if args.wacc <= args.terminal_growth: + parser.error("--wacc must exceed --terminal-growth") + if args.shares <= 0: + parser.error("--shares must be positive") + if args.price is not None and args.price <= 0: + parser.error("--price must be positive") + + +def _validate_growth(parser: argparse.ArgumentParser, values: Sequence[float], flag: str) -> None: + if any(value <= -100 for value in values): + parser.error(f"{flag} values must exceed -100%") + + +def _terminal_value(fcff: float, terminal_growth: float, wacc: float) -> float: + next_year_fcff = fcff * (1 + terminal_growth) + return next_year_fcff / (wacc - terminal_growth) + + +def growth_dcf( + fcff0: float, + growth1: float, + years1: int, + terminal_growth: float, + wacc: float, + growth2: float | None = None, + years2: int | None = None, +) -> tuple[float, float, float, float]: + """Return enterprise value and PVs of stages 1, 2, and terminal value.""" + fcff = fcff0 + elapsed = 0 pv_stage1 = 0.0 - fcf = fcf0 - total_years = 0 - for _t in range(1, years1 + 1): - fcf = fcf * (1 + g1) - total_years += 1 - pv_stage1 += fcf / (1 + disc) ** total_years + for _ in range(years1): + elapsed += 1 + fcff *= 1 + growth1 + pv_stage1 += fcff / (1 + wacc) ** elapsed + pv_stage2 = 0.0 - for _t in range(1, years2 + 1): - fcf = fcf * (1 + g2) - total_years += 1 - pv_stage2 += fcf / (1 + disc) ** total_years - fcf_terminal = fcf * (1 + g_term) - tv = fcf_terminal / (disc - g_term) - pv_terminal = tv / (1 + disc) ** total_years + if growth2 is not None and years2 is not None: + for _ in range(years2): + elapsed += 1 + fcff *= 1 + growth2 + pv_stage2 += fcff / (1 + wacc) ** elapsed + + pv_terminal = _terminal_value(fcff, terminal_growth, wacc) / (1 + wacc) ** elapsed return pv_stage1 + pv_stage2 + pv_terminal, pv_stage1, pv_stage2, pv_terminal -def per_share(fcf0, g1, years, g_term, disc, net_debt, shares, g2=None, years2=None): - if g2 is not None and years2 is not None: - ev, _, _, _ = three_stage_value(fcf0, g1, years, g2, years2, g_term, disc) - else: - ev, _, _ = two_stage_value(fcf0, g1, years, g_term, disc) - equity = ev - net_debt - return equity / shares, ev, equity +def forecast_dcf( + forecast: Sequence[float], terminal_growth: float, wacc: float +) -> tuple[float, float, float]: + """Return enterprise value, PV of forecast FCFF, and PV of terminal value.""" + pv_forecast = sum(fcff / (1 + wacc) ** year for year, fcff in enumerate(forecast, 1)) + pv_terminal = _terminal_value(forecast[-1], terminal_growth, wacc) / ( + (1 + wacc) ** len(forecast) + ) + return pv_forecast + pv_terminal, pv_forecast, pv_terminal -def solve_implied_growth(price, fcf0, years, g_term, disc, net_debt, shares): - """Bisect for the stage-1 growth rate (decimal) that makes IV/share == price.""" - target = price - lo, hi = -0.95, 5.0 +def _equity_value(enterprise_value: float, net_claims: float, shares: float) -> tuple[float, float]: + equity_value = enterprise_value - net_claims + return equity_value, equity_value / shares - def f(g): - v, _, _ = per_share(fcf0, g, years, g_term, disc, net_debt, shares) - return v - target - flo, fhi = f(lo), f(hi) - if flo > 0: +def _solve_implied_growth( + price: float, + fcff0: float, + years1: int, + terminal_growth: float, + wacc: float, + net_claims: float, + shares: float, + growth2: float | None, + years2: int | None, +) -> tuple[float | None, str]: + def difference(growth1: float) -> float: + enterprise_value, _, _, _ = growth_dcf( + fcff0, + growth1, + years1, + terminal_growth, + wacc, + growth2, + years2, + ) + _, value_per_share = _equity_value(enterprise_value, net_claims, shares) + return value_per_share - price + + low, high = -0.99, 5.0 + low_difference = difference(low) + high_difference = difference(high) + if low_difference > 0: return None, "below" - if fhi < 0: + if high_difference < 0: return None, "above" + for _ in range(200): - mid = (lo + hi) / 2 - fm = f(mid) - if abs(fm) < 1e-9: - return mid, "ok" - if (fm > 0) == (flo > 0): - lo, flo = mid, fm + midpoint = (low + high) / 2 + midpoint_difference = difference(midpoint) + if abs(midpoint_difference) < 1e-9: + return midpoint, "ok" + if midpoint_difference > 0: + high = midpoint else: - hi = mid - return (lo + hi) / 2, "ok" + low = midpoint + return (low + high) / 2, "ok" -def main(): - p = argparse.ArgumentParser( - description=__doc__.splitlines()[0], - formatter_class=argparse.RawDescriptionHelpFormatter, +def _add_common_arguments(parser: argparse.ArgumentParser, *, price_required: bool) -> None: + parser.add_argument( + "--terminal-growth", + type=float, + required=True, + help="Perpetual FCFF growth after the explicit forecast, in percent.", ) - p.add_argument( - "--mode", - choices=["forward", "reverse"], - default="forward", - help="forward: assumptions -> IV/share. reverse: price -> implied growth.", + parser.add_argument( + "--wacc", + type=float, + required=True, + help="Weighted average cost of capital, in percent.", ) - p.add_argument( - "--fcf0", + parser.add_argument( + "--shares", type=float, required=True, - help="Base (normalized) free cash flow, in $M. Use owner earnings.", + help="Diluted shares; use the count unit matching the monetary inputs.", ) - p.add_argument( - "--growth", - type=str, - default="10", - help="Stage-1 growth %% (forward only). Comma-separated for sensitivity.", + parser.add_argument( + "--net-claims", + type=float, + required=True, + help=( + "Debt and other senior claims minus excess cash and non-operating assets; " + "negative means net additions to enterprise value." + ), ) - p.add_argument("--years", type=int, default=10, help="Stage-1 length in years (default 10).") - p.add_argument( - "--growth2", - type=str, - default=None, - help="Stage-2 growth %% (three-stage model). Comma-separated for sensitivity. " - "When set, --years/--growth is stage 1 and --years2/--growth2 is " - "stage 2, before the terminal value. Use whenever the near-term and " - "long-run FCF growth rates differ materially.", + price_help = ( + "Current price per share; required to solve implied growth." + if price_required + else "Current price per share; optional comparison with modeled value." ) - p.add_argument( - "--years2", - type=int, - default=None, - help="Stage-2 length in years (three-stage model). Required with --growth2.", + parser.add_argument("--price", type=float, required=price_required, help=price_help) + + +def _build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + subparsers = parser.add_subparsers(dest="command", required=True) + + forward = subparsers.add_parser( + "forward", help="Value one- or two-stage growth in positive FCFF." ) - p.add_argument( - "--terminal-growth", - type=float, - default=2.5, - help="Perpetual growth %% after stage 1 (default 2.5; keep <= long-run GDP).", + forward.add_argument("--fcff0", type=float, required=True, help="Normalized base FCFF.") + forward.add_argument( + "--growth", + type=_percent_list, + required=True, + help="Stage-1 FCFF growth percentages; comma-separate sensitivity cases.", ) - p.add_argument( - "--discount", type=float, default=10.0, help="Discount rate / WACC %% (default 10)." + forward.add_argument("--years", type=int, required=True, help="Stage-1 years.") + forward.add_argument( + "--growth2", + type=_percent_list, + help="Optional stage-2 growth percentages; comma-separate sensitivity cases.", ) - p.add_argument( - "--shares", - type=float, + forward.add_argument("--years2", type=int, help="Stage-2 years; required with --growth2.") + _add_common_arguments(forward, price_required=False) + + forecast = subparsers.add_parser( + "forecast", help="Value an explicit annual FCFF forecast, including initial losses." + ) + forecast.add_argument( + "--fcff", + type=_number_list, required=True, - help="Diluted shares outstanding, same unit as --fcf0 (e.g. millions).", + help="FCFF for years 1..N, comma-separated. Use --fcff=-10,20 for a negative first year.", ) - p.add_argument( - "--net-debt", - type=float, - default=0.0, - help="Net debt in $M (total debt - cash & securities). Negative = net cash.", + _add_common_arguments(forecast, price_required=False) + + reverse = subparsers.add_parser( + "reverse", help="Solve for the stage-1 FCFF growth implied by price." ) - p.add_argument( - "--price", - type=float, - default=None, - help="Current price/share. Required for --mode reverse; optional in forward " - "to print upside/downside.", + reverse.add_argument( + "--fcff0", type=float, required=True, help="Positive normalized base FCFF." ) - args = p.parse_args() - - g_term = args.terminal_growth / 100.0 - disc = args.discount / 100.0 - is_three_stage = args.growth2 is not None - if is_three_stage and args.years2 is None: - p.error("--years2 is required when --growth2 is set") - - model_label = "three-stage" if is_three_stage else "two-stage" - print(f"# DCF ({args.mode}) -- {model_label}\n") - stage_info = f"Stage 1: {args.years}yr" - if is_three_stage: - stage_info += f" Stage 2: {args.years2}yr" - print( - f"- Base FCF: {args.fcf0:,.0f} {stage_info} " - f"Terminal growth: {args.terminal_growth:.1f}% Discount: {args.discount:.1f}%" + reverse.add_argument("--years", type=int, required=True, help="Stage-1 years.") + reverse.add_argument( + "--growth2", + type=float, + help="Optional fixed stage-2 growth percentage after the implied stage 1.", ) + reverse.add_argument("--years2", type=int, help="Stage-2 years; required with --growth2.") + _add_common_arguments(reverse, price_required=True) + return parser + + +def _print_header(args: argparse.Namespace, route: str, horizon: int) -> None: + print(f"# Enterprise DCF — {route}\n") + print(f"- Explicit horizon: {horizon} years") + print(f"- Terminal growth: {args.terminal_growth:.2f}%") + print(f"- WACC: {args.wacc:.2f}%") + print(f"- Diluted shares: {args.shares:,.2f}") + print(f"- Net claims: {args.net_claims:,.2f}") + if args.price is not None: + print(f"- Price: {args.price:,.2f}") + print() + + +def _price_comparison(price: float | None, values: Sequence[float]) -> None: + if price is None: + return + low, high = min(values), max(values) + if high <= 0: + print("\nPrice comparison is not meaningful because modeled equity value is non-positive.") + return + if low <= 0: + high_discount = (1 - price / high) * 100 + print( + "\nThe low modeled equity value is non-positive. " + f"Price discount/(premium) to the high value: {high_discount:+.1f}%." + ) + return + low_discount = (1 - price / low) * 100 + if abs(high - low) < 1e-12: + print(f"\nPrice discount/(premium) to modeled value: {low_discount:+.1f}%") + return + high_discount = (1 - price / high) * 100 print( - f"- Shares: {args.shares:,.1f} Net debt: {args.net_debt:,.0f}" - + (f" Price: {args.price:,.2f}" if args.price is not None else "") + f"\nPrice discount/(premium) to modeled value: {low_discount:+.1f}% at the " + f"low value and {high_discount:+.1f}% at the high value." ) - print() - if args.mode == "reverse": - if args.price is None: - p.error("--price is required for --mode reverse") - g, status = solve_implied_growth( - args.price, args.fcf0, args.years, g_term, disc, args.net_debt, args.shares + +def _run_forward(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + if args.fcff0 <= 0: + parser.error("--fcff0 must be positive; use the forecast route for initial losses") + if args.years <= 0: + parser.error("--years must be positive") + if (args.growth2 is None) != (args.years2 is None): + parser.error("--growth2 and --years2 must be supplied together") + if args.years2 is not None and args.years2 <= 0: + parser.error("--years2 must be positive") + _validate_growth(parser, args.growth, "--growth") + if args.growth2 is not None: + _validate_growth(parser, args.growth2, "--growth2") + + horizon = args.years + (args.years2 or 0) + _print_header(args, "forward growth sensitivity", horizon) + terminal_growth = args.terminal_growth / 100 + wacc = args.wacc / 100 + values: list[float] = [] + terminal_shares: list[float] = [] + + if args.growth2 is None: + print( + "| Stage-1 growth | Enterprise value | Equity value | Value/share | Terminal % of EV |" ) - if status == "above": - print( - "**The current price implies growth above 500%/yr for the whole stage** -- " - "i.e. the price cannot be justified by this model on these cash flows." + print("| :-- | --: | --: | --: | --: |") + for growth in args.growth: + enterprise_value, _, _, pv_terminal = growth_dcf( + args.fcff0, growth / 100, args.years, terminal_growth, wacc ) - elif status == "below": - print( - "**The current price implies a steep perpetual *decline*** -- the market is " - "pricing the cash flows away." + equity_value, value_per_share = _equity_value( + enterprise_value, args.net_claims, args.shares ) - else: - print(f"## Implied stage-1 growth: **{g * 100:.1f}% / yr** for {args.years} years\n") + values.append(value_per_share) + terminal_share = pv_terminal / enterprise_value * 100 + terminal_shares.append(terminal_share) print( - "That is the growth the current price already bakes in. The thesis question: " - "is that bar too high, about right, or too low versus what this business has " - "done and can do?" + f"| {growth:.2f}% | {enterprise_value:,.2f} | {equity_value:,.2f} | " + f"{value_per_share:,.2f} | {terminal_share:.1f}% |" ) - return - - # forward - growths = [float(x) for x in args.growth.split(",") if x.strip() != ""] - growths2 = ( - [float(x) for x in args.growth2.split(",") if x.strip() != ""] if is_three_stage else [None] - ) - - if is_three_stage: - print("## Intrinsic value per share (stage-1 growth x stage-2 growth)") - print() - header = "| S1 \\\\ S2 |" - for g2 in growths2: - header += f" {g2:.0f}% |" - print(header) - sep = "| :-- |" + " --: |" * len(growths2) - print(sep) - ivs = [] - for g1 in growths: - row = f"| {g1:.0f}% |" - for g2 in growths2: - try: - iv, ev, eq = per_share( - args.fcf0, - g1 / 100.0, - args.years, - g_term, - disc, - args.net_debt, - args.shares, - g2=g2 / 100.0, - years2=args.years2, - ) - except ValueError as exc: - p.error(str(exc)) - ivs.append(iv) - if args.price is not None: - upside = (iv / args.price - 1) * 100 - row += f" {iv:,.2f} ({upside:+.0f}%) |" - else: - row += f" {iv:,.2f} |" - print(row) else: - print("## Intrinsic value per share") - print() - header = "| Stage-1 growth | IV / share | Enterprise value | Equity value |" - if args.price is not None: - header += " Upside vs price |" - print(header) - sep = "| :-- | --: | --: | --: |" + (" --: |" if args.price is not None else "") - print(sep) - ivs = [] - for g in growths: - try: - iv, ev, eq = per_share( - args.fcf0, g / 100.0, args.years, g_term, disc, args.net_debt, args.shares + print("| Stage 1 \\ Stage 2 | " + " | ".join(f"{g:.2f}%" for g in args.growth2) + " |") + print("| :-- | " + " | ".join("--:" for _ in args.growth2) + " |") + for growth1 in args.growth: + row = [f"{growth1:.2f}%"] + for growth2 in args.growth2: + enterprise_value, _, _, pv_terminal = growth_dcf( + args.fcff0, + growth1 / 100, + args.years, + terminal_growth, + wacc, + growth2 / 100, + args.years2, ) - except ValueError as exc: - p.error(str(exc)) - ivs.append(iv) - row = f"| {g:.1f}% | {iv:,.2f} | {ev:,.0f} | {eq:,.0f} |" - if args.price is not None: - row += f" {(iv / args.price - 1) * 100:+.1f}% |" - print(row) + _, value_per_share = _equity_value(enterprise_value, args.net_claims, args.shares) + values.append(value_per_share) + terminal_shares.append(pv_terminal / enterprise_value * 100) + row.append(f"{value_per_share:,.2f}") + print("| " + " | ".join(row) + " |") + print("\nValues in the matrix are equity value per diluted share.") - print() - if len(ivs) > 1: + print(f"\nModeled value/share range: **{min(values):,.2f} to {max(values):,.2f}**") + if len(terminal_shares) > 1: print( - f"**Intrinsic-value range: {min(ivs):,.2f} -- {max(ivs):,.2f} / share** " - "(bear--bull across the growth cases above)." + f"Terminal value share of enterprise value: {min(terminal_shares):.1f}% " + f"to {max(terminal_shares):.1f}%" ) - if args.price is not None: - _lo, hi = min(ivs), max(ivs) - mos = (1 - args.price / hi) * 100 if hi > 0 else float("nan") + _price_comparison(args.price, values) + + +def _run_forecast(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + if args.fcff[-1] <= 0: + parser.error("the final explicit FCFF must be positive for a Gordon terminal value") + _print_header(args, "explicit forecast", len(args.fcff)) + terminal_growth = args.terminal_growth / 100 + wacc = args.wacc / 100 + enterprise_value, pv_forecast, pv_terminal = forecast_dcf(args.fcff, terminal_growth, wacc) + equity_value, value_per_share = _equity_value(enterprise_value, args.net_claims, args.shares) + + print("| Year | FCFF | Present value |") + print("| --: | --: | --: |") + for year, fcff in enumerate(args.fcff, 1): + print(f"| {year} | {fcff:,.2f} | {fcff / (1 + wacc) ** year:,.2f} |") + print(f"\n- PV of explicit FCFF: {pv_forecast:,.2f}") + terminal_share = f"{pv_terminal / enterprise_value:.1%}" if enterprise_value > 0 else "n/m" + print(f"- PV of terminal value: {pv_terminal:,.2f} ({terminal_share} of EV)") + print(f"- Enterprise value: {enterprise_value:,.2f}") + print(f"- Equity value: {equity_value:,.2f}") + print(f"- Value per diluted share: **{value_per_share:,.2f}**") + _price_comparison(args.price, [value_per_share]) + + +def _run_reverse(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + if args.fcff0 <= 0: + parser.error("--fcff0 must be positive for reverse growth DCF") + if args.years <= 0: + parser.error("--years must be positive") + if (args.growth2 is None) != (args.years2 is None): + parser.error("--growth2 and --years2 must be supplied together") + if args.years2 is not None and args.years2 <= 0: + parser.error("--years2 must be positive") + if args.growth2 is not None: + _validate_growth(parser, [args.growth2], "--growth2") + + horizon = args.years + (args.years2 or 0) + _print_header(args, "reverse growth", horizon) + implied_enterprise_value = args.price * args.shares + args.net_claims + if implied_enterprise_value <= 0: print( - f"\nAt {args.price:,.2f}: margin of safety to the high case is {mos:.0f}%. " - "Require the thesis to survive the *low* end before you trust it." + "Price implies non-positive operating enterprise value after the stated " + "net claims; no positive-FCFF growth rate can reconcile this model." ) + return + growth, status = _solve_implied_growth( + args.price, + args.fcff0, + args.years, + args.terminal_growth / 100, + args.wacc / 100, + args.net_claims, + args.shares, + args.growth2 / 100 if args.growth2 is not None else None, + args.years2, + ) + if status == "below": + print("The implied stage-1 growth is below -99% per year, outside the search range.") + elif status == "above": + print("The implied stage-1 growth exceeds 500% per year, outside the search range.") + else: + print(f"Implied stage-1 FCFF growth: **{growth * 100:.2f}% per year**") + print(f"Stage-1 duration: {args.years} years") + if args.growth2 is not None: + print(f"Fixed stage 2: {args.growth2:.2f}% for {args.years2} years") + print( + "\nThe implied rate is conditional on the stated base FCFF, horizon, terminal growth, " + "WACC, net claims, and share count." + ) + + +def main() -> None: + parser = _build_parser() + args = parser.parse_args() + _validate_common(parser, args) + if args.command == "forward": + _run_forward(parser, args) + elif args.command == "forecast": + _run_forecast(parser, args) + else: + _run_reverse(parser, args) if __name__ == "__main__": diff --git a/skills/bottom-up-analyst/scripts/epv.py b/skills/bottom-up-analyst/scripts/epv.py index 29ba6bb..43172f3 100644 --- a/skills/bottom-up-analyst/scripts/epv.py +++ b/skills/bottom-up-analyst/scripts/epv.py @@ -1,114 +1,130 @@ -"""Earnings Power Value (EPV) — the no-growth floor. - -Part of the bottom-up-analyst skill's valuation tooling. EPV capitalizes *current normalized* -operating earnings with **zero growth credit**: what is the business worth if it simply earns -what it earns today, forever? It is the conservative anchor in a triangulation — pair it with -``dcf.py`` (which prices in growth) and read the gap between them as "how much of the price is -growth I have to believe in." The reasoning behind the inputs is in -``references/guide_valuation.md``. - -Conventions: monetary inputs (``--ebit``, ``--net-debt``, ``--maint-capex``, ``--da``) share one -unit (e.g. $millions); ``--shares`` matches (e.g. millions) so per-share output is in dollars. -``--tax`` and ``--wacc`` are percentages. - -EPV (enterprise) = normalized NOPAT / WACC, where NOPAT = adjusted EBIT x (1 - tax). -With the optional Greenwald refinement (``--da`` and ``--maint-capex``), adjusted EBIT adds back -the portion of depreciation that exceeds true maintenance capex — earnings the accounting hides. -""" - -import argparse -import sys - -if sys.platform.startswith("win"): - try: - sys.stdout.reconfigure(encoding="utf-8") - except Exception: - pass - - -def main(): - p = argparse.ArgumentParser( - description=__doc__.splitlines()[0], - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - p.add_argument( - "--ebit", - type=float, - required=True, - help="Normalized operating earnings (EBIT) in $M. For cyclicals use " - "mid-cycle EBIT, not the latest year.", - ) - p.add_argument("--tax", type=float, default=21.0, help="Cash tax rate %% (default 21).") - p.add_argument( - "--wacc", type=float, required=True, help="Cost of capital %% used to capitalize earnings." - ) - p.add_argument( - "--shares", - type=float, - required=True, - help="Diluted shares, same unit as --ebit (e.g. millions).", - ) - p.add_argument( - "--net-debt", type=float, default=0.0, help="Net debt in $M (negative = net cash)." - ) - p.add_argument( - "--da", - type=float, - default=None, - help="Depreciation & amortization in $M (optional, for the maintenance-capex " - "refinement; use with --maint-capex).", - ) - p.add_argument( - "--maint-capex", - type=float, - default=None, - help="Maintenance capex in $M (optional). If D&A exceeds it, the excess is " - "added back to EBIT as hidden earning power.", - ) - p.add_argument( - "--price", - type=float, - default=None, - help="Current price/share (optional) to print EPV vs price.", - ) - args = p.parse_args() - - if args.wacc <= 0: - p.error("--wacc must be positive") - - tax = args.tax / 100.0 - wacc = args.wacc / 100.0 - - adj_ebit = args.ebit - note = "" - if args.da is not None and args.maint_capex is not None: - excess = args.da - args.maint_capex - adj_ebit = args.ebit + excess - note = ( - f" (adjusted from {args.ebit:,.0f} by D&A {args.da:,.0f} − maint capex " - f"{args.maint_capex:,.0f} = {excess:+,.0f})" - ) - - nopat = adj_ebit * (1 - tax) - epv_enterprise = nopat / wacc - epv_equity = epv_enterprise - args.net_debt - epv_share = epv_equity / args.shares - - print("# Earnings Power Value — no-growth floor\n") - print(f"- Adjusted EBIT: {adj_ebit:,.0f}{note}") - print(f"- NOPAT (after {args.tax:.0f}% tax): {nopat:,.0f}") - print(f"- Capitalized at WACC {args.wacc:.1f}% -> EPV enterprise: {epv_enterprise:,.0f}") - print(f"- Less net debt {args.net_debt:,.0f} -> EPV equity: {epv_equity:,.0f}") - print(f"\n## EPV / share (no growth): **{epv_share:,.2f}**") - if args.price is not None: - gap = (args.price / epv_share - 1) * 100 if epv_share > 0 else float("nan") - print( - f"\nAt {args.price:,.2f}/share, the market pays **{gap:+.0f}%** versus the " - "no-growth value. That premium is what you are paying for growth and " - "improvement — decide whether the business can deliver it. A price *below* EPV " - "means the market assigns the growth (and maybe some of the base) negative value." - ) - - -if __name__ == "__main__": - main() +"""Earnings Power Value for normalized no-growth operating earnings. + +EPV capitalizes normalized after-tax operating cash earnings at WACC. It is a +no-growth lens, not a guaranteed floor. Monetary inputs use one common unit; +shares use the matching count unit. Rates are percentages. + +Without the optional maintenance-capex refinement, the model assumes D&A and +maintenance capex offset: + + operating earnings = normalized EBIT * (1 - cash tax rate) + +With both ``--da`` and ``--maint-capex``: + + operating cash earnings = EBIT * (1 - tax) + D&A - maintenance capex + +The latter preserves the depreciation tax shield and does not tax the capex +adjustment a second time. +""" + +import argparse +import sys + +if sys.platform.startswith("win"): + try: + sys.stdout.reconfigure(encoding="utf-8") + except Exception: + pass + + +def _build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("--ebit", type=float, required=True, help="Normalized operating EBIT.") + parser.add_argument( + "--tax", type=float, required=True, help="Normalized cash tax rate, in percent." + ) + parser.add_argument( + "--wacc", type=float, required=True, help="Weighted average cost of capital, in percent." + ) + parser.add_argument( + "--shares", + type=float, + required=True, + help="Diluted shares; use the count unit matching the monetary inputs.", + ) + parser.add_argument( + "--net-claims", + type=float, + required=True, + help=( + "Debt and other senior claims minus excess cash and non-operating assets; " + "negative means net additions to enterprise value." + ), + ) + parser.add_argument( + "--da", + type=float, + help="Normalized depreciation and amortization; use with --maint-capex.", + ) + parser.add_argument( + "--maint-capex", + type=float, + help="Estimated maintenance capex; use with --da.", + ) + parser.add_argument( + "--price", type=float, help="Current price per share, to compare price with EPV." + ) + return parser + + +def _validate(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + if not 0 <= args.tax < 100: + parser.error("--tax must be at least 0% and below 100%") + if args.wacc <= 0: + parser.error("--wacc must be positive") + if args.shares <= 0: + parser.error("--shares must be positive") + if args.price is not None and args.price <= 0: + parser.error("--price must be positive") + if (args.da is None) != (args.maint_capex is None): + parser.error("--da and --maint-capex must be supplied together") + if args.da is not None and (args.da < 0 or args.maint_capex < 0): + parser.error("--da and --maint-capex cannot be negative") + + +def main() -> None: + parser = _build_parser() + args = parser.parse_args() + _validate(parser, args) + + tax_rate = args.tax / 100 + wacc = args.wacc / 100 + after_tax_ebit = args.ebit * (1 - tax_rate) + operating_earnings = after_tax_ebit + if args.da is not None: + operating_earnings += args.da - args.maint_capex + if operating_earnings <= 0: + parser.error( + "normalized after-tax operating earnings must be positive; " + "a perpetuity cannot capitalize a non-positive base" + ) + + enterprise_value = operating_earnings / wacc + equity_value = enterprise_value - args.net_claims + value_per_share = equity_value / args.shares + + print("# Earnings Power Value — no-growth operating case\n") + print(f"- Normalized EBIT: {args.ebit:,.2f}") + print(f"- After-tax EBIT at {args.tax:.2f}%: {after_tax_ebit:,.2f}") + if args.da is not None: + print(f"- Add D&A: {args.da:,.2f}") + print(f"- Less maintenance capex: {args.maint_capex:,.2f}") + print(f"- Capitalized operating earnings: {operating_earnings:,.2f}") + print(f"- WACC: {args.wacc:.2f}%") + print(f"- Enterprise value: {enterprise_value:,.2f}") + print(f"- Net claims: {args.net_claims:,.2f}") + print(f"- Equity value: {equity_value:,.2f}") + print(f"- EPV per diluted share: **{value_per_share:,.2f}**") + + if args.price is not None: + if value_per_share <= 0: + print( + "\nPrice comparison is not meaningful because modeled equity value is non-positive." + ) + else: + discount = (1 - args.price / value_per_share) * 100 + print(f"\nPrice discount/(premium) to EPV: {discount:+.1f}%") + + +if __name__ == "__main__": + main()