Vai al contenuto

Confronto tra tecniche di valore terminale (tv.compare)

Esegue più tecniche di valore terminale su un unico insieme coerente di input e restituisce, affiancati, i valori terminali all'orizzonte N con le ipotesi implicite di ciascuno. La conclusione di una valutazione dipende spesso più dalla tecnica che da un singolo input; questo metodo mostra di quanto. La coerenza è garantita dalla struttura: il tasso della fase terminale, il limite alla crescita e l'approccio (asset side o equity side) sono forniti una volta e valgono per ogni tecnica.

Come funziona

Ogni tecnica si scrive {"<id del metodo>": {termini}}, dove i termini sono gli input di quel metodo senza rate e growth_cap:

Tecnica Termini Input comuni utilizzati
tv.gordon growth, next_flow oppure last_flow tasso, limite alla crescita
tv.value_driver nopat_next, growth, ronic tasso, limite alla crescita
tv.h_model last_flow, short_term_growth, long_term_growth, half_life tasso, limite alla crescita
tv.exit_multiple multiple, metric, metric_value, next_flow facoltativo tasso e limite alla crescita quando è fornito next_flow; la grandezza deve essere sull'approccio dichiarato
tv.limited_horizon flow, periods, growth e residual_value facoltativi tasso, limite alla crescita
tv.normalised_income income, capitalisation_rate, basis, growth facoltativo limite alla crescita; il tasso di capitalizzazione resta il proprio; basis deve coincidere con l'approccio dichiarato
tv.liquidation assets, liabilities, liquidation_costs, tax_on_gains, basis nessuno; basis deve coincidere con l'approccio dichiarato

Ogni tecnica è calcolata dal proprio metodo, quindi una riga del confronto coincide con il risultato di quel metodo eseguito da solo. Passaggi e convenzioni di ciascuna tecnica compaiono in explain, preceduti dalla posizione e dall'id, ad esempio [1] tv.gordon: Terminal value at N. La prima tecnica che fallisce restituisce il proprio errore; non ci sono risultati parziali. Una tecnica deve avere esattamente una chiave, l'id del metodo; una voce con più chiavi è rifiutata con un messaggio che le elenca.

Ogni riga riporta method_version, la versione della tecnica che l'ha prodotta. Una modifica numerica in qualsiasi metodo tv.* richiede quindi anche una nuova versione di tv.compare; un test vincola le versioni delle tecniche insieme alla versione di tv.compare.

tv.normalised_income e tv.liquidation dichiarano il proprio basis, confrontato con l'approccio del confronto come per i multipli di uscita (FM-E019 se differiscono). Nel confronto, tv.normalised_income mantiene il proprio tasso di capitalizzazione, che non è il tasso di attualizzazione comune; explain.conventions lo dichiara. Un multiplo di uscita senza next_flow non ha una crescita implicita, quindi non è confrontato con il limite alla crescita; explain.conventions lo dichiara quando si applica.

Esempio

from decimal import Decimal

import fairmark as fm

r = fm.tv.compare(
    "0.10",
    "enterprise",
    [
        {"tv.gordon": {"growth": "0.02", "last_flow": 100}},
        {"tv.value_driver": {"nopat_next": 150, "growth": "0.02", "ronic": "0.12"}},
        {"tv.exit_multiple": {"multiple": "7.5", "metric": "ebitda", "metric_value": 180,
                              "next_flow": 95}},
    ],
    growth_cap="0.03",
)
values = [row["terminal_value"] for row in r.results]
assert r.results[0]["method_version"] == "1"
assert values[0] == Decimal("1275")
assert values[2] == Decimal("1350")
assert round(r.results[2]["output"]["implied_growth"], 6) == Decimal("0.029630")

try:  # il P/E è una grandezza equity side: mai in un confronto asset side
    fm.tv.compare("0.10", "enterprise", [
        {"tv.exit_multiple": {"multiple": 12, "metric": "earnings", "metric_value": 50}},
    ])
except fm.FairmarkError as err:
    assert err.code == "FM-E019"

Input

Campo Significato Default
rate Tasso di attualizzazione della fase terminale, frazione decimale per periodo, comune obbligatorio
basis enterprise oppure equity, comune a tutti i valori terminali confrontati obbligatorio
growth_cap Limite alla crescita perpetua, frazione decimale per periodo, comune nessuno, riportato come assente
techniques Elenco di {"<id del metodo>": {termini}}, almeno uno; una tecnica può comparire più volte obbligatorio

Output

Campo Significato
basis L'approccio dichiarato
results Una riga per tecnica, nell'ordine richiesto: method, method_version, terminal_value e output, l'output della tecnica con le sue ipotesi implicite

Convenzioni (esplicite, riportate in explain.conventions)

Convenzione Opzioni Default
Approccio enterprise oppure equity, dichiarato una volta nessuno: va fornito
Tasso un solo tasso per ogni tecnica che attualizza; il tasso di capitalizzazione di tv.normalised_income resta il proprio nessuno: va fornito
Limite alla crescita un solo valore per ogni tecnica basata sulla crescita, oppure nessuno nessuno, riportato come assente

Errori

Codice Quando
FM-E001 L'elenco delle tecniche è vuoto, una voce ha più di una chiave, l'id di una tecnica è sconosciuto, oppure un campo manca o è sconosciuto
FM-E019 Un multiplo di uscita, un reddito normalizzato o una liquidazione è sull'approccio diverso da quello dichiarato
Qualsiasi codice di una tecnica La prima tecnica che fallisce restituisce il proprio errore (ad esempio FM-E004, FM-E018)

Precisione

Ogni riga ha la precisione del proprio metodo; il confronto non aggiunge calcoli.

Verificato con

  • tests/golden/tv.compare/: sette tecniche su un unico tasso, approccio e limite, ciascun valore atteso calcolato separatamente da uno script indipendente a 50 cifre (scripts/reference_tv.py).
  • Un test Python verifica che ogni riga coincida con il metodo eseguito da solo.