
     Bj{n                        d Z ddlmZ ddlZddlZddlmZmZ  ej        e	          Z
g dZdddd	d
dddddddZdZh dZddZddZddZ G d d          ZdS )uN   LSEG Data Library client — fetches bond data via Platform session (App Key).    )annotationsN)AnyOptional)zTR.YieldToMaturityzTR.YieldToWorstz
TR.ZSpreadzTR.OASpreadzTR.BidPricezTR.AskPricezTR.AssetSwapSpreadzTR.TRBCIndustryGroupzTR.TRBCIndustryzTR.HeadquartersCountryzTR.ModifiedDurationytmytwz_spreadoas	bid_price	ask_priceasset_swap_spreadtrbc_igtrbc_industrycountryduration)zYield to MaturityzYield to WorstzZ Spreadz	OA Spreadz	Bid Pricez	Ask PricezAsset Swap SpreadzTRBC Industry Group NamezTRBC Industry NamezCountry of HeadquarterszModified DurationzRIC,ISIN,IssuerCommonName,IssuerName,MaturityDate,CouponRate,CouponFrequency,CouponType,MoodysRating,SPRating,Currency,Price,IssueDate,AssetType,RCSTRBC2012Genealogy>   n/a<na>no permission nannonereturnOptional[str]c                    | d S t          |                                           }|                                t          v rd n|S N)strstriplower_NULL_STRINGSvalss     /app/app/providers/lseg_api.py_cleanr#   3   s=    
{tCA7799--4414    Optional[float]c                    t          |           }|d S 	 t          t          |                              dd                    S # t          t
          f$ r Y d S w xY w)N,r   )r#   floatr   replace
ValueError	TypeError)r    cleaneds     r"   	_to_floatr-   :   sg    SkkGtS\\))#r22333	"   tts   /A AAc                    | d S t          |                                           }|                                t          v rd S d|v r|                    d          d         n|S )N r   )r   r   r   r   splitr   s     r"   _to_date_strr1   D   sY    
{tCAwwyyM!!t!Qhh1773<<??A-r$   c                      e Zd ZU dZd;dZd Zd Zd<d=dZdZdZ	dZ
d>dZd?dZd@dZdAdBd ZdCdBd"ZdDd$ZdAdEd&ZdFdGd+Zd,gg d-g d.g d/g d0g d1g d2d3Zd4ed5<   dAdHd7Zd?d8ZdId:Zd'S )JLsegApiClienta}  
    Fetches bond data from LSEG via the lseg-data Python library (Platform session).
    Requires LSEG_APP_KEY + LSEG_USERNAME + LSEG_PASSWORD in environment / .env file.

    Strategy: discovery.search supplies static reference data (coupon, maturity, rating,
    currency); ld.get_data supplies live market data (YTM, Z-spread, bid/ask). Both are
    merged per instrument.
    app_keyr   usernamepasswordc                >    || _         || _        || _        d | _        d S r   )_app_key	_username	_password_session)selfr4   r5   r6   s       r"   __init__zLsegApiClient.__init__X   s"    !!r$   c                   | j         d S 	 dd lm} ddlm} |                    | j        |                    | j        | j	                  d          
                                }|                                 |j                            |           || _         t                              d           d S # t           $ r!}t                              d|            d }~ww xY w)Nr   )platform)r5   r6   T)r4   grantsignon_controlzLSEG: Platform session openedu#   LSEG: failed to open session — %s)r;   	lseg.datadatalseg.data.sessionr?   
Definitionr8   GrantPasswordr9   r:   get_sessionopensessionset_defaultloggerinfo	Exceptionerror)r<   ldr?   rI   excs        r"   _openzLsegApiClient._open^   s   =$F	""""""222222)),,!^!^ -    $ *   kmm  LLNNNJ""7+++#DMKK788888 	 	 	LL>DDD	s   B)B6 6
C! CC!c                    | j         N	 | j                                          t                              d           n# t          $ r Y nw xY wd | _         d S d S )NzLSEG: session closed)r;   closerK   rL   rM   )r<   s    r"   rS   zLsegApiClient.closev   sl    =$##%%%23333    DMMM %$s   3= 
A
	A
d   issuer_namemax_resultsintr   
list[dict]c                   |                                   	 ddlm dfd}|                    dd	          } |d
| d          }|sNt                              d|           j                            |dt                    }||j	        s|
                                D ]\  }}t          |                    d                    }	|	r|                    |	t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    d           t                              dt!          |          |           |S # t"          $ r(}
t                              d||
           g cY d}
~
S d}
~
ww xY w) z
        Search LSEG for bonds by issuer. Returns a list of reference-data dicts,
        each keyed by 'ric', plus static fields (coupon, maturity, rating, etc.).
        r   N
filter_strr   r   listc                p   j                             | t                    }||j        rg S g }|                                D ]\  }}t          |                    d                    }|s+|                    |t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d	                    t          |                    d
                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    d           |S )N)filtertopselectRICISINIssuerCommonName
IssuerName
CouponRateMaturityDate	IssueDateCouponFrequency
CouponTypeMoodysRatingSPRatingCurrencyPriceRCSTRBC2012Genealogyricisinnameissuercouponmaturity_date
issue_datecoupon_freqcoupon_typerating_moodys	rating_spcurrencyprice	genealogy)
	discoverysearch_SEARCH_SELECTemptyiterrowsr#   getappendr-   r1   )rZ   rout_rowro   rO   rV   s         r"   _run_searchz9LsegApiClient.search_bonds_by_issuer.<locals>._run_search   s   L''%#) (  
 99Ijjll  FAs 00C ! JJ),)/)@)@)/8J0K0K)L)L)/0E0E)F)F)2377<3H3H)I)I)5cggn6M6M)N)N)5cggk6J6J)K)K)2377;L3M3M)N)N)/0E0E)F)F)/0G0G)H)H)/
0C0C)D)D)/
0C0C)D)D)237773C3C)D)D)/8N0O0O)P)P         
r$   'z''zFAssetType eq 'CORP' and CouponType ne 'FXDI' and IssuerCommonName eq 'z7LSEG: exact name match empty for '%s', trying free-text,AssetType eq 'CORP' and CouponType ne 'FXDI'queryr]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   zLSEG: found %d bonds for '%s'u#   LSEG: search failed for '%s' — %s)rZ   r   r   r[   )rQ   rB   rC   r)   rK   rL   r}   r~   r   r   r   r#   r   r   r-   r1   lenrM   rN   )r<   rU   rV   r   	safe_namerecordsr2r   r   ro   rP   rO   s     `        @r"   search_bonds_by_issuerz$LsegApiClient.search_bonds_by_issuer   s   
 	

K	""""""      B $++C66I!k:-6: : : G  UWbccc\((%I#)	 )   >"(>"$++--  3$SWWU^^44 #NN14171H1H17@R8S8S1T1T178M8M1N1N1:377<;P;P1Q1Q1=cggn>U>U1V1V1=cggk>R>R1S1S1:377CT;U;U1V1V178M8M1N1N178O8O1P1P17
8K8K1L1L17
8K8K1L1L1:3777;K;K1L1L17@V8W8W1X1X, ,   " KK7W{SSSN 	 	 	LL>SQQQIIIIII	s   J-K 
K8K3-K83K8      g      ?rO   r   instruments	list[str]Optional[Any]c           
        | j         }t          | j                  D ]}	 |                    |t                    c S # t
          $ r{}|| j        dz
  k     rAt                              d|dz   | j        |||           t          j	        |           |dz  }n"t                              d| j        ||           Y d}~d}~ww xY wdS )zMCall ld.get_data with exponential-backoff retries. Returns DataFrame or None.   uD   LSEG: get_data attempt %d/%d failed for %s — %s; retrying in %.0fs   u6   LSEG: get_data gave up after %d attempts for %s — %sN)
_RETRY_BASE_DELAYrange_MAX_RETRIESget_data_MARKET_FIELDSrM   rK   warningtimesleep)r<   rO   r   delayattemptrP   s         r"   _get_data_with_retryz"LsegApiClient._get_data_with_retry   s    &T.// 	 	G{{;?????   T.222NN^!T%6S%   Ju%%%QJEENNP);   ts   <
CA1B<<Cricsdict[str, dict]c           	     d   ddl m} ddl}i }t          dt	          |          | j                  D ]~}|||| j        z            }|                     ||          }|t	          |          dk    r|t                              d||t	          |          z              g }|D ]0}	|                     ||	g          }
|
|	                    |
           1|r|
                    |d          nd}||j        r|                                D ]\  }}t          |                    d          p|                    d                    }	|	s?i }t                                          D ]C\  }}|                    |          }|d	v rt          |          ||<   1t#          |          ||<   D|||	<   |S )
z
        Fetch live market data for a list of RICs in batches.
        Each batch is retried up to _MAX_RETRIES times; batches that still fail
        are retried one RIC at a time to maximise recovery.
        Returns a dict keyed by RIC.
        r   Nr   z6LSEG: falling back to per-RIC requests for batch %d-%dT)ignore_index
Instrument
instrument>   r   r   r   )rB   rC   pandasr   r   _BATCH_SIZEr   rK   rL   r   concatr   r   r#   r   _MARKET_FIELD_MAPitemsr-   )r<   r   rO   pdmarketibatchdfframesro   singler   r   entrycol_namenorm_keyraws                    r"   _fetch_market_dataz LsegApiClient._fetch_market_data   s    	"$q#d))T%566 	$ 	$AA 0001E**2u55Bzc%jj1nnTVWYZ]`af]g]gYghhh  . .C!66rC5AAF)f---=CMRYYvDY999zRXz++-- $ $3SWW\22Kcggl6K6KLL  *;*A*A*C*C 9 9&Hh''(++C#JJJ*0++h*3C..h#s$ r$   c           
        |sg S |                                   |                     |          }g }|D ]&}|                    |i           }|                    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          |                    d          |                    d          d           (t                              dt          |                     |S )u   
        Fetch bond data for a list of RICs (used when ISINs/RICs are given directly,
        without a prior search step — no reference data available in this path).
        ro   rp   rq   Nrr   rs   rt   ru   rv   rw   rx   rz   r{   r
   r   r   r   r	   r   r   r   r   r   )r   r   r   r   zLSEG API: fetched %d bonds)rQ   r   r   r   rK   rL   r   )r<   r   r   r   ro   ms         r"   fetch_bondszLsegApiClient.fetch_bonds  s   
  	I

((55 	 	C

3##ANN   	
          {!3!3 u u z!2!2  u!" $QUU+>%?%?#$ "#y!1!1!"y!1!1!"!7!7!"z!2!2+      0 	0#g,,???r$   ,  r   r^   c                   |                                   	 ddlm} |j                            |d|t
                    }||j        rg S g }|                                D ]\  }}t          |	                    d                    }|s+|
                    |t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d	                    t          |	                    d
                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    d           t                              d|t          |                     |S # t           $ r(}	t                              d||	           g cY d}	~	S d}	~	ww xY w)u   
        Search for bonds using a generic text query (e.g. sector name).
        Returns reference-data dicts only — no market data enrichment.
        r   Nr   r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rk   rl   )ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   rz   r{   u   LSEG: query '%s' → %d bondsu)   LSEG: query search failed for '%s' — %s)rQ   rB   rC   r}   r~   r   r   r   r#   r   r   r-   r1   rK   rL   r   rM   rN   )
r<   r   r^   rO   resultsr   r   r   ro   rP   s
             r"   search_bonds_by_queryz#LsegApiClient.search_bonds_by_query>  s6   
 	

!	""""""l))E%	 *  G '-	G!**,,  3SWWU^^,, %(%+CGGFOO%<%<%+CGG4F,G,G%H%H%+CGGL,A,A%B%B%.sww|/D/D%E%E%1#''.2I2I%J%J%1#''+2F2F%G%G%.sww7H/I/I%J%J%+CGGL,A,A%B%B%+CGGN,C,C%D%D%+CGGJ,?,?%@%@%.swww/?/?%@%@        KK7GMMMN 	 	 	LLDeSQQQIIIIII	s$   3H: 
G/H: :
I,I'!I,'I,   c                :   |                                   	 ddlm} |j                            |d|d          }||j        rg S t                      }g }|                                D ]|\  }}t          |	                    d                    }	t          |	                    d                    }
|	r1|	|vr-|
                    |	           |                    |	|
d           }|S # t          $ r(}t                              d	||           g cY d}~S d}~ww xY w)
ua   Return unique issuers matching a text query with their ultimate parent — used for autocomplete.r   Nr   z)IssuerCommonName,UltimateParentCommonNamer   rb   UltimateParentCommonName)rq   parentu/   LSEG: issuer name search failed for '%s' — %s)rQ   rB   rC   r}   r~   r   setr   r#   r   addr   rM   rK   rN   )r<   r   r^   rO   r   seenr   r   r   nprP   s               r"   search_issuer_namesz!LsegApiClient.search_issuer_namesg  sF   

	""""""l))EB	 *  G '-	 UUD "E!**,, ; ;3377#56677377#=>>?? ;$HHQKKKLL!q!9!9:::L 	 	 	LLJESVWWWIIIIII	s$   .C( B"C( (
D2DDDdictc                   |                                   	 ddlm} |j                            |ddd          }||j        rt                              d|           i S t          |j	        d         
                    d                    }|si S |                    |gg d	          }||j        ri S |j	        d         }t          |
                    d
                    pdt          |
                    d                    pdt          |
                    d                    pdd}t                              d|||           |S # t          $ r(}t                              d||           i cY d}~S d}~ww xY w)u  
        Look up GICS classification for an issuer via their listed equity.
        GICS is an equity-level concept — bond RICs don't carry it directly.
        Step 1: discovery search for the company's equity to get its RIC.
        Step 2: ld.get_data on that equity RIC for GICS Sector/IG/Industry names.
        Returns {"sector", "industry_group", "industry"} or empty dict on failure.
        r   NzAssetType eq '[EQUITY]'r   zRIC,IssuerCommonNamer   z-LSEG: no equity found for GICS lookup of '%s'r`   )zTR.GICSSectorzTR.GICSIndustryGroupzTR.GICSIndustryzGICS Sector Namer   zGICS Industry Group NamezGICS Industry Name)sectorindustry_groupindustryu#   LSEG: GICS for '%s' (via %s) → %su/   LSEG: GICS equity lookup failed for '%s' — %s)rQ   rB   rC   r}   r~   r   rK   r   r#   ilocr   r   rL   rM   rN   )	r<   rU   rO   eq
equity_ricr   r   namesrP   s	            r"   lookup_issuer_gicsz LsegApiClient.lookup_issuer_gics  s    	

"	""""""$$!0-	 %  B zRXzNP[\\\	
u 5 566J 	LLL B zRXz	'!*C"(1C)D)D"E"E"SQS"(1K)L)L"M"M"SQS"(1E)F)F"G"G"TRT E
 KK5Z   L 	 	 	LLJKY\]]]IIIIII	s1   A	E  0E #E 5BE 
E?E:4E?:E?sector_prefixc                   |                                   	 ddlm} |                    dd          }|j                            |j        j        j        d| d|t                    }||j	        rg S g }|
                                D ]\  }}t          |                    d                    }	|	s+|                    |	t          |                    d	                    t          |                    d
                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    t          |                    d                    d           t                               d|t%          |                     |S # t&          $ r(}
t                               d||
           g cY d}
~
S d}
~
ww xY w)u  
        Search for peer bonds in the same TRBC sector using a genealogy code prefix filter.
        More reliable than free-text search — uses exact TRBC classification codes so the
        full peer universe is captured regardless of issuer name phrasing.

        sector_prefix: first N segments of RCSTRBC2012Genealogy joined by backslashes,
          e.g. 'B:180\B:181\B:182' for Industry Group (sector) level,
               'B:180\B:181\B:182\B:183' for Industry (sub-sector) level.
        r   N\z\\zhAssetType eq 'CORP' and CouponType ne 'FXDI' and Currency eq 'USD' and startswith(RCSTRBC2012Genealogy,'z')viewr]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   u(   LSEG: genealogy prefix '%s' → %d bondsu*   LSEG: sector search failed for '%s' — %s)rQ   rB   rC   r)   r}   r~   ViewsGOV_CORP_INSTRUMENTSr   r   r   r#   r   r   r-   r1   rK   rL   r   rM   rN   )r<   r   r^   rO   escapedr   r   r   r   ro   rP   s              r"   search_peers_by_sectorz$LsegApiClient.search_peers_by_sector  s    	

)	""""""#++D&99Gl))\'<I=DI I I % * 	 	G '-	G!**,,  3SWWU^^,, (+(.swwv(?(?(.sww7I/J/J(K(K(.sww|/D/D(E(E(1#'',2G2G(H(H(4SWW^5L5L(M(M(4SWW[5I5I(J(J(1#'':K2L2L(M(M(.sww|/D/D(E(E(.sww~/F/F(G(G(.swwz/B/B(C(C(.swwz/B/B(C(C(1#'''2B2B(C(C(.sww7M/N/N(O(O         KKBMSVW^S_S_```N 	 	 	LLE}VYZZZIIIIII	s%   AJ% 3H1J% %
K/KKKNsector_codeig_coder   c                   |                                   	 ddlm} d| d}|r	|d| dz  }|j                            |j        j        j        d| |t                    }||j        rg S g }|	                                D ]\  }}	t          |	                    d                    }
|
s+|                    |
t          |	                    d	                    t          |	                    d
                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    d           t                              d||t#          |                     |S # t$          $ r(}t                              d||           g cY d}~S d}~ww xY w)zOSearch peer bonds filtered by GICS Sector (and optionally Industry Group) code.r   NzGICSSectorCode eq 'r   z and GICSIndustryGroupCode eq 'zGAssetType eq 'CORP' and CouponType ne 'FXDI' and Currency eq 'USD' and r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   u'   LSEG: GICS sector=%s ig=%s → %d bondsu.   LSEG: GICS peer search failed sector=%s — %s)rQ   rB   rC   r}   r~   r   r   r   r   r   r#   r   r   r-   r1   rK   rL   r   rM   rN   )r<   r   r   r^   rO   gics_filterr   r   r   r   ro   rP   s               r"   search_peers_by_gicsz"LsegApiClient.search_peers_by_gics  s   

*	"""""">>>>K LKKKKKl))\'<*'* * % * 	 	G '-	G!**,,  3SWWU^^,, (+(.swwv(?(?(.sww7I/J/J(K(K(.sww|/D/D(E(E(1#'',2G2G(H(H(4SWW^5L5L(M(M(4SWW[5I5I(J(J(1#'':K2L2L(M(M(.sww|/D/D(E(E(.sww~/F/F(G(G(.swwz/B/B(C(C(.swwz/B/B(C(C(1#'''2B2B(C(C(.sww7M/N/N(O(O         KKA;PWY\]dYeYefffN 	 	 	LLI;X[\\\IIIIII	s%   AJ  -H2J   
K*KKKAaa)Aa1Aa2Aa3)A1A2A3)Baa1Baa2Baa3)Ba1Ba2Ba3)B1B2B3)Caa1Caa2Caa3)AAAAAABBBBBBCCCzdict[str, list[str]]_BUCKET_TO_MOODYrating_bucketc                   | j                             |g           }|sg S |                                  	 ddlm} d                    d |D                       }|j                            |j        j        j	        d| d|t                    }||j        rg S g }|                                D ]\  }}	t          |	                    d                    }
|
s+|                    |
t          |	                    d	                    t          |	                    d
                    t          |	                    d                    t          |	                    d                    t!          |	                    d                    t!          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    t          |	                    d                    d           t"                              d|t'          |                     |S # t(          $ r(}t"                              d||           g cY d}~S d}~ww xY w)zPSearch for USD corporate bonds in the same Moody's rating bucket (cross-sector).r   Nz or c              3  "   K   | ]
}d | dV  dS )zMoodysRating eq 'r   N ).0r   s     r"   	<genexpr>z7LsegApiClient.search_peers_by_rating.<locals>.<genexpr>%  s.      'X'XQ(@A(@(@(@'X'X'X'X'X'Xr$   zHAssetType eq 'CORP' and CouponType ne 'FXDI' and Currency eq 'USD' and ()r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   u4   LSEG: rating bucket '%s' (cross-sector) → %d bondsu0   LSEG: rating peer search failed bucket=%s — %s)r   r   rQ   rB   rC   joinr}   r~   r   r   r   r   r   r#   r   r-   r1   rK   rL   r   rM   rN   )r<   r   r^   moody_ratingsrO   rating_filterr   r   r   r   ro   rP   s               r"   search_peers_by_ratingz$LsegApiClient.search_peers_by_rating  s   -11-DD 	I

(	"""""""KK'X'X-'X'X'XXXMl))\'<.*. . . % * 	 	G '-	G!**,,  3SWWU^^,, %(%+CGGFOO%<%<%+CGG4F,G,G%H%H%+CGGL,A,A%B%B%.sww|/D/D%E%E%1#''.2I2I%J%J%1#''+2F2F%G%G%.sww7H/I/I%J%J%+CGGL,A,A%B%B%+CGGN,C,C%D%D%+CGGJ,?,?%@%@%+CGGJ,?,?%@%@%.swww/?/?%@%@%+CGG4J,K,K%L%L         KKNP]_bcj_k_klllN 	 	 	LLK]\_```IIIIII	s%   A%K H1K 
K?K:4K?:K?c                T    |                                   |                     |          S )z+Public wrapper for batch market data fetch.)rQ   r   )r<   r   s     r"   fetch_market_datazLsegApiClient.fetch_market_dataM  s#    

&&t,,,r$   issuer_namesc                   |                                   i }ddlm} |D ]2}|                     ||j                  D ]}|d         }||vr|||<   3|st
                              d           g S t          |                                          }t
          	                    dt          |          t          |                     |                     |          }g }	|                                D ];\  }}
|                    |i           }|	                    i d|
                    d          p|d|
                    d          d	|
                    d	          d
|
                    d
          d|
                    d          d|
                    d          d|
                    d          d|
                    d          d|
                    d          d|
                    d          d|
                    d          d|
                    d          p|                    d          d|d|                    d          d|                    d          d|                    d          d|                    d          |                    d          |                    d          p|
                    d          |                    d          |                    d          |                    d          |
                    d          d           =t
          	                    dt          |	                     |	S ) z
        Search for bonds by issuer, capture reference data from search, then
        enrich with live market data from get_data. Merges both into one record.
        r   )settings)rV   ro   z5LSEG: no bonds found for any of the requested issuersz9LSEG: fetching market data for %d bonds across %d issuersrp   rq   rr   rs   rt   ru   rv   rw   rx   ry   rz   r{   r
   r   r   r   r	   r   r   r   r   r   r|   )r   r   r   r   r   r|   z-LSEG API: merged %d bonds (ref + market data))rQ   
app.configr  r   bonds_per_issuerrK   r   r[   keysrL   r   r   r   r   r   )r<   r  
ref_by_ricr  rq   bondro   r   r   r   refr   s               r"   fetch_bonds_for_issuersz%LsegApiClient.fetch_bonds_for_issuersR  s   
 	

 ')
''''''  	+ 	+D33DhF_3`` + +5kj((&*JsO+
  	NNRSSSIJOO%%&&OIIs<00	2 	2 	2 ((.. "((** 	 	HC

3##ANN SWWV__%;SWWV__ SWWX%6%6 SWWX%6%6	
  SWW_%=%= SWW\%:%: SWW]%;%; SWW]%;%;  SWW_%=%= SWW[%9%9 SWWZ%8%8 SWWW%5%5%K{9K9K S QUU5\\ QUU5\\  QUU:%6%6!" QUU5\\#$ '(ee,?&@&@&'eeI&6&6&L#''):L:L&'eeI&6&6&'eeO&<&<&'eeJ&7&7&)ggk&:&:/      4 	CS\\RRRr$   )r4   r   r5   r   r6   r   )rT   )rU   r   rV   rW   r   rX   )rO   r   r   r   r   r   )r   r   r   r   )r   r   r   rX   )r   )r   r   r^   rW   r   rX   )r   )rU   r   r   r   )r   r   r^   rW   r   rX   )Nr   )r   r   r   r   r^   rW   r   rX   )r   r   r^   rW   r   rX   )r  r   r   rX   )__name__
__module____qualname____doc__r=   rQ   rS   r   r   r   r   r   r   r   r   r   r   r   r   r   __annotations__r
  r  r  r  r$   r"   r3   r3   N   s              0! ! !Q Q Q Q Qf KL   *) ) ) )V& & & &P' ' ' ' 'R    4+ + + +Z4 4 4 4 4l- - - - -` w$$$!!!'''$$$!!!'''. .    . . . . .`- - - -
: : : : : :r$   r3   )r   r   )r   r%   )r  
__future__r   loggingr   typingr   r   	getLoggerr  rK   r   r   r   r   r#   r-   r1   r3   r  r$   r"   <module>r      s*   T T " " " " " "                  		8	$	$    "'!&!+!&!,!,!4!*!0!*!+     DCC5 5 5 5   . . . .~ ~ ~ ~ ~ ~ ~ ~ ~ ~r$   