Pricing Power nel SaaS: come simulare l’impatto degli aumenti di prezzo su churn, MRR e profitto

Pricing Power SaaS - Prezzo, Churn e Valore

This post has already been read 28 times!

In sintesi.Un aumento di prezzo non crea automaticamente valore. Modifica contemporaneamente ricavo medio per cliente, churn, retention, customer lifetime e rischio. Un modello Monte Carlo può aiutare il management a confrontare scenari, ma soltanto se il baseline è coerente con i dati osservati e se le ipotesi sono interpretate correttamente.Nel modello illustrato in questo articolo, gli aumenti fino al 20% migliorano il Gross Profit medio nell’orizzonte simulato. Tuttavia, il beneficio marginale diminuisce, la dispersione degli esiti aumenta e il risultato dipende fortemente da WTP, sensibilità al prezzo e struttura della customer base. Il +20% è quindi il migliore tra gli scenari testati, non il prezzo ottimale dimostrato.

La simulazione non decide quale prezzo adottare. Costruisce uno spazio quantitativo nel quale la decisione può essere discussa.

La domanda corretta non è “quanto possiamo aumentare?”

In una riunione di pricing, Finance osserva margini e ricavi ricorrenti. Il Commerciale teme la reazione dei clienti. Product richiama il valore delle funzionalità introdotte. Customer Success segnala che alcuni account utilizzano meno il prodotto. Marketing prova a stimare l’effetto sulla retention.

Ognuno osserva una parte della relazione economica. La decisione, però, riguarda l’intera customer base e il suo comportamento nel tempo.

Un aumento del 10% modifica il prezzo, ma può modificare anche:

  • il churn e il tasso di rinnovo;
  • il numero di seat e il volume acquistato;
  • gli sconti e la contraction MRR;
  • la durata della relazione;
  • i costi di retention e di servizio;
  • la composizione della customer base.

La domanda manageriale più utile diventa quindi:

Quanto valore aggiuntivo genera il repricing dopo avere considerato la risposta della customer base?

Per rispondere servono almeno quattro prospettive:

  1. l’impatto immediato su prezzo, ARPU e MRR;
  2. la risposta successiva di churn e retention;
  3. il Gross Profit cumulato o attualizzato;
  4. la dispersione degli esiti e il rischio di downside.

Perché l’MRR da solo non basta

Consideriamo un SaaS con 10.000 clienti e un prezzo medio di 50 euro al mese.

[math]\displaystyle \begin{aligned} MRR_0 &= 10.000 \times 50 = 500.000\,€ \end{aligned}[/math]

Con un aumento del 10%, il prezzo diventa 55 euro. Se nessuno abbandona il servizio, l’MRR teorico è 550.000 euro. Se invece il 5% della customer base abbandona immediatamente:

[math]\displaystyle \begin{aligned} Customers_1 &= 10.000 \times (1-0,05) = 9.500 \\ MRR_1 &= 9.500 \times 55 = 522.500\,€ \\ \Delta MRR &= \frac{522.500-500.000}{500.000}=4,5\% \end{aligned}[/math]

Il prezzo è aumentato del 10%, ma l’MRR soltanto del 4,5%. Se il churn continua nei mesi successivi, la customer base segue una traiettoria dinamica:

[math]\displaystyle \begin{aligned} Customers_t = Customers_{t-1}\times(1-Churn_t) \end{aligned}[/math]

Inoltre, un cliente non deve abbandonare per distruggere valore. Può ridurre i seat, passare a un piano inferiore o ottenere uno sconto. Per questo un modello realistico dovrebbe distinguere tra logo churn, revenue churn, contraction ed expansion.

Le metriche da osservare

ARPU e MRR

L’ARPU, cioè il ricavo medio per cliente, è:

[math]ARPU = \frac{Revenue}{Customers}[/math]

In forma semplificata:

[math]MRR = Customers \times ARPU[/math]

Un ARPU maggiore è utile soltanto se il ricavo aggiuntivo compensa la perdita di clienti, i downgrade, gli sconti e gli eventuali costi di retention.

CLV

Quando churn e margine sono relativamente stabili, una prima approssimazione del Customer Lifetime Value lordo è:

[math]CLV \approx \frac{ARPU \times Gross\ Margin}{Churn}[/math]

Con ARPU di 50 euro, Gross Margin dell’80% e churn mensile del 4%:

[math]\displaystyle \begin{aligned} CLV_0 &= \frac{50\times0,80}{0,04}=1.000\,€ \end{aligned}[/math]

Se il prezzo sale a 55 euro ma il churn cresce al 5,2%:

[math]\displaystyle \begin{aligned} CLV_1 &= \frac{55\times0,80}{0,052}\approx846\,€ \end{aligned}[/math]

L’ARPU cresce del 10%, mentre il CLV diminuisce di circa il 15,4%. La formula è soltanto un’approssimazione non attualizzata: non include expansion, contraction, CAC, sconti, costi di servizio o costo del capitale.

Una customer base SaaS non è omogenea

Per rendere il problema concreto, consideriamo tre segmenti:

Segmento Clienti Prezzo mensile Churn mensile base WTP media Sensibilità
Starter 5.000 19 € 7,5% 23 € 2,0
Growth 3.500 59 € 3,8% 78 € 1,5
Enterprise 1.500 299 € 1,6% 390 € 1,0

L’MRR teorico iniziale è:

[math]\displaystyle \begin{aligned} MRR_0 &= 5.000\times19 + 3.500\times59 + 1.500\times299 \\ &= 750.000\,€ \end{aligned}[/math]

Lo Starter rappresenta metà dei clienti e ha il churn più alto. Il suo rischio principale è la perdita di volume. Nel Growth è più importante il rapporto tra prezzo, utilizzo, seat e valore generato. Nell’Enterprise il rischio può essere ritardato fino al rinnovo e manifestarsi prima come negoziazione, riduzione dei seat o sconto.

WTP e pricing power

La Willingness to Pay, o WTP, rappresenta la disponibilità del cliente a pagare. Nel modello viene rappresentata con una distribuzione lognormale:

[math]WTP \sim Lognormal(\mu,\sigma)[/math]

La lognormale garantisce valori positivi e consente una distribuzione asimmetrica. Non dimostra però che la WTP reale segua quella distribuzione. È una scelta di modellazione che dovrebbe essere calibrata con dati di rinnovo, storico dei prezzi, downgrade, utilizzo, interviste ed esperimenti.

Il pricing power non è soltanto la capacità di aumentare il listino. Dipende dal rapporto tra valore percepito, switching cost, alternative disponibili, intensità d’uso e sensibilità del cliente.

Il modello corretto: distinguere baseline e stress incrementale

Il modello applica una probabilità di churn individuale a ogni cliente attivo e a ogni mese. La parte essenziale è distinguere lo stress già presente nel baseline da quello generato dal repricing.

Per un cliente con prezzo attuale [math]P_0[/math], prezzo scenario [math]P_1[/math] e WTP [math]WTP_i[/math], definiamo:

[math]\displaystyle \begin{aligned} s_0 &= \max\left(\frac{P_0}{WTP_i}-1,0\right) \\ s_1 &= \max\left(\frac{P_1}{WTP_i}-1,0\right) \\ \Delta s_{WTP} &= \max(s_1-s_0,0) \end{aligned}[/math]

La probabilità di churn nello scenario è quindi:

[math]\displaystyle \begin{aligned} p_i &= clip\left[c_0\left(1+s\Delta P+s\Delta s_{WTP}\right),0,c_{max}\right] \end{aligned}[/math]

Questa correzione evita che il confronto sia falsato da una componente WTP applicata soltanto agli scenari di prezzo. Nel baseline il churn simulato deve rappresentare il punto di partenza osservato, non un valore modificato accidentalmente dalla formula.

Resta una semplificazione: lo stress viene applicato ogni mese ai clienti attivi. È un’approssimazione ragionevole per un portafoglio mensile, ma non per contratti annuali. Nel B2B, il modello dovrebbe distinguere almeno tra clienti mensili, clienti annuali e clienti prossimi al rinnovo.

Implementazione Python 

Il codice seguente è un motore di scenario analysis. Non è un sistema production-ready: non stima causalità, non include contraction o expansion, non acquisisce nuovi clienti e non modella rinnovi annuali. La correzione principale riguarda la baseline WTP e il confronto coerente tra scenari.

from __future__ import annotations

from dataclasses import dataclass
from typing import Sequence

import numpy as np
import pandas as pd


@dataclass(frozen=True)
class SegmentConfig:
    name: str
    customers: int
    price: float
    monthly_churn: float
    wtp_mean: float
    wtp_cv: float = 0.20
    price_sensitivity: float = 1.5

    def validate(self) -> None:
        if not self.name:
            raise ValueError("segment name cannot be empty")
        if self.customers < 0:
            raise ValueError("customers must be >= 0")
        if self.price <= 0 or self.wtp_mean <= 0:
            raise ValueError("price and wtp_mean must be > 0")
        if not 0 < self.monthly_churn < 1:
            raise ValueError("monthly_churn must be in (0, 1)")
        if self.wtp_cv < 0 or self.price_sensitivity < 0:
            raise ValueError("wtp_cv and price_sensitivity must be >= 0")


@dataclass(frozen=True)
class SimulationConfig:
    months: int = 12
    runs: int = 1_000
    gross_margin: float = 0.80
    seed: int = 42
    max_churn: float = 0.95

    def validate(self) -> None:
        if self.months <= 0 or self.runs <= 0:
            raise ValueError("months and runs must be > 0")
        if not 0 < self.gross_margin <= 1:
            raise ValueError("gross_margin must be in (0, 1]")
        if not 0 <= self.max_churn < 1:
            raise ValueError("max_churn must be in [0, 1)")


def lognormal_parameters(mean: float, cv: float) -> tuple[float, float]:
    sigma_squared = np.log1p(cv**2)
    return np.log(mean) - sigma_squared / 2, np.sqrt(sigma_squared)


def churn_probability(
    base_churn: float,
    price_change: float,
    base_price: float,
    scenario_price: float,
    wtp: np.ndarray,
    sensitivity: float,
    max_churn: float,
) -> np.ndarray:
    baseline_stress = np.maximum(base_price / wtp - 1.0, 0.0)
    scenario_stress = np.maximum(scenario_price / wtp - 1.0, 0.0)
    incremental_wtp_stress = np.maximum(
        scenario_stress - baseline_stress, 0.0
    )

    incremental_price_stress = max(price_change, 0.0)
    multiplier = (
        1.0
        + sensitivity * incremental_price_stress
        + sensitivity * incremental_wtp_stress
    )

    return np.clip(base_churn * multiplier, 0.0, max_churn)


def simulate_pricing(
    segments: Sequence[SegmentConfig],
    price_change: float,
    config: SimulationConfig,
) -> pd.DataFrame:
    if price_change < -1:
        raise ValueError("price_change cannot be below -100%")

    config.validate()
    for segment in segments:
        segment.validate()

    rng = np.random.default_rng(config.seed)
    results = []

    for run in range(config.runs):
        monthly_mrr = np.zeros(config.months)
        monthly_customers = np.zeros(config.months, dtype=int)

        for segment in segments:
            mu, sigma = lognormal_parameters(
                segment.wtp_mean, segment.wtp_cv
            )
            wtp = rng.lognormal(mu, sigma, size=segment.customers)
            active = np.ones(segment.customers, dtype=bool)
            scenario_price = segment.price * (1 + price_change)

            for month in range(config.months):
                active_indices = np.flatnonzero(active)
                if active_indices.size == 0:
                    continue

                churn_prob = churn_probability(
                    base_churn=segment.monthly_churn,
                    price_change=price_change,
                    base_price=segment.price,
                    scenario_price=scenario_price,
                    wtp=wtp[active_indices],
                    sensitivity=segment.price_sensitivity,
                    max_churn=config.max_churn,
                )

                retained = rng.random(active_indices.size) >= churn_prob
                active[active_indices[~retained]] = False

                current_customers = int(active.sum())
                monthly_customers[month] += current_customers
                monthly_mrr[month] += current_customers * scenario_price

        cumulative_mrr = float(monthly_mrr.sum())
        results.append({
            "run": run,
            "ending_customers": int(monthly_customers[-1]),
            "ending_mrr": float(monthly_mrr[-1]),
            "cumulative_mrr": cumulative_mrr,
            "cumulative_gross_profit": (
                cumulative_mrr * config.gross_margin
            ),
        })

    return pd.DataFrame(results)


def probability_of_loss(
    scenario_result: pd.DataFrame,
    base_result: pd.DataFrame,
) -> float:
    if len(scenario_result) != len(base_result):
        raise ValueError("results must have the same number of runs")

    return float((
        scenario_result["cumulative_gross_profit"].to_numpy()
        < base_result["cumulative_gross_profit"].to_numpy()
    ).mean())


def summarize_scenarios(
    segments: Sequence[SegmentConfig],
    price_changes: Sequence[float],
    config: SimulationConfig,
) -> pd.DataFrame:
    """Simula gli scenari e restituisce una tabella riassuntiva."""
    base_result = simulate_pricing(segments, 0.0, config)
    summaries = []

    for change in price_changes:
        result = simulate_pricing(segments, change, config)
        summaries.append({
            "Scenario": f"+{change:.0%}",
            "Mean end MRR": result["ending_mrr"].mean(),
            "P05 end MRR": result["ending_mrr"].quantile(0.05),
            "P50 end MRR": result["ending_mrr"].quantile(0.50),
            "P95 end MRR": result["ending_mrr"].quantile(0.95),
            "Mean cumulative gross profit": (
                result["cumulative_gross_profit"].mean()
            ),
            "Probability of loss": probability_of_loss(
                result, base_result
            ),
        })

    return pd.DataFrame(summaries)


if __name__ == "__main__":
    segments = [
        SegmentConfig(
            name="Starter",
            customers=5_000,
            price=19.0,
            monthly_churn=0.075,
            wtp_mean=23.0,
            wtp_cv=0.20,
            price_sensitivity=2.0,
        ),
        SegmentConfig(
            name="Growth",
            customers=3_500,
            price=59.0,
            monthly_churn=0.038,
            wtp_mean=78.0,
            wtp_cv=0.20,
            price_sensitivity=1.5,
        ),
        SegmentConfig(
            name="Enterprise",
            customers=1_500,
            price=299.0,
            monthly_churn=0.016,
            wtp_mean=390.0,
            wtp_cv=0.15,
            price_sensitivity=1.0,
        ),
    ]

    config = SimulationConfig(
        months=12,
        runs=1_000,
        gross_margin=0.80,
        seed=42,
    )

    scenarios = [0.00, 0.05, 0.10, 0.15, 0.20]
    output = summarize_scenarios(segments, scenarios, config)

    print(output.to_string(index=False, float_format="{:,.2f}".format))
Scenario  Mean end MRR  P05 end MRR  P50 end MRR  P95 end MRR  Mean cumulative gross profit  Probability of loss
     +0%    536,569.08   528,894.65   536,575.50   544,311.20                  6,007,327.99                 0.00
     +5%    549,451.19   540,149.35   549,520.65   557,749.08                  6,220,092.47                 0.00
    +10%    561,616.61   552,469.11   561,593.45   570,627.15                  6,427,006.81                 0.00
    +15%    572,028.42   562,642.96   572,162.95   581,207.01                  6,617,640.32                 0.00
    +20%    581,012.35   571,134.18   580,984.20   590,971.68                  6,800,934.00                 0.00

Come leggere gli output

Per ogni scenario è riportato:

Leggi anche 👉  La Legge di Metcalfe nel Digital Marketing: Come Usare gli Effetti di Rete per Abbattere il CAC e Scalare
Indicatore Domanda a cui risponde
Gross Profit medio Quanto valore produciamo mediamente?
P05 Quanto valore rimane in una fascia sfavorevole della distribuzione?
P50 Qual è il valore centrale?
P95 Qual è un esito favorevole ma non estremo?
P95 − P05 Quanto è ampia la dispersione?
Probability of Loss Quanto spesso lo scenario è peggiore del baseline simulato?

La tabella confronta cinque scenari di repricing su un orizzonte di 12 mesi, con:

  • 1.000 simulazioni per scenario;
  • tre segmenti di clientela;
  • churn applicato mensilmente;
  • WTP simulata per cliente;
  • Gross Margin costante all’80%;
  • nessuna acquisizione di nuovi clienti;
  • nessuna contraction o expansion;
  • nessun rinnovo annuale esplicito.

La lettura corretta è quindi:

Quanto valore produce ciascun aumento di prezzo sulla customer base esistente, date le ipotesi del modello?

Non è una previsione certa del comportamento futuro dell’azienda.

Il baseline: +0% produce 536.569 euro di MRR finale

Lo scenario +0% rappresenta il punto di confronto.

Indicatore Valore
MRR finale medio 536.569 €
P05 MRR finale 528.895 €
Mediana, P50 536.576 €
P95 MRR finale 544.311 €
Gross Profit cumulato medio 6.007.328 €

La prima osservazione importante riguarda la differenza tra l’MRR iniziale teorico e quello finale simulato.

La customer base iniziale genera:

[math]\displaystyle \begin{aligned}
MRR_0 = 750.000\,€
\end{aligned}[/math]

Tuttavia, dopo dodici mesi, lo scenario base produce un MRR medio di circa:

[math]\displaystyle \begin{aligned}
MRR_{12,base} \approx 536.569\,€
\end{aligned}[/math]

La riduzione non deriva dal prezzo, perché il prezzo non cambia nello scenario base. Deriva dal fatto che il churn viene applicato mese dopo mese.

In termini assoluti, la differenza è:

[math]\displaystyle \begin{aligned}
750.000 – 536.569 = 213.431\,€
\end{aligned}[/math]

L’MRR finale è quindi circa il 28,5% più basso dell’MRR teorico iniziale.

Questo non significa necessariamente che l’azienda perderà esattamente 213.431 euro di MRR. Significa che il modello, applicando i tassi di churn indicati ai segmenti per dodici periodi, genera quella traiettoria media.

La conseguenza manageriale è importante:

Il repricing viene valutato sopra una customer base già soggetta a deterioramento naturale.

Prima di discutere l’aumento di prezzo, bisogna quindi verificare se i tassi di churn utilizzati siano realistici e se rappresentino il comportamento osservato dell’azienda.

Tutti gli aumenti testati migliorano l’MRR finale medio

I risultati sono monotonicamente crescenti:

Scenario MRR finale medio Incremento rispetto al baseline Incremento percentuale
+0% 536.569 €
+5% 549.451 € +12.882 € +2,40%
+10% 561.616 € +25.048 € +4,67%
+15% 572.028 € +35.459 € +6,61%
+20% 581.012 € +44.443 € +8,28%

Il primo risultato è intuitivo ma rilevante:

Aumentando il prezzo, l’MRR finale medio cresce in tutti gli scenari testati.

Tuttavia, la crescita dell’MRR è molto inferiore alla crescita del prezzo.

Con un aumento del 20%, ci si potrebbe aspettare una crescita dell’MRR vicina al 20% se la customer base rimanesse invariata. Invece, l’MRR finale cresce soltanto dell’8,28% rispetto al baseline.

Questo scarto contiene l’effetto del churn aggiuntivo e della riduzione dei clienti attivi.

In forma semplificata:

[math]\displaystyle \begin{aligned}
Incremento\ prezzo &= +20\% \\
Incremento\ MRR &= +8,28\%
\end{aligned}[/math]

Il prezzo aumenta quindi più rapidamente del valore finale della base clienti.

Questo significa che il modello sta incorporando una risposta negativa della customer base. L’aumento del prezzo produce più ricavo per cliente, ma una parte del beneficio viene assorbita dalla perdita di clienti attivi.

Il rendimento marginale diminuisce

La crescita complessiva dell’MRR è positiva, ma ogni ulteriore aumento genera un beneficio incrementale più piccolo.

Passaggio Incremento dell’MRR finale medio
+0% → +5% +12.882 €
+5% → +10% +12.165 €
+10% → +15% +10.412 €
+15% → +20% +8.984 €

La sequenza è chiaramente decrescente:

[math]\displaystyle \begin{aligned}
12.882 > 12.165 > 10.412 > 8.984
\end{aligned}[/math]

Questa è una delle informazioni più importanti dell’intera simulazione.

Il repricing continua a produrre valore, ma il valore aggiuntivo ottenuto da ogni nuovo incremento diminuisce progressivamente.

Leggi anche 👉  La Trappola di Kodak e la Cannibalizzazione del Business Model: Come Gestire il Margine a Rischio

Il passaggio da +15% a +20%, per esempio, aggiunge soltanto circa 8.984 euro di MRR finale medio. Il passaggio da +0% a +5% ne aggiunge circa 12.882.

La differenza tra i due incrementi è:

[math]\displaystyle \begin{aligned}
12.882 – 8.984 = 3.898\,€
\end{aligned}[/math]

Quindi il modello mostra un comportamento coerente con una customer base che diventa progressivamente più difficile da monetizzare.

La domanda non dovrebbe essere:

“Il +20% genera più MRR?”

La risposta è sì.

La domanda più utile è:

“Quanto MRR aggiuntivo otteniamo per ogni ulteriore punto percentuale di aumento?”

Su questa metrica, il +20% è meno efficiente degli aumenti precedenti.

Il Gross Profit cumulato cresce, ma anche qui il beneficio marginale diminuisce

Il Gross Profit cumulato medio è:

Scenario Gross Profit cumulato medio Incremento rispetto al baseline
+0% 6.007.328 €
+5% 6.220.092 € +212.764 €
+10% 6.427.007 € +419.679 €
+15% 6.617.640 € +610.312 €
+20% 6.800.934 € +793.606 €

Rispetto al baseline, il +20% genera circa:

[math]\displaystyle \begin{aligned}
6.800.934 – 6.007.328 = 793.606\,€
\end{aligned}[/math]

di Gross Profit cumulato aggiuntivo nel periodo considerato.

In termini percentuali:

[math]\displaystyle \begin{aligned}
\frac{793.606}{6.007.328} \approx 13,21\%
\end{aligned}[/math]

Quindi:

  • il prezzo aumenta del 20%;
  • il MRR finale aumenta dell’8,28%;
  • il Gross Profit cumulato aumenta del 13,21%.

Il Gross Profit cresce meno del prezzo, ma più dell’MRR finale percentuale. Questo è dovuto al fatto che il Gross Profit cumulato considera l’intero percorso dei dodici mesi, non soltanto il valore al mese finale.

Anche il rendimento marginale del Gross Profit diminuisce:

Passaggio Incremento Gross Profit
+0% → +5% +212.764 €
+5% → +10% +206.914 €
+10% → +15% +190.634 €
+15% → +20% +183.294 €

Il passaggio da +15% a +20% resta positivo, ma produce il beneficio marginale più basso della serie.

Questa è un’evidenza di rendimento marginale decrescente, non ancora di distruzione di valore.

Il +20% è il migliore scenario osservato, ma non è ancora il prezzo ottimale

Nel perimetro testato:

[math]\displaystyle \begin{aligned}
\Delta P \in \{0\%,5\%,10\%,15\%,20\%\}
\end{aligned}[/math]

il +20% produce:

  • l’MRR finale medio più alto;
  • il Gross Profit cumulato medio più alto;
  • una mediana più alta;
  • un P05 più alto;
  • un P95 più alto.

Quindi è corretto dire:

Il +20% è lo scenario migliore tra quelli simulati.

Non è invece corretto dire:

Il +20% è il prezzo ottimale.

Il codice non ha cercato il massimo su tutti i possibili livelli di prezzo. Ha confrontato soltanto cinque punti.

È possibile che il Gross Profit continui a crescere al +25%, si avvicini a un massimo al +30% e inizi a diminuire al +35%. È anche possibile che il massimo sia già vicino al +20%.

Per individuarlo, bisogna estendere la griglia, ad esempio:

scenarios = [
    0.00, 0.05, 0.10, 0.15, 0.20,
    0.25, 0.30, 0.35, 0.40
]

Ma anche una curva con un massimo non dimostrerebbe automaticamente che quel punto sia il prezzo da applicare. Il massimo potrebbe dipendere da ipotesi errate su:

  • WTP;
  • churn;
  • sensibilità al prezzo;
  • margine;
  • rinnovi;
  • contraction;
  • segmentazione.

La dispersione aumenta con il repricing

Per osservare il rischio di variabilità, possiamo calcolare:

[math]P95 – P05[/math]

Scenario P95 − P05
+0% 15.417 €
+5% 17.600 €
+10% 18.158 €
+15% 18.564 €
+20% 19.838 €

La dispersione passa da circa 15.417 euro nel baseline a circa 19.838 euro nel caso +20%.

L’aumento assoluto è:

[math]\displaystyle \begin{aligned}
19.838 – 15.417 = 4.421\,€
\end{aligned}[/math]

L’aumento relativo è circa il 28,7%.

Questo significa che il repricing non modifica soltanto il valore medio. Modifica anche la variabilità degli esiti.

Con il +20%, la differenza tra un risultato sfavorevole e uno favorevole è più ampia rispetto al baseline.

Il management sta quindi ottenendo più valore medio, ma sta anche assumendo una maggiore esposizione alla variabilità del comportamento dei clienti.

Questa è la distinzione tra:

  • rendimento atteso;
  • rischio di dispersione.

Uno scenario può essere preferibile in termini di valore medio, ma meno adatto a un’azienda con bassa tolleranza alla variabilità o con vincoli finanziari stringenti.

Cosa dicono P05, P50 e P95

Consideriamo il caso +20%:

Percentile MRR finale
P05 571.134 €
P50 580.984 €
P95 590.972 €
Media 581.012 €

P05

Il P05 indica che il 5% delle simulazioni produce un MRR finale inferiore o uguale a circa 571.134 euro.

Non è il peggior risultato possibile. Non è uno scenario di crisi. È il quinto percentile della distribuzione generata dal modello.

La formulazione corretta è:

“Nella fascia bassa della distribuzione simulata, l’MRR finale è circa 571.000 euro.”

Non:

“Questo è il minimo MRR che possiamo aspettarci.”

P50

Il P50 è la mediana. Circa metà delle simulazioni produce un risultato inferiore e metà un risultato superiore.

Nel caso +20%, la mediana è 580.984 euro, molto vicina alla media di 581.012 euro.

Questa vicinanza suggerisce che la distribuzione non è fortemente asimmetrica, almeno per questo output.

P95

Il P95 indica che soltanto il 5% delle simulazioni produce un MRR finale superiore a circa 590.972 euro.

Rappresenta una fascia favorevole, non un risultato garantito.

Media e mediana sono quasi uguali

Per il +20%:

[math]\displaystyle \begin{aligned}
Media &= 581.012\,€ \\
P50 &= 580.984\,€
\end{aligned}[/math]

La differenza è di appena circa 28 euro. Lo stesso comportamento si osserva negli altri scenari.

Questo suggerisce che la distribuzione dell’MRR finale è relativamente equilibrata. Tuttavia, la dispersione complessiva continua ad aumentare con il prezzo.

Il P05 del +20% supera il P95 del +10%, ma non basta per parlare di dominanza

Confrontiamo:

Scenario Percentile MRR
+20% P05 571.134 €
+10% P95 570.627 €

Il P05 del +20% è superiore al P95 del +10% di circa:

[math]\displaystyle \begin{aligned}
571.134 – 570.627 = 507\,€
\end{aligned}[/math]

Questa vicinanza indica che le distribuzioni sono molto separate nel modello, ma non autorizza a concludere che il +20% abbia una dominanza stocastica sul +10%.

Per dimostrare dominanza stocastica bisognerebbe confrontare l’intera funzione di distribuzione cumulativa dei due scenari, non soltanto due percentili.

La conclusione prudente è:

Nel modello simulato, persino la fascia bassa del +20% è leggermente superiore alla fascia alta del +10% sui percentili considerati.

È un risultato interessante, ma non una prova generale di superiorità del +20%.

Probability of Loss: lo zero va interpretato con cautela

La colonna Probability of loss è pari a zero per tutti gli scenari dal +5% al +20%.

Questo significa che, nelle simulazioni effettuate, nessun risultato di Gross Profit cumulato dello scenario repriced è stato inferiore al risultato corrispondente del baseline.

Non significa che:

  • il rischio reale sia nullo;
  • il repricing sia certamente conveniente;
  • il +20% sia privo di downside;
  • il modello abbia stimato una probabilità reale esattamente pari a zero.
Leggi anche 👉  Embedded Finance: cos’è, come funziona, esempi B2B e strategie di monetizzazione

La formulazione più corretta è:

Su 1.000 simulazioni non sono stati osservati casi di Gross Profit cumulato inferiore al baseline.

Il risultato può dipendere da diverse caratteristiche del modello:

  1. la griglia di prezzo termina al +20%;
  2. la WTP potrebbe essere troppo elevata;
  3. la sensibilità potrebbe essere troppo bassa;
  4. non esiste contraction MRR;
  5. non sono presenti shock comuni;
  6. il margine è costante;
  7. non sono inclusi costi aggiuntivi di retention;
  8. i rinnovi annuali non sono modellati.

Inoltre, con 1.000 simulazioni, lo zero ha una risoluzione limitata. Non possiamo distinguere bene tra:

  • rischio effettivamente nullo;
  • rischio molto basso;
  • rischio non osservato casualmente nel campione.

Questa colonna è quindi più utile come segnale diagnostico del modello che come misura definitiva del rischio aziendale.

Il principale risultato manageriale

La tabella mostra una situazione precisa:

Nel range simulato, il repricing aumenta il valore medio, ma con rendimenti marginali decrescenti e maggiore dispersione.

Questa conclusione è più importante del fatto che il +20% sia l’ultimo e quindi il più alto scenario osservato.

Il modello descrive una curva con questa forma qualitativa:

[math]\displaystyle \begin{aligned}
Prezzo \uparrow &\Rightarrow MRR \uparrow \\
Prezzo \uparrow &\Rightarrow Gross\ Profit \uparrow \\
Prezzo \uparrow &\Rightarrow Beneficio\ marginale \downarrow \\
Prezzo \uparrow &\Rightarrow Dispersione \uparrow
\end{aligned}[/math]

La situazione può essere rappresentata così:

  • fino al +20%, il beneficio medio è positivo;
  • ogni incremento aggiuntivo produce meno valore del precedente;
  • il rischio di variabilità aumenta;
  • non è ancora osservato il punto in cui il Gross Profit inizia a diminuire.

Quindi non abbiamo ancora trovato il limite del pricing power. Abbiamo soltanto osservato che il pricing power, nel modello, non è illimitato né lineare.

Cosa manca per una decisione reale

L’output è utile, ma non è sufficiente per decidere il nuovo listino.

Mancano almeno queste informazioni:

Numero di clienti finali

La tabella mostra l’MRR finale, ma non il numero medio o finale di clienti per scenario.

Sarebbe utile aggiungere:

ending_customers
customer_loss
retention_rate

In questo modo si potrebbe capire se il +20% genera più MRR perché il prezzo è molto più alto oppure perché la perdita di clienti è contenuta.

Churn aggregato e churn per segmento

L’output non mostra quanto dello stress derivi da Starter, Growth o Enterprise.

Sarebbe importante riportare:

  • churn Starter;
  • churn Growth;
  • churn Enterprise;
  • clienti persi per segmento;
  • MRR perso per segmento.

Un aumento uniforme può risultare positivo a livello aggregato anche se distrugge valore nello Starter.

Contraction MRR

Il modello assume che il cliente rimanga attivo allo stesso valore oppure abbandoni completamente.

Nella realtà, il comportamento intermedio può essere molto importante:

Active → Active con meno seat
Active → Piano inferiore
Active → Sconto
Active → Riduzione del volume

L’assenza di contraction tende a rendere il modello meno realistico per il B2B SaaS.

Rinnovi annuali

Per un portafoglio annuale, il cliente potrebbe non reagire per undici mesi. La decisione avviene al rinnovo.

Senza calendario dei rinnovi, l’output può attribuire troppo presto lo stress di prezzo oppure distribuirlo in modo non realistico.

Nuovi clienti e conversione

Il modello considera soltanto la customer base esistente. Non considera l’effetto del nuovo prezzo su:

  • tasso di conversione;
  • nuovi clienti;
  • CAC;
  • volume di pipeline;
  • posizionamento competitivo;
  • mix delle nuove acquisizioni.

Il risultato è quindi una valutazione del valore della base esistente, non del business complessivo.

Interpretazione finale per scenario

Scenario +0%

È il baseline simulato.

Produce 536.569 euro di MRR finale medio e 6,007 milioni di Gross Profit cumulato. Serve come riferimento per valutare gli scenari di repricing.

Scenario +5%

Genera 12.882 euro di MRR finale medio aggiuntivo e 212.764 euro di Gross Profit cumulato aggiuntivo.

È l’aumento con il miglior incremento marginale tra quelli testati. Può essere interessante se l’azienda privilegia prudenza, stabilità e facilità di esecuzione.

Scenario +10%

Genera 25.048 euro di MRR finale aggiuntivo e 419.679 euro di Gross Profit cumulato aggiuntivo rispetto al baseline.

Rappresenta un compromesso intermedio tra monetizzazione e rischio di reazione della customer base.

Scenario +15%

Genera 35.459 euro di MRR finale aggiuntivo e 610.312 euro di Gross Profit cumulato aggiuntivo.

Il beneficio rimane consistente, ma il rendimento per ulteriore punto percentuale continua a ridursi.

Scenario +20%

È il migliore tra gli scenari testati:

  • MRR finale medio: 581.012 euro;
  • Gross Profit cumulato medio: 6,801 milioni di euro;
  • incremento del Gross Profit rispetto al baseline: 793.606 euro;
  • incremento percentuale del Gross Profit: 13,21%;
  • maggiore dispersione tra P05 e P95.

È quindi il candidato più aggressivo, non necessariamente la scelta migliore.

Potrebbe essere preferibile soltanto se l’azienda è disposta ad accettare:

  • maggiore variabilità;
  • rischio di churn più alto;
  • maggiore pressione su Customer Success;
  • possibili negoziazioni e sconti;
  • un piano di monitoraggio e rollback.

Conclusione

L’output non dimostra semplicemente che “aumentare i prezzi conviene”.

Dimostra qualcosa di più preciso:

Date le ipotesi del modello, tutti gli aumenti fino al 20% migliorano il Gross Profit cumulato medio, ma ogni ulteriore aumento produce un beneficio marginale più piccolo e una distribuzione più dispersa.

Il +20% produce il valore medio più alto perché è l’ultimo scenario testato. Non è ancora il prezzo ottimale.

Il risultato più utile per il management è quindi la combinazione:

[math]\displaystyle \begin{aligned}
Valore\ atteso &\uparrow \\
Beneficio\ marginale &\downarrow \\
Dispersione &\uparrow \\
Rischio\ osservato &\approx 0\%\ nel\ modello
\end{aligned}[/math]

L’ultima riga deve essere interpretata con particolare cautela. Il rischio osservato pari a zero non significa che il repricing sia privo di rischio. Significa che, con queste ipotesi, questo numero di simulazioni e questo intervallo di prezzo, non sono stati generati risultati peggiori del baseline.

La decisione reale dovrebbe quindi basarsi su una versione estesa del modello che includa:

  • churn e retention per segmento;
  • contraction ed expansion;
  • rinnovi annuali;
  • costi di retention;
  • nuovi clienti e conversione;
  • scenari oltre il +20%;
  • stress test su WTP e churn;
  • guardrail operativi post-lancio.

In sintesi:

Il modello sostiene il repricing nel perimetro analizzato, ma non autorizza ancora a concludere che il +20% sia il prezzo giusto.

📚Customer Economics, churn e metriche SaaS

La crescita di un business SaaS non si misura soltanto da quanti nuovi clienti vengono acquisiti. CAC, LTV, churn, retention e NRR permettono di collegare acquisizione, valore del cliente e sostenibilità economica. Questi approfondimenti affrontano il tema sia dal punto di vista manageriale sia attraverso modelli pratici in Excel e Python.

👉Unit Economics SaaS: come NDR, LTV, CAC e CAC Payback misurano la vera crescita aziendale

👉Customer Economics nel SaaS: perché LTV, retention e NRR contano più del costo di acquisizione CAC

👉Churn Rate: cos’è, come calcolarlo e strategie per ridurlo con modello Excel

👉Analisi avanzata di Churn Rate e CLV: modello Python ed Excel per ottimizzare la retention clienti

Pubblicità

You may also like...