
    bAj2                        d Z ddlmZ ddlZddlmZmZ ddlmZmZ ddl	m
Z
 ddlZddlmZ ddlmZ  ee      Z e       Zd	Zd
Ze G d d             Ze G d d             Z G d d      Z e       Zy)uJ   Automatic symbol scanner — rotates active pairs by Binance 24h activity.    )annotationsN)	dataclassfield)datetimetimezone)Any)get_settings)
get_loggerz*https://api.binance.com/api/v3/ticker/24hr)UPUSDTDOWNUSDTBULLUSDTBEARUSDTc                  D    e Zd ZU ded<   ded<   ded<   ded<   dZded	<   y
)TickerSnapshotstrsymbolfloatquote_volumeprice_change_pctinttrade_countg        activity_scoreN)__name__
__module____qualname____annotations__r        Mc:\xampp\htdocs\tradingbinance\backend\app\services\symbol_scanner_service.pyr   r      s#    KNEr   r   c                      e Zd ZU ded<   ded<   ded<   ded<    ee      Zded<    ed	       Zd
ed<   dZded<    ee      Z	ded<   y)
ScanResult	list[str]active_symbolscore_symbolsrotation_pickspinned_symbols)default_factoryzlist[dict[str, Any]]
candidatesc                 d    t        j                  t        j                        j	                         S N)r   nowr   utc	isoformatr   r   r   <lambda>zScanResult.<lambda>&   s    HLL4N4X4X4Zr   r   
scanned_atFboolchangedprevious_symbolsN)
r   r   r   r   r   listr(   r/   r1   r2   r   r   r   r!   r!      sT    ',T'BJ$B,Z[J[GT"'"=i=r   r!   c                  z    e Zd ZdZddZd	dZd
dZ	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)SymbolScannerServicez
    Picks the most active USDT pairs from a rotation pool while keeping
    core symbols fixed. Uses Binance mainnet 24h tickers for real liquidity data.
    c                8  	K   t        j                  dd      4 d {   }|j                  t               d {   }|j	                          |j                         }d d d       d {    i }D ]  }|d   		j                  d      st        	fdt        D              r3	dv r8t        |d         }t        |d	         }t        |d
         }t        	|||| j                  |||            |	<    |S 7 7 7 # 1 d {  7  sw Y   xY ww)Ng      4@F)timeoutverifyr   USDTc              3  @   K   | ]  }j                  |        y wr*   )endswith).0suffixr   s     r   	<genexpr>z5SymbolScannerService.fetch_tickers.<locals>.<genexpr><   s     L9Kv6??6*9Ks   )USDCUSDTUSD1USDTEURUSDTquoteVolumepriceChangePercentcount)r   r   r   r   r   )httpxAsyncClientgetMAINNET_TICKER_URLraise_for_statusjsonr;   anyLEVERAGED_SUFFIXESr   r   r   _activity_score)
selfclientresponserawtickersitemr   r   r   r   s
            @r   fetch_tickersz"SymbolScannerService.fetch_tickers1   s    $$T%@@F#ZZ(:;;H%%'--/C A@
 .0D(^F??6*L9KLL<< m!45L$T*>%?@d7m,K,)!1'#33LBRT_`GFO & 3 A; A@@@sU   DC?DDD$D!D,D-BDDDDDDDc                    t        j                  t        |d            }t        j                  t        |d            }t        t	        |      d      dz  }t        |dz  |dz  z   |dz  z   d      S )Ng      ?g      $@g      ?g333333?g       @   )mathlog10maxminabsround)rN   r   r   r   vol_parttrades_part	move_parts          r   rM   z$SymbolScannerService._activity_scoreM   sg    ::c,45jj[#!67,-t4t;	X^kC&77)c/I1MMr   c                    |j                   t        j                  k  ryt        |j                        t        j
                  kD  ryy)NFT)r   settings$symbol_scanner_min_quote_volume_usdtr[   r   !symbol_scanner_max_abs_change_pct)rN   tickers     r   _is_valid_candidatez(SymbolScannerService._is_valid_candidateS   s8    !N!NNv&&'(*T*TTr   Nc                   |xs g }|xs g }g }|D ]>  }||v r|j                  |      }	|	s| j                  |	      s.|j                  |	       @ |j                  d d       |d | D 
cg c]  }
|
j                   }}
t        t        j                  ||z   |z               }||k7  }t        |D cg c]  }||v s||    c}d d      D 
cg c]m  }
|
j                  t        |
j                  dz  d      t        |
j                  d      |
j                  |
j                  |
j                  |v |
j                  |v do }}
t        |||||d d ||	      S c c}
w c c}w c c}
w )
Nc                    | j                   S r*   r   )ts    r   r.   z5SymbolScannerService.select_symbols.<locals>.<lambda>n   s
    1+;+;r   T)keyreversec                    | j                   S r*   rh   )xs    r   r.   z5SymbolScannerService.select_symbols.<locals>.<lambda>   s
    a..r   i@B    )r   quote_volume_mr   r   r   selectedin_pool   )r#   r$   r%   r&   r(   r1   r2   )rG   re   appendsortr   r3   dictfromkeyssortedr\   r   r   r   r   r!   )rN   rR   r$   rotation_poolrotation_slotsr&   r2   pool_candidatesr   rd   ri   r%   activer1   sr(   s                   r   select_symbolsz#SymbolScannerService.select_symbolsZ   s    (-2+1r02#F%[[(F$226:&&v. $ 	!;TJ,;O^,LM,Lq!((,LMdmmL>$AN$RST,, %2C]a7l]C.
 (("'(BA"F$)!*<*<a$@ }}"#"2"2HH688}4 	 
" !%))!#2-
 	
- N  D
s   -E4	E >E A2E%c           	     v  K   t         j                  s?|xs t         j                  }t        ||xs t         j                  g |xs g d|xs g       S | j                          d {   }| j                  ||xs t         j                  |xs t         j                  |xs t         j                  ||      S 7 Qw)NF)r#   r$   r%   r&   r1   r2   )rR   r$   rx   ry   r&   r2   )	ra   symbol_scanner_enableddefault_symbolsr!   symbol_scanner_core_symbolsrT   r}   symbol_scanner_rotation_poolsymbol_scanner_rotation_slots)rN   r$   rx   ry   r&   r2   symbolsrR   s           r   scanzSymbolScannerService.scan   s      ..&B(*B*BG&)QX-Q-Q!-3!1!7R  **,,""%M)M)M'P8+P+P)SX-S-S)- # 
 	
 -s   A#B9%B7&AB9)returndict[str, TickerSnapshot])r   r   r   r   r   r   r   r   )rd   r   r   r0   )NN)rR   r   r$   r"   rx   r"   ry   r   r&   list[str] | Noner2   r   r   r!   )NNNNN)r$   r   rx   r   ry   z
int | Noner&   r   r2   r   r   r!   )	r   r   r   __doc__rT   rM   re   r}   r   r   r   r   r5   r5   +   s    
8N ,0-13
*3
  3
 !	3

 3
 )3
 +3
 
3
n *.*.%)+/-1
&
 (
 #	

 )
 +
 

r   r5   )r   
__future__r   rW   dataclassesr   r   r   r   typingr   rE   app.core.configr	   app.core.loggingr
   r   loggerra   rH   rL   r   r!   r5   symbol_scanner_servicer   r   r   <module>r      s    P "  ( '   ( '	H	>A C        > > >
 
D ./ r   