72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""Deterministic DCF report helpers for the valuation_review skill."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Iterable
|
|
|
|
|
|
def build_dcf_report(rows: Iterable[dict], current_date: str) -> str:
|
|
"""Render a DCF valuation report from normalized row inputs."""
|
|
lines = [f"=== DCF Valuation Analysis ({current_date}) ===\n"]
|
|
|
|
for row in rows:
|
|
error = row.get("error")
|
|
ticker = row["ticker"]
|
|
if error:
|
|
lines.append(f"{ticker}: {error}\n")
|
|
continue
|
|
|
|
current_fcf = float(row["current_fcf"])
|
|
growth_rate = float(row["growth_rate"])
|
|
market_cap = float(row["market_cap"])
|
|
discount_rate = float(row.get("discount_rate", 0.10))
|
|
terminal_growth = float(row.get("terminal_growth", 0.03))
|
|
num_years = int(row.get("num_years", 5))
|
|
|
|
pv_fcf = sum(
|
|
current_fcf
|
|
* (1 + growth_rate) ** year
|
|
/ (1 + discount_rate) ** year
|
|
for year in range(1, num_years + 1)
|
|
)
|
|
terminal_fcf = (
|
|
current_fcf
|
|
* (1 + growth_rate) ** num_years
|
|
* (1 + terminal_growth)
|
|
)
|
|
terminal_value = terminal_fcf / (discount_rate - terminal_growth)
|
|
pv_terminal = terminal_value / (1 + discount_rate) ** num_years
|
|
enterprise_value = pv_fcf + pv_terminal
|
|
value_gap = (enterprise_value - market_cap) / market_cap * 100
|
|
|
|
if value_gap > 20:
|
|
assessment = "SIGNIFICANTLY UNDERVALUED"
|
|
elif value_gap > 0:
|
|
assessment = "POTENTIALLY UNDERVALUED"
|
|
elif value_gap > -20:
|
|
assessment = "POTENTIALLY OVERVALUED"
|
|
else:
|
|
assessment = "SIGNIFICANTLY OVERVALUED"
|
|
|
|
lines.append(f"{ticker}:")
|
|
lines.append(f" Current FCF: ${current_fcf:,.0f}")
|
|
lines.append(f" DCF Enterprise Value: ${enterprise_value:,.0f}")
|
|
lines.append(f" Market Cap: ${market_cap:,.0f}")
|
|
lines.append(f" Value Gap: {value_gap:+.1f}% -> {assessment}")
|
|
lines.append("")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main() -> None:
|
|
"""Read normalized rows from stdin and emit a text report."""
|
|
payload = json.load(__import__("sys").stdin)
|
|
print(build_dcf_report(payload["rows"], payload["current_date"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|