
    bAj9                         d 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	 ddl
mZ ddlmZmZ ddlmZ  ee      Z e	       Zd	d
dddddZdddddddZ G d d      Z e       Zy)zCHistorical market data ingestion, backfill, and quality validation.    )datetime	timedeltatimezone)Decimal)Optional)get_settings)
get_logger)CandleIntervalDataQualityFlag)binance_serviceZ      m  i  )1m5m15m1h4h1d<   i,  i    i@8  Q c            
           e Zd ZdZ	 ddedededee   fdZdededee	   dee   fdZ
d	edeeee   f   fd
Zdee   dedee   fdZdedee	   fdZd	ededefdZy)MarketDataServicez<Download, validate, backfill, and serve only closed candles.symbolintervaldaysreturnc                   K   t         j                  |d      }|dz  |z  }g }d}t        |      |k  rlt        j                  ||d|       d{   }|snH||z   }t        |d   d   j                         dz        dz
  }t        |      dk  rnt        |      |k  rl|D 	cg c]  }	| j                  |	|       }
}	t        j                  d	||t        |
      
       |
S 7 c c}	w w)z)Bulk download historical klines via REST.r   r   N  )limitend_timer   	open_time   history_downloaded)r   r   count)
INTERVAL_SECONDSgetlenr   
get_klinesint	timestamp_enrich_candleloggerinfo)selfr   r   r   interval_seccandles_neededall_candlesr#   batchc	validateds              JC:\xampp\htdocs\tradingbinance\backend\app\services\market_data_service.pydownload_initial_historyz*MarketDataService.download_initial_history%   s     (++Hd;,<7"$"&+/)44x E +-K58K0::<tCDqHH5zD  +/ @KK{!T((H5{	K((RUV_R`a Ls+   AC)C"AC)C)#C$<'C)$C)existing_timesc                 6  K   t        |      dk  r| j                  ||d       d{   S t        |      }t        j	                  |d      }t        |dz        }g }t        dt        |            D ]  }||   ||dz
     z
  }||kD  st        ||dz
     j                         dz        |dz  z   }	t        ||   j                         dz        }
t        j                  ||d|	|
	       d{   }|D ]V  }| j                  ||      }|j	                  d
g       t        j                  j                  gz   |d
<   |j                  |       X t         j#                  d||t%        ||dz
           t%        ||         t        |              |S 7 l7 w)z(Detect and fill gaps from disconnection.      r   Nr   secondsr%   r!   )r"   
start_timer#   quality_flagsgap_backfilled)r   r   	from_timeto_timer'   )r*   r9   sortedr(   r)   r   ranger,   r-   r   r+   r.   r   MISSING_GAPvalueappendr/   warningstr)r1   r   r   r:   r2   gap_thresholdbackfillideltastart_msend_msgap_candlesr6   enricheds                 r8   backfill_gapszMarketDataService.backfill_gaps=   s     ~"66vxb6QQQ/'++Hd;!,*:;!q#n-.A"1%q1u(==E}$~a!e4>>@4GH<Z^K^^^A.88:TAB$3$>$>HDXPV%  %A#221h?H08_b0Q'3399U 1H_- OOH- % $!%!.Q"78q 12k*   /, ; Rs*   &FFA"FA$F0F1B$FFcandlec                 j   g }dD ]  }|j                  |      }|*|j                  t        j                  j                         @t        |t              st        |      n
t        |      }|dk  sl|dk7  sr|j                  |dk(  rt        j                  j                  nt        j                  j                          t        |j                  dd            }t        |j                  dd            }||k  r)|j                  t        j                  j                         t        |      dk(  |fS )z5Validate integrity; return (is_valid, quality_flags).)openhighlowclosevolumer   r\   rY   rZ   )r)   rJ   r   rH   rI   
isinstancer   float
ZERO_PRICENEGATIVE_PRICEOUT_OF_ORDERr*   )r1   rV   flagsfieldvalnumrY   rZ   s           r8   validate_candlez!MarketDataService.validate_candlea   s    ?E**U#C{_88>>?$.sG$<%*%*CaxEX-ax $..44(77== @ VZZ*+FJJua()#:LL55;;<5zQ%%    candlesc                 4   t        j                  t        j                        }t        j                  |d      }g }|D ]W  }|j                  d      }|&|d   }t        |t               r|t        |      z   }n<||k  sBd|d<   |j                  |       Y |S )z4Exclude forming candle to prevent signal repainting.r   
close_timer$   r?   T	is_closed)	r   nowr   utcr(   r)   r]   r   rJ   )	r1   rh   r   rl   r2   closedr6   rj   r$   s	            r8   filter_closed_candlesz'MarketDataService.filter_closed_candlesx   s    ll8<<('++Hd;A|,J!kN	i2!*Y|-L!LJC!%+a   rg   c                     t         j                  |d      }|dk  ry t        j                  t        j
                        t        |      z
  S )Nr   r   r>   )RETENTION_DAYSr)   r   rl   r   rm   r   )r1   r   r   s      r8   get_retention_cutoffz&MarketDataService.get_retention_cutoff   s;    !!(C0!8||HLL)I4,@@@rg   c                 X   t         j                  |d      }|d   }|j                  d      }|t        |t              r|t	        |      z   }| j                  |      \  }}t        j                  t        j                        }|d uxr ||k  }	i |||	| xs t        |      dkD  |dS )Nr   r$   rj   r?   r   )rj   rk   is_suspiciousrB   )
r(   r)   r]   r   r   rf   rl   r   rm   r*   )
r1   rV   r   r2   r$   rj   is_validrb   rl   rk   s
             r8   r.   z MarketDataService._enrich_candle   s    '++Hd;;'	ZZ-
*Y"A"Y|%DDJ..v6%ll8<<(d*?zC/?	

$"!)\;SZ!^"
 	
rg   N)r   )__name__
__module____qualname____doc__rL   r,   listdictr9   r   rU   tupleboolrf   ro   r   rr   r.    rg   r8   r   r   "   s    F 79%(03	d0""%(":>x."	d"H&d &uT49_/E &.T$Z 3 4PT: $AS AXh5G A
T 
S 
T 
rg   r   N)ry   r   r   r   decimalr   typingr   app.core.configr   app.core.loggingr	   
app.modelsr
   r   app.services.binance_servicer   rv   r/   settingsrq   r(   r   market_data_servicer~   rg   r8   <module>r      s    I 2 2   ( ' 6 8	H	> 



 



 
 
D () rg   