# ruff: noqa: E402 """Print a customer's read-only dynamic ETF allocation result for local verification.""" from __future__ import annotations import argparse import asyncio import json from dataclasses import asdict import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from app.core.contracts import RequestContext from app.service.asset_allocation_service import AssetAllocationService from app.service.customer_profile_service import CustomerProfileService def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Verify dynamic allocation for one local customer") parser.add_argument("customer_id", help="Existing customer ID with a completed profile and goal") parser.add_argument( "--market-metrics", action="store_true", help="Also print the classified market metrics used by the optimizer", ) return parser.parse_args() async def verify(customer_id: str) -> dict[str, object]: context = RequestContext( user_id=customer_id, trace_id="local-dynamic-allocation-verification", roles=("customer",), permissions=( "asset-allocation:generate:self", "customer-profile:read:self", "investment-goal:read:self", ), ) return await AssetAllocationService().generate_for_agent(context) async def market_metrics(customer_id: str) -> list[dict[str, object]]: context = RequestContext( user_id=customer_id, trace_id="local-dynamic-allocation-metrics", roles=("customer",), permissions=("customer-profile:read:self",), ) profile = await CustomerProfileService().current_for_agent(context) if profile is None or not isinstance(profile.get("risk_level"), str): return [] return [ asdict(item) for item in await AssetAllocationService()._market_metrics(profile["risk_level"]) ] def main() -> None: args = parse_args() result = asyncio.run(verify(args.customer_id)) if args.market_metrics: result["market_metrics"] = asyncio.run(market_metrics(args.customer_id)) print(json.dumps(result, ensure_ascii=False, default=str, indent=2)) if __name__ == "__main__": main()