feat: add Nailong Fund advisor capabilities
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# 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()
|
||||
Reference in New Issue
Block a user