An iBuyer buys a home for $380K and sells it for $410K. The board sees a $30K "spread" and calls it an 8% gross margin. But that $30K is not one thing — it's the net of seven distinct economic forces, some working for you and some against you. If you can't measure each one independently, you can't tell whether you're getting better at pricing or just riding a hot market.
The Decomposition
Define the realized spread on property as:
This decomposes into seven additive components:
| # | Component | Formula | Typical range |
|---|---|---|---|
| 1 | Market appreciation | HPI(t_sell) − HPI(t_buy) | +1% to +4% |
| 2 | Buy-side discount | FMV − P_buy | +2% to +6% |
| 3 | Renovation uplift | V(S) − FMV_as_is | +1% to +5% |
| 4 | Adverse selection cost | −IAP (winner's curse) | −1% to −3% |
| 5 | Holding cost | −r · T_hold | −1% to −4% |
| 6 | Transaction costs | −(commissions + closing) | −2% to −3% |
| 7 | Sell-side pricing error | P_sell − FMV_renovated | −2% to +2% |
Why Three Components Aren't Enough
Most iBuyer P&L dashboards track: buy price, sell price, renovation cost. That gives you components 2, 3, and 6. The other four are either invisible or lumped into "market conditions." This creates three blind spots:
Blind spot 1: Market appreciation masks bad pricing
In a rising market, component 1 (appreciation) covers up component 4 (adverse selection). You're overpaying on acquisition but the market bails you out before you notice. When the market flattens — and it always does — the adverse selection cost suddenly shows up in your P&L as "margin compression." It was always there. You just couldn't see it.
Blind spot 2: Holding cost is non-linear
Component 5 is modeled as but the actual cost compounds. A home held for 90 days costs more than 3× a home held for 30 days because of seasonal effects, listing fatigue, and price cuts. The continuous model:
The price-cut term is the killer. After 45 days on market, most listings take a 2–3% cut. After 75 days, another 2–3%. These are step functions riding on top of the continuous holding cost.
Blind spot 3: Sell-side pricing error is learnable
Component 7 — the gap between your listing price and what the market actually pays — is treated as noise. But it's systematic. Overpriced listings sit longer (increasing component 5) and eventually sell below FMV (negative component 7). The two components are correlated:
Overpricing by 3% costs you ~15 extra days on market, which costs another 1.5% in holding. The compounding is why "just list high and see" is a $10K mistake per home.
Building the Decomposition Pipeline
For each closed transaction, compute all seven components using the AVM at each point in time:
for each closed deal:
fmv_at_buy = AVM(property, t_buy)
fmv_at_sell = AVM(property, t_sell)
fmv_renovated = AVM(property, t_sell, with_upgrades=True)
c1_appreciation = fmv_at_sell - fmv_at_buy (same-condition)
c2_buy_discount = fmv_at_buy - p_buy
c3_reno_uplift = fmv_renovated - fmv_at_sell
c4_adverse_sel = -IAP(p_buy, fmv_at_buy, a_segment)
c5_holding = -holding_cost(p_buy, t_hold, rate)
c6_transaction = -(commission + closing_costs)
c7_sell_error = p_sell - fmv_renovated
assert abs(sum(c1..c7) - (p_sell - p_buy)) < 0.01The assertion at the bottom is critical. If the seven components don't sum to the actual spread within rounding error, something is wrong with the AVM or the decomposition. This is a checksum on your entire analytics pipeline.
What Changes When You Can See All Seven
Instead of asking "why did margin drop this quarter?" and getting hand-wavy answers about "the market," you can say: component 1 gave us 2.3% tailwind, but component 4 cost us 2.8% — our pricing model is getting worse even though margin looks flat. That's an actionable finding. The aggregate number hides it.
The decomposition is simple arithmetic — but it requires an AVM you trust at three separate points in time. Companies that can't compute all seven components are flying blind. And in a flat market, blind is where you go broke.