stimmo — a transparent, OMI-anchored fair-price check for Milan apartment listings. No ML, no black box: every adjustment lives in a single coefficients file.
A web tool that estimates whether the asking price of a Milan property listing is under-priced, fair, or over-priced, using:
- OMI (Osservatorio del Mercato Immobiliare, Agenzia delle Entrate) — official €/m² ranges per OMI zone × property type × condition.
- OpenStreetMap — Nominatim geocoding + Overpass amenity counts.
- A small, transparent hedonic-style adjustment table (no ML).
⚠️ Italian sold-price data is not public. The OMICompr_min–Compr_maxband is the spine of the estimate; everything else (floor, condition, amenities…) tunes a multiplier on top of it.
uv syncuv run stimmo-webServes a FastAPI + Jinja app on http://127.0.0.1:8000 with a form for
address, surface, property type, OMI condition bucket, fine-grained condition,
floor, total floors, lift, energy class (optional), outdoor space, box auto,
construction era, orientation, second bathroom, and asking price, and renders
the valuation report (verdict, OMI band, adjustments breakdown, recent
semesters trend). Override the bind address via STIMMO_HOST / STIMMO_PORT
env vars.
Open /bookmarklet in the running app, drag the 📋 stimmo link to your
bookmarks bar, then click it on any immobiliare.it Milano listing. The
bookmarklet reads the page's __NEXT_DATA__ JSON (already in your browser —
no server-side request is ever made to immobiliare.it) and opens stimmo with
the form prefilled: address, surface, price, floor, lift, energy class,
condition, outdoor space, construction era, bathrooms, and property type.
A paste fallback is also available on /bookmarklet for users who can't use
bookmarklets: paste the full page source of a listing and submit.
Review every prefilled field before estimating — schema drift is expected over time.
src/stimmo/data/— bundled OMI quotations, zone polygons, and history CSV; live calls to Nominatim and Overpass.src/stimmo/valuation/— the estimation pipeline: adjustments (single tuning surface), engine, and verdict classifier.src/stimmo/web/— FastAPI app and Jinja templates;stimmo-webentry point.scripts/— data refresh tooling (pulls latest OMI assets from the CKAN API).tests/— pytest suite.
OMI semestral assets (sales €/m² + zone polygons) are bundled in
src/stimmo/data/assets/. To pull the most recent semester from
dati.comune.milano.it:
uv run python scripts/refresh_omi.pyThe script discovers the latest "Compravendita" + "Zone e Perimetri" datasets
via the CKAN API and rewrites both files in place. Bump the SEMESTER
constant in src/stimmo/data/omi.py if it advanced.
Italy doesn't publish per-transaction sale data. The closest free proxy is the
OMI €/m² band per semester, which is itself derived from observed sales.
The bundled milano_omi_history.csv carries the last 8 semesters of MILANO
Compravendita quotations; the report shows the matching zone+type+condition
across all of them, with per-semester deltas and an overall trend.
- Polygon coverage is the comune di Milano only — addresses in the metropolitan belt (Sesto San Giovanni, Cinisello, etc.) will fail with "outside Milano".
- No live comparable listings; the band comes from OMI min/max, not from a fitted model. This is by design.
- Verdicts compare asking price to an ask-shifted band (OMI rogito + 6%). See
/aboutfor rationale.
uv run pytest- OMI Compravendita per semestre (Comune di Milano, CKAN): dati.comune.milano.it — quotazioni OMI compravendita
- OMI Zone e Perimetri (Comune di Milano, CKAN): dati.comune.milano.it — zone e perimetri OMI
- Nominatim: nominatim.openstreetmap.org
- Overpass: overpass-api.de
Code: Apache-2.0 (see LICENSE).
Bundled data: OMI quotations and zone polygons are redistributed under IODL 2.0 (Italian Open Data License) from the Comune di Milano CKAN portal — attribution required.
Live data: OpenStreetMap (Nominatim, Overpass) under ODbL — attribution required for any rendered output.
This project is developed with help from Claude Code. See CLAUDE.md
for project context provided to AI assistants. Per-session agent artifacts
(.claude/plans/, .claude/reports/, .claude/settings.local.json) are
gitignored — only CLAUDE.md and shared agent config are version-controlled.
stimmo is a fairness check, not an official appraisal (perizia). It does not replace a qualified professional valuation (perito) and should not be used as the basis for legal, fiscal, or contractual decisions.