Zum Inhalt

Immohai Modell-Spezifikation

Status: verbindlich Dokumenttyp: führende fachliche Modell-Spezifikation Spezifikationsversion: 1.1.1 Modellversion: 0.6.2 Stand: 2026-07-05

1. Zweck und Rang

Diese Datei ist die führende Wahrheit für:

Berechnungslogik
Annahmenauflösung
Szenarien
Jahresprojektion
ETF-Vergleich
KPIs
KPI-Assessments
Case Ratings
Investment Rating
Plausibilitätschecks
Modellgrenzen

Feldverträge stehen in docs/specification/data-quality-and-validation/data-model.md. Übergänge zwischen Eingabe, Szenarioauflösung, Engine, Speicherung und Reporting stehen in docs/specification/model-and-calculations/calculation-interfaces.md. Diese Dokumente dürfen keine abweichenden Formeln oder Schwellen definieren.

2. Quellenhierarchie

1. docs/calculations/model-specification.md
2. docs/specification/data-quality-and-validation/data-model.md
3. docs/specification/model-and-calculations/calculation-interfaces.md
4. weitere führende Spezifikationen des jeweiligen Themas
5. maschinenlesbare Schemas und Modellkonfiguration
6. Implementierung und Tests
7. UI und Reports

UI, Reports, Objektvergleiche und Batch-Auswertungen dürfen keine eigene Fachlogik definieren.

3. Produktziel und Abgrenzung

Immohai beantwortet:

Lohnt sich der Kauf dieser Immobilie im Vergleich zu einer ETF-Alternative?
Wie hoch sind Eigenkapital-, Darlehens- und Liquiditätsbedarf?
Wie robust ist die Einschätzung unter Best-, Base- und Stress-Annahmen?
Welche Daten, Annahmen und Due-Diligence-Punkte sind noch offen?

Immohai ist:

private Entscheidungsunterstützung
transparentes Rechenmodell
Szenario- und Risikowerkzeug

Immohai ist nicht:

Steuerberatung
Rechtsberatung
Finanzierungszusage
Anlageberatung
Verkehrswertgutachten
technische Gebäudeprüfung
Kaufempfehlung

4. Analysearchitektur

Einzelanalyse ─┐
               ├──> PropertyInput -> ScenarioInput[] -> Single-Property-Engine -> AnalysisResult
Batchanalyse ──┘

Verbindlich:

Nur ein normalisiertes und validiertes PropertyInput wird berechnet.
Rohdaten werden nie direkt berechnet.
Identische PropertyInputs und identische versionierte Konfigurationen liefern identische Ergebnisse.
Batch enthält keine zweite Projektions-, KPI-, Assessment- oder Ratinglogik.

5. Quick Mode und Expert Mode

Quick und Expert Mode verwenden dieselbe Berechnungsengine und dasselbe Datenmodell.

Quick Mode:
  wenige Pflichtangaben
  sichtbare versionierte Defaults
  sichtbare Herkunft und Datenqualität

Expert Mode:
  alle Annahmen sichtbar
  Werte und fachlicher Status überschreibbar
  dieselbe Engine und dieselben Formeln

Es gibt keine vereinfachte Parallelberechnung.

6. Einheiten und Timing

Geld: EUR
Fläche: m²
Miete: EUR pro Monat nettokalt
Prozentsätze: Dezimalbruch
Zeitraum: Jahre
Zahlungen: Jahresende, sofern nicht ausdrücklich anders definiert

Beispiele:

6 % = 0.06
2,0 % = 0.02

7. Kanonische Objektmerkmale

property_category:
  apartment
  single_family_house
  two_family_house
  multi_family_house
  commercial
  mixed_use

rental_strategy:
  standard_rental
  shared_flat
  short_term_rental

construction_status:
  existing
  new_build

object_type_profile ist eine UI- und Eingabehilfe. Neue kanonische Datensätze schreiben zusätzlich die getrennten Dimensionen.

8. Annahmenherkunft und Status

Zulässige Herkunftswerte:

manual
imported
scraped
estimated
derived
default
scenario
object_type_adjusted
missing

Jeder berechnungsrelevante Eingabewert verwendet den Vertrag ValueWithOrigin mit mindestens:

value
unit
origin
source
scenario_policy

Optional:

confidence
note
evidence
value_status

value_status:

final
provisional

Regeln:

origin = missing -> value = null
value = null -> origin = missing
value_status = final -> scenario_policy = fixed
manuelle Eingabe allein bedeutet nicht automatisch final

Ein fehlender Wert darf nicht durch einen scheinbar sicheren Zahlenwert ersetzt werden.

9. Auflösung der Base-Annahmen

Priorität:

1. finaler manueller Expert-Override
2. manuelle Eingabe
3. bewusst übernommener Schätz- oder Importwert
4. Profilwert
5. Objektprofil-Anpassung auf einen Profil- oder Defaultwert
6. globaler Default
7. missing

Verbindliche Regeln:

Ein finaler Wert wird nicht verändert.
Ein manueller Wert wird nicht still ersetzt.
Objektprofil-Anpassungen wirken nur auf Profil- oder Defaultwerte.
derived, estimated, imported und scraped sind nicht objektprofilveränderbar.
Bereits object_type_adjusted markierte Werte werden nicht erneut angepasst.
Base enthält kein Szenario-Delta.

10. Szenario-Policy

Jedes potenziell veränderliche Feld besitzt genau eine Policy:

fixed:
  bleibt in Best, Base und Stress identisch

scenario_adjustable:
  erhält ein versioniertes Best- oder Stress-Delta

sensitivity_only:
  bleibt zwischen Best, Base und Stress identisch
  und wird ausschließlich in einer separaten Sensitivität untersucht

10.1 Mietbasis

current_contract_rent -> fixed
market_rent_estimate -> scenario_adjustable
target_rent -> scenario_adjustable
manual_assumption -> scenario_adjustable, außer value_status = final

10.2 Zinsbasis

binding_offer -> fixed
indicative_market_rate -> scenario_adjustable
manual_assumption -> scenario_adjustable, außer value_status = final

ETF-Rendite ist sensitivity_only.

11. Szenarien und Slider

Verbindliche Reihenfolge:

scenario_order = [Best, Base, Stress]
selected_base_scenario = Base

Base-Overrides sind nicht zulässig.

Zulässige Steuerungsarten:

preset:
  Best und Stress verwenden versionierte scenario-presets.json-Deltas

custom_sliders:
  Nutzerwerte werden vor dem Rechenlauf in PropertyInput.scenarios.controls gespeichert
  und daraus reproduzierbar in Best- und Stress-Deltas übersetzt

Sliderwerte werden niemals direkt aus dem DOM von der Szenarioauflösung gelesen. Das Formular erzeugt zuerst ein vollständiges PropertyInput; danach arbeitet die Szenarioauflösung ausschließlich mit diesem Snapshot.

Aktuelle Sliderdimensionen:

rent_variation_pct
interest_variation_pct
rent_growth_variation_pct
value_growth_variation_pct
inflation_variation_pct
vacancy_variation_pct
capex_variation_pct

Symmetrische Anwendung:

Best Miete          = Base Miete × (1 + rent_variation_pct)
Stress Miete        = Base Miete × (1 - rent_variation_pct)

Best Zins           = Base Zins - interest_variation_pct
Stress Zins         = Base Zins + interest_variation_pct

Best Wachstum       = Base Wachstum + jeweilige Variation
Stress Wachstum     = Base Wachstum - jeweilige Variation

Best Inflation      = Base Inflation - inflation_variation_pct
Stress Inflation    = Base Inflation + inflation_variation_pct

Best Leerstand      = Base Leerstand - vacancy_variation_pct
Stress Leerstand    = Base Leerstand + vacancy_variation_pct

Best CAPEX          = Base CAPEX × (1 - capex_variation_pct)
Stress CAPEX        = Base CAPEX × (1 + capex_variation_pct)

Ergebnisse werden fachlich begrenzt:

Miete >= 0
Zins >= 0
Leerstand zwischen 0 und 1
CAPEX >= 0

Nur scenario_adjustable-Felder erhalten Deltas. Die ETF-Rendite bleibt in Best, Base und Stress identisch.

12. Erwerb und Gesamtinvestition

closing_costs
= purchase_price × closing_costs_pct

total_acquisition_cost
= purchase_price + closing_costs

total_initial_investment
= total_acquisition_cost + initial_renovation_costs

Nicht zulässig:

initial_renovation_costs künstlich in closing_costs_pct einrechnen

13. Eigenkapital und Darlehen

equity_contributed
= min(requested_equity_contribution, total_initial_investment)

excess_available_equity
= max(0, requested_equity_contribution - total_initial_investment)

loan_amount
= max(0, total_initial_investment - equity_contributed)

non_purchase_costs_financed_amount
= max(0, loan_amount - purchase_price)

non_purchase_costs_financed_amount ist ein Bankfähigkeits- und Due-Diligence-Hinweis, keine Rechenlücke.

14. Cash-Reserve nach Kauf

cash_reserve_after_closing ist im Modell 0.6.2 ein Informations- und Due-Diligence-Feld. Es verändert weder equity_contributed noch loan_amount automatisch.

15. LTV

initial_ltv
= loan_amount / purchase_price

current_ltv_y
= debt_end_y / property_value_y

Bankorientierte Schwellen beziehen sich auf initial_ltv. Bei purchase_price <= 0 ist keine Berechnung zulässig.

16. Darlehensmodell

Initialer jährlicher Kapitaldienst:

initial_debt_service
= loan_amount × (interest_initial_pct + amortization_initial_pct)

Je Jahr:

interest_y
= debt_start_y × active_interest_rate_y

principal_y
= min(debt_start_y, max(0, planned_debt_service_y - interest_y))

debt_service_y
= interest_y + principal_y

debt_end_y
= max(0, debt_start_y - principal_y)

Bis einschließlich interest_reset_year gilt der Initialzins und der initiale Kapitaldienst.

Ab dem Folgejahr:

reset_debt_service
= debt_start_reset × (interest_reset_pct + amortization_initial_pct)

Die Berechnung ist eine annuitätsnahe Näherung und kein verbindlicher Bank-Tilgungsplan.

17. Miete

Die Investmentberechnung verwendet ausschließlich monthly_cold_rent.

gross_rent_y
= monthly_cold_rent × 12 × (1 + rent_growth_pct)^(y - 1)

Der tatsächlich verwendete Wert, rent_basis, Herkunft, Confidence, Status und Szenario-Policy bleiben sichtbar.

monthly_rent_market ist ausschließlich ein Legacy-Lesealias.

18. Leerstand

vacancy_loss_y
= gross_rent_y × vacancy_pct

19. Laufende Kosten und CAPEX

19.1 Nicht umlagefähige Betriebskosten

non_recoverable_operating_costs_y
= non_recoverable_operating_costs_pa × (1 + inflation_pct)^(y - 1)

19.2 Reservebeitrag

reserve_contribution_y
= reserve_contribution_pa × (1 + inflation_pct)^(y - 1)

Der Reservebeitrag ist eine tatsächliche laufende Zuführung zu einer WEG- oder Objektreserve.

19.3 Wiederkehrender CAPEX

Methode percent_of_gross_rent:

recurring_capex_y
= gross_rent_y × recurring_capex_pct_of_gross_rent

Methode fixed_annual:

recurring_capex_y
= recurring_capex_fixed_pa × (1 + inflation_pct)^(y - 1)

Genau eine Methode ist aktiv. Das nicht aktive Wertfeld ist 0, null oder abwesend.

19.4 Sonder-CAPEX

special_capex_y
= Summe aller für Jahr y definierten Sondermaßnahmen

special_capex.amount ist ein nominaler Betrag im angegebenen Ereignisjahr und wird nicht automatisch inflationshochgerechnet.

19.5 Doppelzählung

reserve_contribution:
  tatsächlicher laufender Reservebeitrag

recurring_capex:
  zusätzliche laufende Investitionen,
  die nicht durch den Reservebeitrag abgebildet sind

special_capex:
  explizite einmalige Maßnahmen oder Sonderumlagen

Eine Maßnahme darf nicht gleichzeitig in mehreren Positionen enthalten sein.

20. NOI

noi_y
= gross_rent_y
- vacancy_loss_y
- non_recoverable_operating_costs_y

Reserve, wiederkehrender CAPEX, Sonder-CAPEX und Finanzierung gehören nicht in den NOI.

21. DSCR

dscr_numerator_y
= noi_y - reserve_contribution_y

dscr_y
= dscr_numerator_y / debt_service_y

Bei debt_service_y = 0 ist DSCR null beziehungsweise not_applicable, sofern kein Darlehen besteht.

loan_amount > 0 und debt_service_y1 <= 0
-> LOAN_WITHOUT_DEBT_SERVICE
-> kritischer Finanzierungsbefund

22. Cashflow vor Steuer

cashflow_before_tax_y
= noi_y
- reserve_contribution_y
- recurring_capex_y
- special_capex_y
- debt_service_y

Cashflow vor Steuer ist die Haupt-Cashflowkennzahl des MVP.

23. Liquiditätsbedarf

annual_support_required_y
= max(0, -cashflow_before_tax_y)

cumulative_support_required_y
= Summe annual_support_required bis Jahr y

Positive Cashflows reduzieren den bereits ausgewiesenen kumulativen Zuschussbedarf nicht rückwirkend.

24. ETF-Alternative

Die ETF-Alternative erhält:

dasselbe eingesetzte Anfangseigenkapital
dieselben negativen Nachschüsse
jährliche Verzinsung mit etf_return_pct

Start:

etf_value_0 = equity_contributed

Je Jahr:

etf_value_y
= etf_value_(y-1) × (1 + etf_return_pct)
+ annual_support_required_y

Die jährliche Einzahlung erfolgt modellhaft am Jahresende.

25. Side Account

Positive Immobilien-Cashflows werden nicht konsumiert, sondern im Side Account mit derselben ETF-Rendite angelegt.

positive_cashflow_y
= max(0, cashflow_before_tax_y)

side_account_y
= side_account_(y-1) × (1 + etf_return_pct)
+ positive_cashflow_y

26. Immobilienwert und Vermögen vor Exit

property_value_y
= purchase_price × (1 + value_growth_pct)^y

property_equity_value_y
= property_value_y - debt_end_y

property_wealth_before_exit_y
= property_equity_value_y + side_account_y

net_vs_etf_before_exit_y
= property_wealth_before_exit_y - etf_value_y

27. Exit

selling_costs_y
= property_value_y × selling_costs_pct

net_sale_proceeds_y
= property_value_y
- selling_costs_y
- debt_end_y

terminal_property_wealth_y
= net_sale_proceeds_y + side_account_y

terminal_net_vs_etf_y
= terminal_property_wealth_y - etf_value_y

Hauptkennzahl:

terminal_net_vs_etf_after_exit

Zusätzlich darf net_vs_etf_before_exit_end angezeigt werden. Spekulationssteuer ist nicht Teil des MVP.

28. Zeitkennzahlen

first_positive_cashflow_year:
  erstes Jahr mit cashflow_before_tax_y > 0

durable_self_funding_year:
  erstes Jahr, ab dem cashflow_before_tax bis zum Betrachtungsende positiv bleibt

first_etf_break_even_year:
  erstes Jahr mit terminal_net_vs_etf_y > 0

durable_etf_break_even_year:
  erstes Jahr, ab dem terminal_net_vs_etf bis zum Betrachtungsende positiv bleibt

ETF-Break-even unterstellt einen hypothetischen Verkauf zum jeweiligen Jahresende einschließlich Verkaufskosten und Restschuld.

durable_self_funding_year ist informativ und kein eigenständiger harter Ratingtreiber.

29. Renditekennzahlen

gross_yield_y1
= gross_rent_y1 / purchase_price

noi_yield_y1
= noi_y1 / total_initial_investment

net_yield_before_financing_y1 ist nur ein Legacy-Lesealias.

30. Kanonische Mindest-KPIs

purchase_price_per_sqm
rent_per_sqm_month
closing_costs
total_acquisition_cost
total_initial_investment
requested_equity_contribution
equity_contributed
excess_available_equity
loan_amount
non_purchase_costs_financed_amount
initial_ltv
current_ltv_y1
gross_rent_y1
gross_yield_y1
noi_yield_y1
purchase_price_factor
noi_y1
reserve_contribution_y1
recurring_capex_y1
debt_service_y1
dscr_y1
cashflow_before_tax_y1
minimum_cashflow
cumulative_support_required
first_positive_cashflow_year
durable_self_funding_year
property_wealth_before_exit_end
terminal_property_wealth_end
etf_value_end
net_vs_etf_before_exit_end
terminal_net_vs_etf_after_exit
first_etf_break_even_year
durable_etf_break_even_year
selling_costs_end
data_quality_score

annual_gross_rent_y1 ist ausschließlich ein Legacy-Lesealias für gross_rent_y1.

31. KPI-Assessments

Zulässige Statuswerte:

good
borderline
critical
not_applicable
insufficient
neutral

31.1 Cashflow

good:
  cashflow >= 0

borderline:
  cashflow < 0
  und Zuschussbedarf <= 10 % gross_rent_y1

critical:
  Zuschussbedarf > 10 % gross_rent_y1

31.2 Kumulativer Zuschussbedarf

Bei equity_contributed > 0:

good:       0
borderline: > 0 und <= 50 % equity_contributed
critical:   > 50 % equity_contributed

Bei equity_contributed = 0:

good:     cumulative_support_required = 0
critical: cumulative_support_required > 0

Es gibt bei null eingesetztem Eigenkapital keinen prozentualen Ersatznenner und keinen stillen 1-EUR-Ersatz.

31.3 DSCR

not_applicable:
  loan_amount = 0

good:
  debt_service > 0 und dscr >= 1.20

borderline:
  debt_service > 0 und 1.00 <= dscr < 1.20

critical:
  Darlehen ohne Kapitaldienst
  oder dscr < 1.00

31.4 Anfangs-LTV

not_applicable:
  loan_amount = 0

good:
  <= 0.80

borderline:
  > 0.80 und <= 1.00

critical:
  > 1.00

31.5 Terminaler ETF-Vergleich

Bei equity_contributed > 0:

good:       terminal_net_vs_etf_after_exit > 0
borderline: -25 % equity_contributed <= Wert <= 0
critical:   Wert < -25 % equity_contributed

Bei equity_contributed = 0:

good:       Wert > 0
borderline: Wert = 0
critical:   Wert < 0

32. ScenarioAssessment und Case Rating

Jedes Szenario erhält ein ScenarioAssessment:

cashflow_status
dscr_status
liquidity_status
terminal_etf_status
critical_findings

Jedes Szenario erhält zusätzlich ein sichtbares ScenarioRating:

GREEN
YELLOW
RED
UNRATED

Das Case Rating:

bewertet ausschließlich den jeweiligen Case
wird im Szenariovergleich angezeigt
beeinflusst keine andere Berechnung
ersetzt nicht das Investment Rating

Case-RED gilt bei mindestens einem harten Case-Befund:

Darlehen ohne Kapitaldienst
DSCR < 1.00 bei Darlehen
initial_ltv > 1.00
kritischer Liquiditätsbefund
kritischer terminaler ETF-Vergleich nach den Null-/Positiv-Eigenkapitalregeln

Case-GREEN setzt gute Cashflow-, Finanzierungs-, Liquiditäts-, ETF- und Datenqualitätsbefunde voraus. Sonst gilt ohne harten kritischen Befund YELLOW.

33. Investment Rating

Das vollständige InvestmentRating wird genau einmal auf Ebene AnalysisResult erzeugt.

GREEN
YELLOW
RED
UNRATED

Komponenten:

profitability
liquidity
financing
robustness
data_quality

Base liefert Profitability, Liquidity und Financing. Stress liefert die Robustness-Komponente. Best ist informativ und beeinflusst das Investment Rating nicht.

34. Datenqualität

Führende Methode:

docs/specification/data-quality-and-validation/data-quality-assessment.md
data_quality_score = null
oder data_quality_score < 50
-> InvestmentRating = UNRATED
-> ScenarioRating = UNRATED

Schwellen:

good:         score >= 75
borderline:   50 <= score < 75
insufficient: score < 50 oder Score fehlt

Datenqualität verändert keine Finanzformel.

35. Rating-Komponenten

35.1 Profitability

Primär: terminal_net_vs_etf_after_exit gemäß Abschnitt 31.5.

35.2 Liquidity

Bei equity_contributed > 0:

critical:
  cumulative_support_required > 50 % equity_contributed
  oder minimum_cashflow < -20 % gross_rent_y1

borderline:
  cumulative_support_required > 0
  oder cashflow_before_tax_y1 < 0

good:
  kein laufender Zuschussbedarf

Bei equity_contributed = 0 ist jeder positive kumulative Zuschussbedarf kritisch.

35.3 Financing

critical:
  initial_ltv > 1.00
  oder dscr_y1 < 1.00
  oder Darlehen ohne Kapitaldienst

borderline:
  initial_ltv > 0.80
  oder dscr_y1 < 1.20
  oder non_purchase_costs_financed_amount > 0

good:
  ausreichender LTV- und DSCR-Puffer

not_applicable:
  kein Darlehen

35.4 Robustness

Bei Base-equity_contributed > 0:

critical:
  Stress-Darlehen ohne Kapitaldienst
  oder Stress-DSCR < 1.00 bei Darlehen
  oder Stress-Zuschussbedarf > 100 % Base-equity_contributed
  oder Stress terminal_net_vs_etf_after_exit < -50 % Base-equity_contributed

borderline:
  Stress-Cashflow Jahr 1 < 0
  oder Stress-Zuschussbedarf > 50 % Base-equity_contributed
  oder Stress terminal_net_vs_etf_after_exit < 0

good:
  kein borderline oder critical Stress-Befund

Bei Base-equity_contributed = 0:

critical:
  Stress-Darlehen ohne Kapitaldienst
  oder Stress-DSCR < 1.00 bei Darlehen
  oder Stress-Zuschussbedarf > 0
  oder Stress terminal_net_vs_etf_after_exit < 0

35.5 Data Quality

Bewertung gemäß Abschnitt 34.

36. Harte Investment-Ratingregeln

36.1 UNRATED

Datenqualität fehlt
oder data_quality_score < 50

UNRATED wird vor RED, YELLOW und GREEN geprüft.

36.2 RED

Mindestens einer der folgenden Befunde führt zu RED:

Darlehen vorhanden und Base debt_service_y1 <= 0
Darlehen vorhanden und Base DSCR < 1.00
initial_ltv > 1.00
kritischer terminaler ETF-Nachteil gemäß Abschnitt 31.5
kritischer Liquiditätsbefund
kritischer Stressbefund

Es gibt keine zusätzliche nicht definierte Regel „mehrere kritische Komponenten“.

36.3 GREEN

GREEN ist nur zulässig, wenn:

Cashflow Jahr 1 >= 0
DSCR >= 1.20 oder not_applicable
initial_ltv <= 0.80 oder not_applicable
terminal_net_vs_etf_after_exit > 0
Stress ohne kritischen oder grenzwertigen Befund
Datenqualität >= 75
keine andere Komponente borderline oder critical

36.4 YELLOW

YELLOW gilt bei gemischten oder grenzwertigen Befunden ohne harten kritischen Befund.

Ein positiver Einzel-KPI überdeckt keinen harten kritischen Befund.

37. Plausibilitätschecks

Plausibilitätschecks erzeugen Warnungen und offene Prüfungen. Sie verändern Formeln und Rating nicht, sofern ein Check nicht zugleich eine ausdrücklich definierte Ratingregel abbildet.

Severity:

info
warning
critical

Aktive MVP-Checks:

LOW_PRICE_PER_SQM:                    purchase_price_per_sqm < 1.000 -> warning
HIGH_PRICE_PER_SQM:                   purchase_price_per_sqm > 20.000 -> warning
VERY_HIGH_PRICE_PER_SQM:              purchase_price_per_sqm > 30.000 -> critical
LOW_RENT_PER_SQM:                     rent_per_sqm_month < 5 -> warning
HIGH_RENT_PER_SQM:                    rent_per_sqm_month > 40 -> warning
VERY_HIGH_RENT_PER_SQM:               rent_per_sqm_month > 60 -> critical
LOW_GROSS_YIELD:                      gross_yield_y1 < 1,5 % -> warning
HIGH_GROSS_YIELD:                     gross_yield_y1 > 8 % -> warning
VERY_HIGH_GROSS_YIELD:                gross_yield_y1 > 12 % -> critical
LOW_PURCHASE_PRICE_FACTOR:            purchase_price_factor < 12 -> warning
HIGH_PURCHASE_PRICE_FACTOR:           purchase_price_factor > 45 -> warning
EQUITY_EXCEEDS_TOTAL_INITIAL_INVESTMENT: excess_available_equity > 0 -> info
NON_PURCHASE_COSTS_FINANCED:           non_purchase_costs_financed_amount > 0 -> warning
DATA_QUALITY_NOT_ASSESSED:             data_quality_score = null -> warning
DEBT_FREE_CASE:                        loan_amount = 0 -> info
LOAN_WITHOUT_DEBT_SERVICE:             loan_amount > 0 und debt_service_y1 <= 0 -> critical
INITIAL_LTV_ABOVE_100:                 initial_ltv > 1.00 -> warning
INITIAL_LTV_ABOVE_110:                 initial_ltv > 1.10 -> critical
DSCR_BELOW_100:                        0.80 <= dscr_y1 < 1.00 -> warning
DSCR_BELOW_080:                        dscr_y1 < 0.80 -> critical
HIGH_CUMULATIVE_SUPPORT_REQUIRED:      Zuschuss > 50 % Eigenkapital -> warning
VERY_HIGH_CUMULATIVE_SUPPORT_REQUIRED: Zuschuss > 100 % Eigenkapital -> critical
SUPPORT_REQUIRED_WITHOUT_INITIAL_EQUITY: Eigenkapital = 0 und Zuschuss > 0 -> critical

Plausibilitätsgrenzen sind transparente MVP-Heuristiken und keine Marktwert-, Bank- oder Anlageberatung.

38. Ergebnisstrukturen

PropertyInput
ScenarioInput
AnnualProjectionRow
ScenarioAssessment
ScenarioRating
ScenarioResult
AnalysisResult
PropertyRecord

Der verbindliche Feldvertrag steht in docs/specification/data-quality-and-validation/data-model.md.

Für AnalysisResult gilt insbesondere:

property_input ist die unveränderbare Kopie des berechneten PropertyInput
property_input_id stimmt mit property_input.meta.property_input_id überein
property_input_schema_version ist eindeutig benannt
analysis_data_quality_method_version wird gespeichert
investment_rating existiert nur auf AnalysisResult-Ebene

39. Speicherung und Reporting

Eine Berechnung wird nicht automatisch gespeichert.

AnalysisResult
-> bewusste Nutzeraktion
-> PropertyRecord

Zulässige Reportquellen:

Reportvorschau aus aktuellem AnalysisResult-Snapshot
Gespeicherter Bericht aus PropertyRecord-Snapshot
Vergleich aus PropertyRecord-Snapshots

Reports und Vergleiche berechnen keine Fachwerte neu. Unberechnete Formularwerte werden nicht mit älteren Ergebnissen gemischt. Alte PropertyRecords werden nicht still aktualisiert.

40. Referenzmodelle

Excel, Python, JSON und CSV dienen als:

Plausibilitätsvergleich
Regressionsquelle
Testfallquelle
fachliche Ideengeber

Sie sind keine normative Modellwahrheit.

Insbesondere werden nicht blind übernommen:

absolute Szenariomieten
ETF-Renditen, die zwischen Best, Base und Stress wechseln
CAPEX als pauschaler Anteil des Immobilienwerts
abweichende Tilgungslogik
abweichendes Cashflow-Timing
fehlende Verkaufskosten

41. Modellgrenzen

Nicht Teil des deterministischen MVP:

steuerliche Detailberatung
Spekulationssteuer
detaillierter Bank-Tilgungsplan
verbindliche Finanzierungsprüfung
technische Gebäudeprüfung
Verkehrswertgutachten
rechtliche Prüfung zulässiger Mieten
Monte Carlo in der produktiven App
automatische Plattformanbindung

Steuerfelder dürfen als inaktive Metadaten vorhanden sein, werden in Modell 0.6.2 aber nicht berechnet.