
    ijf                        % S r SSKrSSKrSSKrSSKJr  \R                  " S5      r\R                  R                  \R                  R                  \R                  R                  \R                  R                  \5      5      5      SS5      rSSS	S
SSSSS\S.
r " S S5      rSq\\   \S'   SS\S-  S\4S jjrS\S\4S jr SS\S\S\\   S\4S jjrg)u  
Adaptive Threshold Manager (v12.8+)

Динамическая корректировка порогов сигналов на основе:
- Rolling WinRate последних N сделок
- Рыночного режима (choppiness)

Каждый тикер отслеживается независимо.

Formula:
    adjustment = -(winrate - breakeven) * max_adjustment / max(1-breakeven, breakeven)
    
    At WR=60%: adj = -0.04 → threshold = base - 0.04 (легче войти)
    At WR=40%: adj =  0.0 → threshold = base (без изменений)
    At WR=20%: adj = +0.04 → threshold = base + 0.04 (сложнее войти)
    N)OptionalAI_Strategymodelszadaptive_state.jsonT      g{Gz?g?g{Gz?g?g      ?)
enabledwindow_size
min_tradesmax_adjustmentwr_breakevenchoppiness_up_adj	trend_adj	clamp_min	clamp_maxpersistence_filec            	           \ rS rSrSrSS\S-  4S jjrS\4S jrS r	S	 r
S
\S\4S jrS
\S\\   4S jrS
\S\\   4S jr SS
\S\\   S\4S jjr SS
\S\S\\   S\4S jjrS
\S\4S jrS\4S jrSrg)AdaptiveThresholdManager,   z>Per-ticker adaptive threshold based on rolling trade outcomes.Nconfigc                 b    0 [         EU=(       d    0 EU l        0 U l        U R                  5         g N)ADAPTIVE_CONFIGr   _state_load)selfr   s     :/home/ai/projects/AI_Strategy/utils/adaptive_thresholds.py__init__!AdaptiveThresholdManager.__init__/   s'    ;;V\r;')

    returnc                 B    U R                   R                  S[        5      $ )Nr   )r   get
STATE_FILEr   s    r   _state_path$AdaptiveThresholdManager._state_path6   s    {{1:>>r   c                    U R                  5       n[        R                  R                  U5      (       a`   [	        US5       n[
        R                  " U5      U l        S S S 5        [        R                  S[        U R                  5       SU 35        g g ! , (       d  f       N>= f! [         a,  n[        R                  SU SU 35        0 U l         S nAg S nAff = f)NrzAdaptiveThreshold: loaded z tickers from z"AdaptiveThreshold: failed to load : )r%   ospathexistsopenjsonloadr   loggerinfolen	Exceptionwarningr   r+   fes       r   r   AdaptiveThresholdManager._load9   s    !77>>$!$_"&))A,DK %8T[[9I8J.Y]X^_`	  $_  !!CD6A3OP !s/   B' B6B' 
B$ B' '
C1"CCc                 z   U R                  5       n [        R                  " [        R                  R	                  U5      SS9  [        US5       n[        R                  " U R                  USS9  S S S 5        g ! , (       d  f       g = f! [         a%  n[        R                  SU SU 35         S nAg S nAff = f)NT)exist_okw   )indentz"AdaptiveThreshold: failed to save r)   )r%   r*   makedirsr+   dirnamer-   r.   dumpr   r3   r0   r4   r5   s       r   _saveAdaptiveThresholdManager._saveD   s    !	MKK-=dCA		$++q3 ! 	MNN?vRsKLL	Ms5   >B !A:1B :
BB B 
B:B55B:tickerwonc                    UR                  5       nXR                  ;  a  SS/ S.U R                  U'   U R                  U   nUS   R                  U(       a  SOS5        U(       a  US==   S-  ss'   OUS==   S-  ss'   [        U R                  S   S5      n[        US   5      U:  aJ  US   R                  S5      nU(       a  US==   S-  ss'   OUS==   S-  ss'   [        US   5      U:  a  MJ  U R                  5         g)	z5Records TP (True) or SL (False) outcome for a ticker.r   )winslossesoutcomesrH      rF   rG   r	   N)upperr   appendmaxr   r2   poprA   )r   rC   rD   statemax_wremoveds         r   record_outcome'AdaptiveThresholdManager.record_outcomeO   s    $+,r"JDKKF#j  cq1&MQM(Oq O DKK.2%
#$u,J'++A.Gf"h1$ %
#$u, 	

r   rH   c                 8    U H  nU R                  X5        M     g)z;Records multiple outcomes at once (e.g., all ladder tiers).N)rQ   )r   rC   rH   rD   s       r   record_outcomes_batch.AdaptiveThresholdManager.record_outcomes_batchg   s    C, r   c                     UR                  5       nU R                  R                  U5      nU(       d  gUS   US   -   nX0R                  S   :  a  gUS:  a  US   U-  $ S$ )z,Rolling win rate, None if insufficient data.NrF   rG   r
   r   )rJ   r   r"   r   )r   rC   rN   totals       r   get_winrate$AdaptiveThresholdManager.get_winraten   sc    'fh/;;|,,(-	uV}u$;t;r   
choppinessc                    U R                   R                  SS5      (       d  gU R                  U5      nUc  gU R                   S   nU R                   S   nX5:  a  X5-
  * SU-
  -  U-  nOX5-
  * U-  U-  n[        U* [	        XF5      5      nUb/  US:  a  X`R                   S   -  nOUS	:  a  X`R                   S
   -  n[        US5      $ )u   
Computes threshold adjustment:
  Positive → harder to trigger (threshold UP)
  Negative → easier to trigger (threshold DOWN)
r   Tg        r   r   g      ?gfffffN@r   gC@r      )r   r"   rX   rL   minround)r   rC   rZ   wrmax_adjbeadjs          r   get_adjustment'AdaptiveThresholdManager.get_adjustmenty   s     {{y$//f%:++./[[( 7G*b)G3CG*r/G+C7(C-. !D {{#677d"{{;//S!}r   base_thresholdc                     U R                  X5      nX$-   n[        U R                  S   [        U R                  S   U5      5      n[	        US5      $ )z>Returns adjusted threshold, clamped to [clamp_min, clamp_max].r   r   r\   )rc   rL   r   r]   r^   )r   rC   re   rZ   rb   adjusteds         r   get_adjusted_threshold/AdaptiveThresholdManager.get_adjusted_threshold   sR     !!&5!'t{{;/4;;{3X>@Xq!!r   c                 0   UR                  5       nU R                  R                  U0 5      nU R                  U5      nUR                  SS5      UR                  SS5      UR                  SS5      UR                  SS5      -   UU R	                  U5      S.$ )NrF   r   rG   )rF   rG   rW   winrate
adjustment)rJ   r   r"   rX   rc   )r   rC   sr_   s       r   	get_state"AdaptiveThresholdManager.get_state   s    KKOOFB'f%EE&!$eeHa(UU61%h(::--f5
 	
r   c                 ,    [        U R                  5      $ r   )dictr   r$   s    r   
all_states#AdaptiveThresholdManager.all_states   s    DKK  r   )r   r   r   )__name__
__module____qualname____firstlineno____doc__rq   r   strr%   r   rA   boolrQ   listrT   r   floatrX   rc   rh   rn   rr   __static_attributes__ r   r   r   r   ,   s    Htd{ ?S ?	!MS t 0-C -4: -	<# 	<(5/ 	< 6: S  #+E? >C H >B"S "/4"+3E?"FK"

 

 

!D !r   r   	_instancer   r    c                 2    [         c  [        U 5      q [         $ r   )r   r   )r   s    r   get_managerr      s    ,V4	r   rC   rD   c                 6    [        5       R                  X5        g r   )r   rQ   )rC   rD   s     r   record_trade_outcomer      s    M  -r   baserZ   c                 6    [        5       R                  XU5      $ r   )r   rh   )rC   r   rZ   s      r   adjusted_thresholdr      s    =//jIIr   r   )rx   r.   r*   loggingtypingr   	getLoggerr0   r+   joinr?   abspath__file__r#   r   r   r   __annotations__rq   r   ry   rz   r   r|   r   r~   r   r   <module>r      s  "  	  			=	)WW\\GGOOBGGOOBGGOOH$=>?#
 "H! H!Z 15	8,- 4t /G . .4 .
 6:Js J% J#+E?J>CJr   