Capstone project

Analisi predittiva del mercato immobiliare italiano

2016 — 2025

Capstone Project del Master in Data Analytics di Epicode: raccolta e analisi dei dati ufficiali del mercato immobiliare italiano nell'ultimo decennio, con l'obiettivo di costruire un modello di previsione per il primo semestre 2026.

L'analisi copre le province di Bologna, Milano, Napoli, Palermo, Roma e Torino — scelte per rappresentare aree geografiche, dimensioni di mercato e dinamiche di prezzo diverse. I dati riguardano esclusivamente abitazioni civili in stato normale, la tipologia prevalente nel mercato residenziale italiano.

Dati scaricati da fonti ufficiali pubbliche, utilizzati esclusivamente a fini accademici. La previsione 2026 è una stima statistica su base storica, non tiene conto di eventi futuri imprevedibili e va letta come indicazione di tendenza, non come valore certo.

N. 01

Andamento prezzi

Prezzo medio al metro quadro, provincia per provincia, dal 2016 al 2025 — media di circa 42.000 righe di quotazioni OMI.

70014002100Covid-19Superbonus 110%Rialzo tassi BCE2016201720182019202020212022202320242025
BolognaMilanoNapoliPalermoRomaTorino
N. 02

Compravendite

Prezzo e volumi raccontano due storie diverse: nel 2021-2022 crescono insieme, poi si separano.

45002016201720182019202020212022202320242025
Il picco 2021–2022 coincide con il Superbonus 110% e i tassi BCE a zero; dal 2023 le compravendite calano con il rialzo dei tassi, mentre i prezzi (grafico sopra) tengono.
N. 03

Previsione H1 2026

Due modelli statistici a confronto — regressione polinomiale e SARIMAX — con il migliore scelto per ogni provincia in base ai risultati sui dati storici.

Bologna

Regressione
1.704 €/mq+1.62%
SARIMAX
1.712 €/mq

Media — R² 0.07

Bologna ha un andamento molto regolare: prezzi in calo graduale fino al 2019, poi risalita costante. Una curva matematica semplice descrive bene questo pattern stabile, mentre SARIMAX tende a sovrastimare le variazioni su serie così piatte.

Milano

SARIMAX
2.004 €/mq+0.55%
Regressione
2.004 €/mq

Alta — R² 0.848

Milano è la provincia con la crescita più accelerata del decennio: +382 €/mq, impennata marcata dal 2022. SARIMAX impara che un prezzo in salita tende a continuare a salire, cogliendo il momentum in atto — il risultato è l'R² più alto tra tutte le province.

Napoli

Regressione
1.907 €/mq+0.61%
SARIMAX
1.905 €/mq

Bassa — entrambi i modelli faticano su questa serie

Napoli ha subito un doppio shock: crollo brusco nel 2020, rimbalzo nel 2021-2022. Due cambi di direzione ravvicinati confondono SARIMAX, che li amplifica invece di smorzarli. La regressione produce stime più prudenti.

Palermo

Regressione
849 €/mq+0.51%
SARIMAX
853 €/mq

Bassa — mercato troppo stabile per entrambi i modelli

Palermo è il mercato più stabile: prezzi in un range ristretto per tutto il decennio, senza trend forte né shock. Con così poca variazione da modellare, SARIMAX va in overfitting, imparando oscillazioni casuali invece di un pattern reale.

Roma

SARIMAX
2.055 €/mq+1.09%
Regressione
2.018 €/mq

Media — R² -2.4 (il migliore disponibile)

Roma ha un andamento a V: discesa continua dal 2016 al 2021, poi risalita decisa fino al 2025. SARIMAX coglie che negli ultimi semestri i prezzi salgono con costanza; la regressione, allenata anche sugli anni di calo, sottostima la ripresa recente.

Torino

Regressione
1.126 €/mq+1.34%
SARIMAX
1.110 €/mq

Bassa — serie troppo piatta e volatile per entrambi

Torino è il caso più difficile: i prezzi oscillano di pochi euro per 10 anni senza direzione chiara. SARIMAX va in overfitting grave (R² -184): con così poco segnale, il modello memorizza le micro-oscillazioni invece di un pattern. La regressione, pur imperfetta, è più conservativa.

Come è stata costruita

SQL — variazione % anno su anno (window function)

WITH prezzo_annuo_provincia AS (
  SELECT Prov, Anno,
         ROUND(AVG(Prezzo_medio_mq), 0) AS Prezzo_medio_annuo
  FROM omi_qi_vcn
  GROUP BY Prov, Anno
)
SELECT
  Prov, Anno, Prezzo_medio_annuo,
  LAG(Prezzo_medio_annuo) OVER (
    PARTITION BY Prov ORDER BY Anno
  ) AS Prezzo_Anno_Precedente,
  ROUND(
    (Prezzo_medio_annuo - LAG(Prezzo_medio_annuo) OVER (
      PARTITION BY Prov ORDER BY Anno
    )) * 100.0 / LAG(Prezzo_medio_annuo) OVER (
      PARTITION BY Prov ORDER BY Anno
    ), 2
  ) AS Variazione_Percentuale
FROM prezzo_annuo_provincia
ORDER BY Prov, Anno;

Python — selezione del miglior ordine SARIMAX per AIC

def trova_miglior_ordine(y_train, esogene_train, ordini):
    miglior_aic = float('inf')
    miglior_ordine = None

    for ordine, ordine_stagionale in ordini:
        try:
            modello = SARIMAX(
                y_train,
                exog=esogene_train,
                order=ordine,
                seasonal_order=ordine_stagionale,
                enforce_stationarity=False,
                enforce_invertibility=False,
            )
            risultato = modello.fit(disp=False)
            if risultato.aic < miglior_aic:
                miglior_aic = risultato.aic
                miglior_ordine = ordine
        except Exception:
            continue

    return miglior_ordine, miglior_aic