
    xj8              
         d dl mZ d dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
 d dlmZmZ d dlmZmZ d dlmZ d dlmZmZ d dlmZmZ d d	lmZ d d
lmZ  e	d           G d d                      Ze	 G d d                      Z G d de          Z G d dee          Z G d de           Z! G d de           Z" G d d          Z#dJdZ$d d!dKd&Z%dLdMd-Z&dNd/Z'dOd3Z(dPd4Z)dQd:Z*dRd?Z+d'd@dAdAdddAdBdCdD	dSdIZ,dS )T    )annotationsN)	dataclassfield)datetimetimezone)DecimalInvalidOperation)
Connection)ProtocolSequence)	stable_idutc_nowcreate_alert)!resolve_fixed_crypto_price_alertsT)frozenc                  f    e Zd ZU ded<   ded<   ded<   dZded<   dZd	ed
<   dZded<   dZd	ed<   dS )
PriceQuotestrcoingecko_idcurrencyzDecimal | Noneprice	CoinGeckoproviderN
str | Noneprovider_timestampfreshquality_statuserror_message)__name__
__module____qualname____annotations__r   r   r   r        ^/home/agent/.hermes/worktrees/FinanceManager-sprint20h1/src/jarvis_finance/market/providers.pyr   r      sx         MMMH%)))))!N!!!! $M$$$$$$r%   r   c                     e Zd ZU ded<   dZded<   dZded<   dZded<   dZded<   dZded	<   dZ	ded
<   dZ
ded<   dZded<   dZded<    ee          Zded<    ee          Zded<    ee          Zded<   edd            ZdS )PriceRefreshResultr   r   r   inttotal_assetsupdated_countskipped_countcached_countstale_countwarning_counterror_countmissing_local_price_countFbooldry_run)default_factoryz	list[str]written_price_idswarningserrorsreturnc                    | j         S N)r+   )selfs    r&   success_countz PriceRefreshResult.success_count.   s    !!r%   N)r8   r)   )r    r!   r"   r#   r*   r+   r,   r-   r.   r/   r0   r1   r3   r   listr5   r6   r7   propertyr<   r$   r%   r&   r(   r(      s2        MMMLMMLKMK%&&&&&G#(5#>#>#>>>>>%555H5555d333F3333" " " X" " "r%   r(   c                      e Zd Zd	d
dZdS )MarketDataProviderCHFr   r   r   r8   r   c                    d S r:   r$   r;   r   r   s      r&   get_crypto_pricez#MarketDataProvider.get_crypto_price4         r%   NrA   r   r   r   r   r8   r   )r    r!   r"   rD   r$   r%   r&   r@   r@   3   s        [[[[[[[r%   r@   c                      e Zd Zd
ddZd	S )BatchMarketDataProviderrA   coingecko_idsSequence[str]r   r   r8   dict[str, PriceQuote]c                    d S r:   r$   )r;   rJ   r   s      r&   get_crypto_pricesz)BatchMarketDataProvider.get_crypto_prices8   rE   r%   NrF   rJ   rK   r   r   r8   rL   )r    r!   r"   rN   r$   r%   r&   rI   rI   7   s        rrrrrrrr%   rI   c                      e Zd ZdS )ProviderRateLimitErrorNr    r!   r"   r$   r%   r&   rQ   rQ   ;           Dr%   rQ   c                      e Zd ZdS )ProviderFetchErrorNrR   r$   r%   r&   rU   rU   ?   rS   r%   rU   c                  `    e Zd ZdZdddddej        dddZdd dZdd!dZe	d"d            Z
dS )#CoinGeckoClient	coingeckoz https://api.coingecko.com/api/v3   g      ?g       @N)base_urlmax_retriesinitial_backoff_secondsmax_backoff_secondsopenersleeperrZ   r   r[   r)   r\   floatr]   r8   Nonec                   |                     d          | _        || _        || _        || _        |pt
          j        j        | _        || _	        d S )N/)
rstriprZ   r[   r\   r]   urllibrequesturlopenr^   r_   )r;   rZ   r[   r\   r]   r^   r_   s          r&   __init__zCoinGeckoClient.__init__F   sI     ,,&'>$#6 6 6r%   rA   r   r   r   c           
         |                      |g|                              |t          ||                                d dd                    S )Nmissingprice missingr   r   )rN   getr   upperrC   s      r&   rD   z CoinGeckoClient.get_crypto_priceN   sP    %%|nh??CC|X^^%5%5tIetuuu
 
 	
r%   rJ   rK   rL   c                j    d t                               |          D             }                                }|si S t          j                            d                    |          |dd          } j         d| } j        }d t           j
        dz             D ]}	                      |d          5 }	t          j        |	                                                    d	                    d d d            n# 1 swxY w Y    fd
|D             c S # t          j        j        $ r}}
d|
j         |
j        dk    r=| j
        k     r2                     t)          | j                             |dz  }Y d }
~
|
j        dk    rdndfd|D             cY d }
~
c S d }
~
wt,          $ rh}
t/          |
          | j
        k     r3                     t)          | j                             |dz  }Y d }
~
dfd|D             cY d }
~
c S d }
~
ww xY wfd|D             S )Nc                    g | ]}||S r$   r$   ).0cids     r&   
<listcomp>z5CoinGeckoClient.get_crypto_prices.<locals>.<listcomp>U   s    BBBscBsBBBr%   ,true)idsvs_currenciesinclude_last_updated_atz/simple/price?      )timeoutzutf-8c           
     j    i | ]/}|                     |                    |          pi           0S r$   )_quote_from_payloadrm   )rq   r   r   payloadr;   s     r&   
<dictcomp>z5CoinGeckoClient.get_crypto_prices.<locals>.<dictcomp>a   sZ      Q  Q  Q  }Id&>&>|XW^WbWbcoWpWpWvtv&w&w  Q  Q  Qr%   zHTTP i  rY   staleerrorc           
     ^    i | ])}|t          |                                d           *S )Nrl   r   rn   )rq   rr   r   
last_errorstatuss     r&   r   z5CoinGeckoClient.get_crypto_prices.<locals>.<dictcomp>i   sM      F  F  Fz}ZX^^-=-=tTZjtuuu  F  F  Fr%   c           
     ^    i | ])}|t          |                                d d          *S Nr   rl   r   rq   rr   r   r   s     r&   r   z5CoinGeckoClient.get_crypto_prices.<locals>.<dictcomp>p   sM      G  G  G{~ZX^^-=-=tT[kuvvv  G  G  Gr%   c           
     ^    i | ])}|t          |                                d d          *S r   r   r   s     r&   r   z5CoinGeckoClient.get_crypto_prices.<locals>.<dictcomp>q   s:    ~~~svZX^^%5%5tGcmnnn~~~r%   )dictfromkeyslowerre   parse	urlencodejoinrZ   r\   ranger[   r^   jsonloadsreaddecoder   	HTTPErrorcoder_   minr]   	Exceptionr   )r;   rJ   r   rv   curqueryurldelayattemptrespexcr   r~   r   s   ` `        @@@r&   rN   z!CoinGeckoClient.get_crypto_pricesT   s   BBdmmM::BBBnn 	I&&sxx}}sou'v'vww55e55,!%
T-122 	G 	GGG[[b[11 FT"j););G)D)DEEGF F F F F F F F F F F F F F F Q  Q  Q  Q  Q  Q  MP  Q  Q  Q  Q  Q  Q<) F F F/SX//
8s??w1A'A'ALLUD,D!E!EFFFQJEHHHH$'HOO F  F  F  F  F  F  BE  F  F  F  F  F  F  F  F  F  F  F G G G XX
T---LLUD,D!E!EFFFQJEHHHH G  G  G  G  G  CF  G  G  G  G  G  G  G  G  G  G  GG ~~~~z}~~~~sb   (D"?:D9D"D			D"D		D""H#6AF.F.&H#.H#;AHHH#H#datar   c                   |                                 }|                    |          }|&t          | |                                d dd          S 	 t	          t          |                    }n6# t          $ r) t          | |                                d dd          cY S w xY w|                    d          }d }|rg	 t          j        t          |          t          j                                                  }n&# t          t          f$ r t          |          }Y nw xY wt          | |                                ||          S )	Nrj   rk   rl   r   zinvalid pricelast_updated_at)tz)r   )r   rm   r   rn   r   r   r	   r   fromtimestampr)   r   utc	isoformat	TypeError
ValueError)r   r   r   r   valuer   tsprovider_tss           r&   r}   z#CoinGeckoClient._quote_from_payloads   sO   nn=lHNN,<,<dS\l{||||	{CJJ''EE 	{ 	{ 	{lHNN,<,<dSZjyzzzzzz	{XX'(( 	&&&4SWWNNNXXZZz* & & &!"gg&,(8(8%T_````s$   A0 00B#"B# ?D    D#"D#)
rZ   r   r[   r)   r\   r`   r]   r`   r8   ra   rF   rG   rO   )r   r   r   r   r   r   r8   r   )r    r!   r"   provider_keytimesleeprh   rD   rN   staticmethodr}   r$   r%   r&   rW   rW   C   s        L*Lab  FI  hk  tx  BF  BL      
 
 
 
 
    > a a a \a a ar%   rW   r   r   r8   datetime | Nonec                    | sd S 	 t          j        |                     dd                    }n# t          $ r Y d S w xY w|j        r|n|                    t
          j                  S )NZz+00:00)tzinfo)r   fromisoformatreplacer   r   r   r   )r   dts     r&   	_parse_dtr      sw     t#EMM#x$@$@AA   tt?22

(,
 ? ??s   (/ 
==iQ max_age_seconds	timestampr   r)   r2   c                   t          |           }|dS t          j        t          j                  |z
                                  |k    S )NT)r   r   nowr   r   total_seconds)r   r   r   s      r&   is_price_staler      sA    	9		B	ztL&&+::<<NNr%   rA   connr
   asset_idr   r   c                z    |                      d||                                f                                          S )Nz
        SELECT * FROM crypto_prices
        WHERE asset_id=? AND price_currency=?
        ORDER BY COALESCE(provider_timestamp, fetched_at, '') DESC, fetched_at DESC
        LIMIT 1
        )executern   fetchone)r   r   r   s      r&   latest_crypto_price_rowr      s<    <<	 
8>>##$  hjjr%   quotec                  t                      }t          d||j        |j        |j        |          }|                     d|||j        |j                                        |j        t          |j        d          nd|j        |j	        ||j
        |j        f
           |j
        dv r;t          | ddd|d	|j
         d
|j
         d|j        |j        |j        d           |                                  |S )Ncryptopricez
        INSERT INTO crypto_prices(crypto_price_id, asset_id, coingecko_id, price_currency, price, provider, provider_timestamp, fetched_at, quality_status, error_message)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        f >   r   r   rj   conflictwarnungmarket_datacrypto_assetcrypto_price_zCrypto price quality is .)r   r   r   )prioritycategoryentity_type	entity_idrule_idmessageevidence)r   r   r   r   r   r   rn   r   formatr   r   r   r   commit)r   r   r   r   price_ids        r&   store_crypto_pricer      s   
))C%2DenV[VdfijjHLL	 
8U/1E1E1G1Gejepe|PUP[]`IaIaIa  CE  GL  GU  W\  Wo  qt  v{  vJ  LQ  L_  	`   HHHTISamu  @f  PU  Pd  @f  @f  pb  KP  K_  pb  pb  pb  ~C  ~P  ^c  ^l  w|  wJ  mK  mK  	L  	L  	L  	LKKMMMOr%   symbolr   ra   c               D    t          | ddd|dd|||dd| 	  	         d S )	Nr   r   r   crypto_price_missing_localz4Crypto asset has no fresh local price after refresh.)r   r   r   zcrypto_price_missing_local:r   r   r   r   r   r   r   fingerprintr   )r   r   r   r   r   s        r&   !_create_missing_local_price_alertr      sP    ",F"LhWW<(<<
 
 
 
 
 
r%   c                    t          | ||          }t          |o#|d         dk    ot          |d         |                     S )Nr   r   
fetched_atr   )r   r2   r   )r   r   r   r   latests        r&   _has_fresh_local_pricer      sq    $T8X>>F  M6"23w>  M~V\]iVj  }L  HM  HM  HM  DM  N  N  Nr%   only_missing
only_staleonly_symbollimit
int | Nonec                  |                      d                                          }g }|r|                                nd }	|D ]}
|	r!|
d         pd                                |	k    r%t          | |
d         |          }|d uo|d         dvo|d         dk    }t	          |o"|d         dk    ot          |d	         |
                    }|r|r|r|s|                    |
           |t          |          |k    r n||fS )NzZSELECT asset_id, coingecko_id, symbol FROM crypto_assets WHERE is_active=1 ORDER BY symbolr   r   r   r   )Nr   r   r   r   r   )r   fetchallrn   r   r2   r   appendlen)r   r   r   r   r   r   r   assetsfilteredwanted_symbolassetr   has_anyis_stales                 r&   _filter_assetsr      st   \\vww  A  A  C  CFH+6@K%%'''DM   	eHo3::<<MM(uZ/@(KK$r
)JrvVfOgkrOr  Q6*:#;w#F  Q>Z`amZn  AP  LQ  LQ  LQ  R  R 	G 	 	h 	X%!7!7E8r%   r   rJ   rK   rL   c                p     t           d          r                     |          S  fd|D             S )NrN   c                >    i | ]}|                     |          S r$   )rD   )rq   rr   r   r   s     r&   r   z'_provider_get_batch.<locals>.<dictcomp>   s+    SSScC**399SSSr%   )hasattrrN   )r   rJ   r   s   ` `r&   _provider_get_batchr      sK    x,-- C))-BBBSSSSS]SSSSr%   i  Fg        d   )	r   r   r   r   r   r   r3   sleep_seconds
batch_sizer3   r   r`   r   c       
        	                                    t          |          }t          | |||||          \  }}t          |          |_        |s|s|s|;|xj        t          dt          |          t          |          z
            z  c_        g }|D ]}|d         }|d         s|s:t          | ddd|d	d
d|d         id		  	         t          | ||d         d            |xj        dz  c_        |xj	        dz  c_	        |j
                            |d          d           t          | |          }|r4|d         dk    r(t          |d         |          s|xj        dz  c_        |                    |           t                      }t!          dt          |          t          d|
                    D ]}|r|	dk    rt#          j        |	           |||t          d|
          z            }d |D             }	 t'          ||          }n&# t(          $ rfd|D             }Y d nd ww xY w|D ]}|                    |d                   pt-          |d         d dd          }|s2t/          | |d         |          }|j                            |           |j        K|j        dk    r@|xj        dz  c_        |                    |d                    |st;          | |           n|j        dv r;|xj	        dz  c_	        |j
                            |d          d|j                    nA|xj        dz  c_        |j                            |d          d|j         p|j                    |j        dk    r|xj!        dz  c_!        |j        |j        dk    r(|s&t          | |d         |d         |d                    |ss|D ][}|d         |v rtE          | |d         |          s6|xj#        dz  c_#        t          | |d         |d         |d                    \| $                                 n-|D ]*}tE          | |d         |          s|xj#        dz  c_#        +|S )N)r   r3   )r   r   r   r   r   r   r   r   r   r   cryptor   missing_coingecko_idz8Crypto asset has no CoinGecko ID; price refresh skipped.r   r   )r   r   r   r   ry   z: missing_coingecko_idr   r   r   r   c                    g | ]
}|d          S )r   r$   )rq   r   s     r&   rs   z)refresh_crypto_prices.<locals>.<listcomp>  s    888u^$888r%   c                T    i | ]$}|t          |d dt                              %S r   )r   r   )rq   rr   r   r   s     r&   r   z)refresh_crypto_prices.<locals>.<dictcomp>  s9    zzzorc:c8T'adehaiaijjjzzzr%   rj   rk   rl   )r   r   )r   r   >   r   rj   z: r   )%rn   r(   r   r   r*   r,   maxr   r   r/   r6   r   r   r   r-   setr   r   r   r   r   rm   r   r   r5   r   r   r+   addr   r0   r7   r   r.   r   r1   r   )r   r   r   r   r   r   r   r   r3   r   r   result
all_assetsr   request_assetsr   r   r   refreshed_fresh_asset_idsstartchunkrv   quotesr   r   r   s     `                      @r&   refresh_crypto_pricesr     sS    ~~H7CCCF'xQ`o{  IS  al  ty  z  z  zJj//F Fz F[ FE4EAs:V'D E EEN % %$^$ 	 ITIVdpx  CY  c]  iq  sx  yA  sB  hC  Qg  h  h  h  h1$RWX`Rapt  @H  I  I  I  I  A%    A%  O""eHo#M#M#MNNN(xBB 	f-.'99.QWXdQe  xG  CH  CH  CH91$e$$$$*-%%q#n--s1j/A/ABB c c 	&]Q&&J}%%%uus1j/A/A'AAB88%888	{(3AAFF 	{ 	{ 	{zzzzzvyzzzFFFFFF	{ 	c 	cEJJu^455  dE.DY[cei  {D  Tc  :d  :d  :dE :-dU:=NV[\\\(//999{&5+?7+J+J$$)$$)--eJ.?@@@ p5dX_noooo%)===$$)$$&&%/'S'SU=Q'S'STTTT""a'""$$h%h%h5;N;fRWRf%h%hiii#w..""a'""#u';w'F'FPW'F1$zAR[`ai[jy~  @N  zO  Zb  c  c  c  c'	c*  6 	c 	cEZ $===)$j0A8_]] c00A5001$zAR[`ai[jy~  @N  zO  Zb  c  c  c  c  	6 	6E)$j0A8_]] 600A500Ms   H
I(H<<I)r   r   r8   r   )r   r   r   r)   r8   r2   rF   )r   r
   r   r   r   r   )r   r
   r   r   r   r   r8   r   )r   r
   r   r   r   r   r   r   r   r   r8   ra   )
r   r
   r   r   r   r   r   r)   r8   r2   )r   r
   r   r   r   r)   r   r2   r   r2   r   r   r   r   )r   r@   rJ   rK   r   r   r8   rL   )r   r
   r   r@   r   r   r   r)   r   r2   r   r2   r   r   r   r   r3   r2   r   r`   r   r)   r8   r(   )-
__future__r   r   r   urllib.errorre   urllib.parseurllib.requestdataclassesr   r   r   r   decimalr   r	   sqlite3r
   typingr   r   jarvis_finance.imports.commonr   r   jarvis_finance.quality.alertsr   #jarvis_finance.quality.data_qualityr   r   r(   r@   rI   RuntimeErrorrQ   rU   rW   r   r   r   r   r   r   r   r   r  r$   r%   r&   <module>r     sz   " " " " " "               ( ( ( ( ( ( ( ( ' ' ' ' ' ' ' ' - - - - - - - -       % % % % % % % % < < < < < < < < 6 6 6 6 6 6 Q Q Q Q Q Q $% % % % % % % % " " " " " " " "(\ \ \ \ \ \ \ \s s s s s0( s s s	 	 	 	 	\ 	 	 		 	 	 	 	 	 	 	Aa Aa Aa Aa Aa Aa Aa AaH@ @ @ @ EK O O O O O O	 	 	 	 	       N N N N
   (T T T T "R R R R R R R Rr%   