
    iA                     p   d 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 ddl	m
Z
 ddlZddlZddlmZmZ dZdZ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da defdZ!e"dk(  rS e#d        e!       Z$g dZ% e#d       e$jM                  e%        e#d        e#d        e#de         e#de        yy)u  
VOLATILITY SCORER - Identifie les cryptos avec le bon profil de variabilité
=====================================================================

Objectif: Identifier les cryptos qui ont des cycles réguliers (calme → breakout)
et qui génèrent fréquemment des opportunités d'achat exploitables.

Métriques calculées:
1. Amplitude moyenne sur 1h, 4h, 24h
2. Fréquence des phases calmes (BB squeeze)
3. Qualité des breakouts après phases calmes
4. Régularité des cycles (prévisibilité)

Résultat: Score de 0-100 pour chaque crypto
- 80-100: Excellent (SOL-like, cycles réguliers)
- 60-79: Bon (tradable)
- 40-59: Moyen (acceptable)
- 0-39: Mauvais (trop stable ou trop chaotique)
    N)datetime	timedelta)DictListOptional)Client)BINANCE_API_KEYBINANCE_API_SECRETzvolatility_stats.jsonzvolatility_scores.json   P   <   (   {Gzt?gQ?      g333333?g      ?c                   `   e Zd ZdZd ZdefdZdefdZd Zd Z	de
fdZd	ed
ededej                  fdZddej                  dedee
   fdZdej                  dee
   defdZdee
   defdZd	edefdZdedefdZddeee      fdZd	edefdZd	edefdZd	ede
fdZd	ede
fdZy)VolatilityScoreru^   Analyse la qualité de la volatilité des cryptos pour identifier les meilleures opportunitésc                     t        t        t              | _        | j	                         | _        | j                         | _        y N)r   r	   r
   client_load_statsstats_load_scoresscores)selfs    ./volatility_scorer.py__init__zVolatilityScorer.__init__5   s1    _.@A%%'
'')    returnc                    t         j                  j                  t              rK	 t	        t        d      5 }t        j                  |      }t        |t              r|cddd       S 	 ddd       di dS # 1 sw Y   xY w#  Y xY w)u&   Charge les statistiques de volatilitérN)last_updatesymbols)	ospathexistsVOLATILITY_STATS_FILEopenjsonload
isinstancedictr   fdatas      r   r   zVolatilityScorer._load_stats:   s|    77>>/0/5 $99Q<D!$-#$ $-$  
 	
$ $s(   B  'A4	B  'B  4A=9B   Bc                 h   t         j                  j                  t              ry	 t	        t        d      5 }t        j                  |      }t        |t              r|cddd       S t        j                  dt        |      j                   d       	 ddd       i S i S # 1 sw Y   i S xY w#  Y i S xY w)u    Charge les scores de volatilitér!   Nu'   ⚠️ volatility_scores.json contient u!    au lieu de dict - réinitialisé)r$   r%   r&   VOLATILITY_SCORES_FILEr(   r)   r*   r+   r,   loggerwarningtype__name__r-   s      r   r   zVolatilityScorer._load_scoresI   s    77>>01	0#6 I!99Q<D!$-#	I I )PQUVZQ[QdQdPe  fG  (H  II 	r	I 		s4   B, 'B	B, &,BB, B)$B, )B, ,B1c                     t        t        d      5 }t        j                  | j                  |d       ddd       y# 1 sw Y   yxY w)zSauvegarde les statistiquesw   indentN)r(   r'   r)   dumpr   r   r.   s     r   _save_statszVolatilityScorer._save_statsX   s8    '- 	/IIdjj!A.	/ 	/ 	/	   #=Ac                     t        t        d      5 }t        j                  | j                  |d       ddd       y# 1 sw Y   yxY w)zSauvegarde les scoresr7   r8   r9   N)r(   r1   r)   r;   r   r<   s     r   _save_scoreszVolatilityScorer._save_scores]   s8    (#. 	0!IIdkk1Q/	0 	0 	0r>   c                     | j                   j                  d      syt        j                  | j                   d         }t        j                         |z
  j                         dz  }|t        k\  S )u<   Vérifie si une mise à jour est nécessaire (toutes les 6h)r"   Ti  )r   getr   fromisoformatnowtotal_secondsUPDATE_INTERVAL_HOURS)r   r"   hours_since_updates      r   should_updatezVolatilityScorer.should_updateb   sY    zz~~m,,,TZZ-FG&lln{:IIKdR!%:::r   symbolintervallookback_hoursc                    	 | j                   j                  |||      }t        j                  |g d      }|d   j	                  t
              |d<   |d   j	                  t
              |d<   |d   j	                  t
              |d<   |d   j	                  t
              |d<   |S # t        $ r/}t        d| d	|        t        j                         cY d
}~S d
}~ww xY w)u#   Récupère les données historiques)rI   rJ   limit)	timestampr(   highlowclosevolume
close_timequote_volumetradestaker_buy_basetaker_buy_quoteignore)columnsrQ   rO   rP   rR   u!   ❌ Erreur récupération klines : N)r   
get_klinespd	DataFrameastypefloat	Exceptionprint)r   rI   rJ   rK   klinesdfes          r   r[   zVolatilityScorer.get_klinesl   s    	"[[++!$ , F f / B W+,,U3BwKF**51BvJ5	((/BuIh<..u5BxLI 	"5fXRsCD<<>!	"s   B$B' '	C0$CCCrc   periodc                 4   t        |      |k  rg S |d   j                  |      j                         |d<   |d   j                  |      j                         |d<   |d   |d   z  dz  |d<   |d   j	                  d      }|d   |k  }|j                         S )uA   Détecte les phases de BB squeeze (Bollinger Bands se resserrent)rQ   )windowsmastdd   bb_widthg      ?)lenrollingmeanri   quantiletolist)r   rc   re   	thresholdsqueezess        r   calculate_bb_squeezez%VolatilityScorer.calculate_bb_squeeze   s    r7VI wK''v'6;;=5	wK''v'6::<5	U)bi/36: zN++D1	j>I-  r   rr   c                    t        |      dk  st        |      syg }t        dt        |      dz
        D ]y  }||dz
     s||   r|j                  |   d   }|j                  |dz   |dz    d   j	                         }||z
  |z  }|dkD  r|j                  d	       i|j                  d       { |syt        |      t        |      z  S )
u9   Mesure la qualité des breakouts après les phases calmesr8                 rQ   r   rO   r         ?)rl   anyrangeilocmaxappendsum)r   rc   rr   quality_scoresientry_pricemax_price_afterbreakout_gains           r   calculate_breakout_qualityz+VolatilityScorer.calculate_breakout_quality   s    r7Q;c(mq#h-!+, 	/A!}Xa[ ggaj1 #%''!A#ac"26":">">"@!0;!>+ M !5("))#."))#.	/ >"S%888r   c                    t        |      syg }t        dt        |            D ]"  }||dz
     r||   s|j                  |       $ t        |      dk  ryg }t        dt        |            D ]  }|j                  ||   ||dz
     z
         ! t	        j
                  |      }t	        j                  |      }|dk(  ry||z  }t        dd|z
        }|S )u;   Mesure la régularité des cycles (distance entre squeezes)ru   rv      r   rx   )ry   rz   rl   r}   nprn   ri   r|   )	r   rr   squeeze_startsr   	distancesmean_distancestd_distancecv
regularitys	            r   calculate_cycle_regularityz+VolatilityScorer.calculate_cycle_regularity   s    8} q#h-( 	)AAaC=Xa[%%a(	) ~" 	q#n-. 	FA^A.!1DDE	F 	*vvi(A M)cBh'
r   c           	      >   	 | j                  |t        j                  d      }| j                  |t        j                  d      }|j                  s|j                  ry|d   |d   z
  |d   z  |d<   |d   |d   z
  |d   z  |d<   |d   j                         }|d   j                         }t        |      dk\  r"|j                  d      d   j                         n|}| j                  |d	
      }| j                  |d	
      }t        |      dk\  rt        |dd       n
t        |      }	| j                  ||      }
| j                  |      }|||||	|
|t        j                         j                         dS # t        $ r}t!        d| d|        Y d}~yd}~ww xY w)u   Analyse complète d'un symbole0   *   NrO   rP   rQ   	amplitude   r   )re   i)rI   amplitude_1hamplitude_4hamplitude_24hsqueeze_frequencybreakout_qualitycycle_regularityanalyzed_atu   ❌ Erreur analyse rZ   )r[   r   KLINE_INTERVAL_1HOURKLINE_INTERVAL_4HOURemptyrn   rl   tailrs   r~   r   r   r   rD   	isoformatr`   ra   )r   rI   df_1hdf_4hr   r   r   squeezes_1hsqueezes_4hr   r   r   rd   s                r   analyze_symbolzVolatilityScorer.analyze_symbol   s   *	OOFF,G,GLEOOFF,G,GLE{{ekk #(-%,">%.!PE+"'-%,">%.!PE+ -224L -224LCFu:QSCSUZZ^K8==?YeM 33E"3EK33E"3EK <?{;Kr;Q[%6!7WZ[fWg  $>>ukR  $>>{K ! , ,!.%6$4$4'||~779	 	  	'xr!56	s   AE8 DE8 8	FFFr   c           	         |syd}|d   }t         |cxk  r	t        k  r	n n|dz  }nP|t         k  r|t        d|t         z  z        z  }n.|t        z
  t        z  }|t        dt        dd|z
  z              z  }|d   }t        |cxk  r	t
        k  r	n n|dz  }nP|t        k  r|t        d|t        z  z        z  }n.|t
        z
  t
        z  }|t        dt        dd|z
  z              z  }|d   }|t        k\  r|dz  }n|t        d|t        z  z        z  }|d   }|t        k\  r|d	z  }n|t        d	|t        z  z        z  }t        d
|      S )u(   Calcule le score de tradabilité (0-100)r   r      rv   r      r   r      rj   )	MIN_AMPLITUDE_1HMAX_AMPLITUDE_1Hintr|   MIN_SQUEEZE_FREQUENCYMAX_SQUEEZE_FREQUENCYMIN_BREAKOUT_QUALITYMIN_CYCLE_REGULARITYmin)r   r   scorer   excessfreqqualityr   s           r   calculate_scorez VolatilityScorer.calculate_score   s|    .)	y<,<<RKE))Sy+;;<==E  "226FFFSCa&j 1233E () DA,AARKE))St&;;<==E 226KKFSCa&j 1233E *+**RKESw)==>??E -.
--RKESz,@@ABBE3r   Nr#   c                 t    t        d       |sd	  j                  j                         }|d   D cg c]#  }|d   j                  d      r|d   dk(  r|d   % }}t        dt	        |       d       d}g }g }g }|D ]  }	 j                  |	      }
|
s j                  |
      }|
 j                  d   |	<   ||t        k\  rdn|t        k\  rdn|t        k\  rdnd|
d   |
d   |
d   |
d   d j                  |	<   |dz  }|t        k\  r|j                  |	       n5|t        k\  r|j                  |	       n|t        k  r|j                  |	       |dz  dk(  st        d| dt	        |       d        t        j                         j!                          j                  d<    j#                           j%                          t        d| d       t        dt         dt	        |              t        dt         dt	        |              t        d t         dt	        |              |rat        d!       t'        | fd"d#$      d
d% }|D ]<  } j                  |   }t        d&|d'd(|d)   d*d+|d   d,d-|d   d.d/|d   d0
       > y
y
c c}w # t
        $ r}t        d	|        Y d
}~y
d
}~ww xY w)1u<   Met à jour les scores de volatilité pour tous les symbolesu.   🔄 Mise à jour des scores de volatilité...r#   rI   USDTstatusTRADINGu   📊 u    symboles à analyseru$   ❌ Erreur récupération symboles: Nr   	excellentgoodmediumpoorr   r   r   r   )r   categoryr   r   r   r   rv   2   u      Analysé /z...r"   u   
✅ Analyse terminée: z cryptosu      🌟 Excellent (≥z): u      ✅ Bon (≥u      ⚠️ Mauvais (<u!   
🌟 Top 10 cryptos excellentes:c                 (    j                   |    d   S )Nr   )r   )sr   s    r   <lambda>z)VolatilityScorer.update.<locals>.<lambda>v  s    t{{1~g?V r   T)keyreverse
   z   12z Score=r   3dz | Amp=z.2%z | Freq=z.0fz | Qual=z.0%)ra   r   get_exchange_infoendswithrl   r`   r   r   r   EXCELLENT_SCORE
GOOD_SCOREMEDIUM_SCOREr   r}   r   rD   r   r=   r@   sorted)r   r#   exchange_infor   rd   analyzedr   r   r   rI   r   r   sorted_excellentsymscs   `              r   updatezVolatilityScorer.update/  s   >? $ = = ?0=i0H X1x[11&9akY>V X; X Xc'l^+@AB
 	 #	GF''/E,,U3 16

9%f-"','?"':"5$)\$9$).$9)./B)C(-.@(A(-.@(A'F# A O+$$V,j(KK'\)KK'b=A%L
!CL>EFG#	GL %-LLN$<$<$>

=! 	)(8<=&&7s3y>:JKL
|3s4yk:;$\N#c$i[AB68%i5V`defigij' a[[%C872g;r*:'"^BTUXAY Z !45c:(2FXCYZ]B^` aa {X  <QC@As(   !J (JJ J 	J7J22J7c                 Z    | j                   j                  |i       j                  dd      S )z&Retourne le score d'un symbole (0-100)r   r   r   rB   r   rI   s     r   	get_scorezVolatilityScorer.get_score|  s$    {{vr*..w;;r   c                 Z    | j                   j                  |i       j                  dd      S )u#   Retourne la catégorie d'un symboler   unknownr   r   s     r   get_categoryzVolatilityScorer.get_category  s$    {{vr*..z9EEr   c                 2    | j                  |      t        k\  S )u$   Vérifie si un symbole est excellent)r   r   r   s     r   is_excellentzVolatilityScorer.is_excellent  s    ~~f%88r   c                 2    | j                  |      t        k  S )u"   Vérifie si un symbole est mauvais)r   r   r   s     r   is_poorzVolatilityScorer.is_poor  s    ~~f%44r   )r   r   )r5   
__module____qualname____doc__r   r   r   r   r=   r@   boolrH   strr   r\   r]   r[   r   rs   r_   r   r   r   r   r   r   r   r   r   r    r   r   r   r   2   sK   h*

T 
d /
0
;t ;" " "S "R\\ "2!r|| !S !$t* ! 9R\\ 9T$Z 9TY 964: % @,S ,T ,\/T /c /bKahtCy1 KaZ< < <F3 F3 F93 94 95c 5d 5r   r   r   c                  .    t         
t               a t         S )z1Retourne l'instance singleton du VolatilityScorer)_volatility_scorerr   r   r   r   get_volatility_scorerr     s     !-/r   __main__u   🧪 Test du Volatility Scorer
)
BTCUSDTETHUSDTSOLUSDTBNBUSDTADAUSDTDOTUSDT	MATICUSDTLINKUSDTUNIUSDTAVAXUSDTu&   🔍 Test sur 10 cryptos populaires...zQ
================================================================================u'   ✅ Test terminé. Fichiers générés:z   - )'r   r)   r$   r   r   typingr   r   r   binance.clientr   pandasr\   numpyr   configr	   r
   r'   r1   rF   r   r   r   
POOR_SCOREr   r   r   r   r   r   r   r   r   r5   ra   scorertest_symbolsr   r   r   r   <module>r      s
  (  	 ( ' ' !   6 0 1   

       X5 X5x
  /  z	
,-"$FL
 

23
MM,	-	
34	E'(
)*	E()
*+% r   