
    i;N                        d Z ddlZddlmZmZ ddlmZmZmZm	Z	 ddl
Z
ddlZddlZddlmZ ddlmZmZ ddlmZ  ej(                  ej*                          ej,                  d	      Z	 dd
lmZmZ dZ	 ddlm Z  dZ!e G d d             Z"e G d d             Z# G d d      Z$dededee%   defdZ&e'dk(  rx	  e(d        e(d        e(d        ejR                          ed      z
  Z* ejR                         Z+g d Z, e$d!d"#      Z-e-j]                  e*e+e,      Z/e-ja                  e/       yy# e$ r dZeZej=                  d       Y w xY w# e$ r dZ!ej=                  d       Y w xY w)$u  
Adaptive Backtesting - Backtest avec retraining périodique simulé
Inspiré de FreqAI - Émule le comportement réel du bot avec adaptation

Features:
- Simulation retraining périodique (tous les N jours)
- Utilise UNIQUEMENT les données disponibles AVANT chaque retraining
- Métriques réalistes (win rate, profit, drawdown, Sharpe)
- Comparaison vs backtest classique (optimiste)
- Visualisation des résultats
    N)datetime	timedelta)DictListTupleOptional)Path)	dataclassfield)defaultdict)levelAdaptiveBacktesting)AIPredictorPatternItemTFu"   ⚠️ AI Predictor non disponible)BinanceClientu$   ⚠️ Binance Client non disponiblec                      e Zd ZU dZeed<   eed<   eed<   dZe	e   ed<   dZ
e	e   ed<   dZeed	<   d
Zeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dededefdZdefdZy)BacktestTradeu%   Représente un trade dans le backtestsymbol
entry_timeentry_priceN	exit_time
exit_price        quantityBUYsideUNKNOWNpatternscore	stop_losstake_profitpnlpnl_pctg?fees_pctOPENstatushold_time_hoursreasonc                 t   || _         || _        || _        || j                  z
  | j                  z  }|dz  | j                  z
  | _        | j                  || j                  z
  z  | j                  | j                  z  | j                  z  dz  z
  | _        || j                  z
  j                         dz  | _
        y)zFermer le traded     N)r   r   r&   r   r$   r#   r   r"   r   total_secondsr'   )selfr   r   r(   price_changes        ./backtesting_adaptive.pyclosezBacktestTrade.closeB   s    $" #T%5%559I9II$s*dmm;==J1A1A$ABdmmVZVfVfFfimivivFvy|F|} !*DOO ;JJLtS    returnc                    | j                   | j                  j                         | j                  | j                  r| j                  j                         nd | j
                  | j                  | j                  | j                  t        | j                  d      t        | j                  d      | j                  t        | j                  d      dS )N      )r   r   r   r   r   r   r   r   r"   r#   r&   r'   )r   r   	isoformatr   r   r   r   r   r   roundr"   r#   r&   r'   r-   s    r/   to_dictzBacktestTrade.to_dictP   s    kk//335++7;~~1134//||ZZ1%T\\1-kk$T%9%91=
 	
r1   )__name__
__module____qualname____doc__str__annotations__r   floatr   r   r   r   r   r   r   r    r!   r"   r#   r$   r&   r'   r0   r   r9    r1   r/   r   r   +   s    /K$(Ix!("&J&HeD#GSE5IuKCGUHeFC OU T T( TC T
 
r1   r   c                      e Zd ZU dZdZeed<   dZeed<   dZeed<   dZ	e
ed<   dZe
ed<   dZe
ed	<   dZe
ed
<   dZe
ed<   dZe
ed<   dZe
ed<   dZe
ed<   dZe
ed<   dZe
ed<   dZe
ed<   dZe
ed<   dZeed<   ddee   defdZdefdZy)BacktestMetricsu%   Métriques de performance du backtestr   total_tradeswinning_tradeslosing_tradesr   win_ratetotal_profit
total_loss
net_profitavg_winavg_lossprofit_factormax_drawdownmax_drawdown_pctsharpe_ratiosortino_ratioavg_hold_time_hoursretrains_counttradesretrainsc                    |syt        |      | _        || _        |D cg c]  }|j                  dkD  s| }}|D cg c]  }|j                  dk  s| }}t        |      | _        t        |      | _        | j                  dkD  r| j                  | j                  z  nd| _        t        d |D              | _        t        t        d |D                    | _
        | j                  | j                  z
  | _        |r| j                  t        |      z  nd| _        |r| j                  t        |      z  nd| _        | j                  dkD  r| j                  | j                  z  nd| _        d}d}d}|D ]%  }	||	j                  z  }||kD  r|}||z
  }
|
|kD  s$|
}' || _        |dkD  r||z  dz  nd| _        |D cg c]  }|j"                   }}t        |      dkD  rt%        j&                  |      }t%        j(                  |      }|dkD  r||z  t%        j*                  d      z  nd| _        |D cg c]
  }|dk  s	| }}|r<t%        j(                  |      }|dkD  r||z  t%        j*                  d      z  nd| _        t%        j&                  |D cg c]  }|j0                  dkD  s|j0                    c}      | _        yc c}w c c}w c c}w c c}w c c}w )u2   Calculer les métriques depuis une liste de tradesNr   c              3   4   K   | ]  }|j                     y wNr"   .0ts     r/   	<genexpr>z,BacktestMetrics.calculate.<locals>.<genexpr>   s     4!4   c              3   4   K   | ]  }|j                     y wrX   rY   rZ   s     r/   r]   z,BacktestMetrics.calculate.<locals>.<genexpr>   s     !8A!%%!8r^   r*   r5      )lenrD   rS   r"   rE   rF   rG   sumrH   absrI   rJ   rK   rL   rM   rN   rO   r#   npmeanstdsqrtrP   rQ   r'   rR   )r-   rT   rU   r\   winslossescumulative_pnlpeakmax_ddtradedrawdownreturns
avg_return
std_returnrdownside_returnsdownside_stds                    r/   	calculatezBacktestMetrics.calculate|   s   K&!/aQUUQY//#2quuz!22!$i [CGCTCTWXCX++d.?.??^_4t44c!8!889++doo=8<t((3t94!9?#f+5QDHOOVWDWT..@]^  	"Eeii'N$%n,H& !	" #9=$!4q '--199--w<!)JJLVYZNj!8BGGCL H`aD ,3<aa!e<<!vv&67S_bcScj<&?2773<%Oij" $&77v+g!QRQbQbefQfA,=,=+g#h [ 02> .  = ,hs3   KKKK=K5
K KK,Kr2   c                    i d| j                   d| j                  d| j                  dt        | j                  dz  d      dt        | j
                  d      dt        | j                  d      d	t        | j                  d      d
t        | j                  d      dt        | j                  d      dt        | j                  d      dt        | j                  d      dt        | j                  d      dt        | j                  d      dt        | j                  d      dt        | j                  d      d| j                   S )NrD   rE   rF   rG   r*   r4   rJ   rH   rI   rK   rL   rM   rN   rO   rP   rQ   rR   r5   rS   )rD   rE   rF   r7   rG   rJ   rH   rI   rK   rL   rM   rN   rO   rP   rQ   rR   rS   r8   s    r/   r9   zBacktestMetrics.to_dict   sw   
D--
d11
 T//
 dmmc115	

 %3
 E$"3"3Q7
 %3
 uT\\1-
 dmmQ/
 U4#5#5q9
 E$"3"3Q7
 d&;&;Q ?
 E$"3"3Q7
 U4#5#5q9
 "5)A)A1#E
  d11!
 	
r1   N)r   )r:   r;   r<   r=   rD   intr?   rE   rF   rG   r@   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   r   r   ru   r   r9   rA   r1   r/   rC   rC   a   s    /L#NCM3HeL%JJGUHeM5L%!e!L%M5!$$NC5i] 3 5is 5in
 
r1   rC   c                       e Zd ZdZ	 	 	 	 	 ddededededef
dZded	efd
Z	defdZ
dedee   d	ee   fdZdededefdZdedeeef   fdZdededee   d	efdZdefdZddedefdZy)AdaptiveBacktesteru   
    Backtester avec retraining adaptatif simulé
    
    Simule le comportement réel du bot:
    1. Démarre avec modèle initial
    2. Trade pendant N jours
    3. Retrain sur données accumulées
    4. Repeat
    initial_capitalmax_positionsposition_size_usdtretrain_interval_daysmax_hold_hoursc                    || _         || _        || _        || _        t	        |      | _        t	        |      | _        g | _        g | _        d| _	        d| _
        t        j                  d       t        j                  d| d       t        j                  d|        t        j                  d	| d       t        j                  d
| d       y)uG  
        Args:
            initial_capital: Capital initial USDT
            max_positions: Nombre max positions simultanées
            position_size_usdt: Taille de chaque position
            retrain_interval_days: Intervalle entre retrainings (jours)
            max_hold_hours: Durée max d'une position (heures)
        days)hoursNr   u#   ✅ Adaptive Backtester initialiséu      • Capital initial:  USDTu      • Max positions: u      • Taille position: u      • Retrain interval: z jours)rz   current_capitalr{   position_sizer   retrain_intervalmax_hold_timeopen_positionsclosed_tradeslast_retrainrS   loggerinfo)r-   rz   r{   r|   r}   r~   s         r/   __init__zAdaptiveBacktester.__init__   s      /.*/ )/D E&^<3524 9:..?uEF,]O<=./A.B%HI/0E/FfMNr1   current_timer2   c                 T    | j                   y|| j                   z
  | j                  k\  S )u#   Vérifier si retraining nécessaireF)r   r   )r-   r   s     r/   should_retrainz!AdaptiveBacktester.should_retrain   s-    $t000T5J5JJJr1   c           
         t         j                  d|j                  d              | j                  D cg c]  }|j                  |k  s| }}t        |      dk  r"t         j                  dt        |              yt        d       }|dd D ]N  }|j                  }||   dxx   d	z  cc<   |j                  d
kD  r||   dxx   d	z  cc<   ?||   dxx   d	z  cc<   P |j                         D ]?  \  }}|d   d
kD  s|d   |d   z  }t         j                  d| d|dz  dd|d    d       A || _        | xj                  d	z  c_        t         j                  d| j                   d       yc c}w )u   
        Simuler le retraining des modèles
        
        Important: Utilise UNIQUEMENT les trades fermés AVANT current_time
        pour éviter le look-ahead bias
        u   
🔄 RETRAINING @ z%Y-%m-%d %H:%M   u)   ⚠️ Pas assez de trades pour retrain: Nc                      ddddS )Nr   )rh   ri   totalrA   rA   r1   r/   <lambda>z3AdaptiveBacktester.retrain_models.<locals>.<lambda>  s    Q!a,P r1   r   r5   r   rh   ri   u      • z: r*   .1f% (z trades)u   ✅ Retrain #u	    terminé)r   r   strftimer   r   ra   warningr   r   r"   itemsr   rS   )	r-   r   r\   past_tradespattern_statsrm   r   statswrs	            r/   retrain_modelsz!AdaptiveBacktester.retrain_models   s    	*<+@+@AQ+R*STU #'"4"4TQ|8SqTT{b NNFs;GWFXYZ $$PQ ' 	6EmmG'"7+q0+yy1}g&v.!3.g&x0A50	6 ,113 	ZNGUW~!6]U7^3ggYbCCg?OxXY	Z )q mD$7$7#8	BC; Us   E5E5symbolsc                     g S )u   
        Obtenir les signaux de trading pour un timestamp donné
        
        Note: Dans un vrai backtest, on chargerait les données historiques
        Pour simplifier, on retourne des signaux simulés
        rA   )r-   r   r   s      r/   get_signalszAdaptiveBacktester.get_signals$  s	     	r1   signalcurrent_pricec                    t        | j                        | j                  k\  ry| j                  | j                  k  ry| j                  |z  }t        |j                  ||||j                  |j                  |dz  |dz        }| j                  j                  |       | xj                  | j                  z  c_        t        j                  d|j                   d|d       y)zOuvrir un nouveau tradeNg\(\?g=
ףp=?)r   r   r   r   r   r   r    r!   u      ✅ z
 ouvert @ .6f)ra   r   r{   r   r   r   r   r   r   appendr   debug)r-   r   r   r   r   rm   s         r/   
open_tradezAdaptiveBacktester.open_trade/  s    t""#t'9'99$"4"44%%5==#%NN,,#d*%-	
 	""5) 2 22wv}}oZc7JKLr1   pricesc           
         t        | j                        D ]@  }|j                  |j                        }|"||j                  k\  r|j                  ||d       | j                  j                  |       | j                  j                  |       | xj                  |j                  |z  z  c_	        t        j                  d|j                   d|dd|j                  dd       ||j                  k  r|j                  ||d	       | j                  j                  |       | j                  j                  |       | xj                  |j                  |z  z  c_	        t        j                  d
|j                   d|dd|j                  dd       ||j                  z
  | j                   k\  s|j                  ||d       | j                  j                  |       | j                  j                  |       | xj                  |j                  |z  z  c_	        t        j                  d|j                   d|dd|j                  dd       C y)u:   Vérifier les conditions de sortie pour positions ouvertesNTPu      🟢 z TP @ r   z (+.2f%)SLu      🔴 z SL @  (TIMEOUTu      ⏰ z TIMEOUT @ )listr   getr   r!   r0   remover   r   r   r   r   r   r#   r    r   r   )r-   r   r   rm   r   s        r/   check_exitszAdaptiveBacktester.check_exitsI  s   $--. 	lE"JJu||4M$  1 11M<>##**51""))%0$$(FF$x~VM#;NcRWR_R_`cQddfgh /M<>##**51""))%0$$(FF$x~VM#;NbQVQ^Q^_bPccefg u///D4F4FFM<C##**51""))%0$$(FF$wu||nKc?RRTUZUbUbcfTggijk;	lr1   
start_dateend_datec           	         t         j                  d       t         j                  d       t         j                  d       t         j                  d|j                  d       d|j                  d              t         j                  dt        |              t         j                  d| j                   d	       | j                  | _        g | _        g | _        || _        d
| _	        |}d
}||k  r|dz  }| j                  |      r| j                  |       |dz  d
k(  rLt         j                  d|j                  d       dt        | j                         d| j
                  dd	       |t        d      z  }||k  r| j                  D ]:  }|j                  |j                  |d       | j                  j                  |       < t!               }|j#                  | j                  | j                         t         j                  d       t         j                  d       t         j                  d       | j%                  |       |S )u  
        Exécuter le backtest adaptatif
        
        Args:
            start_date: Date de début
            end_date: Date de fin
            symbols: Liste des symboles à trader
        
        Returns:
            Métriques de performance
        =
============================================================u    🚀 ADAPTIVE BACKTEST DÉMARRÉ<============================================================u
   Période: z%Y-%m-%du    → z
Symboles: zCapital initial: r   r   r5      u   📅 z | Trades: z | Capital: .0fr   ENDu   ✅ BACKTEST TERMINÉ)r   r   r   ra   rz   r   r   r   r   rS   r   r   r   r0   r   r   rC   ru   _print_metrics)r-   r   r   r   current_date
days_countrm   metricss           r/   runzAdaptiveBacktester.runj  s     	M"67Fj!4!4Z!@ AxGXGXYcGdFefgjW/0'(<(<'=UCD#33 & "
h&!OJ ""<0##L1 A~"eL$9$9*$E#FkRUVZVhVhRiQjjvw{  xL  xL  MP  wQ  QV  W  XI1--L h&" (( 	-EKK))8U;%%e,	-
 "#$,,d.A.ABM"+,FG$r1   r   c           	         t         j                  d       t         j                  d|j                   d|j                   d|j                   d       t         j                  d|j
                  dd       t         j                  d	|j                  dd
       t         j                  d|j                  d       t         j                  d|j                  dd|j                  dd       t         j                  d|j                  d       t         j                  d|j                  d       t         j                  d|j                  dd       t         j                  d|j                          y)u   Afficher les métriquesu   
📊 RÉSULTATS:z   Trades: z (W:z L:)z   Win Rate: r   %z   Profit Net: r   z   Profit Factor: z   Max Drawdown: z USDT (r   z   Sharpe Ratio: z   Sortino Ratio: z   Avg Hold Time: r   hz   Retrains: N)r   r   rD   rE   rF   rG   rJ   rM   rN   rO   rP   rQ   rR   rS   )r-   r   s     r/   r   z!AdaptiveBacktester._print_metrics  sD   (*k'"6"6!7tG<R<R;SSVW^WlWlVmmnopmG$4$4S#9;<og&8&8%=UCD()>)>s(CDE'(<(<S'AIaIabeHffhij'(<(<S'ABC()>)>s(CDE()D)DS(IKLmG$:$:#;<=r1   filenamec                    | j                   | j                  | j                  | j                  j                  | j
                  j                         dz  d|j                         | j                  dd D cg c]  }|j                          c}t        j                         j                         d}t        |d      5 }t        j                  ||d       ddd       t        j!                  d	|        yc c}w # 1 sw Y   'xY w)
u   Sauvegarder les résultatsr+   )rz   r{   r   r}   r~   r   N)configr   rT   	timestampwr4   )indentu   💾 Résultats sauvegardés: )rz   r{   r   r   r   r   r,   r9   r   r   nowr6   openjsondumpr   r   )r-   r   r   r\   resultsfs         r/   save_resultszAdaptiveBacktester.save_results  s     $(#7#7!%!3!3!%!3!3)-)>)>)C)C"&"4"4"B"B"Dt"K (,0,>,>tu,EFqqyy{F!113
 (C  	,AIIgq+	, 	4XJ?@ G	, 	,s   5C8>C==DN)g     @
   g      Y@r   0   )zbacktest_results.json)r:   r;   r<   r=   r@   rw   r   r   boolr   r   r   r>   r   r   r   r   r   rC   r   r   r   rA   r1   r/   ry   ry      s)    +2&(-2./')O"'O #O &+O ),	O
 "%OBK8 K K'D8 'DR	 	49 	kIZ 	M MH MUZ M4l l$sEz:J lB> >> #Y> $3>@>o >AO As Ar1   ry   r   r   r   r2   c           	         t         j                  d       t         j                  d       t         j                  d       t         j                  d       t        d      }|j                  | ||      }t         j                  d       t        d      }|j                  | ||      }t         j                  d       t         j                  d	       t         j                  d       |j	                         |j	                         |j
                  |j
                  z
  |j                  |j                  z
  |j                  |j                  z
  d
d}t         j                  d|j
                  dd|j
                  dd|d   d   dd       t         j                  d|j                  dd|j                  dd|d   d   dd       t         j                  d|j                  dd|j                  dd|d   d   dd       |S ) zu
    Comparer backtest adaptatif vs classique
    
    Returns:
        Dict avec comparaison des deux approches
    r   u%   🔬 COMPARAISON: ADAPTIVE vs CLASSICr   u,   
1️⃣ ADAPTIVE BACKTEST (avec retraining)r   )r}   u+   
2️⃣ CLASSIC BACKTEST (sans retraining)i  u   📊 COMPARAISON RÉSULTATS)win_rate_deltaprofit_deltasharpe_delta)adaptiveclassic
differencez
   Win Rate: Adaptive r   z% vs Classic r   r   r   z+.1fr   z   Profit: Adaptive r   z vs Classic r   r   z+.0fz USDT)z   Sharpe: Adaptive r   r   z+.2fr   )r   r   ry   r   r9   rG   rJ   rP   )r   r   r   adaptive_backtesteradaptive_metricsclassic_backtesterclassic_metrics
comparisons           r/   compare_adaptive_vs_classicr     sg    KK
KK78
KK KK?@,1E*..z8WM KK>?+#F(,,Z7KO KK
KK-.
KK %,,."**,.77/:R:RR,77/:T:TT,99O<X<XX
J KK*+;+D+DS*IWfWoWopsVttw  yC  DP  yQ  Rb  yc  dh  xi  ik  l  m
KK&'7'B'B3&G|TcTnTnorSssu  wA  BN  wO  P^  w_  `d  ve  ek  l  m
KK&'7'D'DS&IVeVrVrsvUwwy  {E  FR  {S  Tb  {c  dh  zi  ij  k  lr1   __main__r   u   🧪 TEST ADAPTIVE BACKTESTER   r   )BTCUSDTETHUSDTBNBUSDTSOLUSDTi'  r   )rz   r}   )1r=   numpyrd   r   r   typingr   r   r   r   r   osloggingpathlibr	   dataclassesr
   r   collectionsr   basicConfigINFO	getLoggerr   ai_predictorr   r   AI_PREDICTOR_AVAILABLEImportErrordictr   binance_apir   BINANCE_AVAILABLEr   rC   ry   r>   r   r:   printr   startendr   
backtesterr   r   r   rA   r1   r/   <module>r      s  
  ( . .  	   ( #   ',, '			0	195!;) 2
 2
 2
j c
 c
 c
LAA AAH*H *,4*+/9*9=*Z z&	&M	
)*	&M HLLNYB//E
(,,.C:G#J
 nnUC1GG$# w  9"K
NN789  ;
NN9:;s$   +
D3 6E 3EEE.-E.