
    ir/                        d Z ddl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
 ddlmZmZmZmZ ddlZdZ e
e      j&                  dz  Z e
e      j&                  dz  Z e
e      j&                  dz  d	z  Z e
e      j&                  dz  d
z  Zg dZdZd#defdZdee   fdZdedee   fdZdedefdZdedede de dee   f
dZ!dedeeef   fdZ"dedeee f   fdZ#defdZ$d Z% G d d       Z&d! Z'e(d"k(  r e'        yy)$u  
🔄 Service de Mise à Jour des Données Historiques
==================================================
Tourne en arrière-plan et met à jour régulièrement
la base de données des klines pour les 62 cryptos.

Ce service:
- Met à jour les données toutes les heures (configurable)
- Ajoute uniquement les nouvelles bougies (incrémental)
- Fonctionne silencieusement en arrière-plan
- Écrit les logs dans un fichier

Usage:
    python historical_data_updater.py                    # Mode foreground
    python historical_data_updater.py --interval 30     # Toutes les 30 min
    python historical_data_updater.py --daemon          # Mode silencieux
    N)datetime	timedelta)Path)DictListAnyOptionalzhttps://api.binance.comhistorical_datazwatchlist.jsonzupdater.logzupdater_status.json)1h4h1d<   daemon_modec                    t         j                  d       t        j                  t        d      g}| s2|j                  t        j                  t        j                               t        j                  t        j                  dd|       y)	zConfigure le loggingTexist_okutf-8encodingz)%(asctime)s | %(levelname)s | %(message)sz%Y-%m-%d %H:%M:%S)levelformatdatefmthandlersN)
OUTPUT_DIRmkdirloggingFileHandlerLOG_FILEappendStreamHandlersysstdoutbasicConfigINFO)r   r   s     ./historical_data_updater.pysetup_loggingr&   3   sd    d###Hw?@H--cjj9:ll:#	    returnc                      t         j                         rAt        t         d      5 } t        j                  |       }|j                  dg       cddd       S g S # 1 sw Y   g S xY w)zCharge la liste des cryptosrsymbolsN)WATCHLIST_FILEexistsopenjsonloadget)fdatas     r%   load_watchlistr4   G   sX    .#& 	+!99Q<D88Ir*	+ 	+ I	+ Is   'AA"symbolc                     t         |  dz  }|j                         r.	 t        |dd      5 }t        j                  |      cddd       S y# 1 sw Y   yxY w#  Y yxY w)u+   Charge les données existantes d'un symbole_historical.jsonr*   r   r   N)r   r-   r.   r/   r0   )r5   filepathr2   s      r%   load_existing_datar9   O   sd    vh&677H	hg6 $!yy|$ $ 	$ 	s(   A A	A AA A Ar3   c                     t         j                  d       t         | dz  }t        |dd      5 }t        j                  | |dd	       d
d
d
       y
# 1 sw Y   y
xY w)u$   Sauvegarde les données d'un symboleTr   r7   wr   r      F)indentensure_asciiN)r   r   r.   r/   dump)r3   r5   r8   r2   s       r%   	save_datar@   Z   sZ    d#vh&677H	hg	. 9!		$!%89 9 9s   AAinterval
start_timeend_timec           	         t          d}g }|}||k  r}| |||dd}	 t        j                  ||d      }|j                          |j	                         }	|	s	 |S |j                  |	       |	d   d   dz   }t        j                  d	       ||k  r}|S # t        j                  j                  $ r)}
t        j                  d
|  d| d|
        Y d}
~
|S d}
~
ww xY w)u$   Récupère les klines depuis Binancez/api/v3/klines  )r5   rA   	startTimeendTimelimit   )paramstimeout      g?zErreur API pour /: N)BASE_URLrequestsr1   raise_for_statusr/   extendtimesleep
exceptionsRequestExceptionr   error)r5   rA   rB   rC   url
all_klinescurrent_startrJ   responseklineses              r%   
get_klinesr`   a   s    Jn
%CJM
(
" &
	||CCH%%']]_F  f%"2JqMA-MJJt' (
"2 	 ""33 	MM,VHAhZr!EF		s   :B 1B C/CCklinec                 R   | d   t        j                  | d   dz        j                         t        | d         t        | d         t        | d         t        | d         t        | d         | d   t        | d	         t	        | d
         t        | d         t        | d         dS )zParse une kline bruter   rE   rN   r<            rM         	   
   )	timestampr   r.   highlowclosevolume
close_timequote_volumetradestaker_buy_basetaker_buy_quote)r   fromtimestamp	isoformatfloatint)ra   s    r%   parse_klinerx      s     1X**58d?;EEGeAheAhU1XuQxa/AheAheAh-a/ r+ r'   c                    t        |       }i }|t        j                  |  d       i S t        t	        j
                         j                         dz        }t        D ]  }||j                  di       vr|d   |   }|j                  dg       }|s5|d   d   }|dz   }t        | |||      }	|	sS|	D 
cg c]  }
t        |
       }}
|j                  |       ||d<   t        |      |d<   |d   d	   |d
<   t        |      ||<    t	        j
                         j                         |d<   t	        j
                         j                         |d<   t        ||        |S c c}
w )u   
    Met à jour les données d'un symbole (incrémental)
    
    Returns:
        Dictionnaire avec le nombre de nouvelles klines par intervalle
    u%   : Pas de données existantes, skippedrE   	intervalsr^   rL   ro   rN   countr   end_date
fetched_atlast_update)r9   r   warningrw   r   nowrj   INTERVALS_TO_UPDATEr1   r`   rx   rT   lenru   r@   )r5   existingnew_klines_countrC   rA   interval_datar^   last_timestamprB   new_klines_rawk
new_kliness               r%   update_symbolr      sw    "&)H6("GHI	8<<>++-45H' 98<<R88 -h7""8R0  L1#a'
 $FHj(K2@AQ+a.AJAMM*% '-M(#%([M'"(.r
:(>M*%),ZX&59: &\\^557H\&lln668H] h# Bs   5E statusc                     t         j                  d       t        t        dd      5 }t	        j
                  | |d       ddd       y# 1 sw Y   yxY w)	u    Met à jour le fichier de statutTr   r;   r   r   r<   )r=   N)r   r   r.   STATUS_FILEr/   r?   )r   r2   s     r%   update_statusr      sF    d#	k3	1 'Q		&!A&' ' 's   AAc            	      Z   t               } | st        j                  d       yt        j                         }d}d}t        j                  dt        |        d       | D ]i  }	 t        |      }|rDt        |j                               }|dkD  r&||z  }|dz  }t        j                  d| d| d	       t        j                  d
       k t        j                         |z
  }t        j                         j                         t        |       ||t!        |d      t        j                         t#        t$              z   j                         d}	t'        |	       t        j                  d| d| d|dd       y# t        $ r&}t        j                  d| d|        Y d}~Fd}~ww xY w)u)   Exécute un cycle de mise à jour completz Aucun symbole dans la watchlist!Nr   u&   🔄 Début du cycle de mise à jour (z
 symboles)rN   z  z: +z klinesg?u   Erreur mise à jour rP   )minutes)r~   symbols_checkedsymbols_updatednew_klines_addedduration_secondsnext_updateu   ✅ Cycle terminé: u    symboles mis à jour, +z	 klines (z.1fzs))r4   r   r   rU   infor   r   sumvaluesdebugrV   	ExceptionrY   r   r   ru   roundr   DEFAULT_UPDATE_INTERVALr   )
r+   rB   total_new_klinesupdated_symbolsr5   
new_counts	total_newr_   elapsedr   s
             r%   run_update_cycler      s   G:;JOLL9#g,zRS @	@&v.J
 1 1 34	q=$	1$#q(OMMBvhc)G"DEJJsO@  iikJ&G  ||~//1w<*,!'1- ;R)SS^^`F &LL''88PQaPbbklstwkxxz{|!  	@MM01#>??	@s   #A&E;;	F*F%%F*c                   2    e Zd ZdZedfdedefdZd Zd Z	y)	HistoricalDataUpdateru(   Service de mise à jour en arrière-planFinterval_minutesdaemonc                 f    |dz  | _         || _        d| _        t        j                         | _        y )Nr   F)rA   r   running	threadingEvent_stop_event)selfr   r   s      r%   __init__zHistoricalDataUpdater.__init__  s+    (2-$??,r'   c                    d| _         t        j                  d       t        j                  d       t        j                  d| j                  dz   d       t        j                  d| j                  rdnd	        t        j                  d       t                | j                   r| j                  j                         s~| j                  j                  | j                         | j                   r$| j                  j                         s
t                | j                   r| j                  j                         s|y
y
y
y
)u   Démarre le serviceTz<============================================================u5   🚀 Démarrage du service de mise à jour historiquez   Intervalle: r   z minutesz	   Mode: Daemon
ForegroundN)	r   r   r   rA   r   r   r   is_setwaitr   s    r%   startzHistoricalDataUpdater.start	  s    XLMt}}':&;8DEyT[[l KLMX 	 ll4#3#3#:#:#<!!$--0||D$4$4$;$;$= " ll4#3#3#:#:#<l#<lr'   c                 p    t        j                  d       d| _        | j                  j	                          y)u   Arrête le serviceu"   🛑 Arrêt du service demandé...FN)r   r   r   r   setr   s    r%   stopzHistoricalDataUpdater.stop  s(    9:r'   N)
__name__
__module____qualname____doc__r   rw   boolr   r   r    r'   r%   r   r      s)    2/FW\ - -PT -#*r'   r   c                     t        j                  d      } | j                  dt        t        dt         d       | j                  ddd	
       | j                  ddd
       | j                         }t        |j                         |j                  rt                yt        |j                  |j                        }	 |j                          y# t        $ r( |j                          t        j                   d       Y yw xY w)zFonction principaleu0   Service de mise à jour des données historiques)descriptionz
--intervalu0   Intervalle de mise à jour en minutes (défaut: ))typedefaulthelpz--daemon
store_truez"Mode daemon (pas d'output console))actionr   z--onceu#   Exécuter une seule fois et quitter)r   N)r   r   u   Service arrêté proprement)argparseArgumentParseradd_argumentrw   r   
parse_argsr&   r   oncer   r   rA   r   KeyboardInterruptr   r   r   )parserargsupdaters      r%   mainr   $  s    $$1cdF
38OOPgOhhij  l

<A  C
B  D Ddkk*yy ${{G
4 4234s   C .DD__main__)F))r   r/   rU   rR   r   r   r!   r   r   pathlibr   typingr   r   r   r	   r   rQ   __file__parentr   r,   r   r   r   r   r   r&   strr4   r9   r@   rw   r`   rx   r   r   r   r   r   r   r   r'   r%   <module>r      s  $      
 (  , ,  %(^""%66
h&&)99>  #44}D8n##&77:OO )   t (S	 	s 	x~ 	9D 9# 9s c s c dSWj Bt S#X "4# 4$sCx. 4l'$ '+}b" "H4> zF r'   