
    A/j                       % S r SSKJr  SSKJr  SSKJr  0 SS_SS_SS	_S
S	_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_0 SS_S S!_S"S!_S#S$_S%S$_S&S'_S(S'_S)S*_S+S*_S,S-_S.S-_S/S0_S1S0_S2S3_S4S3_S5S6_S7S6_ES8S8S9S9S:S:S;SSSSS<.ErS=\S>'   S?r	S@SASB.r
        SJSC jrSKSD jrSLSE jrSKSF jrSGSGSGSGSGSH.             SMSI jjrgG)Nu?   Bond risk scoring — pure computation, no I/O or side effects.    )annotations)Optional)BondRiskResultAAAd   AaazAA+_   Aa1AAZ   Aa2zAA-W   Aa3zA+T   A1AP   A2zA-M   A3zBBB+I   Baa1BBBF   Baa2zBBB-A   Baa3zBB+7   Ba1BB2   Ba2zBB--   Ba3zB+(   B1B#   B2zB-   B3zCCC+   Caa1      
      )CCCCaa2zCCC-Caa3CCCaCDDDDDDWDzdict[str, float]_RATING_SCALEg     @P@g333333?g?)ratingspreadc                    XU4 Vs/ s H=  nU(       d  M  UR                  5       [        ;   d  M&  [        UR                  5          PM?     nnU(       a  [        U5      $ S $ s  snf )N)stripr<   max)moodysspfitchrscoress        -/root/lseg-credit/backend/app/scoring/bond.py_best_rating_scorerH   /   sd     e$$A 	!m+ 	!aggi $  
 !3v;*d*s   A!A!A!c                (    U [         :  a  gU S:  a  gg)NzInvestment Grader(   z
High Yield
Distressed)_IG_THRESHOLDscores    rG   _rating_grade_labelrN   <   s    !{    c                `    U c  gU S::  a  gU S::  a  gU S::  a  gU S::  a  g	U S
::  a  gU S::  a  gg)u@   Tighter spread → lower credit risk → higher score (0–100).g      I@r!         Y@r   g     V@   g     R@i^  g     K@i  g      D@i  g      9@g      $@ )
spread_bpss    rG   _spread_scorerU   D   sP    RSSSSSrO   c                .    U S:  a  gU S:  a  gU S:  a  gg)NK   zLOW RISKr   zMODERATE RISKr(   zELEVATED RISKz	HIGH RISKrS   rL   s    rG   _composite_graderX   W   s#    {{{rO   N)rating_moodys	rating_sprating_fitchz_spreadasset_swap_spreadc                X   SnSnUb  USpvOUb  USpv[        XU5      n[        U5      n	Ub  U[        S   -  U	[        S   -  -   n
OU	n
[        [	        [        U
S5      S5      S	5      n
[        U U
[        U
5      UUb  [        U5      OS[        U	S	5      UUUSL=(       a	    U[        :  S
9	$ )u   
Compute a composite 0–100 risk score for a single bond.

Weights: Rating 60 % · Spread 40 %.
If no rating is available the full weight falls on spread.
Spread priority: Z-spread > Asset Swap Spread.
Nnoner\   r]   r=   r>   g        rQ      )	isincomposite_scorecomposite_graderating_scorerating_gradespread_scorespread_usedrT   is_investment_grade)
rH   rU   _WEIGHTSroundminrA   r   rX   rN   rK   )ra   rY   rZ   r[   r\   r]   rT   rg   	rat_score	spr_score	composites              rG   compute_bond_riskro   a   s      #'JK"*JK		&"35HK"=\JIj)I 22Y(AS5SS		c#i-u5q9I!(37@7L(3RV9a(%T1Pi=6P
 
rO   )rB   Optional[str]rC   rp   rD   rp   returnOptional[float])rM   floatrq   str)rT   rr   rq   rs   )ra   rt   rY   rp   rZ   rp   r[   rp   r\   rr   r]   rr   rq   r   )__doc__
__future__r   typingr   app.scoring.typesr   r<   __annotations__rK   ri   rH   rN   rU   rX   ro   rS   rO   rG   <module>rz      s{   E "  ,
#	3#s# 
2# r# 	2	# r	#
 
2#
 r# 	2# r# 2# r# 	2# r# B# # 
B# # B# # 
2# r# 	2# r# 
2# r#  	2!#  r!#" 2##" r##$ 	2%#$ r%#( B)#( )#* q3# :  d+
+
+
+ 
+ 	
+& $(#"& $)-+
+ !+ 	+
  + + '+ +rO   