
    je                        S r SSKJr  SSKrSSKJr  SSKJr  SSKJ	r	  SSK
Jr  SSKJr  \R                  " \5      r " S	 S
5      rg)uK   LSEG bond analytics service — orchestrates data loading and risk scoring.    )annotationsN)Optional)settings)LsegDataLoader)compute_bond_risk)BondRiskResultc                  x    \ rS rSrSr  S   SS jjrS rSSS jjrSS jrSSS jjr	SSS	 jjr
SSS
 jjrSrg)LsegBondService   u   
Loads LSEG bond data and computes risk scores.

Data source priority:
  1. LSEG API (if LSEG_APP_KEY is set) — fetches live data for ISINs in LSEG_ISINS
  2. File fallback (LSEG_DATA_PATH) — reads downloaded Excel/CSV files from disk
Nc                "   U=(       d    [         R                  U l        U=(       d    [         R                  U l        U=(       d    [         R
                  U l        [        U=(       d    [         R                  5      U l	        S U l
        S U l        g )N)r   lseg_app_key_app_key	isin_list_isinsissuer_list_issuersr   lseg_data_path_file_loader_api_client_cache)selfapp_keyisinsissuers	data_paths        6/root/lseg-credit/backend/app/services/bond_service.py__init__LsegBondService.__init__   s_    88#8#81x1178#7#7*9+O8O8OP,0    c                    U R                   c9  SSKJn  U" U R                  [        R
                  [        R                  S9U l         U R                   $ )Nr   )LsegApiClient)r   usernamepassword)r   app.providers.lseg_apir!   r   r   lseg_usernamelseg_password)r   r!   s     r   _get_api_clientLsegBondService._get_api_client!   sE    #<,!//!// D
 r   c                   U R                   b  U(       Ga?  U R                  (       ad  U R                  (       aS  [        R	                  S[        U R                  5      5        U R                  5       R                  U R                  5      nOU R                  (       ad  U R                  (       aS  [        R	                  S[        U R                  5      5        U R                  5       R                  U R                  5      nO/[        R	                  S5        U R                  R                  5       nU Vs/ s H  o0R                  U5      PM     snU l         U R                   $ s  snf )NzLSEG: fetching %d ISINs via APIz$LSEG: searching bonds for %d issuersz0LSEG: loading from files (no App Key configured))r   r   r   loggerinfolenr'   fetch_bondsr   fetch_bonds_for_issuersr   
load_bonds_enrich)r   forcerawbs       r   _loadLsegBondService._load+   s    ;;%}}=s4;;?OP**,88E4==BCDVW**,DDT]]SNO''224478Cq<<?C8DK{{ 9s   3E!c           
        [        UR                  S5      =(       d    SUR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      S9n0 UES	UR                  5       0E$ )
NisinUNKNOWNrating_moodys	rating_sprating_fitchz_spreadasset_swap_spread)r7   r9   r:   r;   r<   r=   risk)r   get
model_dump)r   bondresults      r   r0   LsegBondService._enrich9   sw    !2&!.Y((?3hh{+.1XXj)"hh':;"
 5$4 1 1 344r   c                     U R                  US9$ )Nr1   )r4   )r   force_refreshs     r   get_all_bondsLsegBondService.get_all_bondsD   s    zzz..r   c                   ^ U R                  US9nUR                  5       R                  5       m[        U4S jU 5       S 5      $ )NrE   c              3     >#    U  H4  oR                  S 5      =(       d    SR                  5       T:X  d  M0  Uv   M6     g7f)r7    N)r?   upper).0r3   targets     r   	<genexpr>+LsegBondService.get_bond.<locals>.<genexpr>J   s.     Q1%%-*=2)D)D)F&)PQQs   /?	?)r4   rL   stripnext)r   r7   rF   bondsrN   s       @r   get_bondLsegBondService.get_bondG   s;    


/##%QQSWXXr   c                x   U R                  US9nU(       d	  SS 0 SSS S.$ U Vs/ s H
  o3S   S   PM     nn0 nSnU H6  nUS   S   nUR                  US5      S-   XW'   US   S   (       d  M1  US-  nM8     U Vs/ s H,  nUR                  S	5      =(       d    UR                  S
5      PM.     nnU V	s/ s H	  oc  M  U	PM     nn	[        U5      [        [	        U5      [        U5      -  S5      UU[        U5      U-
  U(       a#  [        [	        U5      [        U5      -  S5      S.$ S S.$ s  snf s  snf s  sn	f )NrE   r   )total_bondsavg_composite_scoregrade_distributioninvestment_grade_counthigh_yield_countavg_spread_bpsr>   composite_scorecomposite_grade   is_investment_grader<   r=   )r4   r?   r,   roundsum)
r   rF   rS   r3   scoresgrade_countsig_countgspread_valsss
             r   get_portfolio_summary%LsegBondService.get_portfolio_summaryL   so   


/ '+&(*+$%"&  9>>1F)-.>')A&	+,A*..q!4q8LOy.//A	  
 EE*;':!;; 	 
 #.?+Qq+? u:#(Vs6{)BA#F".&. #E
X 5OZeC$4s;7G$GK
 	
 ae
 	
! ?
 @s   D-;3D24D7>D7)r   r   r   r   r   r   )NNNN)r   Optional[str]r   Optional[list[str]]r   rl   r   rk   )F)r1   boolreturn
list[dict])rA   dictrn   rp   )rF   rm   rn   ro   )r7   strrF   rm   rn   zOptional[dict])rF   rm   rn   rp   )__name__
__module____qualname____firstlineno____doc__r   r'   r4   r0   rG   rT   ri   __static_attributes__ r   r   r
   r
      sJ     TXQU1-1AN1 	5/Y
#
 #
r   r
   )rv   
__future__r   loggingtypingr   
app.configr   app.providers.lsegr   app.scoring.bondr   app.scoring.typesr   	getLoggerrr   r*   r
   rx   r   r   <module>r      s9    Q "    - . ,			8	$`
 `
r   