
    ZiԤ                     
   U 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mZ  ej&                  d      ZdZd	ZdZdZdZ	 ddlZddlmZ ddlmc mZ dd
lmZmZ  ej@                  d       	  ejB                  d       ejF                  jI                         rejF                  jK                         dkD  rb	 dZejF                  jM                  d      Z'ejF                  jQ                  d      jR                  dz  Z*ejW                  de' de*dd       dZndZejW                  d        ee.      j^                  dz  Z0e0dz  Z1 ee.      j^                  dz  Z2dZ3dZ4dZ5dZ6dZ7dZ8dZ9d Z:d!Z;dZ<dZ=dZ>d"Z?d#Z@d$ZAd%ZBd&ZCerH G d' d(ej                        ZE G d) d*ej                        ZF	 ej                  j                  eFeEg       d+ej                  d,eKd-ej                  fd.ZLddde3fd/ej                  d0ej                  d1ej                  d2ej                  d3eKd-eej                     fd4ZMe@eAfd/ej                  d5eKd6eNd-ej                  fd7ZO G d8 d9      ZPdaQeeP   eRd:<   d-ePfd;ZSeTd<k(  r ej                  ej                  d=>        eS       ZW eXd?d@         eXdA        eXd@         eXdBe         eXdCeWj                  du         eXdDeWj                           eXdE ej                  eWj                         de]F              ej                  j                  dG       d"Z`dH ej                  ej                  j                  e`      dIz        z   Zc ej                  ej                  j                  e`      dJz  dKz         Ze eXdLe` dM       eWj                  ecee      Zg eXdN ej                  egdO               eXdP        ehdQ      D ]v  ZidH ej                  ej                  j                  dR      dIz        z   Zj ej                  ej                  j                  dR      dJz  dKz         ZkeWj                  ejek       x  eXdS emeWj                         dT       eWj                         rm eXdU       eWj                         Zq eXdN ej                  eqdO               eXdV       eWj                  ecee      Zr eXdN ej                  erdO              yyy# e"$ r Y |w xY w# e,e"f$ r d	ZejW                  d       Y w xY w# e-$ r ejW                  d       Y w xY w# eI$ r Y w xY w)Wu  
═══════════════════════════════════════════════════════════════════════════════
 LSTM REVERSAL PREDICTOR - Détection avancée des retournements de marché
 Optimisé pour GPU RTX 5060 Ti / 5070 (16 GB VRAM)
═══════════════════════════════════════════════════════════════════════════════

Architecture:
  - BiLSTM (bidirectionnel) 3 couches × 256 hidden → capture contexte passé ET futur
  - Multi-Head Self-Attention (4 têtes) → focus sur les bougies clés du retournement
  - Feature Engineering spécialisé retournement (30 features)
  - Double sortie: classification (4 classes) + régression (probabilité retournement)

Classes de prédiction:
  0 = NEUTRAL       — Pas de retournement imminent
  1 = REVERSAL_UP   — Retournement haussier détecté (achat)
  2 = REVERSAL_DOWN — Retournement baissier détecté (vente)
  3 = CONTINUATION  — Tendance continue (pas de retournement)

Entraînement:
  - Online learning: se ré-entraîne toutes les 30 min sur données récentes
  - Transfer learning: pré-entraîné sur historique, fine-tuné en temps réel
  - Data augmentation: bruit gaussien + time-warping pour robustesse

Auteur: IA Trading Bot
Date: 01/03/2026
    N)datetime	timedelta)Path)DictListOptionalTuple)dequeLSTMReversalFcpu)
DataLoaderTensorDataset      cudai   @u   ✅ LSTM Reversal: GPU z (z.0fz	 GB VRAM)u3   ℹ️  LSTM Reversal: GPU non accessible, mode CPUTu1   ℹ️  LSTM Reversal: CPU mode (pas de GPU CUDA)u-   ℹ️  LSTM Reversal: PyTorch non disponiblemodelszlstm_reversal.ptzlstm_reversal_stats.json<               g      ?gMbP?@         g?g?g      ?c                   6     e Zd ZdZddedef fdZddZ xZS )MultiHeadAttentionu7   Attention multi-têtes pour focus sur les bougies clés
hidden_dim	num_headsc                 b   t         |           || _        ||z  | _        ||z  dk(  sJ d       t	        j
                  ||      | _        t	        j
                  ||      | _        t	        j
                  ||      | _        t	        j
                  ||      | _	        | j                  dz  | _
        y )Nr   u-   hidden_dim doit être divisible par num_heads      ?)super__init__r   head_dimnnLinearquerykeyvalueout_projscale)selfr   r   	__class__s      :/home/ubuntu/crypto_trading_bot/lstm_reversal_predictor.pyr"   zMultiHeadAttention.__init__v   s    G&DN&)3DM	)Q._0__.:z:DJyyZ8DH:z:DJIIj*=DM#-DJ    c                    |j                   \  }}}| j                  |      j                  ||| j                  | j                        j                  dd      }| j                  |      j                  ||| j                  | j                        j                  dd      }| j                  |      j                  ||| j                  | j                        j                  dd      }||j                  dd      z  | j                  z  }t        j                  |d      }||z  j                  dd      j                         j                  |||      }	| j                  |	      S )Nr   r   dim)shaper&   viewr   r#   	transposer'   r(   r*   Fsoftmax
contiguousr)   )
r+   xBTCqkvattnouts
             r-   forwardzMultiHeadAttention.forward   s   ggGAq!

1""1aGQQRSUVWA  At~~t}}EOOPQSTUA

1""1aGQQRSUVWAB++tzz9D99Tr*D!8&&q!,779>>q!QGC==%%r.   )r   )r:   torch.TensorreturnrD   )__name__
__module____qualname____doc__intr"   rC   __classcell__r,   s   @r-   r   r   t   s    E
	.s 
	.s 
	.
	&r.   r   c                   Z     e Zd ZdZeeeeee	fde
de
de
de
de
def fdZd	d
defdZ xZS )ReversalLSTMu/  
        BiLSTM + Attention pour la détection de retournements.

        Entrée: (batch, 60, 30) — 60 timesteps × 30 features
        Sortie:
          - class_logits: (batch, 4)   — logits des 4 classes
          - reversal_prob: (batch, 1)  — probabilité brute de retournement [0-1]
        
input_sizehidden_size
num_layersr   num_classesdropoutc                 4   t         |           t        j                  t        j                  |d      t        j
                  d      t        j                         t        j                  |dz              | _        t        j                  d||dd|      | _
        t        j
                  |dz        | _        t        |dz  |      | _        t        j
                  |dz        | _        t        j                  t        j                  |dz  d      t        j                         t        j                  |      t        j                  dd      t        j                         t        j                  |dz        t        j                  d|            | _        t        j                  t        j                  |dz  d      t        j                         t        j                  |dz        t        j                  dd      t        j                                | _        y )Nr   r    T)rO   rP   rQ   batch_firstbidirectionalrS   r      r   )r!   r"   r$   
Sequentialr%   	LayerNormGELUDropout
input_projLSTMlstmln_lstmr   	attentionln_attn
classifierSigmoidreversal_head)r+   rO   rP   rQ   r   rR   rS   r,   s          r-   r"   zReversalLSTM.__init__   sz    G !mm		*b)R 	

7S=)	DO '% "DI <<a8DL 0aKDN<<a8DL !mm		+/3/	

7#		#r"	

7S=)		"k*DO "$		+/2.	

7S=)		"a 

"Dr.   r:   rD   rE   c                 J   | j                  |      }| j                  |      \  }}| j                  |      }| j                  |      }| j	                  ||z         }|d d dd d f   }|j                  d      }||z   }| j                  |      }| j                  |      }	||	fS )Nr1   r   r2   )r\   r^   r_   r`   ra   meanrb   rd   )
r+   r:   lstm_out_attn_out	last_step	mean_poolpooledclass_logitsreversal_probs
             r-   rC   zReversalLSTM.forward   s    "A))A,KHa||H-H ~~h/H||Hx$78H !B*I !,I*F??62L ..v6M..r.   )rF   rG   rH   rI   NUM_FEATURESHIDDEN_SIZE
NUM_LAYERS	NUM_HEADSNUM_CLASSESDROPOUTrJ   floatr"   r	   rC   rK   rL   s   @r-   rN   rN      sm    	 (4(3'1&/(3&-4	!$4	"%4	 "%4	 !$	4	
 #&4	 $4	l	/^ 	/ 	/r.   rN   dataperiodrE   c                 @   t        j                  | t         j                        }t        |       |k  r|S t        j                  | d|       ||dz
  <   d|dz   z  }t        |t        |             D ]  }| |   |z  ||dz
     d|z
  z  z   ||<    ||dz
     |d|dz
   |S )zEMA sur tout l'arraydtypeNr   g       @)np
zeros_likefloat64lenrf   range)rv   rw   rB   r?   is        r-   
_ema_arrayr      s    
--BJJ
/C
4y6
ggd7Fm,C
OvzA63t9% 4a1s1q5zQU33A46A:C!Jr.   pricesvolumeshighslowsseq_lenc                    t        |       |dz   k  ry| |dz    d }|t        |      |dz   k\  r	||dz    d nt        j                  |dz         }|t        |      |dz   k\  r	||dz    d n|j                         }|t        |      |dz   k\  r	||dz    d n|j                         }t        j                  |      }	t        j
                  |      dz   }
t        |d      }t        |d      }t        |d      }t        |d      }t        j                  |      }t        j                  |      }t        j                  |      }t        dt        |            D ]S  }||dz
  | }t        j                  |      ||<   t        j
                  |      }||   d|z  z   ||<   ||   d|z  z
  ||<   U t        j                  |      }t        d	t        |            D ]G  }t        ||   ||   z
  t        ||   ||d	z
     z
        t        ||   ||d	z
     z
              }|||<   I t        |d
      }d}t        j                  |dft        j                        }t        |      D ]  }||z   }||   |	z
  |
z  ||df<   |dk\  r||   ||dz
     z
  ||dz
     dz   z  dz  nd||d	f<   t        j                  ||d	f   dd      dz  ||d	f<   |dk\  r||   ||dz
     z
  ||dz
     dz   z  dz  nd||df<   t        j                  ||df   dd      dz  ||df<   |dk\  r+t        j
                  |t        d|dz
        |d	z          |
z  nd||df<   |d
k\  rt        j                  ||d
z
  |d	z          }t        j                  t        j                  |dkD  |d            }t        j                  t        j                  |dk  | d            }|dkD  r||z  }ddd	|z   z  z
  dz  dz
  ||df<   nd||df<   t        j                  |t        d|dz
        |d	z          }t        j
                  |t        d|dz
        |d	z          dz   } t        j                  ||   |z
  | z  dd      dz  ||df<   ||   |	z
  |
z  ||df<   ||   |	z
  |
z  ||df<   ||   dkD  r1t        j                  ||   ||   z
  ||   z  dz  dd      dz  ||df<   |dk\  rB||dz
     dkD  r7t        j                  ||   ||dz
     z
  ||dz
     z  dz  dd      dz  ||df<   ||   |	z
  |
z  ||df<   ||   |	z
  |
z  ||df<   ||   dkD  r3||   ||   z
  ||   z  dz  }!t        j                  |!dd      dz  ||df<   ||   ||   z
  }"|"dkD  r||   ||   z
  |"z  dz
  ||df<   |	dkD  r.t        j                  ||   ||   z
  |	z  dz  dd      dz  ||d
f<   |	dkD  r(t        j                  ||   |	z  dz  dd      dz  ||df<   |dk\  rF||   ||dz
     z
  ||dz
     dz   z  dz  ||df<   t        j                  ||df   dd      dz  ||df<   |dk\  r%t        j                  |t        d|dz
        |       nt        j                  |d|d	z          dz   }#|#dkD  r(t        j                  ||   |#z  d	z
  dd      dz  ||df<   ||   dkD  r1t        j                  ||   ||   z
  ||   z  dz  dd      dz  ||df<   ||   dkD  r1t        j                  ||   ||   z
  ||   z  dz  dd      dz  ||d f<   |dk\  r_||   ||dz
     z
  ||dz
     dz   z  dz  }$||dz
     ||dz
     z
  ||dz
     dz   z  dz  }%t        j                  |$|%z
  dd      dz  ||df<   |dk\  rZ||dz
     ||dz
     z
  ||dz
     dz   z  dz  }&|dk\  r$%z
  nd}'|dk\  r%|&z
  nd}(t        j                  |'|(z
  dd      dz  ||df<   |dk\  rt        j                   ||dz
  |d	z          })t        j                   ||dz
  |dz
         }*||df   }+|)|*k  r|+d!kD  rd||d"f<   n|)|*kD  r|+d!k  rd#||d"f<   |dk\  rf|dk\  r||df   |t        d|dz
        df   z
  nd},|dk\  r||d	f   |t        d|dz
        d	f   z
  nd}-|,dkD  r|-dk  rt        ||d"f   d$      ||d"f<   |dk\  rCt        j                  ||dz
  |       dz   }.t        j                  ||   |.z  dd      dz  ||d%f<   |dk\  rWt        j                   ||dz
  |d	z          }/t        j                  ||dz
  |d	z          }0|0|/z
  dz   }1||   |/z
  |1z  dz
  ||d&f<   |dk\  ro||dz
     dkD  rd||dz
     dkD  rY||   ||dz
     z
  ||dz
     z  dz  }2||dz
     ||dz
     z
  ||dz
     z  dz  }3t        j                  |2|3z
  dd      dz  ||d'f<   t        ||   |t        d|d	z
           z
        }4||   ||   z
  dz   }5t        j                  |4|5z  dd	      ||df<   |dk\  rx||   dkD  rp||dz
     dkD  ret        ||   ||   z
        ||   z  dz  }6t        ||dz
     ||dz
     z
        ||dz
     z  dz  }7t        j                  |7|6z
  dd      dz  ||d(f<   |dk\  r<||   ||dz
     z
  ||dz
     dz   z  dz  }8t        j                  |8dd      dz  ||d)f<   |d
k\  st        j                   ||d
z
  |d	z          }9t        j                  ||d
z
  |d	z          }:|:|9z
  dz   };||   |9z
  |;z  dz
  ||d*f<    |S )+u  
    Extrait 30 features orientées retournement pour une séquence de bougies.

    Features 0-19: reprend les 20 features standard (compatibilité)
    Features 20-29: features SPÉCIALISÉES retournement

    Retourne: ndarray (seq_len, 30) ou None si pas assez de données
       Ng|=	            r   r      r   ry   r      d   
   r   r    r         r               r0            gɿ   g      333333?                  )r~   r{   onescopyrf   stdr   r|   r   maxabszerosfloat32clipdiffwheremin)<r   r   r   r   r   pr@   hlomean_pstd_pema9ema21ema12ema26bb_midbb_upperbb_lowerr   wsatrtr
atr_smoothoffsetfeaturestchangesgainslossesrsvol_meanvol_stdbwbb_rangevol_ma10mom3_now	mom3_prevmom3_pp	accel_now
accel_prevprice_min_recentprice_min_prevrsi_at_recent	rsi_slope	mom_slope
vol_max_20low_20high_20range_20	slope_now
slope_prevbodywickgap_nowgap_prevroc7low_14high_14range_14s<                                                               r-   extract_reversal_featuresr      s    6{Wr\!2 A%,%8S\WWY\=Y'B, !_a_f_fgnqsgs_tA#(#4UwQS|9S"oYZY_Y_YaA#'#3D	Wr\8Q"o	WXW]W]W_B WWQZFFF1IE aDq"Eq"Eq"E ]]1F}}QH}}QH2s1v (a"fQKGGAJq	FF1IQi!a%'Qi!a%'( --
C1c!f 11s1Q4!AE(?3SA1q59I5JKA C$J Fxx"RZZ8H7^ ^?J A$-50A JKa!A$1q5/aAh.>?#EUVA!Q$Q7!;A LMPR7!A$1r6*qRy5/@ACGXYA!Q$Q7!;A EFG#aR.Q 785@QRA 7ggaBq1uo.GGGBHHWq['1=>EWWRXXgkG8Q?@FzV^"%q2v"6#!=!CA!$A 771SAF^AE23&&3q!b&>!a%01E9!A$/W!<b!DqHA q'F*e3A(V+u4A 8a<WWd1ga&8E!H%Ds%JBPQRUVVHQTN 6d1q5kAoWWd1gQU&;tAE{%JS%PRTVWX[\\HQTN $A;/58B#A;/58B !9q=1++vay83>B ggb!R025HQUO A;!,a< thqk1X=CHQUO A: gguQx%(':f&Ds&JBPQRUVVHQUO A: ggjmf&<s&BAqIAMHQUO 6 taAh1QU8e3CDsJHQUO gghq"uor1=AHQUO 4572771SAF^A./6APQEASV[A[a< ggadXo&92qAAEHQUO Q4!8 ggqtbe|qt&;c&A1bIBNHQUO 8a< ggqteAh%(&BS&H"aPSTTHQUO
 6!qQxAa!eHu,<=CH1q5Aa!eH,1q5E1ABSHI ggh&:BBQFHQUO 6Qx!AE(*qQx%/?@3FG01Q9,AI01QW,AJ ggi*&<b!DqHHQUO 7!vvaBq1uo6VVAa"fQV$45N$QTNM.0]T5I"%B!N2}t7K"&BAvKLPQ6HQTNXc!QUmQ6F-GGWX	KLPQ6HQTNXc!QUmQ6F-GGWX	q=Y]&)(1b5/3&?HQUO 7!b&,u4J ggadZ&7A>BHQUO 7VVAa"fQUO,FffQq2va!e_-G'%/H tf}83>HQUO 7uQU|a'E!b&MA,=qE!a%L0E!a%L@3FIA,q2v6%B-G#MJ ggi*&<b!DqHHQUO 1Q4!C1q5M**+tbe|e#''$+q!4B 6eAhluQU|a'7$q'E!H,-a83>G4A;q1u56q1uEKH ggh&8"a@1DHQUO 6aD1QU8O!a%5(89C?D ggdB2Q6HQUO 7VVBq2va!e,-FffQq2va!e_-G'%/H tf}83>HQUO}^?@ Or.   lookforwardthreshold_pctc                 4   t        |       }t        j                  |t        j                        }t	        d||z
        D ]  }| |dz   ||z   dz    }| |   }t        j
                  |      }t        j                  |      }	||z
  |z  dz  }
|	|z
  |z  dz  }| |   | |dz
     z
  | |dz
     z  dz  }|
|k\  r+t        |
      t        |      dz  kD  r|dk  rd||<   d||<   || k  r+t        |      t        |
      dz  kD  r|dkD  rd||<   d||<   d||<    |S )	u  
    Crée les labels de retournement pour l'entraînement.

    Pour chaque bougie t, on regarde les `lookforward` bougies suivantes:
      - Si le mouvement min→max depuis t dépasse +threshold → REVERSAL_UP (1)
      - Si le mouvement max→min depuis t dépasse -threshold → REVERSAL_DOWN (2)
      - Si le prix continue dans la même direction que les 5 bougies précédentes → CONTINUATION (3)
      - Sinon → NEUTRAL (0)

    Retourne: array (n_samples,) d'int64
    ry   r   r   r   g?r   r   r   )r~   r{   r   int64r   r   r   r   )r   r   r   nlabelsr   futurecurrent
max_future
min_futureup_move	down_move	past_moves                r-   create_reversal_labelsr     sE    	FAXXarxx(F1a+o& Aa+o12)VVF^
VVF^
'72S8')W4s:	 AYA.&Q-?#E	m#Gs9~7K(K1}q	q	=.(S^c'lS>P-P1}q	q	F1I58 Mr.   c                   4   e Zd ZdZd Zd Zd Zd Zd Z	 	 	 dde	j                  d	e	j                  d
e	j                  de	j                  def
dZ	 	 dde	j                  d	e	j                  d
e	j                  de	j                  fdZdefdZdefdZdefdZy)LSTMReversalPredictoru   
    Prédicteur de retournements basé sur BiLSTM + Attention.
    S'intègre dans le pipeline ai_predictor.py pour améliorer la détection creux/rebond.
    c                    d | _         d | _        d | _        d| _        d | _        d| _        d| _        t        d      | _        t        d      | _	        t        j                         | _        ddddddd ddt        dk(  d
| _        | j                          | j!                          t"        j%                  d	t         d
       y )NFr     )maxlenz1.0        r   )
model_versiontotal_predictionsaccuracyreversal_up_detectedreversal_down_detectedfalse_reversals
last_train
train_losstrain_accuracygpu_usedu.   ✅ LSTMReversalPredictor initialisé (device=))model	optimizer	scheduler
is_trainedlast_train_timeprediction_countcorrect_predictionsr
   _data_buffer_label_buffer	threadingLock_lockDEVICEstats_init_model_load_statsloggerinfor+   s    r-   r"   zLSTMReversalPredictor.__init__  s    /3
37 !#$  $)#5$)$6^^%
 #!"$%&' !&(

 	DVHANOr.   c                 \   t         st        j                  d       yt        j	                  dd       t
        j                         r	 	 t        j                  j                  t        t        g       t        j                  t        t
              t        d      }t!        |t"              rxd|v rtt               j%                  t              | _        | j&                  j)                  |d          |j+                  dd      | _        t        j/                  d	t
                n|| _        d| _        n>t               j%                  t              | _        d| _        t        j/                  d       t        j2                  j5                  | j&                  j7                         t8        d      | _        t        j2                  j<                  j?                  | j:                  ddd      | _         tC        d | j&                  j7                         D              }t        j/                  d|dd|dz  dz  dd       y# t        $ r Y w xY w# t0        $ rS}t        j                  d
t
         d|        t               j%                  t              | _        d| _        Y d}~5d}~ww xY w)u   Initialise ou charge le modèleu0   ⚠️ PyTorch non disponible — mode dégradéNTparentsexist_okF)map_locationweights_onlymodel_state_dictr  u   ✅ Modèle reversal chargé: u   ⚠️ Impossible de charger z: u5   🆕 Nouveau modèle reversal créé (non entraîné)g-C6?)lrweight_decayr   r    r   )modefactorpatiencec              3   <   K   | ]  }|j                           y w)N)numel).0r   s     r-   	<genexpr>z4LSTMReversalPredictor._init_model.<locals>.<genexpr>W  s     BQqwwyBs   u   📐 Modèle reversal: ,u    paramètres (r   i   z.1fz MB))"TORCH_AVAILABLEr  warning	MODEL_DIRmkdir
MODEL_PATHexiststorchserializationadd_safe_globalsrN   r   AttributeErrorloadstrr  
isinstancedicttor  load_state_dictgetr  r  	ExceptionoptimAdamW
parametersLEARNING_RATEr  lr_schedulerReduceLROnPlateaur  sum)r+   loadeden_paramss       r-   r  z!LSTMReversalPredictor._init_model,  s   NNMN 	t4(''88,HZ9[\ C
O&W\]fd+0Bf0L!-!2!26!:DJJJ..v6H/IJ&,jjt&DDOKK"@ MN!'DJ&*DO &**62DJ#DOKKOP **JJ!!#D + 
 11CCNNsQ D 

 B$***?*?*ABB-hq\STW^H^_bGccghi? &   (!>zl"QCPQ)^..v6
"'(s8   
)H? 3B?I ?	II II 	J+AJ&&J+c                    | j                   sy	 t        j                  dd       t        j                  | j                   j                         | j                  | j                  t        j                         j                         dt        t                     t        j                  dt                y# t        $ r"}t        j!                  d|        Y d}~yd}~ww xY w)u    Sauvegarde le modèle sur disqueNTr  )r  r  r  	timestampu#   💾 Modèle reversal sauvegardé: u"   ⚠️ Erreur sauvegarde modèle: )r  r*  r+  r.  save
state_dictr  r  r   now	isoformatr3  r,  r  r  r9  r)  )r+   rB  s     r-   _save_modelz!LSTMReversalPredictor._save_modelZ  s    zz
	EOOD4O8JJ$(JJ$9$9$;"oo%\\^557	
 :  KK=j\JK 	ENN?sCDD	Es   B'B7 7	C" CC"c                     t         j                         rK	 t        t         d      5 }t        j                  |      }ddd       | j
                  j                         yy# 1 sw Y   &xY w# t        $ r Y yw xY w)z!Charge les stats depuis le disquerN)
STATS_PATHr-  openjsonr2  r  updater9  )r+   fsaveds      r-   r  z!LSTMReversalPredictor._load_statsj  sk    *c* )a IIaLE)

!!%(	 ) )  s'   A- A!#A- !A*&A- -	A98A9c                     	 t        t        d      5 }t        j                  | j                  |dt
               ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY w)zSauvegarde les statsr   r   indentdefaultN)rN  rM  rO  dumpr  r3  r9  )r+   rQ  s     r-   _save_statsz!LSTMReversalPredictor._save_statst  sS    	j#& @!		$**a3?@ @ @ 		s-   A (AA AA A 	AANr   r   r   r   rE   c                 F   ddddg dddd}t         r| j                  s|S t        j                  |t        j                        }t        ||||      }||S 	 | j                  j                          t        j                         5  t        j                  |t        j                        j                  d      j                  t              }| j                  |      \  }	}
t        j                  |	d	
      j!                         j#                         d   }|
j!                         j%                         }t'        t        j(                  |            }ddd       ddddd}t+                 dz  }|dk(  xr |d   t,        k\  xr dk\  }|dk(  xr |d   t,        k\  xr dk\  }| j.                  dxx   dz  cc<   |r| j.                  dxx   dz  cc<   |r| j.                  dxx   dz  cc<   t'        |      ||   t1        t+              d      t1        t+        |      d      |D cg c]  }t1        t+        |      d       c}t3        |      t3        |      dS # 1 sw Y   xY wc c}w # t4        $ r$}t6        j9                  d|        |cY d}~S d}~ww xY w)u  
        Prédit s'il y a un retournement imminent.

        Retourne un dict:
        {
            'reversal_class': int,          # 0=neutral, 1=reversal_up, 2=reversal_down, 3=continuation
            'reversal_label': str,          # 'NEUTRAL', 'REVERSAL_UP', 'REVERSAL_DOWN', 'CONTINUATION'
            'reversal_probability': float,  # 0-1 probabilité de retournement
            'confidence': float,            # 0-100 confiance dans la prédiction
            'class_probabilities': list,    # [p_neutral, p_rev_up, p_rev_down, p_continuation]
            'is_reversal_signal': bool,     # True si signal fort de retournement haussier
            'is_danger_signal': bool,       # True si signal fort de retournement baissier
        }
        r   NEUTRALr   )      ?r   r   r   F)reversal_classreversal_labelreversal_probability
confidenceclass_probabilitiesis_reversal_signalis_danger_signalry   Nr1   r2   REVERSAL_UPREVERSAL_DOWNCONTINUATION)r   r   r   r   r   r   g?r   r   r   r   r   u$   ⚠️ Erreur prédiction reversal: )r(  r  r{   arrayr}   r   evalr.  no_gradtensorr   	unsqueezer6  r  r7   r8   r   numpyitemrJ   argmaxru   REVERSAL_CONFIDENCE_MINr  roundboolr9  r  r)  )r+   r   r   r   r   default_result
prices_arrr   Xrm   rev_probprobsrev_probabilitypredicted_class
labels_mapr_  ra  rb  r:   rB  s                       r-   predictzLSTMReversalPredictor.predict  s|   (  '$'#7"' %
 djj!!XXfBJJ7
,Z%N!!+	"JJOO 8LL?II!LOOPVW)-A&h		,B7;;=CCEaH"*,,."5"5"7"%bii&6"78 '=_Q_`Ju_56<J  1$ 'a33'3&   1$ 'a33'3&  JJ*+q0+!

12a72

3494 #&o"6",_"=(-eO.Da(H#E*$5q9DI'JqeAh(:'J&*+=&>$()9$: ;8 8D (K
  	"NNA!EF!!	"sD   .I3 CI!CI3 ,I.I3 !I+&I3 3	J <JJ J c           
         t         rt        |      t        t        z   dz   k  ryt	        j
                  |t        j                        }t        |      }t        t        dz   t        |      t        z
  d      D ]  }t        |d|dz    ||d|dz    nd||d|dz    nd||d|dz    nd      }|8||   }	| j                  5  | j                  j                  |       | j                  j                  |	       ddd        y# 1 sw Y   xY w)u   
        Alimente le buffer d'entraînement avec de nouvelles données.
        Appelé périodiquement par le bot avec les données les plus récentes.
        r   Nry   r   r   )r(  r~   SEQUENCE_LENGTHREVERSAL_LOOKFORWARDr{   rf  r}   r   r   r   r  r  appendr  )
r+   r   r   r   r   rr  r   end_idxfeatlabels
             r-   	feed_datazLSTMReversalPredictor.feed_data  s    #f+BV0VY[0["[XXfBJJ7
'
3 _r13z?EY3Y[\] 	5G,<GaK()0)<1%$','8lw{#d&*&6\gk"D	D wZZ 5%%,,T2&&--e45 5	55 5s   7DD	c                     t         syt        | j                        t        k  ry| j                  yt        j                         | j                  z
  j                         dz  }|t        k\  S )u0   Vérifie si un ré-entraînement est nécessaireFTr   )	r(  r~   r  MIN_SAMPLES_TRAINr  r   rH  total_secondsRETRAIN_INTERVAL_MIN)r+   elapseds     r-   should_retrainz$LSTMReversalPredictor.should_retrain  s^    t  !$55'<<>D$8$88GGIBN...r.   c                    t         r| j                  sddiS | j                  5  t        | j                        t
        k  r!dt        | j                        dcddd       S t        j                  t        | j                        t        j                        }t        j                  t        | j                        t        j                        }ddd       t        j                  dt               dt                t        j                  d	
      \  }}t!        ||      D ci c]  \  }}t#        |      t#        |       }}}t        j                  d|        t        j$                  t&        t        j                        }t        |      }	t)        t&              D ]4  }
t        j*                  ||
k(        }|dkD  r|	t&        |z  z  ||
<   0d||
<   6 t-        j.                  |      j1                  t              }t3        dt#        t        |      dz              }t        j4                  j7                  t        |            }|||d    ||d|    }}|||d    ||d|    }}t        j4                  j9                  dd|j:                        j=                  t        j                        }t        j>                  |||z   gd      }t        j>                  ||gd      }tA        t-        j.                  |      t-        j.                  |            }tC        |tD        d	d      }t-        j.                  |      j1                  t              }t-        j.                  |      j1                  t              }tG        jH                  |      }tG        jJ                         }| jL                  rtN        ntP        }| j                  jS                          tU        d      }d}t)        |      D ]  }d} d}!|D ]$  \  }"}#|"j1                  t              }"|#j1                  t              }#| jV                  jY                          | j                  |"      \  }$}% ||$|#      }&|#dk(  |#dk(  z  jU                         j[                  d      }' ||%|'      }(|&d|(z  z   })|)j]                          t,        jF                  j^                  ja                  | j                  jc                         d       | jV                  je                          | |)jg                         z  } |!dz  }!' | t3        |!d      z  }*| j                  ji                          t-        jj                         5  | j                  |      \  }+}, ||+|      jg                         }-|+jm                  d      }.|.|k(  jU                         jo                         jg                         }/|-|k  rK|-}| j                  jq                         js                         D 01ci c]  \  }0}1|0|1ju                          }}0}1ddd       | j                  jS                          |dz   t3        d|dz        z  dk(  s||dz
  k(  r*t        j                  d|dz    d| d|*dd-dd /d!
       | jv                  je                  -        |r| j                  jy                  |       | j                  ji                          d	| _&        t{        j|                         | _?        t-        jj                         5  | j                  |      \  }+},|+jm                  d      }.|.|k(  jU                         jo                         jg                         }2ddd       t        |d"      | j                  d#<   t        2d"      | j                  d$<   t{        j|                         j                         | j                  d%<   | j                          | j                          d&|t        |      t        |2d"      t        |d"      |t        d'}3t        j                  d(|2d!d)|d       |3S # 1 sw Y   pxY wc c}}w c c}1}0w # 1 sw Y   9xY w# 1 sw Y   xY w)*ux   
        Ré-entraîne le modèle avec les données du buffer.
        Retourne les métriques d'entraînement.
        statusunavailableinsufficient_data)r  samplesNry   u   🎓 Entraînement reversal: u    échantillons sur T)return_countsz   Classes: r   r[  r   g333333?g{Gz?)axisF)
batch_sizeshuffle	drop_last)weightinfr   r   r   r2   r   z	   Epoch /z: train_loss=z.4fz
 val_loss=z	 val_acc=z.1%r   r   r  r   success)r  epochsr  val_accuracyval_lossclass_distributiondeviceu)   ✅ Entraînement reversal terminé: acc=z loss=)Er(  r  r  r~   r  r  r{   rf  listr   r  r   r  r  r  uniqueziprJ   r   rs   r   r@  r.  ri  r6  r   randompermutationnormalr4   astypeconcatenater   r   
BATCH_SIZEr$   CrossEntropyLossBCELossr  ONLINE_EPOCHSPRETRAIN_EPOCHStrainru   r  	zero_gradrj  backwardutilsclip_grad_norm_r<  steprl  rg  rh  rm  rf   rG  itemscloner  r7  r   rH  r  ro  r  rI  rJ  rX  )4r+   rs  yr  countsucdistclass_weightstotalcls_idcountweights_tensorn_valindicesX_trainX_valy_trainy_valnoiseX_train_augy_train_augtrain_dstrain_loaderX_val_ty_val_tclass_criterionrev_criterionr  best_val_loss
best_stateepoch
epoch_loss	n_batchesbatch_Xbatch_yrm   rt  loss_cls
rev_targetloss_revlossavg_loss
val_logitsrh   r  	val_predsval_accr?   r@   	final_accresults4                                                       r-   train_onlinez"LSTMReversalPredictor.train_online  s.   
 djjm,,ZZ 	C4$$%(99"5#dFWFWBXY	C 	C d//0

CAd001BA	C 	3CF8;NvhWX 1D9+.vv+>?41aAA??l4&)* 2::>AK( 	,FFF1;'Eqy(-u1D(Ef%(+f%	, m477? As3q6D=)*))''A/756?+Qwv-?756?+Qwv-? 		  D'--8??

Knngw%?aHnngw%7a@ !LL%u||K'@
 "(z4[`a,,u%((0,,u%((0 --^D

 #'//

e
6] .	*EJI$0  !**V,!**V,((*)-G)<&h +<A  '!|1=DDFPPQRS
(:>#.0 ..tzz/D/D/FL##%diik)
Q	-0 "C	1$55H JJOO \ $

7 3
A*:w?DDF&--!-4	$/668==?DDFm+$,M;?::;P;P;R;X;X;Z![41a!QWWY,![J![\ JJ	SFaK00A5&1*9Li	{!F8=RUV`aijm`nnwx  AD  xE  F  GNN)].	*b JJ&&z2

'||~ ]]_ 	E JJw/MJ"))a)0I"g-446;;=BBDI	E
 $)#:

< ',Y':

#$#+<<>#;#;#=

<  	  1v!)Q/mQ/"&
 	?	#fUbcfTghiO	C 	C @h "\\ \2	E 	EsD   4`?!A0`?*a$Baa
aAa%?a	aa"	%a.c                     i | j                   | j                  t        | j                        | j                  dut
        dS )u(   Retourne les statistiques du prédicteurN)r  buffer_sizemodel_loadedr  )r  r  r~   r  r  r  r  s    r-   	get_statszLSTMReversalPredictor.get_stats  sA    
jj
//t001 JJd2
 	
r.   )NNN)rF   rG   rH   rI   r"   r  rJ  r  rX  r{   ndarrayr   ry  r  rp  r  r  r   r.   r-   r   r     s    
P@,j\E  '+$(#'	Q"

Q"Q" zzQ" jj	Q" -1	Q"n CG?C5

 5RZZ 5524**54	/ 	/Od Ob
4 
r.   r   _reversal_predictorc                  .    t         
t               a t         S )u5   Retourne le singleton du prédicteur de retournements)r  r   r  r.   r-   get_reversal_predictorr    s     "35r.   __main__z"%(asctime)s [%(name)s] %(message)s)levelformat
z<============================================================zLSTM Reversal PredictorzDevice: zModel loaded: z	Trained: zStats: rT  *   r   r    i  r   u   
Test prédiction (z bougies)...u   Résultat: )rU  u*   
Alimentation buffer pour entraînement...r   i,  zBuffer: u    échantillonsu   
Entraînement online...u'   
Re-prédiction après entraînement...)srI   osrO  timeloggingr  rk  r{   r   r   pathlibr   typingr   r   r   r	   collectionsr
   	getLoggerr  r(  r  r.  r$   r7   torch.nntorch.nn.functional
functionaltorch.utils.datar   r   set_num_threadsset_num_interop_threadsRuntimeErrorr   is_availabledevice_countget_device_namegpu_nameget_device_propertiestotal_memoryvram_gbr  AssertionErrorImportError__file__parentr*  r,  rM  r{  ro   rp   rq   rr   rt   rs   r=  r  r  r  r  r  r|  REVERSAL_THRESHOLD_PCTrn  HIGH_CONFIDENCE_THRESHOLDModuler   rN   r/  r0  r1  r  rJ   r   r   ru   r   r   r  __annotations__r  rF   basicConfigINFOpredprintr  r  dumpsr  r3  r  seedr   cumsumrandnr   r   r   ry  r  r   rh   prices_chunkvolumes_chunkr  r~   r  r  r  metricsresult2r  r.   r-   <module>r     s  6 
      (  . . 			>	*
 		A##:E!%%%a( zz UZZ%<%<%>%B	OFzz11!4Hjj66q9FFPGKK1(2gc])TU GH N!!H,	++
(^""%??
 
	
 
         &RYY &6Q/ryy Q/h,,l<N-OP
RZZ 
 
 
 6:3726.=	Ubjj U(*

U&(jjU &(ZZU ),	U CK2::BV	Ur 0D3I-2:: -),-+0-NPjj-hO
 O
j 8< X34 ; 5  zGgll3WX!#D	Bvh-	#%	VH	HVH
	N4::T12
34	Idoo&
'(	GJDJJt~~/3GH
IJ IINN2A9299RYY__Q/#566FbffRYY__Q'$.56G	 <
01\\&'*F	K


6!45
67	791X 4YRYYryys';c'ABBryys3d:TAB|]34 
HS**+,N
;<)+##%JDJJwq9:;<8:,,vw/JDJJwq9:;< ; Y   - 	OFKKMN	O  A
KK?@Ar  sm   -T: T 7T: AT /T: U TT: TT: T73T: 6T77T: :UUU U 