refactor: reconcile FundamentalsSnapshot to use canonical schema from trading.py

This commit is contained in:
Viktor Barzin 2026-02-23 21:45:18 +00:00
parent aa47e896dd
commit 6f512cf91f
No known key found for this signature in database
GPG key ID: 0EB088298288D958
6 changed files with 40 additions and 55 deletions

View file

@ -28,41 +28,42 @@ class TestFundamentalsSnapshot:
def test_create_with_all_fields(self) -> None:
snap = FundamentalsSnapshot(
ticker="AAPL",
eps=6.57,
eps_ttm=6.57,
pe_ratio=28.3,
peg_ratio=2.1,
revenue_growth=0.08,
revenue_growth_yoy=0.08,
profit_margin=0.26,
debt_to_equity=1.87,
market_cap=2_800_000_000_000.0,
fetched_at=datetime.now(timezone.utc),
)
assert snap.ticker == "AAPL"
assert snap.eps == 6.57
assert snap.eps_ttm == 6.57
assert snap.pe_ratio == 28.3
assert snap.peg_ratio == 2.1
assert snap.revenue_growth == 0.08
assert snap.revenue_growth_yoy == 0.08
assert snap.profit_margin == 0.26
assert snap.debt_to_equity == 1.87
assert snap.market_cap == 2_800_000_000_000.0
assert isinstance(snap.fetched_at, datetime)
def test_create_with_optional_fields_none(self) -> None:
snap = FundamentalsSnapshot(ticker="XYZ")
snap = FundamentalsSnapshot(ticker="XYZ", fetched_at=datetime.now(timezone.utc))
assert snap.ticker == "XYZ"
assert snap.eps is None
assert snap.eps_ttm is None
assert snap.pe_ratio is None
assert snap.peg_ratio is None
assert snap.revenue_growth is None
assert snap.revenue_growth_yoy is None
assert snap.profit_margin is None
assert snap.debt_to_equity is None
assert snap.market_cap is None
def test_serialization_round_trip(self) -> None:
snap = FundamentalsSnapshot(ticker="MSFT", eps=11.0, pe_ratio=35.0)
snap = FundamentalsSnapshot(ticker="MSFT", eps_ttm=11.0, pe_ratio=35.0, fetched_at=datetime.now(timezone.utc))
data = snap.model_dump()
rebuilt = FundamentalsSnapshot.model_validate(data)
assert rebuilt.ticker == "MSFT"
assert rebuilt.eps == 11.0
assert rebuilt.eps_ttm == 11.0
assert rebuilt.pe_ratio == 35.0
@ -134,10 +135,10 @@ class TestAlphaVantageProvider:
assert result is not None
assert result.ticker == "AAPL"
assert result.eps == 6.57
assert result.eps_ttm == 6.57
assert result.pe_ratio == 28.3
assert result.peg_ratio == 2.1
assert result.revenue_growth == 0.08
assert result.revenue_growth_yoy == 0.08
assert result.profit_margin == 0.26
assert result.debt_to_equity == pytest.approx(1.87)
assert result.market_cap == 2_800_000_000_000.0
@ -198,7 +199,7 @@ class TestAlphaVantageProvider:
result = await provider.fetch("GOOG")
assert result is not None
assert result.eps == 5.80
assert result.eps_ttm == 5.80
assert result.pe_ratio is None
assert result.peg_ratio is None
@ -240,7 +241,7 @@ class TestFMPProvider:
assert result is not None
assert result.ticker == "AAPL"
assert result.eps == 6.57
assert result.eps_ttm == 6.57
assert result.pe_ratio == 28.3
assert result.debt_to_equity == 1.87
assert result.market_cap == 2_800_000_000_000.0
@ -296,10 +297,10 @@ class TestYahooFinanceProvider:
assert result is not None
assert result.ticker == "AAPL"
assert result.eps == 6.57
assert result.eps_ttm == 6.57
assert result.pe_ratio == 28.3
assert result.peg_ratio == 2.1
assert result.revenue_growth == 0.08
assert result.revenue_growth_yoy == 0.08
assert result.profit_margin == 0.26
assert result.debt_to_equity == pytest.approx(1.87)
assert result.market_cap == 2_800_000_000_000.0
@ -348,18 +349,18 @@ class TestRotatingProvider:
RotatingProvider(providers=[])
async def test_returns_first_success(self) -> None:
snap = FundamentalsSnapshot(ticker="AAPL", eps=6.0)
snap = FundamentalsSnapshot(ticker="AAPL", eps_ttm=6.0, fetched_at=datetime.now(timezone.utc))
p1 = _StubProvider(result=snap)
p2 = _StubProvider(result=FundamentalsSnapshot(ticker="AAPL", eps=99.0))
p2 = _StubProvider(result=FundamentalsSnapshot(ticker="AAPL", eps_ttm=99.0, fetched_at=datetime.now(timezone.utc)))
rp = RotatingProvider(providers=[p1, p2])
result = await rp.fetch("AAPL")
assert result is not None
assert result.eps == 6.0 # from p1, not p2
assert result.eps_ttm == 6.0 # from p1, not p2
async def test_falls_back_on_none(self) -> None:
snap = FundamentalsSnapshot(ticker="AAPL", pe_ratio=30.0)
snap = FundamentalsSnapshot(ticker="AAPL", pe_ratio=30.0, fetched_at=datetime.now(timezone.utc))
p1 = _StubProvider(result=None)
p2 = _StubProvider(result=snap)
@ -378,7 +379,7 @@ class TestRotatingProvider:
assert result is None
async def test_handles_exceptions(self) -> None:
snap = FundamentalsSnapshot(ticker="AAPL", eps=5.0)
snap = FundamentalsSnapshot(ticker="AAPL", eps_ttm=5.0, fetched_at=datetime.now(timezone.utc))
p1 = _StubProvider(error=RuntimeError("boom"))
p2 = _StubProvider(result=snap)
@ -386,7 +387,7 @@ class TestRotatingProvider:
result = await rp.fetch("AAPL")
assert result is not None
assert result.eps == 5.0 # fell through after p1 raised
assert result.eps_ttm == 5.0 # fell through after p1 raised
async def test_all_raise(self) -> None:
p1 = _StubProvider(error=RuntimeError("boom1"))