feat: auto-reconcile stale holding mirrors

Closes #94
This commit is contained in:
Hermes Agent
2026-09-14 12:55:04 +09:00
parent adf131f19c
commit c70ac0fb24
19 changed files with 1181 additions and 16 deletions
+52
View File
@@ -117,6 +117,58 @@ def test_get_portfolios_network_error_raises_unavailable():
# REQ-123: cost-basis parsing (canonical + diagnostics)
# ---------------------------------------------------------------------------
def test_get_cost_basis_evidence_parses_identity_quantity_and_complete_basis():
def handler(req: httpx.Request) -> httpx.Response:
assert req.url.path == "/v1/portfolios/pf-1/holdings/cost-basis"
return httpx.Response(200, json={
"portfolio_id": "pf-1",
"symbol": "019685",
"current_quantity": "726",
"cost_basis_per_unit": "2172.46829187",
"total_cost_basis": str(726 * 2172.46829187),
"data_completeness_warning": None,
})
adapter = PortfolioHubReadAdapter("https://pf.test", token="tok", client=_client(handler))
evidence = adapter.get_cost_basis_evidence("pf-1")
assert evidence.portfolio_id == "pf-1"
assert evidence.symbol == "019685"
assert evidence.current_quantity == 726.0
assert evidence.cost_basis_per_unit == pytest.approx(2172.46829187)
assert evidence.data_completeness_warning is None
assert evidence.observed_at.tzinfo is not None
@pytest.mark.parametrize("payload", [
{"cost_basis_per_unit": 1, "total_cost_basis": 1},
{
"portfolio_id": "wrong", "symbol": "019685", "current_quantity": 1,
"cost_basis_per_unit": 1, "total_cost_basis": 1,
},
{
"portfolio_id": "pf-1", "symbol": "019685", "current_quantity": 1,
"cost_basis_per_unit": "NaN", "total_cost_basis": 1,
},
])
def test_get_cost_basis_evidence_rejects_missing_mismatched_or_nonfinite(payload):
def handler(req: httpx.Request) -> httpx.Response:
return httpx.Response(200, json=payload)
adapter = PortfolioHubReadAdapter("https://pf.test", token="tok", client=_client(handler))
with pytest.raises(PortfolioHubUnavailableError):
adapter.get_cost_basis_evidence("pf-1")
def test_get_cost_basis_evidence_never_uses_legacy_fields():
def handler(req: httpx.Request) -> httpx.Response:
return httpx.Response(200, json={"avg_cost": 1234, "wac": 1234})
adapter = PortfolioHubReadAdapter("https://pf.test", token="tok", client=_client(handler))
with pytest.raises(PortfolioHubUnavailableError):
adapter.get_cost_basis_evidence("pf-1")
def test_get_cost_basis_with_diagnostics_prefers_canonical_when_valid():
"""REQ-123 AC-1: cost_basis_per_unit가 있으면 우선 사용."""