Skip to content

alediaferia/stimmo

stimmo

License Python

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 OMI Compr_minCompr_max band is the spine of the estimate; everything else (floor, condition, amenities…) tunes a multiplier on top of it.

Install

uv sync

Run

uv run stimmo-web

Serves 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.

Importing from immobiliare.it

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.

Architecture

  • 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-web entry point.
  • scripts/ — data refresh tooling (pulls latest OMI assets from the CKAN API).
  • tests/ — pytest suite.

Refreshing the data

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.py

The 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.

"Recent closing prices"

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.

Caveats

  • 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 /about for rationale.

Tests

uv run pytest

Data sources

License

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.

AI-assisted development

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.

Disclaimer

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.

About

Transparent, OMI-anchored fair-price check for apartment listings.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages