# True-Wealth Valuation Pilot C2

Use this reference when extending Equity/ETF valuation for already-imported True Wealth initial snapshot positions. It captures durable workflow and modeling safeguards from Phase C2.

## Scope guard

- Do not import additional positions while doing valuation hardening.
- Do not import PostFinance/Raiffeisen data during the True-Wealth pilot.
- Keep dashboard/report rendering local-DB only; provider/API calls belong only in explicit CLI/scheduled jobs.
- Report only aggregate counts in chat; never quantities, prices, market values, balances, raw rows, or source-file contents.
- If provider symbols are absent, do not guess. Create/refresh mapping-review items and leave status as `missing_provider_symbol`.

## Instrument identity and mapping

- ISIN remains the instrument truth for equities/ETFs.
- Provider symbol is a separate market-data mapping, not the instrument identity.
- Never auto-map market prices from name alone. Ticker without exchange remains review-needed.
- Manual mapping confirmation should allow provider, provider_symbol, exchange/provider_market, currency/trading currency, confidence, note, and should write an audit event.
- Mapping confirmation should resolve `missing_provider_symbol` / `ambiguous_instrument_mapping` alerts for that instrument when complete.

## Currency-hedged ETFs

Add or verify instrument metadata fields:

- `is_currency_hedged`
- `hedged_to_currency`
- `hedge_status`: `hedged`, `unhedged`, `unknown`
- optional `base_exposure_currency`
- optional `trading_currency`

Rules:

- Do not infer hedged status unless clearly supported and still mark review-required if uncertain.
- `hedge_status=unknown` should create a deduplicated `hedge_status_unknown` alert/warning.
- Manual hedge-status changes require audit log.
- If `is_currency_hedged=true` and `hedged_to_currency=CHF`, valuation may still use a price currency and FX conversion for display, but Total Return / FX attribution must not present naive free FX-PnL as methodically clean. Add a warning such as `currency_hedged_fx_attribution` and suppress precise Total Return if appropriate.

## Instrument status and valuation policy

Add or verify:

- `instrument_status`: `active`, `delisted`, `suspended`, `merged`, `inactive`, `unknown`
- `valuation_policy`: `live_price`, `last_known_price`, `manual_value`, `exclude_from_auto_price_update`

Rules:

- `delisted`, `suspended`, `merged`, `inactive`, or `exclude_from_auto_price_update` instruments must be excluded from automatic price refresh.
- Create/update one deduplicated `delisted_or_suspended` alert rather than daily alert floods.
- Dashboard should show frozen/manual valuation state clearly.
- Status changes require audit log.
- Do not automatically mark delisted from weak provider failures; use suspected/review flags.

## Historical FX failure handling

Historical FX APIs may be paywalled or unavailable. Provider failures such as 403/paywall/rate-limit/unavailable must not crash valuation/import flows.

Implement behavior:

- Persist local `fx_rates` error row or equivalent with `quality_status='manual_override_required'`.
- Set `fx_source='manual_override_required'` where applicable.
- Create deduplicated alerts: `historical_fx_unavailable` and `manual_override_required`.
- Keep affected positions `partially_valuable`, not failed/import-blocked.
- Never use latest FX as historical snapshot FX without explicit manual confirmation.
- Manual FX override requires non-empty note and audit event; resolving appropriate FX alerts is allowed after a valid override.

## Price/FX timestamp alignment

Add valuation timestamp status:

- `aligned`
- `acceptable`
- `stale_mismatch`
- `missing_timestamp`

Rules:

- Use a configurable tolerance such as `max_price_fx_time_delta_hours=24` for MVP EOD data.
- If price and FX timestamps are too far apart, do not crash; mark warning and create `stale_valuation` alert.
- Avoid false precision when timestamps are missing or mismatched.
- Be careful comparing timezone-aware and date-only timestamps; normalize naive dates to UTC before subtraction.

## Corporate action safeguards

Add or verify:

- `corporate_action_status`: `not_checked`, `none_known`, `suspected`, `confirmed`, `adjusted`, `ignored`
- `split_or_corporate_action_review_required`

MVP heuristic:

- If a new local price moves unrealistically versus the previous local price, e.g. >25% day-to-day, create `corporate_action_suspected` and `split_or_corporate_action_review_required` alerts/flags.
- Do not automatically split-adjust in MVP.
- Do not show high-confidence performance across suspected corporate actions.

## Valuation status

Classify each position:

- `valuable`: quantity, instrument, local market price, FX/not-needed/methodically-clean hedge handling, acceptable timestamp alignment, no blocking quality flags, and active/approved valuation policy.
- `partially_valuable`: holding exists but FX, price, hedge status, timestamp alignment, cost basis, or other methodical element is incomplete.
- `not_valuable`: missing core quantity/instrument/account, excluded instrument status/policy, or no mapping/manual value path.

Even if current market value can be computed, historical performance/Total Return stays incomplete while `snapshot_only` or `cost_basis_uncertain` remains active.

## Runtime pilot checklist

1. Apply migrations and run Git-safety baseline.
2. Identify only the already-imported True-Wealth snapshot instruments.
3. Refresh provider-symbol mapping quality and instrument metadata quality.
4. If no confirmed provider symbols exist, run market-price dry run and expect `total_mappings=0`; no provider calls should occur.
5. Refresh valuation statuses via local DB only.
6. Report aggregate counts for provider-symbol, hedge, instrument status, FX, market price, timestamp alignment, corporate action, valuation, and active alerts.
7. Run compile, pytest, Git-safety after removing `.pytest_cache`/`__pycache__` if needed.

## Tests to include

- Missing provider symbol creates alert; confirmed mapping writes audit and resolves alert.
- Hedge unknown creates warning; hedge-status change writes audit; CHF-hedged ETF does not present naive FX-PnL as clean Total Return.
- Missing FX remains active; FX present resolves missing-FX; historical FX unavailable creates manual-override-required without crash; manual FX override requires note and audit.
- Market price present resolves `missing_market_price`; delisted/suspended/excluded instruments are not auto-fetched and do not create alert floods.
- Aligned timestamps classify OK; stale mismatch creates `stale_valuation`.
- >25% local price move creates corporate-action suspected/review-required and no automatic split correction.
- Valuation status covers `not_valuable`, `partially_valuable`, `valuable`; dashboard reads local DB only.
