summaryrefslogtreecommitdiff
path: root/backend/tests
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-18 01:27:30 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-18 01:27:30 -0700
commit0811b116b992ac977630c7deb687f995d89dc9a6 (patch)
tree1909e37f58b5e52e700f9049f02ff06d2bbcb00b /backend/tests
parent23fcb2087473d13fa0bcc9adf3f0e10039f249fb (diff)
feat: add _run_dcf, _run_ev_ebitda, _run_ev_revenue, _run_price_to_book
Diffstat (limited to 'backend/tests')
-rw-r--r--backend/tests/test_api.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py
index a5c4eb5..8c7edb8 100644
--- a/backend/tests/test_api.py
+++ b/backend/tests/test_api.py
@@ -684,3 +684,107 @@ def test_dcf_capped_growth_rate_skips_sign_flip() -> None:
series = pd.Series([-10.0, 20.0], index=pd.to_datetime(["2022", "2023"]))
result = data_service._dcf_capped_growth_rate(series)
assert result is None
+
+
+def test_run_dcf_happy_path() -> None:
+ import pandas as pd
+ fcf = pd.Series(
+ [70.0, 80.0, 90.0, 100.0],
+ index=pd.to_datetime(["2021", "2022", "2023", "2024"]),
+ )
+ result = data_service._run_dcf(fcf, shares_outstanding=1_000_000_000.0)
+ assert "intrinsic_value_per_share" in result
+ assert result["intrinsic_value_per_share"] > 0
+ assert "growth_rate_used" in result
+ assert "enterprise_value" in result
+ assert "net_debt" in result
+
+
+def test_run_dcf_negative_base_fcf() -> None:
+ import pandas as pd
+ # last (most recent) FCF is negative
+ fcf = pd.Series(
+ [100.0, 90.0, 80.0, -50.0],
+ index=pd.to_datetime(["2021", "2022", "2023", "2024"]),
+ )
+ result = data_service._run_dcf(fcf, shares_outstanding=1_000_000_000.0)
+ assert "error" in result
+ assert result["error"]
+
+
+def test_run_dcf_insufficient_history() -> None:
+ import pandas as pd
+ fcf = pd.Series([100.0], index=pd.to_datetime(["2024"]))
+ result = data_service._run_dcf(fcf, shares_outstanding=1_000_000_000.0)
+ assert result == {}
+
+
+def test_run_dcf_zero_shares() -> None:
+ import pandas as pd
+ fcf = pd.Series([100.0, 110.0], index=pd.to_datetime(["2023", "2024"]))
+ result = data_service._run_dcf(fcf, shares_outstanding=0.0)
+ assert result == {}
+
+
+def test_run_ev_ebitda_happy_path() -> None:
+ result = data_service._run_ev_ebitda(
+ ebitda=100.0,
+ total_debt=50.0,
+ total_cash=20.0,
+ preferred_equity=0.0,
+ minority_interest=0.0,
+ shares_outstanding=10.0,
+ target_multiple=15.0,
+ )
+ # implied_ev = 100 * 15 = 1500; net_debt = 50-20 = 30; equity = 1470; per_share = 147
+ assert result["implied_price_per_share"] == 147.0
+ assert result["implied_ev"] == 1500.0
+ assert result["net_debt"] == 30.0
+
+
+def test_run_ev_ebitda_zero_ebitda() -> None:
+ result = data_service._run_ev_ebitda(
+ ebitda=0.0, total_debt=0.0, total_cash=0.0,
+ preferred_equity=0.0, minority_interest=0.0,
+ shares_outstanding=10.0, target_multiple=15.0,
+ )
+ assert result == {}
+
+
+def test_run_ev_revenue_happy_path() -> None:
+ result = data_service._run_ev_revenue(
+ revenue=500.0,
+ total_debt=50.0,
+ total_cash=20.0,
+ preferred_equity=0.0,
+ minority_interest=0.0,
+ shares_outstanding=10.0,
+ target_multiple=5.0,
+ )
+ # implied_ev = 500*5 = 2500; net_debt = 30; equity = 2470; per_share = 247
+ assert result["implied_price_per_share"] == 247.0
+
+
+def test_run_ev_revenue_zero_revenue() -> None:
+ result = data_service._run_ev_revenue(
+ revenue=0.0, total_debt=0.0, total_cash=0.0,
+ preferred_equity=0.0, minority_interest=0.0,
+ shares_outstanding=10.0, target_multiple=5.0,
+ )
+ assert result == {}
+
+
+def test_run_price_to_book_happy_path() -> None:
+ result = data_service._run_price_to_book(
+ book_value_per_share=20.0, target_multiple=3.0
+ )
+ assert result["implied_price_per_share"] == 60.0
+ assert result["target_multiple_used"] == 3.0
+ assert result["book_value_per_share"] == 20.0
+
+
+def test_run_price_to_book_zero_bvps() -> None:
+ result = data_service._run_price_to_book(
+ book_value_per_share=0.0, target_multiple=3.0
+ )
+ assert result == {}