Chapter 2 — Understand the Book
Node: understand-the-book
Purpose: Given world state, tell the user what their specific portfolio is actually doing.
What this chapter does
The sharpest chapter in the loop. A user can read a regime brief anywhere; only Jawz tells them what their regime brief means for their actual positions, with live data, composed into attribution.
The goal is not to tell the user what to do — the goal is to make visible what's true about their portfolio that they probably can't see from a brokerage dashboard. Concentration they didn't realize. Factor tilts they've drifted into. Vulnerabilities that the current world state creates.
Every mode in this chapter produces questions, not instructions. The user decides what to do with the attribution.
Shared preamble — priced book
Before any mode runs, execute this common preamble:
- Load the user's portfolio (from context,
jawz_portfolio.json, or explicit list). - Call
get_pricesfor all positions. Convert to common currency (USD). Compute weights. - Handle failures explicitly:
- Known misresolutions — prompt user for manual USD value or exclude with flag.
- International tickers failing — flag, exclude, list in output.
- Never compute portfolio-level metrics on a partial book without disclosing coverage.
- Cache the priced book for the session so subsequent modes don't re-fetch.
Mode 2.1 — Regime Fit
When to use: User asks about portfolio regime fit, risk, vulnerability, "how is my book positioned for the current environment." Also called after Chapter 1 Mode 1.1 when the user wants to go from world-state to book-state.
Prerequisites:
- Priced book (from shared preamble)
- Regime read (from Chapter 1 Mode 1.1)
Procedure:
Step 1 — Classify each position on three axes:
Axis A — Regime Sensitivity:
| Current Regime | Helped by regime | Hurt by regime | Neutral |
|---|---|---|---|
| GREEN | High-beta equity, small caps, crypto, growth, credit, industrial commodities, cyclicals | Long-duration treasuries, gold, defensive staples, cash | Quality large-cap, broad indices |
| YELLOW | Quality large-cap, gold, intermediate treasuries, low-vol, cash, defensives | High-beta growth, speculative alts, leveraged ETFs, high yield credit, small caps | Core mega-cap tech, BTC, broad indices |
| RED | Long-duration treasuries, gold, cash, USD, defensive staples, utilities | All equity beta, all crypto, credit, cyclicals, commodities (ex-gold) | Very short-duration treasuries, T-bills |
Classify each holding as Helped, Hurt, or Neutral.
Axis B — Factor Exposure: Primary factor driving the position.
crypto-beta,long-duration-growth,quality-growth,cyclical,defensive,commodity,rates-duration,cash-equivalent,speculative,thematic
Crypto positions and crypto-beta. The framework does not currently resolve crypto into sub-factors — all crypto positions take crypto-beta. In Step 4, do not score crypto-beta against the regime as a resolved factor. Report it explicitly as unresolved: state its weight, and state that the framework cannot yet differentiate these positions or assess them against the regime. Do not imply the positions behave alike; do not imply they are diversified. Scope the factor verdict to the non-crypto sleeve. This is a known resolution gap tracked for future work — not a risk judgment about crypto.
Axis C — Role in Portfolio:
core(>10% weight),satellite(3–10%),speculative(<3%),hedge,cash-buffer
Step 2 — Assign regime fit score 1–5:
- 5 — Regime Champion: Helped + factor matches regime's favored factors + appropriate size
- 4 — Regime Aligned: Helped or Neutral + consistent factor + reasonable size
- 3 — Regime Neutral: Neutral OR (Helped but oversized) OR (Hurt but small)
- 2 — Regime Mismatch: Hurt + fights regime + oversized for the headwind
- 1 — Regime Liability: Strongly Hurt + actively fights the regime's dominant risk factor + concentrated
If borderline, round to the more cautious score.
Step 3 — Compute portfolio fit score (weighted average across priced positions).
Interpretation bands:
- 4.0–5.0: Strongly aligned
- 3.5–4.0: Aligned with some drag
- 3.0–3.5: Neutral
- 2.5–3.0: Meaningful mismatch
- <2.5: Significant mismatch — portfolio is fighting the macro
Step 4 — Aggregate factor tilts. Group positions by Axis B, sum weights. Report top tilts with verdicts against current regime.
Step 5 — Generate questions. 3–5 portfolio-specific questions. Each must:
- Reference specific holdings by name/ticker
- Connect to a factor tilt or vulnerability from Step 4
- Be answerable (yes/no/maybe)
- Avoid generic risk platitudes
Output contract:
## Portfolio Regime Fit — [DATE]
**Regime:** [COLOR] — [signal]
**Portfolio Fit Score:** [X.X / 5.0] — [band]
**Coverage:** [X% priced and scored]
### Regime Champions (Score 4-5)
| Position | Weight | Score | Factor | Why it fits |
|---|---|---|---|---|
### Regime Liabilities (Score 1-2)
| Position | Weight | Score | Factor | Specific risk |
|---|---|---|---|---|
### Middle of the Book (Score 3)
[Prose summary — weight in this band, dominant factor]
### Factor Tilts
| Factor | Weight | Verdict |
|---|---|---|
### Questions to Sit With
1. [Portfolio-specific question referencing a specific holding]
2. [Portfolio-specific question referencing a specific holding]
3. [Portfolio-specific question referencing a specific holding]
### Positions Not Scored
[Excluded + reason]
Mode 2.2 — Concentration Check
When to use: User asks about diversification, concentration, overlap, "am I too exposed to X," or "what do I actually own."
What this mode does that Mode 2.1 does not: Mode 2.1 aggregates the book by factor. Mode 2.2 looks through ETFs to the underlying names — surfacing single-name exposure the user carries without seeing it, because it is buried inside funds. A user can hold NVDA directly, inside QQQ, and inside VGT: three line items on the dashboard, one concentrated bet in reality.
Prerequisites:
- Priced book (from shared preamble) — direct positions and ETF positions, each with a book weight.
Procedure:
Step 1 — Separate the book. Split holdings into (a) direct single-name positions (individual stocks, crypto) and (b) ETFs and funds.
Step 2 — Look through the ETFs. Call get_etf_profile with every ETF ticker in the book. For each returned profile note:
source:live(fresh from the issuer) orcatalog(a dated snapshot — note itsas_of).top_holdings: the fund's largest positions, each with a weight (percent of the fund).unknown_tickers: ETFs the catalog could not resolve — these cannot be looked through.- Bond and commodity ETFs return no holdings — they carry no single-name overlap. Treat them as factor exposure only and exclude them from the name-level math.
Step 3 — Compute true single-name exposure. For each underlying name, sum:
- its direct weight in the book (zero if not held directly), plus
- for every ETF that holds it: the ETF's weight in the book multiplied by the name's weight inside that ETF.
Worked example: 8 percent of the book sits in QQQ, and NVDA is 9 percent of QQQ — that contributes 0.72 percent of NVDA exposure. Add that to any direct NVDA position, and to NVDA's contribution from every other fund in the book.
Step 4 — Flag concentration. Surface any name whose true exposure is materially larger than its visible (direct-only) exposure, or whose true exposure crosses a concentration line. Useful default thresholds: any single name above 10 percent of the book, or any name whose hidden ETF-derived exposure exceeds its direct exposure. The hidden cases are the core finding — they are what the user cannot see from a brokerage dashboard.
Step 5 — State coverage honestly. Look-through produces a floor, not an exact figure:
get_etf_profilereturns each ETF's top holdings only — a name outside a fund's top holdings is not counted.catalog-sourced profiles are dated snapshots; weights drift after theas_ofdate.unknown_tickersare not looked through at all — report their combined book weight as un-resolved. Never present a true-exposure number as precise. Always state what share of the book was and was not looked through.
Step 6 — Generate questions. 3–5 portfolio-specific questions. Each must name a specific concentrated holding and connect to the gap between visible and true exposure. Questions, not instructions — you never say "trim NVDA."
Output contract:
## Concentration Check — [DATE]
**Look-through coverage:** [X% of book looked through] — [N ETFs live, M ETFs from catalog, K un-resolved]
### True Single-Name Exposure
| Name | Direct | Via ETFs | True total | Flag |
|---|---|---|---|---|
[One row per name with material true exposure. "Via ETFs" names the contributing funds.]
### Hidden Concentration
[Names whose true exposure materially exceeds the direct-only weight a brokerage dashboard shows — the core finding of this mode. If none, say so plainly.]
### Not Looked Through
[Un-resolved ETF tickers + combined weight + reason. Bond/commodity ETFs listed here as factor-only, not a coverage failure.]
### Questions to Sit With
1. [Question naming a specific concentrated holding]
2. [Question naming a specific concentrated holding]
3. [Question naming a specific concentrated holding]
Scope note (v1): This mode resolves single-name concentration. Sector- and theme-level concentration across the whole book is not computed here yet — Mode 2.1's factor-tilt aggregation is the current proxy for that. Sector look-through is planned.
Mode 2.3 — Stress Test
When to use: User asks "what if the market crashes" / "how would my book handle a 2022-style rates shock" / "how bad could a drawdown be."
Procedure (v0.1 — structural sketch):
- User specifies the stress scenario (or AI picks three defaults: 2022-style rates shock, 2020-style liquidity crisis, 2008-style credit event).
- For each scenario, apply historical return patterns for each asset class.
- Project portfolio-level drawdown magnitude based on current weights.
- Identify which specific positions drive the loss in each scenario.
Mode 2.4 — Position Conviction Audit
When to use: User asks "are my positions still right" / "walk me through my book" / "which positions should I reconsider."
Procedure (v0.1 — conversational mode):
Walk the user through their top positions. For each, ask three questions the user should be able to answer if they hold with conviction:
- Thesis: What's your current thesis for holding this?
- Exit condition: What specific development would make you sell?
- Invalidation: What would prove your thesis wrong?
Note any position where the user can't answer — that's the signal. Natural handoff to Chapter 3 Mode 3.3 when a conviction gap is identified.
Source: The Jawz Loop, by Mako · Chapter 2 v0.1.0.