You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fithia2/tests/unit/test_financial_features.py

111 lines
3.5 KiB
Python

"""Unit tests for financial feature calculations."""
import pytest
from libs.oracle_client.models import FinancialDataResponse, FinancialPeriod
TWO_PERIOD_RESPONSE = FinancialDataResponse(
ticker="AAPL",
periods=[
FinancialPeriod(
period="2026-Q1",
period_end="2025-12-28",
revenue=124_300_000_000,
net_income=36_000_000_000,
eps=2.34,
gross_margin=0.472,
operating_margin=0.315,
),
FinancialPeriod(
period="2025-Q4",
period_end="2025-09-27",
revenue=119_600_000_000,
net_income=34_900_000_000,
eps=2.26,
gross_margin=0.461,
operating_margin=0.308,
),
],
)
def test_compute_financial_features_latest_values():
from libs.features.financial_features import compute_financial_features
features = compute_financial_features(TWO_PERIOD_RESPONSE)
assert features["latest_eps"] == pytest.approx(2.34)
assert features["latest_gross_margin"] == pytest.approx(0.472)
assert features["latest_operating_margin"] == pytest.approx(0.315)
def test_eps_growth_qoq():
from libs.features.financial_features import compute_financial_features
features = compute_financial_features(TWO_PERIOD_RESPONSE)
expected = (2.34 - 2.26) / abs(2.26)
assert features["eps_growth_qoq"] == pytest.approx(expected)
def test_revenue_growth_qoq():
from libs.features.financial_features import compute_financial_features
features = compute_financial_features(TWO_PERIOD_RESPONSE)
expected = (124_300_000_000 - 119_600_000_000) / 119_600_000_000
assert features["revenue_growth_qoq"] == pytest.approx(expected)
def test_periods_sorted_by_period_end_descending():
from libs.features.financial_features import compute_financial_features
# Provide periods out of chronological order; latest should still be picked
response = FinancialDataResponse(
ticker="AAPL",
periods=[
FinancialPeriod(period="2025-Q4", period_end="2025-09-27", eps=2.26),
FinancialPeriod(period="2026-Q1", period_end="2025-12-28", eps=2.34),
],
)
features = compute_financial_features(response)
assert features["latest_eps"] == pytest.approx(2.34)
def test_single_period_no_growth_fields():
from libs.features.financial_features import compute_financial_features
response = FinancialDataResponse(
ticker="AAPL",
periods=[
FinancialPeriod(
period="2026-Q1", period_end="2025-12-28", eps=2.34, gross_margin=0.472
)
],
)
features = compute_financial_features(response)
assert features["latest_eps"] == pytest.approx(2.34)
assert features["eps_growth_qoq"] is None
assert features["revenue_growth_qoq"] is None
def test_empty_periods_returns_empty_dict():
from libs.features.financial_features import compute_financial_features
response = FinancialDataResponse(ticker="AAPL", periods=[])
assert compute_financial_features(response) == {}
def test_none_eps_in_prior_skips_growth():
from libs.features.financial_features import compute_financial_features
response = FinancialDataResponse(
ticker="AAPL",
periods=[
FinancialPeriod(period="2026-Q1", period_end="2025-12-28", eps=2.34),
FinancialPeriod(period="2025-Q4", period_end="2025-09-27", eps=None),
],
)
features = compute_financial_features(response)
assert features["eps_growth_qoq"] is None