How stimmo turns an address
into a verdict.
A six-step pipeline, one coefficients file, no machine learning. Same inputs, same output — every time.
for Milan apartment listings.
The pipeline
§ Address → verdict · 6 steps-
01
Geocode
OSM Nominatim resolves the address to lat / lon. Queries are restricted to Milano comune.
-
02
Locate the OMI zone
Point-in-polygon against Milano's official OMI microzone shapes.
-
03
Pull the €/m² band
Compr_min – Compr_max for that zone × property type × condition bucket.
-
04
Count amenities
OSM Overpass — schools, transit, markets, pharmacies, parks within 500 m.
-
05
Adjust the band
A single coefficients table multiplies floor, lift, size, condition, energy, outdoor, era, orientation, exposure, room density, second bathroom, parking box, and amenities.
-
06
Classify
Compare asking price to an ask-shifted band (rogito + 6 %). ±5 % around it is fair.
Data sources
OMI quotations
Per-zone €/m² ranges for sales, split by property type and condition (Normale / Scadente / Ottimo). The spine of every estimate.
- License
- IODL 2.0
- File
- data/assets/milano_omi_valori.csv
OMI zone polygons
Microzone shapes used for point-in-polygon zone assignment. Comune di Milano only — addresses outside the comune are rejected.
- License
- IODL 2.0
- File
- data/assets/milano_omi_zones.geojson
OMI history
Trailing 8 semesters (~4 years) of bands per zone × type × condition. Drives the trend strip on the report.
- License
- IODL 2.0
- File
- data/assets/milano_omi_history.csv
NTN — transactions
Numero di Transazioni Normalizzate, quarterly. Shown for market context only — never used as a pricing input.
- License
- IODL 2.0
- File
- milano_ntn_total.csv · milano_ntn_by_size.csv
Nominatim — geocoding
Free geocoder, called once per estimate. Queries are scoped to Milano to avoid stray matches.
- License
- ODbL
- File
- nominatim.openstreetmap.org
Overpass — amenities
Counts of schools, pharmacies, markets, transit stops and parks within 500 m. If unreachable, the estimate still renders with a zero amenity score and a warning.
- License
- ODbL
- File
- overpass-api.de
No machine learning.
stimmo has no trained model. The entire tuning surface is a single file — valuation/adjustments.py. Every multiplier (floor, lift, size, condition, energy, outdoor, era, orientation, exposure, room density, second bathroom, parking box, and amenities) lives there in plain Python.
The verdict is deterministic: same inputs, same output. If you disagree with a coefficient, you can read the line where it lives, change it, and re-run.
Ask-shifted, not rogito.
OMI publishes transacted prices — what changed hands at the notary, after negotiation. In Milano, asking prices typically run 5–10 % above the eventual sale price.
We shift the OMI band upward by a fixed +6 % ask-premium before classifying. ±5 % around the shifted band is "fair". The constant lives in verdict.py::ASK_PREMIUM_PCT.
What stimmo doesn't model
Spese condominiali
Routine condominium fees and extraordinary works (lavori straordinari deliberati). Can shift true cost €10–50 k. Invisible to OMI.
Piano nobile
The classic 1° piano premium in storied buildings. Inside the same building, can drive ±5–10 %.
Street noise & view
A unit on a quiet cortile vs. one on Corso Buenos Aires. OMI averages, doesn't see this.
Comparable listings
Italian per-transaction sale data isn't public. We don't fit a model on stale asking prices — by design.
Metropolitan belt
Sesto, Cinisello, Cologno, Rho — outside the Milano comune polygon. Will fail with "outside Milano".
Commercial property
Shops, offices, ateliers — different OMI category, different dynamics. Residential subtypes only.
stimmo is a fairness check, not an official appraisal.
It does not replace a qualified perito and should not be used as the basis for legal, fiscal, or contractual decisions. Use it to sanity-check an asking price, negotiate, or walk away — not to sign anything.