
    AiN                     b   d 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  ej                  d      Z
ej                  j                  ej                  j                  e            Zej                  j!                  ed      ZdZdZd	Zd	Zd
ZdZdZdZdZdZ G d d      Z G d d      Zdad Zy)u  
═══════════════════════════════════════════════════════════════════════════════
🧠 MARKET BEHAVIOR DETECTOR — Régime comportemental des participants
═══════════════════════════════════════════════════════════════════════════════

Au lieu de mesurer le marché par des indicateurs techniques (RSI, EMA, volume),
ce module mesure le COMPORTEMENT HUMAIN des participants du marché à travers
la qualité des surges détectés par le spy.

PRINCIPE:
  En période de conviction (marché directionnel), les surges ont du "follow-through":
  le prix continue à monter après le spike initial. Les investisseurs restent.
  
  En période de spéculation (incertitude géopolitique, navigation à vue),
  les surges sont des coups de sonde: spike puis reversal immédiat.
  Les investisseurs entrent et sortent dans la même fenêtre de 10-30 secondes.

MÉTRIQUES:
  1. Follow-Through Rate (FTR): % des trades récents où le prix a monté
     au-delà de +0.1% après l'entrée (max_pnl > 0.1%)
  2. Instant Reversal Ratio (IRR): % des trades récents finissant en
     INSTANT_REVERSAL (max_pnl = 0.00%, hold < 45s)
  3. Avg Winner Hold vs Avg Loser Hold: en marché sain, les winners
     durent plus longtemps. En clapot, tout est court.

RÉGIMES:
  CONVICTION    — FTR ≥ 50%, IRR < 25%  → Trading normal
  SPECULATION   — FTR 25-50% ou IRR 25-40% → Sélectivité accrue
  PANIQUE       — FTR < 25% ou IRR ≥ 40% → Observation uniquement

═══════════════════════════════════════════════════════════════════════════════
    N)datetimetimezone)dequemarket_behaviorzmarket_behavior_state.json         ?g      ?g?g333333?g?<      c                       e Zd ZdZdZdZdZy)BehaviorRegimeu#   Les trois régimes comportementaux.
CONVICTIONSPECULATIONPANIQUEN)__name__
__module____qualname____doc__r   r   r        2/home/ubuntu/crypto_trading_bot/market_behavior.pyr   r   O   s    -JKGr   r   c                   p    e Zd ZdZd Zd Zd Zd ZddZe	d        Z
d Zd	 Zd
 Zd Zd Zd Zd Zd Zy)MarketBehaviorDetectoru  
    Détecteur de régime comportemental basé sur la qualité des trades spy.
    
    Consomme les résultats des trades (via feed_trade_result) et les surges
    observés (via feed_surge_observation) pour qualifier le comportement
    collectif des participants du marché.
    c                    t        t        dz        | _        t        d      | _        t        j
                  | _        t        j                         | _        d| _	        dddddddd| _
        | j                          t        j                  d| j                   d	| j                  d
   dd| j                  d   dd| j                  d    d	       y )N   )maxlend   r         ?        )ftrirravg_winner_holdavg_loser_holdsample_sizesurge_ft_ratesurge_observationsu5   🧠 MarketBehaviorDetector initialisé — régime:  (FTR=r   .0%, IRR=r    
, samples=r#   ))r   WINDOW_SIZEtrade_resultsr%   r   r   current_regimetimeregime_sinceregime_consecutivemetrics_load_stateloggerinfoselfs    r   __init__zMarketBehaviorDetector.__init___   s    "+/: #(s"3 -77 IIK"#   "#
 	KDL_L_K` a!\\%05VDLL<OPS;T U  $] ;<A? 	@r   c                    | j                   j                  |j                  dd      |j                  dd      |j                  dd      |j                  dd      |j                  dd      |j                  dt        j                               |j                  dd      t        k\  d	|j                  dd      v d
       | j                          | j                          y)ui  
        Appelé après chaque trade spy terminé (vente).
        
        trade_data: dict avec au minimum:
            - max_pnl: float (% max atteint pendant le trade)
            - pnl_pct: float (% final à la vente)
            - hold_seconds: float
            - exit_reason: str
            - symbol: str
            - timestamp: float (epoch)
        max_pnlr   pnl_pcthold_secondsexit_reason symbol	timestampINSTANT_REVERSALr9   r:   r;   r<   r>   r?   had_follow_throughwas_instant_reversalN)r,   appendgetr.   
FT_MIN_PNL_recalculate_save_state)r6   
trade_datas     r   feed_trade_resultz(MarketBehaviorDetector.feed_trade_result   s     	!!!~~i3!~~i3&NN>1=%>>-< nnXr2#TYY[A",..A">*"L$6*..XZ:[$[	#
 		 	r   c           
         |dk  ry||z
  |z  dz  }|t         k\  }| j                  j                  ||||||t        j                         d       | j                  D cg c]!  }t        j                         |d   z
  dk  r|# }}|rDt	        d |D              t        |      z  | j                  d<   t        |      | j                  d	<   yyc c}w )
u  
        Appelé pour mesurer le "follow-through" d'un surge APRÈS sa détection.
        
        Le spy peut vérifier le prix 60s après un surge (tradé ou non) pour
        savoir si le mouvement a continué. C'est le thermomètre le plus pur
        du comportement collectif.
        
        symbol: str
        surge_price: float (prix au moment de la détection)
        check_price: float (prix N secondes plus tard)
        elapsed_seconds: float
        r   Nr   )r>   surge_pricecheck_pricecontinuation_pcthad_continuationelapsedr?   r?   i  c              3   ,   K   | ]  }|d    s	d  yw)rO      Nr   ).0os     r   	<genexpr>z@MarketBehaviorDetector.feed_surge_observation.<locals>.<genexpr>   s     C!Q/A-BAC   
r$   r%   )SURGE_FT_MIN_CONTINUATIONr%   rD   r.   sumlenr1   )	r6   r>   rL   rM   elapsed_secondsrN   rO   rT   
recent_obss	            r   feed_surge_observationz-MarketBehaviorDetector.feed_surge_observation   s     !(;6+EL+/HH&&&& 0 0&(
 	 "&!8!8 >Aq~5<  >
 >CzCCc*oU LL) 25ZDLL-.	 >s   &Cc                 D   t        | j                        t         d }t        |      }|dk  r|| j                  d<   yt        d |D              }||z  }t        d |D              }||z  }|D cg c]  }|d   dkD  s| }}|D cg c]  }|d   dk  s| }	}|rt        d |D              t        |      z  nd}
|	rt        d	 |	D              t        |	      z  nd}| j                  j                  t        |d
      t        |d
      t        |
d      t        |d      |d       | j                  ||| j                  j                  dd            }|| j                  k(  r| xj                  dz  c_        y| xj                  dz  c_        | j                  t        k\  rl| j                  }|| _
        t        j                         | _        d| _        t        j!                  d| d| d|dd|dd| j                  d   dd| d       y| j#                  |      | j#                  | j                        kD  r[| j                  }|| _
        t        j                         | _        d| _        t        j%                  d| d| d|dd|dd| d       yyc c}w c c}w )uC   Recalcule métriques et régime à partir de la fenêtre glissante.Nr
   r#   c              3   ,   K   | ]  }|d    s	d  yw)rB   rR   Nr   rS   ts     r   rU   z6MarketBehaviorDetector._recalculate.<locals>.<genexpr>   s     DQA.B,CqDrV   c              3   ,   K   | ]  }|d    s	d  yw)rC   rR   Nr   r_   s     r   rU   z6MarketBehaviorDetector._recalculate.<locals>.<genexpr>   s     FQA.D,EqFrV   r:   r   c              3   &   K   | ]	  }|d      ywr;   Nr   r_   s     r   rU   z6MarketBehaviorDetector._recalculate.<locals>.<genexpr>   s     BQq0B   c              3   &   K   | ]	  }|d      ywrc   r   r_   s     r   rU   z6MarketBehaviorDetector._recalculate.<locals>.<genexpr>   s     @Aa/@rd      rR   )r   r    r!   r"   r#   r$   r   u   🧠 CHANGEMENT DE RÉGIME: u    → r&   r'   r(   z, surge_FT=z, n=r*   u   🧠⚠️ RÉGIME DÉGRADÉ: u    (immédiat) (FTR=)listr,   r+   rY   r1   rX   updateround_classify_regimerE   r-   r0   REGIME_STABILITY_COUNTr.   r/   r3   r4   	_severitywarning)r6   recentnft_countr   ir_countr    r`   winnerslosersr!   r"   	candidateolds                 r   rG   z#MarketBehaviorDetector._recalculate   s    d(();,-8Kq5*+DLL' D&DDl F&FFl %9)q(8199#8q|a'7!88V]3B'BBS\QcdSY#@@@3v;N_`a=a=$_a8#NA6
 	 ))#sDLL4D4D_VY4Z[	 +++##q(###q(#&&*@@))&/#$(IIK!*+'23%uYK H9F3s) 4  $_ =cB C1 	*T^^D<O<O-PP))&/#$(IIK!*+'4SEyk J9F3s)4s!= QE :8s   0J>JJJc                     |t         k  s	|t        k\  rt        j                  S |t        k\  r"|t
        k  r|t        k\  rt        j                  S t        j                  S )u.   Classifie le régime à partir des métriques.)	FTR_SPECULATION_MINIRR_PANIQUE_MINr   r   FTR_CONVICTION_MINIRR_CONVICTION_MAXSURGE_FT_CONVICTION_MINr   r   )r6   r   r    r$   s       r   rj   z'MarketBehaviorDetector._classify_regime  sU     $$(>!))) $$/A)AmWnFn!,,, )))r   c                     t         j                  dt         j                  dt         j                  dij	                  | d      S )u?   Score de sévérité pour transitions immédiates vers le pire.r   rR   r   )r   r   r   r   rE   )regimes    r   rl   z MarketBehaviorDetector._severity  s<     %%q&&""A
 #fa.		r   c                    | j                   | j                  t        t        j                         | j                  z
  dz  d      t	        | j
                        | j                   t        j                  k7  | j                         dS )u-   Retourne le régime actuel et les métriques.r	   rR   )r}   r/   regime_duration_minr1   should_tradeposition_multiplier)	r-   r/   ri   r.   dictr1   r   r   get_position_multiplierr5   s    r   
get_regimez!MarketBehaviorDetector.get_regime  sm     )) --#($))+8I8I*IR)OQR#SDLL) //>3I3II#'#?#?#A
 	
r   c                     t         j                  dt         j                  dt         j                  dij	                  | j
                  d      S )u  
        Multiplicateur de taille de position selon le régime.
        
        CONVICTION  → 1.0  (100%, trading normal)
        SPECULATION → 0.5  (50%, taille réduite, sélectivité)
        PANIQUE     → 0.0  (0%, observation uniquement)
        r   r   r   r   r   r   r   rE   r-   r5   s    r   r   z.MarketBehaviorDetector.get_position_multiplier%  C     %%s&&""C
 #d!!3
'		(r   c                 <    | j                   t        j                  k7  S )u$   True si le régime permet de trader.)r-   r   r   r5   s    r   r   z#MarketBehaviorDetector.should_trade3  s    ""n&<&<<<r   c                     t         j                  dt         j                  dt         j                  dij	                  | j
                  d      S )u0  
        Surge strength minimum adapté au comportement des participants.
        
        En CONVICTION, on fait confiance aux surges normaux.
        En SPECULATION, on exige des surges plus forts (filtrer le bruit).
        En PANIQUE, on ne trade pas (mais on retourne le seuil pour le log).
        r   g?g      @g      ?r   r5   s    r   get_min_surge_strengthz-MarketBehaviorDetector.get_min_surge_strength7  r   r   c                     | j                   }| j                  }ddddj                  |d      }t        j                         | j                  z
  dz  }| d| d|d	   d
d|d   d
d|d   d
d|d    d|ddS )z%Ligne de log compacte pour le statut.u   🟢u   🟡u   🔴)r   r   r   u   ⚪r	   z Comportement: r&   r   r'   z IRR=r    z
 surge_FT=r$   z n=r#   z depuis z.0fzmin))r1   r-   rE   r.   r/   )r6   mr}   emojidurations        r   get_status_linez&MarketBehaviorDetector.get_status_lineE  s    LL$$%fPTTU[]bcIIK$"3"33r9g_VH -eHS>qxn 5/*3/ 0=!" #s^4	)	
r   c           	      <   	 | j                   | j                  | j                  | j                  t	        | j
                        t	        | j                        dd t        j                  t        j                        j                         d}t        dz   }t        |dd      5 }t        j                  ||dt         	       ddd       t#        j$                  |t               y# 1 sw Y   $xY w# t&        $ r"}t(        j+                  d
|        Y d}~yd}~ww xY w)u<   Sauvegarde l'état sur disque pour survie aux redémarrages.iN)r}   r/   r0   r1   r,   r%   saved_atz.tmpwutf-8encodingr   )indentdefaultzBehavior state save error: )r-   r/   r0   r1   rg   r,   r%   r   nowr   utc	isoformatBEHAVIOR_STATE_FILEopenjsondumpstrosreplace	Exceptionr3   debug)r6   statetmpfes        r   rH   z"MarketBehaviorDetector._save_stateU  s    	<-- $ 1 1&*&=&=<<!%d&8&8!9&*4+B+B&CCD&I$LL6@@BE &.Cc31 ;Q		%1c:;JJs/0; ;  	<LL6qc:;;	<s0   B!C0 #C$"C0 $C-)C0 0	D9DDc                    	 t         j                  j                  t              s| j	                          yt        t        dd      5 }t        j                  |      }ddd       j                  dt        j                        | _        |j                  dt        j                               | _        |j                  dd      | _        |j                  d	| j                        | _        |j                  d
g       D ]  }| j                   j#                  |        |j                  dg       D ]  }| j$                  j#                  |        t&        j)                  d| j                   dt+        | j                                 y# 1 sw Y   -xY w# t,        $ r2}t&        j/                  d|        | j	                          Y d}~yd}~ww xY w)u    Charge l'état depuis le disque.Nrr   r   r}   r/   r0   r   r1   r,   r%   u(      📂 Behavior state chargé: régime=r)   zBehavior state load error: )r   pathexistsr   _bootstrap_from_historyr   r   loadrE   r   r   r-   r.   r/   r0   r1   r,   rD   r%   r3   r4   rY   r   r   )r6   r   r   r`   rT   r   s         r   r2   z"MarketBehaviorDetector._load_stateh  s   	+77>>"56,,.)3A %Q		!% #())Hn6O6O"PD %		.$))+ FD&+ii0Da&HD# 99Y=DLYY3 -""))!,-YY3R8 2''..q12 KKB4CVCVBW X##&t'9'9#:";= >% %  	+LL6qc:;((**	+s5   3F F F	D*F 	FF 	G(GGc                    t         j                  j                  t        d      }	 t         j                  j	                  |      st
        j                  d       yt        |dd      5 }t        j                  |      }ddd       sy|t         d D ]  }| j                  j                  |j                  dd      |j                  d	d      |j                  d
d      |j                  dd      |j                  dd      t        j                         |j                  dd      t        k\  d|j                  dd      v d        | j!                          t
        j                  dt#        | j                         d| j$                          | j'                          y# 1 sw Y   $xY w# t(        $ r"}t
        j+                  d|        Y d}~yd}~ww xY w)u   
        Bootstrap initial: charger espion_history.json pour avoir un état
        de départ basé sur les trades réels récents.
        zespion_history.jsonuE      📂 Pas d'historique spy — démarrage en CONVICTION (optimiste)Nr   r   r   r9   r   r:   r;   r<   r=   r>   r@   rA   u)      📂 Bootstrap depuis espion_history: u    trades → régime=zBootstrap error: )r   r   join
SCRIPT_DIRr   r3   r4   r   r   r   r+   r,   rD   rE   r.   rF   rG   rY   r-   rH   r   r   )r6   history_filer   historytrader   s         r   r   z.MarketBehaviorDetector._bootstrap_from_history  s   
 ww||J0EF	277>>,/cdlC': 'a))A,'  !+/ 
""))$yyA6$yyA6$)IIna$@#(99]B#?#ii"5!%*/))Iq*AZ*O,>%))M[]B^,^	+ 	
 KKCCHZHZD[C\ ]##'#6#6"79 :/' '2  	2LL,QC011	2s<   4F. F. )F!?
F. 
DF. !F+&F. .	G7GGN)r   )r   r   r   r   r7   rJ   r\   rG   rj   staticmethodrl   r   r   r   r   r   rH   r2   r   r   r   r   r   r   V   sa    @@6$AP>@*  	
(=(
 <&+6%2r   r   c                  .    t         
t               a t         S )u;   Retourne l'instance singleton du détecteur comportemental.)_detector_instancer   r   r   r   get_behavior_detectorr     s     !35r   ) r   r   r   r.   loggingr   r   collectionsr   	getLoggerr3   r   dirnameabspath__file__r   r   r   r+   ry   rw   rz   rx   r{   rF   SURGE_FT_WINDOWrW   rk   r   r   r   r   r   r   r   <module>r      s   B 
    ' 			,	-WW__RWW__X67
ggll:/KL       
   
     R2 R2r
  r   