From 7d5885bf11789c0bb1f37e7ff0fc756abfa60298 Mon Sep 17 00:00:00 2001 From: Pigbibi Date: Fri, 9 Oct 2026 16:12:59 +0800 Subject: [PATCH] Accept Firstrade total_value fields as AFS provider equity. Snapshot build failed with provider_equity_unavailable because collect only read total_equity, while Firstrade balances and account-list mirrors expose total_value / account_list_total_value. Keep exact-key matching. --- application/account_facts_readonly.py | 8 +++++++- tests/test_account_facts_readonly.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/application/account_facts_readonly.py b/application/account_facts_readonly.py index 31a74a0..362f6ac 100644 --- a/application/account_facts_readonly.py +++ b/application/account_facts_readonly.py @@ -233,7 +233,13 @@ def collect_firstrade_account_facts( missing_market_value += int(value_missing) missing_currency += int(currency_missing) - provider_equity = _exact_balance_value(balances, ("total_equity",)) + # Firstrade balance payloads commonly use total_value; the client also + # mirrors account-list totals as account_list_total_value. Keep exact + # keys only (never fuzzy cash substrings). + provider_equity = _exact_balance_value( + balances, + ("total_equity", "total_value", "account_list_total_value"), + ) cash_balance = _exact_balance_value(balances, ("cash_balance",)) available_cash = _exact_balance_value(balances, ("available_cash",)) buying_power = _exact_balance_value(balances, ("buying_power",)) diff --git a/tests/test_account_facts_readonly.py b/tests/test_account_facts_readonly.py index f2f2e26..b1af9f0 100644 --- a/tests/test_account_facts_readonly.py +++ b/tests/test_account_facts_readonly.py @@ -403,3 +403,20 @@ def test_requires_timezone_aware_monotonic_observation_times(): ) assert error.value.reason_code == "observation_time_invalid" + + +@pytest.mark.parametrize( + "field", + ["total_value", "account_list_total_value", "total_equity"], +) +def test_accepts_firstrade_total_value_as_provider_equity(field): + client = CachedReadOnlyClient() + client.balances = {field: "$1,234.50", "currency": "USD"} + + result = collect_firstrade_account_facts( + client, + expected_account="synthetic-account-a", + clock=lambda: datetime(2026, 10, 8, 12, tzinfo=timezone.utc), + ) + + assert result["balances"]["provider_equity"] == "1234.5"