diff options
Diffstat (limited to 'backend/tests/test_wacc.py')
| -rw-r--r-- | backend/tests/test_wacc.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/backend/tests/test_wacc.py b/backend/tests/test_wacc.py new file mode 100644 index 0000000..a7dffcd --- /dev/null +++ b/backend/tests/test_wacc.py @@ -0,0 +1,102 @@ +import pandas as pd +import pytest + +from app import main +from app.services import data_service + + +def quarterly_frame(rows: dict[str, list[float]]) -> pd.DataFrame: + columns = pd.to_datetime(["2025-12-31", "2025-09-30", "2025-06-30", "2025-03-31"]) + return pd.DataFrame(rows, index=columns).T + + +def test_ticker_wacc_computes_capm_wacc_when_data_is_available(monkeypatch: pytest.MonkeyPatch) -> None: + # Given: WACC inputs matching the reference Excel sheet. + data_service.WACC_CACHE.clear() + monkeypatch.setattr( + data_service, + "get_company_info", + lambda symbol: {"beta": 0.98, "marketCap": 45_500_000_000.0}, + ) + monkeypatch.setattr(data_service, "get_fast_info", lambda symbol: {}) + monkeypatch.setattr( + data_service, + "get_balance_sheet", + lambda symbol, quarterly=False: quarterly_frame( + { + "Total Debt": [724_000_000.0] * 4, + "Cash And Cash Equivalents": [795_000_000.0] * 4, + } + ), + ) + monkeypatch.setattr( + data_service, + "get_income_statement", + lambda symbol, quarterly=False: quarterly_frame( + { + "Interest Expense": [8_145_000.0] * 4, + "Tax Provision": [25_000_000.0] * 4, + "Pretax Income": [100_000_000.0] * 4, + } + ), + ) + + # When: the public route function is called. + result = main.ticker_wacc("ref") + + # Then: it returns the CAPM WACC and all major inputs without live yfinance calls. + assert result["symbol"] == "REF" + assert result["available"] is True + assert result["wacc"] == pytest.approx(0.0979) + assert result["cost_of_equity"] == pytest.approx(0.0979) + assert result["cost_of_debt"] == pytest.approx(0.045) + assert result["tax_rate"] == pytest.approx(0.25) + assert result["currency"] == "USD" + assert result["currency_warning"] is None + assert result["market_cap"] == 45_500_000_000.0 + assert result["total_debt"] == 724_000_000.0 + assert result["cash"] == 795_000_000.0 + + +def test_ticker_wacc_returns_unavailable_when_market_cap_is_missing(monkeypatch: pytest.MonkeyPatch) -> None: + # Given: yfinance helpers return no usable capitalization data. + data_service.WACC_CACHE.clear() + monkeypatch.setattr(data_service, "get_company_info", lambda symbol: {}) + monkeypatch.setattr(data_service, "get_fast_info", lambda symbol: {}) + monkeypatch.setattr(data_service, "get_balance_sheet", lambda symbol, quarterly=False: pd.DataFrame()) + monkeypatch.setattr(data_service, "get_income_statement", lambda symbol, quarterly=False: pd.DataFrame()) + + # When: the public route function is called for an invalid symbol. + result = main.ticker_wacc("missing") + + # Then: the API responds gracefully with fallback assumptions and no WACC. + assert result["symbol"] == "MISSING" + assert result["available"] is False + assert result["wacc"] is None + assert result["risk_free_rate"] == 0.044 + assert result["beta"] == 1.0 + assert result["equity_risk_premium"] == 0.055 + assert result["cost_of_debt"] == 0.05 + assert result["tax_rate"] == 0.21 + assert result["currency"] == "USD" + assert result["currency_warning"] is None + assert result["market_cap"] is None + + +def test_wacc_currency_warning_when_mismatch(monkeypatch: pytest.MonkeyPatch) -> None: + data_service.WACC_CACHE.clear() + monkeypatch.setattr( + data_service, + "get_company_info", + lambda symbol: {"financialCurrency": "CAD", "currency": "USD", "marketCap": 45_500_000_000.0, "beta": 0.98}, + ) + monkeypatch.setattr(data_service, "get_fast_info", lambda symbol: {"currency": "USD"}) + monkeypatch.setattr(data_service, "get_balance_sheet", lambda symbol, quarterly=False: pd.DataFrame()) + monkeypatch.setattr(data_service, "get_income_statement", lambda symbol, quarterly=False: pd.DataFrame()) + + result = main.ticker_wacc("CCJ") + + assert result["currency"] == "CAD" + assert isinstance(result["currency_warning"], str) + assert "USD" in result["currency_warning"] + assert "CAD" in result["currency_warning"] |
