Trust

Methodology

Every derived metric on the dashboard is defined here. If a number on a chart confuses you, the chart subtitle should link back to this page.

What data we have

Where every number originates.

  • MorphMarket listings. The primary feed. Scraped daily and supplemented by the Eye in the Sky browser extension that emits live events as users browse listings. See the daily-log at /daily-log for ingest volume.
  • Cross-platform listings. Fauna Classifieds, Reptile Forums, Preloved, Kijiji. Smaller and slower. Surfaces at /cross-platform.
  • Sold events. Two flavours: confirmed (the extension saw a listing flip from live to sold) and inferred (the scraper has not seen a listing for 14+ days and the seller has not relisted; we infer sale). Both feed the demand-side curves; the difference is tagged on every chart that uses sold events.
  • Price history. A per-listing stream of observed prices over time. Used for trend lines and the spread analysis on /sold.

Median ask

The 50th percentile of currently-live listing prices. Each row's price is the USD equivalent when available, falling back to the raw listed price otherwise. Excludes prices below $1 and above $100,000.

Median is used in place of mean everywhere on the dashboard because the price distribution is heavy-tailed: a single $20,000 outlier shifts the mean meaningfully but the median barely. The cost of median is that it ignores variance, so every panel that quotes a median also displays the sample size (n) next to it.

KDE ridge / density plots

A KDE (kernel density estimate) ridge is a smooth histogram. It shows where listings cluster in price by trait. Wider ridge = more dispersion (the market is undecided), narrower ridge = tighter pricing.

Implementation: epanechnikov kernel, bandwidth scaled with sample size. Below n=10 the ridge fades; below n=5 it is hidden.

Days to sell

From the listing's first observation (either MorphMarket's first listed date, when we have it, or our scrape's first seen at) to its sold event. Listings still live show up as null in the histogram and are excluded.

Arbitrage flag

When the same animal (matched by image pHash) appears on both MorphMarket and a cross-platform listing at materially different prices, we flag it as a candidate arbitrage. The match is best-effort: pHash collisions exist and listings can be legitimately the same animal at different stages of life. Treat as a heads-up, not a confirmation.

Geck Inspect Market Index

Weekly weighted basket of high-value combos. Geometric average across all anchor combos that had a sale that week, normalised so the oldest week in the window = 1000.

Definition lives in v_market_index (migration 0005). Weeks with fewer than 2 combos are excluded from the geometric average; the resulting weeks are shaded on the chart when sample size dips below 4.

Anchor morph sub-indices

Per-anchor weekly median observed market price, rebased to 1000 at the start of the window. Anchors are coarse morph families: Lilly White, Axanthic, Harlequin, Cappuccino (the last grouping Cappuccino, Sable, and Frappuccino because they share parentage and price together in practice).

A listing can contribute to multiple anchors. The view is v_market_sub_index (migrations 0035, 0036). Sourced from price_history (live observations), not only confirmed sold events, because our sold-events stream is thin enough that a sold-only definition would render most weeks empty. This is similar to how Zillow ZHVI smooths over all observed sales rather than waiting for closed deals only.

Per-combo index

Daily median observed market price per canonical combo, available for the dozen canonical high-value combos. Powered by the materialised view combo_index_daily (migrations 0035, 0036), refreshed nightly via refresh_combo_index_daily(). The summary view v_combo_index_summary adds 7d / 30d / 90d deltas, which the per-combo entity hero and the /indices dashboard read directly.

Source: every observation in price_history for the trailing 365 days whose listing matches one of the canonical combos (via _combo_id_from_traits()). We use observed asks rather than confirmed sold prices because the sold-events stream is currently too sparse to drive a daily series for most combos.

Confidence score (0..99)

A coarse 0..99 score attached to every derived number. It aggregates two signals: sample size and source mix. Sample size dominates below n=20; source mix matters more above. Visually, confidence renders as a coloured pip (red below 25, amber up to 50, green above 80).

Source attribution

Every chart tags which source bundles contributed: MorphMarket listings, MorphMarket sold events, breeder direct, Pangea, Fauna Classifieds, Kijiji, etc. The catalogue lives in src/lib/market/sources.ts. The sources filter on every page is the same control, so narrowing to just MorphMarket sold events (for example) is one click everywhere.

Price adjustments (What's it worth)

The price estimator on /whats-it-worth takes the combo's base percentile band (p10/p25/p50/p75/p90 of sold listings in the last 180 days) and multiplies through by a set of adjustment factors that account for age, sex, weight, and proven-breeder status. Factors live in price_adjustment_factors (migration 0033) and are refreshed when the empirical data accumulates enough samples per bucket.

Limits we want to call out

  • Region inference is location-string regex based. A "Seattle, WA" seller maps to US; a "London" seller to UK. False negatives are common; refine if you spot one.
  • Sold-inferred events are noisy. A listing pulled because the seller went on vacation reads as a sale in our pipeline. The 14-day rule is tuned empirically and will move.
  • Trait normalisation is a moving target. The taxonomy table (morph_taxonomy_synonyms) holds the alias mappings; if you see "Lilly White" not matching a listing that has it, send the listing URL.

Last reviewed: 2026-05-22. Every claim here has a corresponding SQL view or function path. If a chart copy says something the methodology page does not back up, that is a bug in the chart copy; please flag it.