
    A/j                    n   U d Z ddlmZ ddlmZ ddlmZ i dddddd	d
d	ddddddddddddddddddddddddddi ddd d!d"d!d#d$d%d$d&d'd(d'd)d*d+d*d,d-d.d-d/d0d1d0d2d3d4d3d5d6d7d6d8d8d9d9d:d:d;ddddd<Zd=ed><   d?Z	d@dAdBZ
d[dIZd\dMZd]dOZd\dPZdQdQdQdQdQdRd^dZZdQS )_u?   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spreadmoodysOptional[str]spfitchreturnOptional[float]c                F    d | ||fD             }|rt          |          nd S )Nc                    g | ]>}|r:|                                 t          v t          |                                          ?S  )stripr<   ).0rs     /app/app/scoring/bond.py
<listcomp>z&_best_rating_score.<locals>.<listcomp>4   sL        m++ 	aggii +++    )max)r?   rA   rB   scoress       rK   _best_rating_scorerP   /   s>    
 "e$  F
 !*3v;;;d*rM   scorefloatstrc                0    | t           k    rdS | dk    rdS dS )NzInvestment Grader(   z
High Yield
Distressed)_IG_THRESHOLDrQ   s    rK   _rating_grade_labelrX   <   s&    !!{{|<rM   
spread_bpsc                n    | dS | dk    rdS | dk    rdS | dk    rdS | d	k    rd
S | dk    rdS | dk    rdS dS )u@   Tighter spread → lower credit risk → higher score (0–100).Ng      I@r!         Y@r   g     V@   g     R@i^  g     K@i  g      D@i  g      9@g      $@rG   )rY   s    rK   _spread_scorer]   D   sr    tRuStStStStSt4rM   c                6    | dk    rdS | dk    rdS | dk    rdS dS )NK   zLOW RISKr   zMODERATE RISKr(   zELEVATED RISKz	HIGH RISKrG   rW   s    rK   _composite_grader`   W   s1    {{z{{{{;rM   N)rating_moodys	rating_sprating_fitchz_spreadasset_swap_spreadisinra   rb   rc   rd   re   r   c                   d}d}||d}}n||d}}t          |||          }t          |          }	|"|t          d         z  |	t          d         z  z   }
n|	}
t          t	          t          |
d          d          d	          }
t          | |
t          |
          ||t          |          ndt          |	d	          |||duo
|t          k    
	  	        S )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nonerd   re   r=   r>   g        r[      )	rf   composite_scorecomposite_graderating_scorerating_gradespread_scorespread_usedrY   is_investment_grade)
rP   r]   _WEIGHTSroundminrN   r   r`   rX   rV   )rf   ra   rb   rc   rd   re   rY   ro   	rat_score	spr_score	composites              rK   compute_bond_riskrw   a   s     #'JK"*JK

		&"35HK
"=)\JJIj))I 22Y(AS5SS			c#i--u55q99I!(337@7L(333RV9a((%T1Pi=6P
 
 
 
rM   )r?   r@   rA   r@   rB   r@   rC   rD   )rQ   rR   rC   rS   )rY   rD   rC   rR   )rf   rS   ra   r@   rb   r@   rc   r@   rd   rD   re   rD   rC   r   )__doc__
__future__r   typingr   app.scoring.typesr   r<   __annotations__rV   rq   rP   rX   r]   r`   rw   rG   rM   rK   <module>r}      s   E E 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++
+ 
+ 
+ 
+      &    $(#"& $)-+ + + + + + + +rM   