
    i^                        d 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mZm	Z	m
Z
 ddlZ ej                  e      Z	 ddlZ eedd       eedd       eed	d
       eedd       eedd       eedd       eedd       eedd      dZej'                  d        G d d      ZdadefdZdedee   dedee   fd Zed!k(  r ej2                  ej4                  "       d#d$ ej6                          ed%&      z
  d'Zd(d)d*d+dd,d-d.d/Zd0d1d2d3d4d5d6d7d/Zd8d9d:ed;d<d=d>Z e       Z e jC                  ee      Z" e#d?d@         e#dA        e#d@         e#dBe"dC    dD        e#dEe"dF   dGdH        e#dIe"dJ   rdKndL         e#dM       e"dN   D ]  Z$ e#dOe$         e jK                  ee      Z& e#d?d@         e#dP        e#d@         e#dBe&dC    dD        e#dQe&dR   rdKndL         e#dM       e&dN   D ]  Z$ e#dOe$          e#d?d@         e#dS        e#d@        e&dC   dTe"dC   z
  z
  Z' e#dUe"dC            e#dVe&dC            e#dWe' dX        e#dYe'dZk\  rdKndL        yy# e$ r dddddddddZY w xY w)[u  
═══════════════════════════════════════════════════════════════════════════════
🔄 SMART ROTATION - Système de Rotation Intelligente du Portefeuille
═══════════════════════════════════════════════════════════════════════════════

Ce module analyse les positions actuelles et les opportunités d'achat pour
effectuer des rotations intelligentes:
- Vendre une position dont le cycle de gain est terminé
- Acheter immédiatement une valeur avec un meilleur potentiel

Stratégie:
1. Calculer le "score de fin de cycle" pour chaque position
2. Calculer le "score d'opportunité" pour chaque candidat d'achat
3. Si une rotation offre un gain potentiel significatif → exécuter

Auteur: Trading IA Bot
Date: Décembre 2024
═══════════════════════════════════════════════════════════════════════════════
    N)datetime	timedelta)DictListTupleOptionalROTATION_MIN_CYCLE_END_SCORE   ROTATION_MIN_OPPORTUNITY_SCORE2   ROTATION_MIN_SCORE_ADVANTAGE   ROTATION_MIN_PROFIT      ROTATION_MIN_HOLD_TIME
   ROTATION_COOLDOWN   ROTATION_MAX_PER_HOUR   ENABLE_SMART_ROTATIONT)min_cycle_end_scoremin_opportunity_scoremin_score_advantagemin_profit_for_rotationmin_hold_time_minutesrotation_cooldown_minutesmax_rotations_per_hourenabledu.   🔄 Config rotation chargée depuis config.py7      c            	       (   e Zd ZdZddefdZddee   deeef   fdZ	dee   d	eeef   d
eeef   dee   fdZ
dededefdZdededefdZd	eeef   dee   deeef   dee   fdZdedeeef   fdZddedefdZdefdZd Zd ZdefdZy)SmartRotationz@
    Gestionnaire de rotation intelligente du portefeuille.
    Nconfigc                     |xs t         j                         | _        g | _        i | _        d| _        t        j                         | _        i | _	        d | _
        t        j                  d       y )Nr   u   🔄 Smart Rotation initialisé)ROTATION_CONFIGcopyr$   rotation_historylast_rotationsrotations_this_hourr   now
hour_start_prices_cache_prices_cache_timeloggerinfo)selfr$   s     ./smart_rotation.py__init__zSmartRotation.__init__X   sY    6 4 4 6 " #$ ",,."&56    symbolsreturnc                 x   ddl }| j                  r,|j                         | j                  z
  dk  r| j                  S 	 ddl}d}|j	                  | dd      }|j
                  dk(  rm|j                         D ci c]  }|d	   t        |d
          }}|| _        |j                         | _        t        j                  dt        |       d       |S t        j                  d|j
                          	 | j                  xs i S c c}w # t        $ r"}t        j                  d|        Y d}~;d}~ww xY w)uT   
        Récupère les prix actuels depuis l'API Binance (avec cache 30s).
        r   Nr   zhttps://api.binance.comz/api/v3/ticker/pricer   timeout   symbolpriceu   🔄 Prix récupérés: z	 symboleszErreur API prix: status=u   Erreur récupération prix: )timer.   r-   requestsgetstatus_codejsonfloatr/   r0   lenwarning	Exception)	r1   r5   r=   r>   base_urlresponseitempriceses	            r2   get_current_pricesz SmartRotation.get_current_pricesc   s+    	 ""		d6M6M(MQS'S%%%	? 1H||xj0D$Er|RH##s*KS==?[4$x.%W*>>[[%+"*.))+'6s6{m9MN!9(:N:N9OPQ !!'R' \  	?NN9!=>>	?s0   =D ;D	AD "D 	D 	D9D44D9	watchlist	positionscurrent_pricesc                 V   	 ddl }|j                  dd      }|j                  dk7  r|S |j                         }g }t	        |j                               }|D 	ch c]  }	|	j                  dd       }
}	|D ]i  }|j                  dd      }|j                  d	      s(||v s||
v r1g d
}||v r:|j                  d	d      }d|v sd|v rU	 t        |j                  dd            }t        |j                  dd            }t        |j                  dd            }t        |j                  dd            }t        |j                  dd            }|dk  r|dk  s|dkD  r||z
  }|dkD  r	||z
  |z  }nd}|dk  r|dkD  rd}n|dk  r|dkD  rd}n|dkD  r|dk  rd}nd}|j                  |||||||dkD  rdnd|dz  |d z  |d!z  |dz  d|d!z  z   |d"d#	d$|d%d&	       l |j                  d' d%(       |dd }t        j                  d)t        |       d*       |dd D ]5  }t        j!                  d+|d    d,|d-    d.|d/   d0d1|d2   d3z  d4d5	       7 ||z   S c c}	w # t        t        f$ r Y w xY w# t"        $ r$}t        j%                  d6|        |cY d}~S d}~ww xY w)7u   
        Génère des candidats alternatifs à partir des top cryptos Binance.
        Utilisé quand la watchlist ne contient pas assez de candidats hors positions.
        r   Nz*https://api.binance.com/api/v3/ticker/24hrr   r8   r:   r;    USDT)USDCUSDTBUSDUSDTTUSDUSDTEURUSDT	FDUSDUSDTUSDEUSDTUSDPUSDTDAIUSDTPAXUSDTGUSDUSDTUSTUSDTUSTCUSDTFRAXUSDTLUSDUSDTCUSDUSDTUSDTUSDTSUSDUSDTRAIUSDTMMUSDT	BFUSDUSDTUSDEURpriceChangePercentquoteVolume	lastPrice	highPricelowPricei@KL r         ?333333?<   r       gffffff?r   -   皙?g{Gzr
   r             @)	price_currentema_diff	ema_slopeema_slope_long
momentum_3
momentum_5rsibb_positionbb_bandwidthPOSSIBLET)	r;   r<   price_change_pctquote_volumerange_positionfeaturessmart_signalscore	generatedc                 &    | j                  dd      S )Nr   r   )r?   xs    r2   <lambda>z@SmartRotation._generate_alternative_candidates.<locals>.<lambda>   s    !%%*; r4   keyreverseu   🔄 u!    candidats alternatifs générés   : score=r   z	, change=r   .2fz%, vol=r   g    .Az.1fMu   Erreur génération candidats: )r>   r?   r@   rA   setkeysendswithreplacerB   append
ValueError	TypeErrorsortr/   r0   rC   debugrE   rD   )r1   rL   rM   rN   r>   rG   tickers
candidatesposition_symbolswwatchlist_symbolstickerr;   STABLECOINS
base_assetr   r   current_pricehigh_24hlow_24hprice_ranger   r   top_candidatescrJ   s                             r2    _generate_alternative_candidatesz.SmartRotation._generate_alternative_candidates   s   q	  ||$PZ\|]H##s*  mmoG J"9>>#34>G Hx!4 H H! SHb1 v. --;L1L
 [( $^^FB7
J&%:*=7',VZZ8La-P'Q$#(M1)E#FL$)&**[!*D$EM$VZZQ%?@H#FJJz1$=>G $i/  (",0@10D  #+W"4K"Q*7'*A[)P), &+0@10D "'#-2BS2H ")A-.32F " "%%"(!.,<(4*8-:0@10D%)9B)>.>.C*:Q*>*:Q*>#%)9A)=#>+9,/
% )3!&%)'' {Sl OO ;TOJ'_NKK%N 344UVW#BQ' Ms1X;-x'
|9QOaMbcfLggnopq  pA  BE  pE  FI  oJ  JK  L  MM ~--A !Ih #I.   	NN<QC@A	st   'I; /I; I 2AI; BI%I; 
I%#I; $A<I% A?I;  I; %I84I; 7I88I; ;	J(J#J(#J(positionr   c                  	   d}g }|j                  dd      }|j                  dd      }|dk  s|dk  rddgdS ||z  dz
  dz  }|j                  dd      }|j                  d	d      }	|j                  d
d      }
|j                  dd      }|j                  dd      }|j                  dd      }|j                  dd      }|j                  dd      }|dk  r|dz  }|j                  d|dd       nF|dk  r!|dk  r|dz  }|j                  d|dd       n |dk  r|dk  r|dz  }|j                  d       |dkD  r!|	d k  r|dz  }|j                  d!|dd"       nA|dkD  r|	dk  r|dz  }|j                  d#       n |d$kD  r|
dk  r|d%z  }|j                  d&       |d'kD  r|d(z  }|j                  d)|d*d+       n%|d,kD  r |d-k  r|dz  }|j                  d.|d*d+       |d/kD  r|d-k  r|d%z  }|j                  d0       n |d1kD  r|	dk  r|d2z  }|j                  d3       |d$k  r|dz  }|j                  d4|dd       t        |      d5k  r$t        |      d5k  r|d2z  }|j                  d6       |d7k\  r|d8z  }|j                  d9|dd       nA|d:k\  r|d(z  }|j                  d;|dd       n |dk\  r|d2z  }|j                  d<|dd       |d-k  r!|dk  r|d8z  }|j                  d=|dd       nP|dk  r!|	d>k  r|d(z  }|j                  d?|dd       n*|d>k  r%|d>k  r |d>k  r|d%z  }|j                  d@|dd       |j                  dA      xs |j                  dB      }|r	 t        |t              rt        j                  |      }n|}t        j                         |z
  j                         dCz  }|dCk\  r*t        |      d$k  r|d(z  }|j                  dD|d*dE       n]|dFk\  r*t        |      d$k  r|dz  }|j                  dD|d*dG       n.|d(k\  r)t        |      dHk  r|dIz  }|j                  dJ|d*dG       t        dt        |dz  dKz              }|||||| j                  dL   k\  dMS #  Y 7xY w)Nu  
        Calcule un score indiquant si le cycle de gain est terminé pour une position.
        
        Score élevé = cycle terminé → candidat à la vente/rotation
        
        Args:
            position: Données de la position (entry_price, quantity, etc.)
            features: Indicateurs techniques actuels
            
        Returns:
            Dict avec score et raisons
        r   entry_pricerv   u   Données de prix invalides)r   reasonsrq   d   rw   rx   ry   rz   r{   r|   r   r}   rn   r~         ?g   u   🔻 Momentum effondré (r   %)gٿr      u   📉 Momentum en baisse (m3=gɿr   u   ↘️ Momentum négatif皙?333333ÿu   🔄 Pic atteint (EMA_diff=u   %, slope↓)u   📊 EMA en retournementro      u&   ⚠️ Tendance moyen terme baissièreP   r!   u   🔴 RSI surachat (.0f)F   333333ӿu   ⚠️ RSI élevé + baisse (g?u%   📈 Sommet BB (prêt à redescendre)333333?   u   BB haute + tendance baissièreu$   😴 Squeeze BB (volatilité morte: rs   u   ⏸️ Stagnation totaleru   r
   u   💰 Profit à sécuriser (+      ?u   🎯 TP atteint (+u   📈 Petit profit (+u&   📉 En perte avec momentum négatif (皙u*   ⚠️ En perte avec tendance baissière (u&   ↘️ Légère perte en aggravation (	timestamp
entry_timerp   u   ⏰ Stagne depuis zmin sans TPr   min皙?r   u   ⏳ En attente depuis _   r   )r   	raw_score
profit_pctr   cycle_ended)r?   r   abs
isinstancestrr   fromisoformatr+   total_secondsr   intr$   )r1   r   r   r   r   r   r   r   rw   rx   ry   rz   r{   r|   r}   r~   r   entry_dthold_minutesnormalized_scores                       r2   calculate_cycle_end_scorez'SmartRotation.calculate_cycle_end_score   sS    ll=!4 _a8!}1,H+IJJ${2a73>
 <<
A.LLa0	!&6:\\,2
\\,2
ll5"%ll=#6||NC8 RKENN6z#6FbIJ$:#4RKENN9*S9ILM$:#4RKENN56 c>i%/RKENN8#lST^	D 0RKENN56^ 5RKENNCD 8RKENN0S	;<2X*t+RKENN:3s)1EF *t"3RKENNBC4I$4QJENN;< #RKENNA,sASSUVW z?T!c*o&<QJENN56
 RKENN9*S9ILM3RKENN/
3/?rBC3QJENN1*S1ADE *q.RKENNCJsCSSUVW4I$4RKENNG
SVGWWYZ[4J$5*t:KRKENNCJsCSSUVW \\+.L(,,|2L
j#.'55jAH)H ( 9HHJRO  2%#j/C*?RKENN%7S7I#UV!R'C
Oc,ARKENN%7S7I#MN!R'C
Oc,AQJENN%;L;MS#QR
 sCb(8$9: &$+t{{;P/QQ
 	
s   :CR	 	R	candidatec           
         d}g }|j                  dd      }|j                  dd      }|j                  dd      }|j                  dd      }|j                  dd      }	|j                  dd	      }
|j                  d
d      }|j                  dd      }|j                  dd      }|dk(  r|dz  }|j                  d       n&|dk(  r|dz  }|j                  d       n
|dk(  r|dz  }t        |dz  dz        }||z  }|dk\  r|j                  d| d       n|dk\  r|j                  d| d       |dk  r|dz  }|j                  d|dd        n]|d!k  r|dz  }|j                  d"|dd        n<|d#k  r|d$z  }|j                  d%       n |dkD  r|d&k  r|d'z  }|j                  d(       |dk  r!|d)kD  r|dz  }|j                  d*|dd        n]|d+kD  r|dk\  r|dz  }|j                  d,       n<|d-k\  r|d'z  }|j                  d.       n |d/k  r|dz  }|j                  d0|dd        |	dk  r|dz  }|j                  d1|	d2d       nb|	d3k  r|d$z  }|j                  d4|	d2d       nA|	d5k  r|d6z  }|j                  d7|	d2d       n |	d8kD  r|d9z  }|j                  d:|	d2d       |
d;k  r|dz  }|j                  d<       nS|
d=k  r|d$z  }|j                  d>       n7|
d?k  r|d6z  }|j                  d@       n|
dAkD  r|d9z  }|j                  dB       dC|cxk  rdDk  rn n|d9z  }|j                  dE|dd        n*d	|cxk  rdFk  r	n n|dz  }n|j                  dG|dd        t        dt	        dt        |dz  dHz                    }|||j                  dIdJ      ||| j
                  dK   k\  dLS )Muh  
        Calcule un score d'opportunité pour un candidat d'achat potentiel.
        
        Score élevé = excellente opportunité d'achat
        
        Args:
            candidate: Données du candidat (symbol, smart_signal, etc.)
            features: Indicateurs techniques
            
        Returns:
            Dict avec score et raisons
        r   rw   rx   rz   r{   r|   r   r}   rn   r~   r   r   HOLDsmart_scoreACHATr   u   ✅ Signal ACHAT IAr   r!   u   🟡 Signal POSSIBLEr   r   r
   r   u   🌟 Score IA élevé (r   rp   u   ✅ Score IA correct (r   u   📉 Creux profond EMA (r   r   r   u   📊 Bon creux EMA (gr   u   ↘️ Léger creux EMAro   r   u   Tendance neutre/haussière皙?u   🚀 Rebond détecté (mom3=+rs   u   📈 Momentum positifr   u   ➡️ Momentum stabilisér   u   ⚠️ Chute en cours (u   🔥 RSI survente forte (r   #   u   📊 RSI survente (rr      zRSI favorable (r   r   u   ⚠️ RSI trop élevé (333333?u   💎 BB basse (zone d'achat)g      ?u   📉 Proche BB basseg?zBB zone basser   u   ⚠️ BB trop hauter   g      @u   ✅ Bonne volatilité (g      @u   ⚠️ Volatilité anormale (   r;   rP   r   )r   r   r;   r   is_opportunity)r?   r   r   maxr   r$   )r1   r   r   r   r   rw   rx   rz   r{   r|   r}   r~   r   r   ai_score_bonusr   s                   r2   calculate_opportunity_scorez)SmartRotation.calculate_opportunity_score  sR     <<
A.LLa0	\\,2
\\,2
ll5"%ll=#6||NC8 !}}^V<mmM15 7"RKENN01Z'RKENN12V#QJE [3.34"NN4[MCDBNN3K=BC d?RKENN5hs^2FGRKENN1(3rBCRKENN46\hnQJENN78 a<J,RKENN::c:J"MN$9>RKENN234QJENN78$RKENN4Z4DBGH
 8RKENN6s3iqAB2XRKENN0S	;<2XQJENN_SIQ782XRKENN6s3iqAB
 RKENN9:4RKENN123QJENN?+4RKENN12
 ,%#%RKENN4\#4FbIJL'C'QJENN:<:LBOP q#c3us{S/@+A"BC &mmHb1.$++>U2VV
 	
r4   features_mapc                 @   | j                   j                  dd      sg S | j                          | j                  | j                   d   k\  r%t        j                  d| j                   d       g S g }| j                         }|D ch c]  }|j                  dd       }}t        |t        |j                               z
        }|dk  r7t        j                  d	| d
       t        |      }| j                  |||      }g }	t        j                  dt        |       dt        |       d       |j                         D ]{  \  }
}|j                  |
i       j                         }|
|v r}||
   }||d<   |j                  dd      }|dkD  r\||z  dz
  dz  }|j                  d|dz        |d<   |j                  d|dz        |d<   t        j                  d|
 d|dd|dd       |st        j                  d|
 d       |j                  d      xs |j                  d      }d}|r	 t        |t               rt#        j$                  |      }n|}t#        j&                         |z
  j)                         d z  }|| j                   d!   k  r/t        j                  d|
 d"|d#d$| j                   d!    d%       ~	 |
| j,                  v r[| j,                  |
   t/        | j                   d(   )      z   }t#        j&                         |k  rt        j                  d|
 d*       | j1                  ||      }t        j                  d|
 d+|d,    d|d-   dd.|d/           |d-   dkD  r8|d-   d0k  r0|d,   d1k  r(t        j                  d|
 d2|d-   dd3|d,    d       e|	j3                  |
||||d4       ~ g }t        j                  d5t        |       d6       |D ]$  }|j                  dd      }
|
|v rt        j                  d|
 d7       4|j                  d8i       }|st        j                  d|
 d9       b|j                  d:d;      }|d<v rt        j                  d|
 d=| d       |j                  d>d      }d }||k  r t        j                  d|
 d?| d@| d       | j5                  ||      }t        j                  d|
 dA|d,    dB| dC|dD           |dD   s|j3                  |
||||dE       ' t        j                  dFt7        dG |	D                      t        j                  dHt        |              |	D ]  }|dI   d/   s|D ]  }|dI   d,   }|dJ   d,   }|| j                   dK   z
  } |dI   j                  d-d      dLk  r| dz  } t        j                  dM|d    dN|d    dO| dP| dQ|  
       | | j                   dR   k\  s|j3                  |d   ||dI   dS   |dI   d-   |d   ||j                  dTd      |dJ   dS   | ||z   t#        j&                         j9                         dU         |j;                  dV dW       |S c c}w # t*        $ r&}t        j                  d|
 d&|        Y d'}~d'}~ww xY w)Xu{  
        Identifie les meilleures opportunités de rotation.
        
        Args:
            positions: Positions actuelles {symbol: position_data}
            watchlist: Liste des candidats d'achat avec features
            features_map: Dictionnaire {symbol: features}
            
        Returns:
            Liste des rotations recommandées triées par avantage
        r   Tr   u!   ⏳ Max rotations/heure atteint (r   r;   rP   r   u   🔄 Watchlist limitée (u5    candidats), génération de candidats alternatifs...u   🔄 Analyse rotation: z positions, z
 candidatsrv   r   r   rq   r   rz   r{   r   r   z: Prix actuel=z.6fz, P&L=r   %z: Pas de features disponiblesr   r   i  rp   r   u   : Trop récent (r   zmin < zmin)z: Erreur parsing date: Nr   )minutesz: En cooldown rotationz: Score cycle=r   r   z	%, ended=r   r   r   z: Petit profit (z%) et score trop bas ()r;   r   r   cycle_analysisr   u   🔍 Analyse de z candidats potentielsu   : SKIP (déjà en position)r   z: SKIP (pas de features)r   r   )VENTE
ABANDONNEEEN_POSITIONz: SKIP (signal=r   z: SKIP (score IA= < r   z, ai_score=z	, is_opp=r   )r;   r   r   opportunity_analysisai_scoreu   📊 Positions fin de cycle: c              3   2   K   | ]  }|d    d   sd  yw)r   r   rq   N ).0ps     r2   	<genexpr>z<SmartRotation.find_rotation_opportunities.<locals>.<genexpr>  s     8{qXYZjXklyXz8{s   u   📊 Opportunités: r   r   r   r   z   Rotation z -> z: sell=z, buy=z, advantage=r   r   r   )sell_symbol
sell_scoresell_reasonssell_profit_pct
buy_symbol	buy_scorebuy_ai_scorebuy_reasons	advantagerotation_scorer   c                     | d   S )Nr   r   r   s    r2   r   z;SmartRotation.find_rotation_opportunities.<locals>.<lambda>  s
    Q{^ r4   r   )r$   r?   _check_hourly_resetr*   r/   r0   rK   rC   r   r   listr   r   itemsr'   r   r   r   r   r+   r   rE   r)   r   r   r   r   sum	isoformatr   )!r1   rM   rL   r   	rotationsrN   r   r   candidates_countpositions_scoresr;   posr   
real_pricer   r   r   r   r   rJ   cooldown_endr   opportunitiesr   r   r   MIN_AI_SCORE_FOR_ROTATIONopp_analysispos_itemopp_itemr   r   r   s!                                    r2   find_rotation_opportunitiesz)SmartRotation.find_rotation_opportunities;  s    {{y$/I 	  "##t{{3K'LLKK;D<T<T;UUVWXI	 002 ;DDQQUU8R0DD03y~~7G3HHIaKK34D3EEz{|YI==iTbcI .s9~.>l3y>JZZdef$??, @	KFC#''388:H '+F3
,6)!ggmQ7?#-#;q"@C!GJ-5\\,
UV-WH\*-5\\,
UV-WH\*LL3vhnZ<LFS]^aRbbc!des6(*GHI -F1FJL
K!*c2#+#9#9*#E#-$,LLNX$=#L#L#NQS#SL#dkk2I&JJs6(2B<PSBTTZ[_[f[fg~[  [A  AE  &F  G  K ,,,#226:Y KK(CD>   <<>L0LL3vh.D!EF!;;CJNLL3vhn^G5L4MVTbcoTpqtSuu~  @N  O\  @]  ^  _  ` l+a/N<4PSV4V!'*R/LL3vh.>~l?[\_>``v  xF  GN  xO  wP  PQ  "R  S## $"0 ,% u@	F 'I'77LMN" %	I]]8R0F "s6(*EFG }}Z4Hs6(*BCD %==@LEEs6(/,qIJ !}}]A6H(*%33s6(*;H:SIbHccdef;;IxPLLL3vhh|G/D.E[QYPZZcdp  rB  eC  dD  E  F,-$$$!* (,8 (& ?%	P 	4S8{DT8{5{4|}~+C,>+?@A( #	H,-m<)  &&67@
$%;<WE	
 &4K(LL	 ,-11,BTINI|HX,>+?tHXDVCWW^_i^jjpqzp{  |H  IR  HS  T  U,A BB$$'/'9&0(01A(B9(M+34D+El+S&.x&8%.(0Z(C'/0F'G	'R%.*4y*@%-\\^%=%=%?& '	#	L 	3TBI EZ ! KLL3vh.EaS!IJJKs   Y)/BY..	Z7ZZrotationc                    | j                   j                  dd      sy	 ddlm} |j                  rdS 	 | j                          | j                  | j                   d   k\  rdd| j                   d    d	fS |d
   | j                   d   k  rdd|d
    d| j                   d    d	fS |d   | j                   d   k  rdd|d    d	fS |d   | j                   d   k  rdd|d    d	fS y# t
        $ r Y w xY w)u   
        Décide si une rotation doit être exécutée.
        
        Args:
            rotation: Données de la rotation proposée
            
        Returns:
            (should_execute, reason)
        r   T)Fu   Rotation désactivéer   )AIPredictorFr   zMax rotations/heure (r   r   r   zAvantage insuffisant (r   r   r   zScore vente trop bas (r   r   zScore achat trop bas ()Tu   Rotation validée)Fu+   Mode CRASH MARCHÉ actif - pas de rotation!)r$   r?   ai_predictorr  _market_crash_moderE   r   r*   )r1   r  r  s      r2   should_rotatezSmartRotation.should_rotate   s?    {{y$/1	0--LL . 	  "##t{{3K'LL1$++>V2W1XXYZZZ K 4;;/D#EE28K3H2IT[[YnMoLppqrrr L!DKK0E$FF28L3I2J!LLLK 4;;/F#GG28K3H2IKKK('  		s   C& &	C21C2c                    | j                  |      \  }}|sd||dS |d   }|d   }t        j                  d       t        j                  d| d|d    d	       t        j                  d
| d|d    d	       t        j                  d|d    d       d||dd|d}|r/	  ||dd|d    d	      }||d<   |r ||dd|d    d	      }	|	|d<   |j                  d      s|j                  d      r| j                  |       |S # t        $ r5}
t        j	                  d|
        d|d<   t        |
      |d<   Y d}
~
nd}
~
ww xY w)u  
        Exécute une rotation (vente puis achat).
        
        Args:
            rotation: Données de la rotation
            execute_callback: Fonction pour exécuter les ordres
            
        Returns:
            Résultat de l'exécution
        F)successreasonr  r   r   u   
🔄 ROTATION EN COURSu      📤 VENTE: z (Score fin cycle: r   r   u      📥 ACHAT: u    (Score opportunité: r   u      📊 Avantage: +r    ptsT)r  r   r   sell_executedbuy_executedr  SELLu%   🔄 ROTATION: Cycle terminé (score=r  BUYu.   🔄 ROTATION: Opportunité détectée (score=r  u   Erreur exécution rotation: r  errorN)r  r/   r0   rE   r  r   r?   _record_rotation)r1   r  execute_callbackshould_execr  r   r   resultsell_result
buy_resultrJ   s              r2   execute_rotationzSmartRotation.execute_rotation*  s    #00:V  $  }-l+
.0ok]2Eh|F\E]]^_`oj\1GQ\H]G^^_`a)(;*?)@EF &$"! 
 ).{F1VW_`lWmVnno/pr*5'!1*e4bcklwcxbyyz2{"}J-7F>* ::o&&**^*D!!(+  );A3?@$)y!"%a&w)s   ".D 	E+D>>Ec                    | xj                   dz  c_         t        j                         | j                  |d   <   t        j                         | j                  |d   <   t        j                         j	                         |d<   | j
                  j                  |       t        | j
                        dkD  r| j
                  dd | _        | j                          y)u#   Enregistre une rotation effectuée.rq   r   r   executed_atr   iN)	r*   r   r+   r)   r   r(   r   rC   _save_history)r1   r  s     r2   r  zSmartRotation._record_rotationg  s      A% 7?||~H]346>llnH\23 #+,,.":":"<$$X. t$$%*$($9$9#$$?D! 	r4   c                     t        j                         }|| j                  z
  j                         dk\  rd| _        || _        yy)u)   Reset le compteur horaire si nécessaire.  r   N)r   r+   r,   r   r*   )r1   r+   s     r2   r   z!SmartRotation._check_hourly_resetx  s;    lln$//!002d:'(D$!DO ;r4   c                 p   	 t         j                  j                  t         j                  j                  t              d      }t        |dd      5 }t        j                  | j                  |dd       ddd       y# 1 sw Y   yxY w# t        $ r"}t        j                  d	|        Y d}~yd}~ww xY w)
z&Sauvegarde l'historique des rotations.zrotation_history.jsonr   zutf-8)encoding   F)indentensure_asciiNz'Erreur sauvegarde historique rotation: )ospathjoindirname__file__openrA   dumpr(   rE   r/   r   )r1   filepathfrJ   s       r2   r#  zSmartRotation._save_history  s    	Hww||BGGOOH$=?VWHhg6 R!		$//15QR R R 	HLLB1#FGG	Hs6   AB
 $A>5B
 >BB
 B
 
	B5B00B5c           	         | j                          | j                  j                  dd      | j                  | j                  d   t	        d| j                  d   | j                  z
        dt        j                         | j                  z
  j                         z
  t        | j                        | j                  r| j                  d   nd| j                  dS )	u+   Retourne le statut du système de rotation.r   Tr   r   r%  N)r   r*   max_per_hourremaining_this_hourhour_reset_intotal_rotationslast_rotationr$   )r   r$   r?   r*   r   r   r+   r,   r   rC   r(   )r1   s    r2   
get_statuszSmartRotation.get_status  s      " {{y$7#'#;#; KK(@A#&q$++6N*ORVRjRj*j#k!X\\^doo%E$T$T$VV"4#8#89:>:O:OT2226UYkk	
 		
r4   )N)__name__
__module____qualname____doc__r   r3   r   r   rB   rK   r   r   r   r
  r   boolr  r   r  r   r#  r;  r   r4   r2   r#   r#   S   sR   	7t 	7($s) (tCJ?O (>x$t* x59#t)_x:>sEz:JxOSTXzxtj
$ j
$ j
4 j
XQ
T Q
T Q
d Q
fC04S$YC04T
C 48T	?C HLDzCJ()d ()uT3Y/? ()T; ; ;z ""H
D 
r4   r#   r6   c                  .    t         
t               a t         S )z8Retourne l'instance globale du gestionnaire de rotation.)_smart_rotationr#   r   r4   r2   get_smart_rotationrC    s     '/r4   rM   rL   r   c                 <    t               }|j                  | ||      S )u  
    Fonction utilitaire pour analyser les opportunités de rotation.
    
    Args:
        positions: Positions actuelles
        watchlist: Candidats d'achat
        features_map: Features par symbole
        
    Returns:
        Liste des rotations recommandées
    )rC  r
  )rM   rL   r   rotation_mgrs       r2   analyze_rotation_opportunityrF    s!     &'L33Iy,WWr4   __main__)levelg      Y@r   rq   )hours)r   quantityr   g     Y@r   r   r   H   r   g333333?)rv   rw   rx   rz   r{   r|   r}   r~   g      I@g      пrs   r   g{Gz?    r   r   ETHUSDTr   K   AU   )grader   )r;   r   r   r   ai_compatibility
z<============================================================u#   🔴 Analyse Fin de Cycle (BTCUSDT)zScore: r   z/100zProfit: r   z+.2fr   u   Cycle terminé: r   u   ✅ OUIu   ❌ NONzRaisons:r   z  - u#   🟢 Analyse Opportunité (ETHUSDT)u   Opportunité valide: r   u   🔄 Simulation Rotationr   zVente BTCUSDT: score zAchat ETHUSDT: score zAvantage rotation: +r  u   Rotation recommandée: r   )(r?  rA   loggingr+  r   r   typingr   r   r   r   numpynp	getLoggerr<  r/   r$   getattrr&   r0   ImportErrorr#   rB  rC  rF  basicConfigINFOr+   test_positiontest_features_selltest_features_buytest_candidater  r   cycle_resultprintrr   
opp_resultr   r   r4   r2   <module>re     s  (   	 ( . . 			8	$-&v/MrR%,V5UWY%Z#*63QST#U#*63H$#O!(1I2!N%,V5H"%M")&2I1"M6#:DA	O KK@BHB
 B
L M XD XT$Z X04X9=dX" zGgll+ "hllnyq'99M 	 	 %&)B7N H 55mEWXL	Bvh-	
/0	VH	GL)*$
/0	H\,/5Q
78	,}*EY9U
VW	*)$ QCj 55nFWXJ	Bvh-	
/0	VH	GJw'(
-.	!z:J/K)QZ![
\]	*	" QCj 
Bvh-	
$%	VH7#s\'-B'BCI	!,w"7!8
9:	!*W"5!6
78	 4
01	#bIi#P
QRU I     " "$  " $( "$ &( #$ =O s   A I6 6J
	J
