Methodology

How we calculate
prices and trends.

Every median, percentage, and trend on PorscheStats comes from one shared engine — a kernel-weighted, mileage-normalized estimator built so that a single sale aging past a date cutoff can't whipsaw the pricing trends we publish.

Overview

One engine, every number

The price and trend you see — on a model page, in your watchlist, in any chart we publish — all come from one shared engine. It does four things:

  1. 1Weight every sale by recency using a Gaussian kernel.
  2. 2Normalize prices for mileage so a 50k-mile car and an 8k-mile car compare fairly.
  3. 3Take the weighted median (robust to a single outlier sale).
  4. 4Compare smoothed medians at now, 3 months ago, 6 months ago, and 1 year ago to compute trend percentages.

That's it. No magic. The interesting parts are how we weight and when we hide a number because the data's too thin to be honest.

The core trick

Kernel-weighted median

Most market estimators use a hard time window — e.g. median of all sales in the last 90 days. That works fine when there are 200 sales a quarter. It falls apart when there are 4. A single sale crossing the 90-day boundary on its 91st day causes a step change in the reported median, and that step change ripples through every percentage built on top of it.

Instead, we weight each sale by a Gaussian kernel centered on the date we're asking about:

weighti = exp( −½ · ((T − sale_datei) / bandwidth)² )

T = reference date · bandwidth = current half-width in days (60 → 365, see below)

Weight assigned to a sale based on how old it is, by bandwidth

0.000.250.500.751.000d60d120d180d240d300d360d60-day bandwidth120-day240-dayAge of sale (days)

A sale from yesterday gets weight ≈ 1. A sale from 90 days ago at bandwidth 60d gets weight ≈ 0.32. A sale from 2 years ago at bandwidth 60d gets weight ≈ 10-32— effectively zero. When a sale ages past the "edge" of a hypothetical cutoff, nothing dramatic happens — its weight just keeps drifting down. Your number moves a tenth of a percent, not twenty.

We then take the weighted median (not weighted mean) of mileage- normalized prices: sort by price, walk through accumulating weights, and report the value where cumulative weight crosses 50%. Medians shrug off the single outrageously-modified GT3 sale; weighted medians shrug off it and gradually phase it out as it ages.

Apples to apples

Mileage normalization

A 50,000-mile 996 GT3 and an 8,000-mile 996 GT3 are not the same car. Lumping them into one median is misleading — and on rare cars where the few recent sales happen to be all-low or all-high mileage, it's actively wrong.

We fit a simple linear regression of price against mileage across all sales of that model/trim/generation (the regression is stable because it pools every sale, not just recent ones). Each sale is then normalized to the median mileage of the cohort:

price_normi = pricei − slope · (mileagei − ref_mileage)

slope is from regression of all sales · ref_mileage is the cohort median · slope must be negative (higher miles → lower price) or we skip normalization

The normalizer is fit on the entire cohort, then applied to whatever sales the kernel is currently weighting. This means a single recent low-mileage sale doesn't distort the slope; it just gets normalized down, like every other sale.

For low-volume cars

Adaptive bandwidth

A 992 Carrera sells hundreds of times a quarter. A Gunther Werks Speedster sells two or three times a year. The bandwidth that's right for one is catastrophic for the other.

So the bandwidth isn't fixed — it ladders up until we have enough data to be honest. Starting at 60 days, we check how many sales are effectively contributing (see N_eff below). If fewer than 4, we widen:

60d
Common models
992 Carrera, 718 Cayman, 991 Turbo S
120d
Moderate volume
991.1 GT3, 997.2 Carrera S
240d
Limited production
996 GT3, 991.2 GT3 RS
365d
Truly rare
Singer, Gunther Werks, Sport Classics

For a healthy 992.1 GT3, the bandwidth stays at 60d — recent sales dominate, older ones contribute nothing. For a 996 GT3 with 3 sales in the last 90 days, the bandwidth widens to 120d or 240d to pull in late-2025 sales (heavily down-weighted, but contributing). For a Singer with two sales a year, it goes all the way to 365d. If even 365d doesn't produce N_eff ≥ 4, we mark the trend Insufficient data rather than report a noise number dressed up as a signal.

When we hide a number

Effective sample size (N_eff)

When sales have different weights, the count of sales doesn't tell you how much information is actually in your estimate. If 30 sales have weight 0.01 and 1 sale has weight 1.0, you essentially have one data point — not 31. The standard statistical measure for this is effective sample size:

N_eff = ( Σ wi )² / Σ wi²

Equals the raw count when all weights are equal · shrinks as weights concentrate

We require N_eff ≥ 4 at both endpoints before showing a trend percentage. Below that, you'll see Insufficient data instead of a made-up number. The same threshold gates the "Based on N sales" subtitle wherever a trend is displayed — if we can't back the number, we won't show it.

The 996 GT3 case

Why your numbers don’t swing wildly

A real example. Two snapshots of the same 996 GT3 one week apart, with no new sales in between. Here's what changed under the old hard-window math vs. the current engine:

996 GT3, no new salesOld · May 18Old · May 25New · May 18New · May 25
Reported median$112,998$117,000$124,955$124,955
3-month trend−3.3%+18.5%+3.9%+3.9%
6-month trend−4.2%−0.8%+3.9%+3.9%
1-year trend+41.2%N/A+15.1%+15.1%

The shift was one sale (Feb 20, $80,500 — a modified GT3) aging past the 90-day window. Under hard-window math, it dropped out entirely on day 91 and the 3-month trend flipped sign by 22 percentage points. Under kernel math, its weight just drifted from 0.61 to 0.50, and the smoothed numbers didn't move at all to the precision we display.

We backtest this property continuously — replaying historical data at weekly intervals across a mix of high-volume and rare models — and assert that no displayed trend can swing more than a few percentage points week-over-week without genuinely new sales arriving.

Keeping signal clean

Outliers & restomods

Two more knobs worth knowing about:

1.5× IQR filtering

For supplementary stats (all-time average, price ranges) we apply 1.5× interquartile-range outlier removal — the standard Tukey method. We don't apply it to the smoothed median because weighted medians are already robust to outliers.

Restomods get their own buckets

A Singer 911 is not a 964 Carrera. A Gunther Werks 400R is not a 993. Restomods, backdates, and special editions live in dedicated trim categories — Singer, Gunther Werks 400R, RUF Modified, Backdated — so they never pollute the median of a stock generation.

When a number on PorscheStats moves, it's because the market moved — not because we lost a sale at an arbitrary calendar boundary.

Want to see it in action?

Browse any model's analytics page — the trend badges, median, and 90-day stats all come from the engine described above.