
    =j7=                        d 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 ddlm	Z	m
Z
mZ ddlmZmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZmZmZ ddlmZ  ee      Z  e       Z! G d d      Z" G d d      Z# e#       Z$y)zKBinance API service with testnet support, rate limiting, and error logging.    N)datetimetimezone)Decimal)AnyCallableOptional)AsyncClientBinanceSocketManager)BinanceAPIException)retrystop_after_attemptwait_exponential)get_settings)
get_logger)
API_ERRORSAPI_WEIGHT_USEDWS_CONNECTED)	get_redisc                   *    e Zd ZdZddedefdZddZy)	RateLimiterz0Token bucket rate limiter for Binance API calls.max_requestswindow_secondsc                 `    || _         || _        g | _        t        j                         | _        y N)r   r   requestsasyncioLock_lock)selfr   r   s      FC:\xampp\htdocs\tradingbinance\backend\app\services\binance_service.py__init__zRateLimiter.__init__   s&    (,%'\\^
    Nc                 B  K   | j                   4 d {    t        j                         }| j                  D cg c]  }||z
  | j                  k  s| c}| _        t        | j                        | j                  k\  rA| j                  || j                  d   z
  z
  }|dkD  rt        j                  |       d {    | j                  j                  t        j                                d d d       d {    y 7 c c}w 7 I7 # 1 d {  7  sw Y   y xY ww)Nr   )
r   time	monotonicr   r   lenr   r   sleepappend)r   nowt
sleep_times       r    acquirezRateLimiter.acquire    s     :::.."C(,W1q4CVCV9VQWDM4==!T%6%66!00C$--:J4JK
>!--
333MM  !12 ::W 4 :::sh   DC?D#D
DDA&D
<D=1D
.D9D:DD
D
DDDD)i  <   returnN)__name__
__module____qualname____doc__intr!   r,    r"   r    r   r      s    :$S $ $3r"   r   c                      e Zd ZdZej
                  ej                  ej                  ej                  ej                  ej                  dZd Zd.dZd.dZedefd       Zdefd	Zd/d
ee   defdZdefdZdee   ddfdZdeddfdZdefdZd/dedededz  ddfdZ e ed       e ddd            	 	 	 d0d
edededee   dee   de!e   fd       Z"d
ede#fdZ$d1d
ededefd Z%d2d
edede!e   fd!Z&de!e   fd"Z'	 	 	 	 d3d
ed#ed$e#d%ed&ee#   d'ee#   d(ee   defd)Z(	 d4d*e!e   d+e)ee#ge*f   d,e+ddfd-Z,y)5BinanceServicezJConnects to Binance Testnet/Spot API with reconnection and error handling.)1m5m15m1h4h1dc                     d | _         d | _        t               | _        d| _        g | _        g | _        d| _        d| _        d| _	        i | _
        d | _        y )NFr   i  )clientbsmr   rate_limiter
_connected	_ws_tasks_error_callbacks_time_offset_msrecv_window_last_weight_used_exchange_info_cache_loopr   s    r    r!   zBinanceService.__init__7   sW    -137'M-/02$% $&'*,!:>
r"   r/   Nc                 B  K   t        j                         }| j                  /| j                  #| j                  |urd | _        d | _        d| _        | j                  y t        j                  t        j                  xs d t        j                  xs d t        j                         d {   | _        t        | j                        | _        d| _        || _        t        j                  dt        j                  t        j                  j                          y 7 pw)NF)api_key
api_secrettestnetTbinance_connected)rN   mode)r   get_event_loopr?   rI   r@   rB   r	   createsettingsbinance_api_keybinance_api_secretbinance_testnetr
   loggerinfotrading_modevalue)r   current_loops     r    connectzBinanceService.connectD   s     --/ ;;"tzz'=$**T`B`DKDH#DO;;"'..,,422:d,,
 

 (4!
,,&&,, 	 	

s   B*D,D-A1Dc                   K   | j                   D ]  }|j                           | j                   j                          | j                  r0| j                  j	                          d {    d | _        d | _        d| _        y 7 w)NF)rC   cancelclearr?   close_connectionr@   rB   )r   tasks     r    
disconnectzBinanceService.disconnecta   sd     NNDKKM #;;++..000DKDH 1s   A%B'B(Bc                 :    | j                   xr | j                  d uS r   )rB   r?   rJ   s    r    is_connectedzBinanceService.is_connectedk   s    :4;;d#::r"   c                    K   | j                          d{    | j                  j                          d{   }t        t	        j                         dz        }|d   |z
  | _        | j
                  S 7 _7 ?w)z0Sync local clock offset with Binance serverTime.N  
serverTime)r\   r?   get_server_timer4   r$   rE   )r   server_timelocal_mss      r    sync_server_timezBinanceService.sync_server_timeo   sf     lln KK7799tyy{T)**<88C###	 	9s   A:A6!A:A8>A:8A:symbolc                 :  K   | j                          d {    | j                  j                          d {    | j                  j	                          d {   }|r2|j                  dg       D ]  }|d   |k(  s|| j                  |<   |c S  |S 7 ~7 ^7 >w)Nsymbolsrl   )r\   rA   r,   r?   get_exchange_infogetrH   )r   rl   rX   ss       r    ro   z BinanceService.get_exchange_infow   s     lln'')))[[2244XXi,X;&(89D--f5H -  	)4s7   BB!BB!BB#B?BBBc                    K   t         j                  st         j                  sy	 | j                          d{    t        j                  dd       y7 # t        $ r Y yw xY ww)z<Abort if API key has withdrawal permission (security check).TNwithdraw_permission_checkz'Verify manually in Binance API settings)noteF)rS   rV   rT   r\   rW   rX   	ExceptionrJ   s    r    verify_no_withdraw_permissionz,BinanceService.verify_no_withdraw_permission   s[     ##8+C+C	,,.  KK3:cKd !  		s8   "A&A AA A&A 	A# A&"A##A&response_headersc                     |sy |j                  d      xs |j                  d      }|r0t        |      | _        t        j                  | j                         y y )Nzx-mbx-used-weightzX-MBX-USED-WEIGHT)rp   r4   rG   r   set)r   rw   weights      r    _track_response_headersz&BinanceService._track_response_headers   sS    !%%&9:g>N>R>RSf>g%([D" 6 67 r"   errorc                 P  K   t        |dd       }|dk(  r<ddlm} ddlm} |j                  |j                  dt        |      i       d {    y |dk(  rKt        j                  dd	      }t        j                  d
|       t        j                  |       d {    y y 7 V7 w)Nstatus_codei  r   )circuit_breaker)CircuitBreakerReasonr|   i        rate_limit_backoff)delay)getattrapp.services.circuit_breakerr   
app.modelsr   triggerAPI_BANstrrandomuniformrW   warningr   r'   )r   r|   statusr   r   r   s         r    _handle_rate_limit_errorz'BinanceService._handle_rate_limit_error   s     t4S=D7!))*>*F*FRUV[R\H]^^^s]NN1a(ENN/uN=--&&&  _ 's%   A	B&B"AB&B$B&$B&c                 r  K   	 | j                          d {    | j                          d {    | j                  j                          d {    | j                  j                          d {    y7 a7 K7 +7 # t        $ r*}t        j                  dt        |             Y d }~yd }~ww xY ww)NTbinance_ping_failed)r|   F)
r\   rk   rA   r,   r?   pingru   rW   r|   r   )r   es     r    r   zBinanceService.ping   s     	,,.  '')))##++---++""$$$	 !)-$ 	LL.c!fL=	sr   B7B A9B A;!B A=!B 3A?4B 8B79B ;B =B ?B 	B4
 B/*B7/B44B7endpointcontextc                     t        |dd       }t        |t              r|j                  }t        j                  d||t        |      |xs i        y )Nr~   binance_api_error)r   r~   r|   r   )r   
isinstancer   r~   rW   r|   r   )r   r   r|   r   r~   s        r    _log_api_errorzBinanceService._log_api_error   sN    e]D9e01++K#e*Mr 	 	
r"      r   
   )
multiplierminmax)stopwaitintervallimit
start_timeend_timec                 ^  K   | j                          d {    | j                  j                          d {    	 | j                  j	                  |t
        j                        }|||d}|r||d<   |r||d<    | j                  j                  di | d {   }|D 	cg c]  }	t        j                  |	d   dz  t        j                        t        t        |	d               t        t        |	d               t        t        |	d	               t        t        |	d
               t        t        |	d               t        j                  |	d   dz  t        j                        t        t        |	d               t        |	d         d	 c}	S 7 7 a7 c c}	w # t         $ rZ}
t#        j$                  d      j'                          | j)                  |
       d {  7   | j+                  d|
||d        d }
~
wt,        $ r}
| j+                  d|
||d        d }
~
ww xY ww)N)rl   r   r   	startTimeendTimer   rf   tzr      r      r            )		open_timeopenhighlowclosevolume
close_timequote_volumetrades_count
get_klinesr   )rl   r   r5   )r\   rA   r,   INTERVAL_MAPrp   r	   KLINE_INTERVAL_1HOURr?   r   r   fromtimestampr   utcr   r   r4   r   r   labelsincr   r   ru   )r   rl   r   r   r   r   kline_intervalparamsrawkr   s              r    r   zBinanceService.get_klines   s     lln'')))	!..228[=]=]^N06N]b%cF&0{#$,y!...888C  A "*!7!7!t!U#C!I.#C!I."3qt9-$S1Y/%c!A$i0"*"8"81"V$+C!I$6$'!I
   	) 9 # 	|488://222aFPX1YZ 	aFPX1YZ	s   H-F!H-FH-AF$ FF$ $C/FF$ H-H-F$ F$ $	H*-8H%G(&HH*H%%H**H-c                 >  K   | j                          d {    | j                  j                          d {    	 | j                  j	                  |       d {   }t        |d         S 7 Y7 97 # t        $ r}| j                  d|d|i        d }~ww xY ww)N)rl   priceget_ticker_pricerl   )r\   rA   r,   r?   get_symbol_tickerr   ru   r   )r   rl   resultr   s       r    r   zBinanceService.get_ticker_price   s     lln'')))	;;888GGF6'?++	 	)G 	 2A&7IJ	sT   BA0!BA2BA6 A4A6 /B2B4A6 6	B?BBBc                   K   | j                          d {    | j                  j                          d {    	 | j                  j	                  ||       d {   }|d   D cg c]  }t        |d         t        |d         g  }}|d   D cg c]  }t        |d         t        |d         g  }}|r|d   d   n
t        d      }|r|d   d   n
t        d      }	|r|r|	|z
  n
t        d      }
|r
|r||	z   dz  n
t        d      }|r|
|z  d	z  n
t        d      }||||	|
|d
S 7 7 7 c c}w c c}w # t        $ r}| j                  d|d|i        d }~ww xY ww)Nrl   r   bidsr   r   asks0r   1d   )r   r   best_bidbest_askspread
spread_pctget_orderbookrl   )r\   rA   r,   r?   get_order_bookr   ru   r   )r   rl   r   bookbr   ar   r   r   r   midr   r   s                 r    r   zBinanceService.get_orderbook   so    lln'')))	3363OOD<@LILqWQqT]GAaDM2LDI<@LILqWQqT]GAaDM2LDI%)tAwqzws|H%)tAwqzws|H,0TX(ws|F/38h&!+'#,C14&3,,'#,J$$ (  	)OII  	Xv4FG	ss   E&D.!E&D1E& D? D3D? *#D5	D? #D:9A4D? -E&1E&3D? 5
D? ?	E#EE##E&c                   K   | j                          d {    | j                  j                          d {    	 | j                  j	                  ||       d {   }|D cg c]l  }t        |d         t        t        |d               t        t        |d               |d   t        j                  |d   dz  t        j                        d	n c}S 7 7 7 c c}w # t        $ r}| j                  d
|d|i        d }~ww xY ww)Nr   idr   qtyisBuyerMakerr$   rf   r   )trade_idr   quantityis_buyer_maker	traded_atget_recent_tradesrl   )r\   rA   r,   r?   r   r   r   r   r   r   r   ru   r   )r   rl   r   tradesr*   r   s         r    r   z BinanceService.get_recent_trades  s    lln'')))	;;88e8TTF  	  A !$AdG$S7_5 'AeH 6&'&7!)!7!7&	D8HX\\!Z  	 		 	)T	  	 3Q68JK	sg   DC!DCD C& CC& 'A1C!C& DDC& !C& &	D
/DD

Dc           	        K   | j                          d {    | j                  j                          d {    	 | j                  j	                          d {   }|d   D cg c]E  }t        |d         dkD  st        |d         dkD  r!|d   t        |d         t        |d         dG c}S 7 7 }7 \c c}w # t        $ r}| j                  d|        d }~ww xY ww)Nbalancesfreer   lockedasset)r   r   r   get_account_balance)r\   rA   r,   r?   get_accountr   ru   r   )r   accountr   r   s       r    r   z"BinanceService.get_account_balance  s     lln'')))	 KK3355G !, -A1V9%)WQx[-AA-E wZ#AfI.%ak2
 - 	 	)5  	 5q9	sg   C#B4!C#B6C#B? B8B? 'A
B:1B? 3C#6C#8B? :B? ?	C CC  C#sider   
order_typer   
stop_priceclient_order_idc                   K   t         j                  j                  dk(  rt        d      t         j                  rt         j
                  st        d      | j                          d {    | j                          d {    | j                  j                          d {    	 |||t        |      | j                  d}|r||d<   |r|dv rt        |      |d<   d|d	<   |rt        |      |d
<    | j                  j                  di | d {   }	t        j                  d|||	j!                  d      |       |	S 7 7 7 7 5# t"        $ rZ}
t%        j&                  d      j)                          | j+                  |
       d {  7   | j-                  d|
||d        d }
~
wt.        $ r}
| j-                  d|
||d        d }
~
ww xY ww)Npaperz&Use PaperTradingService for paper modezProduction Binance orders are blocked. Set ALLOW_PRODUCTION_TRADING=true only after Go/No-Go, canary, 2FA approval, and manual review.)rl   r   typer   
recvWindownewClientOrderId)LIMITSTOP_LOSS_LIMITr   GTCtimeInForce	stopPriceorder_createdorderId)rl   r   order_idr   create_orderr   )rl   r   r5   )rS   rY   rZ   
ValueErroris_live_tradingallow_production_tradingr\   rk   rA   r,   r   rF   r?   r   rW   rX   rp   r   r   r   r   r   r   ru   )r   rl   r   r   r   r   r   r   r   r   r   s              r    r   zBinanceService.create_order*  s       &&'1EFF##H,M,MP 
 lln##%%%''))) 	 "M"..&F -<)*'CC"%e*w(-}%&)*o{#34;;33=f==FKKI. /   M7 	%)" > # 	~6::<//222fd3ST 	fd3ST	s   A'G)E*GE!G#E$G)A*E E	.E GGG	E 	G8F)FF))G5GGGrn   callbackreconnect_delayc                     K   dt         ddf fd}|D ]8  }t        j                   ||            } j                  j	                  |       : yw)z1Start WebSocket price stream with auto-reconnect.rl   r/   Nc                 $  K   	 	 	j                          d {    	j                  j                  | j                               }|4 d {   }	 |j	                          d {   }|rd|v rt        |d         }t                d {   }|j                  dt        j                  t        j                        j                         d       d {    t        j                  d        | |       d {    7 7 7 7 |7 37 # 1 d {  7  sw Y   nxY wni# t        j                  $ r Y y t         $ rI}t"        j%                  d| t'        |             t        j(                         d {  7   Y d }~nd }~ww xY ww)Nczbinance:ws_last_seeni,  )exr   ws_reconnect)rl   r|   )r\   r@   symbol_ticker_socketlowerrecvr   r   ry   r   r)   r   r   	isoformatr   r   CancelledErrorru   rW   r   r   r'   )
rl   streamwsmsgr   rr   r  r  r   s
          r    _stream_symbolz9BinanceService.start_price_stream.<locals>._stream_symboli  sK    9,,.((!XX::6<<>JF%v"(*	/C"scz(/C(9*3+$5&'ee$:$,LL$>$H$H$J'* ', '" !" !"
 !- 0 0 3&.vu&= = = # )%"1 %6!" !>  &vvv --   9NN>&ANO!--8889' s   FD% D3D% DD% D&D'%DD	A
DD%D=D>DD% D% D	DDDD!DD!D% $F%F8F:F9F;E><FFFF)r   r   create_taskrC   r(   )r   rn   r  r  r  rl   ra   s   ` ``   r    start_price_streamz!BinanceService.start_price_streama  sM     	9 	9 	90 F&&~f'=>DNN!!$' s   AAr.   r   )i  NN)r   )2   )MARKETNNN)g      @)-r0   r1   r2   r3   r	   KLINE_INTERVAL_1MINUTEKLINE_INTERVAL_5MINUTEKLINE_INTERVAL_15MINUTEr   KLINE_INTERVAL_4HOURKLINE_INTERVAL_1DAYr   r!   r\   rb   propertyboolrd   r4   rk   r   r   dictro   rv   r{   ru   r   r   r   r   r   r   listr   r   r   r   r   r   r   r   r   floatr  r5   r"   r    r7   r7   +   s   T 000022....--L?
:  ;d ; ;$ $	hsm 	t 	
T 
8 84 8	'I 	'$ 	'	D 	

s 

9 

td{ 

^b 

 "1%,<qVX,YZ
 $("&(( ( 	(
 SM( 3-( 
d( [(TS W # c 4 0c # tDz &4: . ##'(,)-55 5 	5
 5  5 W%5 "#5 
5v "%	"(c"( C>3./"( 	"(
 
"(r"   r7   )%r3   r   r   r$   r   r   decimalr   typingr   r   r   binancer	   r
   binance.exceptionsr   tenacityr   r   r   app.core.configr   app.core.loggingr   app.core.metricsr   r   r   app.core.redis_clientr   r0   rW   rS   r   r7   binance_servicer5   r"   r    <module>r*     sj    Q    '  * * 5 2 @ @ ( ' F F +	H	>3 3(X( X(v
 !"r"   