
    i`                         d Z ddlZddlmZmZ ddlmZmZmZm	Z	 ddl
Z
 e
j                  d      Z G d d      ZdadefdZy)	u   
Multi-Timeframe Analyzer - Analyse sur plusieurs échelles de temps
Améliore la fiabilité des signaux en détectant la convergence sur 5m, 15m, 1h, 4h
    N)datetime	timedelta)DictListOptionalTupleMultiTimeframeAnalyzerc                   |    e Zd ZdZg dZdddddZd Z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eef   fdZy)r	   z5Analyse multi-timeframe pour confirmation des signaux)5m15m1h4hg333333?g      ?g333333?c                 <    d | _         t        j                  d       y )Nu(   ✅ Multi-Timeframe Analyzer initialisé)klines_fetcherloggerinfo)selfs    ./multi_timeframe_analyzer.py__init__zMultiTimeframeAnalyzer.__init__   s    ">?    c                     || _         y)z*Injecte le fetcher de klines depuis le botN)r   )r   fetchers     r   set_klines_fetcherz)MultiTimeframeAnalyzer.set_klines_fetcher   s
    %r   symbolreturnc           
         | j                   st        j                  d       dddS i }g }g }	 | j                  D ]  }| j                  ||d      }|rt	        |      dk  r(|D cg c]  }t        |d          }	}|D cg c]  }t        |d	          }
} |||	|
      }|skt        |d
      sx|j                  }|t        |dd      t        |dd      t        |dd      d||<   |j                  |       |j                  | j                  |           |sdddS t        d t        ||      D              t        |      z  }| j                  |      }t        d||z         }d||||t        d |j                         D              t	        |      dS c c}w c c}w # t         $ r3}t        j#                  d| d|        dt%        |      dcY d}~S d}~ww xY w)u(  
        Analyse un symbole sur tous les timeframes
        
        Args:
            symbol: Symbole à analyser
            analyze_func: Fonction d'analyse à appliquer (ex: analyze_symbol)
        
        Returns:
            Dict avec scores par timeframe et score final pondéré
        u2   ⚠️ Klines fetcher non configuré pour multi-TFF
no_fetcher)successreasond   )intervallimit2         scorepattern 
confidencer   statuswatching)r&   r'   r)   r*   no_datac              3   ,   K   | ]  \  }}||z    y w)N ).0sws      r   	<genexpr>zAMultiTimeframeAnalyzer.analyze_symbol_multi_tf.<locals>.<genexpr>U   s      H41aQ Hs   Tc              3   2   K   | ]  }|d    dkD  sd  yw)r&   <      Nr.   )r/   rs     r   r2   zAMultiTimeframeAnalyzer.analyze_symbol_multi_tf.<locals>.<genexpr>c   s     $T1AgJQSOQ$Ts   )r   
timeframesweighted_scorealignment_bonusfinal_scorealigned_counttotal_timeframeszErreur analyse multi-TF z: N)r   r   warning
TIMEFRAMESlenfloathasattrr&   getattrappendTIMEFRAME_WEIGHTSsumzip_calculate_alignment_bonusminvalues	Exceptionerrorstr)r   r   analyze_funcresultsscoresweightstfklineskpricesvolumesanalysisr&   r8   r9   r:   es                    r   analyze_symbol_multi_tfz.MultiTimeframeAnalyzer.analyze_symbol_multi_tf#   s    ""NNOP$==3	8oo ?,,Vb,LVr!1 066!%!+66067151;77 (@' :$NNE!&#*8Y#C&-ha&H")(Hj"I	#GBK MM%(NN4#9#9"#=>1?4 #(I>> ! H3vw3G HH3w<WN #==gFO c>O#CDK  %"0#2*!$$T0@$T!T$'L = 77N  	8LL3F82aSAB$A77	8sO   8F$ &F;F$ FF$ %F$ 2A.F$ !A8F$ 
F$ $	G -(GG G rN   c                     t        |      dk  ry|j                         D cg c]  }|d   	 }}t        d |D              ryt        d |D              ryt        d |D              t        |      d	z  k\  ry
yc c}w )u   
        Calcule un bonus si les timeframes sont alignés
        
        Returns:
            Bonus de 0 à 25 points selon l'alignement
           r   r&   c              3   &   K   | ]	  }|d kD    yw)r4   Nr.   r/   r0   s     r   r2   zDMultiTimeframeAnalyzer._calculate_alignment_bonus.<locals>.<genexpr>x        &!q2v&      c              3   &   K   | ]	  }|d kD    yw)r#   Nr.   r\   s     r   r2   zDMultiTimeframeAnalyzer._calculate_alignment_bonus.<locals>.<genexpr>|   r]   r^      c              3   ,   K   | ]  }|d kD  s	d  yw)r4   r5   Nr.   r\   s     r   r2   zDMultiTimeframeAnalyzer._calculate_alignment_bonus.<locals>.<genexpr>   s     +QAFq+s   
ffffff?
   )r?   rI   allrE   )r   rN   r6   rO   s       r   rG   z1MultiTimeframeAnalyzer._calculate_alignment_bonusk   s     w<!&-nn&67!G*77 &v&& &v&& +&++s6{S/@@  8s   A9c                     |rd|vry|d   }|j                         D cg c]  }|d   	 }}|rt        |      t        |      z  nd}|dkD  ry|dkD  ry|d	k  ry
|dk  ryyc c}w )u   
        Détermine la consistance de la tendance sur les timeframes
        
        Returns:
            'STRONG_BULLISH', 'BULLISH', 'NEUTRAL', 'BEARISH', 'STRONG_BEARISH'
        r7   NEUTRALr&   r#   F   STRONG_BULLISH7   BULLISH   STRONG_BEARISH-   BEARISH)rI   rE   r?   )r   rN   tf_datar6   rO   	avg_scores         r   get_trend_consistencyz,MultiTimeframeAnalyzer.get_trend_consistency   s     ,g5,'&-nn&67!G*7717CK#f+-R	r>#^^#^ 8s   A!multi_tf_resultc                 L   |j                  d      sy|j                  dd      }|j                  dd      }|j                  dd      }|dk  ry|d	k  r	d
d|ddfS |dkD  r||z  nd}|dk  rd
d|dz  ddfS | j                  |      }|dv rd
d| dfS dd| d| d|ddfS )u   
        Décide si on doit entrer en position basé sur l'analyse multi-TF
        
        Returns:
            (should_enter: bool, reason: str)
        r   )Fu   Données multi-TF insuffisantesr:   r   r;   r<   rZ   )FzPas assez de timeframesrj   FzScore multi-TF trop faible (z.1f)rc   zAlignement insuffisant (r    z.0fz%))ro   rm   u"   Tendance baissière sur multi-TF (Tu   Signal confirmé sur /z TF (score=)getrr   )r   rs   r:   r;   total_tfalignment_ratiotrends          r   should_enter_positionz,MultiTimeframeAnalyzer.should_enter_position   s    ""9-;%))-;'++OQ?"&&'91= a<3 8S8IKKK 7?l-(2S 4_S5H4MRPPP**?;11>ugQGGG,]O1XJkR]^aQbbcdddr   N)__name__
__module____qualname____doc__r>   rD   r   r   rL   r   rX   r@   rG   rr   r   boolr{   r.   r   r   r	   r	      s    ?*J 	@&F8c F8D F8P$ 5 6T c 4eT eeD#I>N er   r   c                  .    t         
t               a t         S )z:Retourne l'instance globale de l'analyseur multi-timeframe)_multi_tf_analyzerr	   r.   r   r   get_multi_tf_analyzerr      s     !35r   )r   numpynpr   r   typingr   r   r   r   logging	getLoggerr   r	   r   r   r.   r   r   <module>r      sR   
  ( . . 			3	4qe qej  5 r   