Two inconsistencies found verifying the IBKR /strategy/multistrat page: 1. A FAILED backtest with a high Sharpe (multistrat: Sharpe 1.7, gate FAIL) rendered a GREEN "Validated edge ... backtest passed" banner directly above the FAIL badge — the Sharpe>=1.0 fallback overrode the explicit FAIL. The verdict now respects the badge: an explicit FAIL is an amber "Backtest didn't clear the gate ... treat it as unproven", never a green "passed". The backtest Sharpe figure also goes neutral-grey (not alarming red) when unvalidated — the number itself (1.7) isn't bad, it just didn't validate. 2. The UCITS lines the EU DU account actually holds (CSPX/CBU0/IDTM/IGLN/ICOM) weren't in ASSET_DESCRIPTIONS, so the holdings "what it is" column read "other". Mapped each to its plain description (US stocks / US Treasuries / Gold / Commodities), same as its US cousin. Regression tests: a passed=False + Sharpe 1.7 detail renders amber "didn't clear the gate" and never "backtest passed"/"Validated edge"; UCITS tickers resolve to plain descriptions, never "other". Verified desktop+mobile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
59 lines
3.0 KiB
Python
59 lines
3.0 KiB
Python
"""display_names.py — the SINGLE internal-id -> human-name map every cockpit view uses (the plain-language
|
|
global constraint). Covers every STRATEGY_REGISTRY entry (never a raw id falls through to the template) plus
|
|
the sim-book override pills absorbed from app.py's former local `_SIM_BOOK_LABELS`, and the asset->plain-
|
|
description map used by the holdings table."""
|
|
from __future__ import annotations
|
|
|
|
from fxhnt.application.display_names import ASSET_DESCRIPTIONS, asset_description, display_name
|
|
from fxhnt.registry import STRATEGY_REGISTRY
|
|
|
|
|
|
def test_every_registry_strategy_has_a_display_name() -> None:
|
|
for sid, entry in STRATEGY_REGISTRY.items():
|
|
# multistrat/vrp are deliberately overridden with a friendlier pill label (see the next test) — every
|
|
# other registry entry must resolve to its own registry `display_name`.
|
|
if sid not in ("multistrat", "vrp"):
|
|
assert display_name(sid) == entry["display_name"]
|
|
assert display_name(sid) != sid # never the bare raw id
|
|
|
|
|
|
def test_sim_book_overrides_are_plain_language() -> None:
|
|
# The interim local pill labels from app.py's `_SIM_BOOK_LABELS` (Task 1), absorbed here.
|
|
assert display_name("multistrat") == "ETF Portfolio"
|
|
assert display_name("vrp") == "Options income (put spreads)"
|
|
|
|
|
|
def test_unknown_id_falls_back_to_itself_never_raises() -> None:
|
|
assert display_name("not-a-real-strategy") == "not-a-real-strategy"
|
|
|
|
|
|
def test_asset_descriptions_cover_the_multistrat_instruments() -> None:
|
|
assert ASSET_DESCRIPTIONS == {
|
|
# US listings (modelled book / us-venue)
|
|
"SPY": "US stocks", "IEF": "US Treasuries", "GLD": "Gold",
|
|
"PDBC": "Commodities", "DBMF": "Managed futures",
|
|
# UCITS listings actually held in the EU DU account (the multi-strat leg trades these)
|
|
"CSPX": "US stocks", "CBU0": "US Treasuries", "IDTM": "US Treasuries",
|
|
"IGLN": "Gold", "ICOM": "Commodities",
|
|
}
|
|
for sym, desc in ASSET_DESCRIPTIONS.items():
|
|
assert asset_description(sym) == desc
|
|
|
|
|
|
def test_ucits_holdings_never_read_other() -> None:
|
|
# The EU DU account holds the UCITS remap (KID/PRIIPs blocks the US ETFs), so the holdings table sees
|
|
# CSPX/CBU0/IDTM/IGLN/ICOM — each MUST resolve to the same plain "what it is" as its US cousin, never the
|
|
# generic "other" (the bug found verifying the IBKR detail page: real holdings reading "other").
|
|
assert asset_description("CSPX") == "US stocks"
|
|
assert asset_description("IGLN") == "Gold"
|
|
assert asset_description("ICOM") == "Commodities"
|
|
assert asset_description("CBU0") == "US Treasuries"
|
|
assert asset_description("IDTM") == "US Treasuries"
|
|
|
|
|
|
def test_asset_description_unknown_symbol_falls_back_to_generic() -> None:
|
|
# An unmapped symbol (e.g. a future vrp option contract) gets a plain generic word, never a blank or an
|
|
# odd raw contract string — the symbol itself is still shown in its own column.
|
|
assert asset_description("XYZ") == "other"
|
|
assert asset_description("SPY 260130P00500000") == "other"
|