
    i                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
mZ e	j                  j                  d e ee      j!                         j"                  j"                               ddlmZmZ ddlmZ ddlmZmZmZmZmZmZ ddZd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+d Z,d Z-ddZ.e/dk(  r e	j`                   e.              yy)z
Smoke tests for analysis/regime.py and analysis/bias.py.

Regime: tabular driven (input -> expected regime).
Bias: synthetic H4 series.

Run:
    cd ~/apex_v16
    python -m tests.test_regime_bias
    )annotationsN)Path)BiasDatacompute_algo_bias)determine_regime)	downtrendhh_hl_h1lh_ll_h1
ranging_h1sidewaysuptrendc                     t        d|         y )Nz  ok  )print)labels    -/home/work/apex_v16/tests/test_regime_bias.py_okr      s    	F5'
    c            	     ^    t        ddddddd      }|j                  |        t        di |S )zHHelper: build kwargs with sensible defaults, override for the test case.g      I@RANGINGr         ?F)rsi_h1market_structuretrend_maturity	atr_ratio	vol_spikeh1_struct_bullh1_struct_bear )dictupdater   )kwargsdefaultss     r   _regimer#   '   s=    "H OOF'h''r   c                    t        ddd      \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            d x}}t        d       y )N   BEARISH_EXPANSION   r   r   r   TRENDING==z%(py0)s == %(py3)srpy0py3assert %(py5)spy5z0regime: H1 RSI<30+BEARISH_EXP+mat>=3 -> TRENDING
r#   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   r-   _@py_assert2@py_assert1@py_format4@py_format6s         r   test_regime_strong_bearishrB   6   y    R2EVWXGAq!1
?1
11
:;r   c                    t        ddd      \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            d x}}t        d       y )NK   BULLISH_EXPANSIONr'   r(   r)   r*   r,   r-   r.   r1   r2   z0regime: H1 RSI>70+BULLISH_EXP+mat>=3 -> TRENDINGr3   r<   s         r   test_regime_strong_bullishrG   <   rC   r   c                    t        dd      \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}}t        d       y )Ng      @T)r   r   BREAKOUTr*   r,   r-   r.   r1   r2   z'regime: ATR>2.0 + vol_spike -> BREAKOUTr3   r<   s         r   test_regime_breakoutrJ   B   su    t4GAq!1
?1
11
12r   c                    t        dd      \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}}t        d       y )Ngffffff?   r   r   r)   r*   r,   r-   r.   r1   r2   z$regime: ATR>1.3 + mat>=3 -> TRENDINGr3   r<   s         r   !test_regime_atr_maturity_trendingrN   H   su    A6GAq!1
?1
11
./r   c                    t        dd      \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}}t        d       y )Ng333333?rL   rM   TRENDING_SOFTr*   r,   r-   r.   r1   r2   z-regime: ATR 1.1-1.3 + mat>=3 -> TRENDING_SOFTr3   r<   s         r   test_regime_atr_moderate_softrQ   N   sv    A6GAq!111178r   c                    t        dddd      \  } }}d}| |k(  }|st        j                  d|fd| |f      d	t        j                         v st        j
                  |       rt        j                  |       nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            d x}}t        d       y )N<   rF   TrL   )r   r   r   r   r)   r*   r,   r-   r.   r1   r2   z)regime: HH+HL struct + RSI>50 -> TRENDINGr3   r<   s         r    test_regime_struct_bull_trendingrT   T   s}    R2E%)!=GAq!1
?1
11
34r   c                    t               \  } }}d}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j
                  |       rt        j                  |       ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d x}}d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j
                  |      rt        j                  |      nd	t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}}g }||k(  }|st        j                  d|fd||f      d
t        j                         v st        j
                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}}t        d       y )Nr   r*   r,   r-   r.   r1   r2   zMulti-TF neutralreasonnearz)regime: default neutral inputs -> RANGINGr3   )r-   rV   rW   r>   r?   r@   rA   s          r   test_regime_default_rangingrX   [   s$   iOAvt1	>1	11	''6'''''6'''''''6'''6'''''''''''42:4244234r   c                    t        ddddd      \  } }}d}| |k(  }|st        j                  d|fd	| |f      d
t        j                         v st        j
                  |       rt        j                  |       nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}}t        |      }d}||k\  }|st        j                  d|fd||f      dt        j                         v st        j
                  t              rt        j                  t              nddt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}t        dt        |       d       y )N#   r&   g?   T)r   r   r   r   r   r   r*   r,   r-   r.   r1   r2      )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenrW   )r/   py1r0   py6zassert %(py8)spy8z+regime: near-trending diagnostics emitted (z hints))r#   r4   r5   r6   r7   r8   r9   r:   r;   r^   r   )r-   r=   rW   r>   r?   r@   rA   @py_assert5@py_assert4@py_format7@py_format9s              r   $test_regime_ranging_with_diagnosticsrf   c   s   $7qJAq$
 1	>1	11	t99>933tt9
5c$i[HIr   c                 f   t        d      } t        |       }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|j                  }d	}||k(  }|st        j                  d|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}t        d       y )N
   NEUTROr*   z,%(py2)s
{%(py2)s = %(py0)s.bias
} == %(py5)sbr/   py2r2   assert %(py7)spy7NONEz9%(py2)s
{%(py2)s = %(py0)s.allowed_direction
} == %(py5)szbias: <20 bars -> NEUTRO)r   r   biasr4   r5   r6   r7   r8   r9   r:   r;   allowed_directionr   dfrk   r?   rc   @py_assert3rA   @py_format8s          r   !test_bias_neutro_on_short_historyrx   r   s    	B"A66X6X6X116X(&(&((((&((((((1(((1((((((&((((((("#r   c            	     h   ddl } g }d}g ddz  }|D ]@  }|}||z   }t        ||      dz   }t        ||      dz
  }|j                  ||||dd       |}B | j	                  |      }	t        |	      }
|
j                  }d	}||u }|st        j                  d
|fd||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }t        j                  d|
j                         dz   d|iz  }t        t        j                   |            dx}x}}|
j"                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }t        j                  d|
j"                   d|
j                         dz   d|iz  }t        t        j                   |            dx}x}}|
j$                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                   |            dx}x}}t'        d|
j(                          y)z
    Noisy uptrend (some red bars) -> RSI stays in [50,80] so RSI override
    does NOT fire; EMA+struct path produces RIALZISTA.
    r   N      Y@)
333333?g?皙ٿ      ?r{         皙?r{   r|   r}   rL   皙?  openhighlowclosevolumeFisz7%(py2)s
{%(py2)s = %(py0)s.rsi_h4_override
} is %(py5)srk   rl   zoverride fired unexpectedly: 
>assert %(py7)sro   	RIALZISTAr*   rj   zgot  | BUYrq   rn   z0bias: EMA+struct bullish path -> RIALZISTA comp=)pandasmaxminappend	DataFramer   rsi_h4_overrider4   r5   r6   r7   r8   r9   _format_assertmsg	h1_reasonr:   r;   rr   rs   r   h1_compatibilitypdrowsbasepatterndeltaochlru   rk   r?   rc   rv   rA   rw   s                   r   !test_bias_bullish_ema_struct_pathr   z   s.   
 DD KQNG 5L1IO1IOQ!a4PQ 
d	B"ATT%TTTTTTTTT1TTT1TTTTTTTTT)Fq{{m'TTTTTTTT66A[A6[ AAA6[AAAAAA1AAA1AAA6AAA[AAADAKK="AAAAAAAA'%'%''''%''''''1'''1''''''%'''''''
:1;M;M:NOPr   c            	        dd l } g }d}g ddz  }|D ]@  }|}||z   }t        ||      dz   }t        ||      dz
  }|j                  ||||dd       |}B | j	                  |      }	t        |	      }
|
j                  }d}||u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|
j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|
j                   }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}t#        d|
j$                          y )Nr   rz   )
333333ӿgɿr   r~   r   r}   r|   r   r   r~   rL   r   r   r   Fr   r   rk   rl   rn   ro   
RIBASSISTAr*   rj   SELLrq   z1bias: EMA+struct bearish path -> RIBASSISTA comp=)r   r   r   r   r   r   r   r4   r5   r6   r7   r8   r9   r:   r;   rr   rs   r   r   r   s                   r   !test_bias_bearish_ema_struct_pathr      s   DDJQNG 5L1IO1IOQ!a4PQ 
d	B"A%%%%%%%%%%%%1%%%1%%%%%%%%%%%%%66!\!6\!!!!6\!!!!!!1!!!1!!!6!!!\!!!!!!!(&(&((((&((((((1(((1((((((&(((((((
;A<N<N;OPQr   c                    t        ddd      } t        |       }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}t        d       y)zx
    Strong uptrend will saturate RSI > 80 -> RSI override returns
    RIBASSISTA / SELL (mean-reversion expected).
    (   r   bodystepTr   r   rk   rl   rn   ro   Nr   r*   rj   r   rq   z+bias: RSI H4>80 override -> RIBASSISTA SELL)r   r   r   r4   r5   r6   r7   r8   r9   r:   r;   rr   rs   r   rt   s          r   $test_bias_rsi_h4_override_overboughtr      sv   
 
#C	(B"A$$$$$$$$$$$$1$$$1$$$$$$$$$$$$$66!\!6\!!!!6\!!!!!!1!!!1!!!6!!!\!!!!!!!(&(&((((&((((((1(((1((((((&(((((((56r   c                    t        ddd      } t        |       }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}x}}t        d       y )Nr   r   r   Tr   r   rk   rl   rn   ro   r   r*   rj   r   rq   z)bias: RSI H4<20 override -> RIALZISTA BUY)r   r   r   r4   r5   r6   r7   r8   r9   r:   r;   rr   rs   r   rt   s          r   "test_bias_rsi_h4_override_oversoldr      st   	2Cc	*B"A$$$$$$$$$$$$1$$$1$$$$$$$$$$$$$66 [ 6[    6[      1   1   6   [       '%'%''''%''''''1'''1''''''%'''''''34r   c                    ddl } t        d      D cg c]
  }d|dz  z    c}t        dd      D cg c]
  }d|d	z  z
   c}z   }t        t        |            D cg c]  }||   |dz   t        |      k  r||dz      n||   t        ||   |t	        |dz   t        |      dz
                 d
z   t	        ||   |t	        |dz   t        |      dz
                 d
z
  dd }}| j                  |      }t        |      }|j                  }d}||k  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	t        j                  d|j                   d|j                   d|j                          dz   d|	iz  }
t#        t        j$                  |
            dx}x}}t'        d|j                   d|j                   d|j(                          yc c}w c c}w c c}w )a3  
    Construct a series where EMA20>EMA50 (rising recent prices) but
    last 8 bars have LH/LL struct -> ambiguous -> NEUTRO with
    h1_compatibility 0.5 and ambiguous=True.

    Build: 20 bars rising 100->110 (lifts EMA20 above EMA50), then
    8 bars descending from 110 down to 105 (last-8 LH/LL).
    r   N   rz   r}   r\   	   g     [@g333333?g?r   )r   r   r   r   r   gffffff?)<=)z8%(py2)s
{%(py2)s = %(py0)s.h1_compatibility
} <= %(py5)srk   rl   zunexpected strong bias: z comp=r   r   ro   zbias: EMA-struct conflict -> z ambig=)r   ranger^   r   r   r   r   r   r4   r5   r6   r7   r8   r9   r   rr   r   r:   r;   r   	ambiguous)r   iclosesr   ru   rk   r?   rc   rv   rA   rw   s              r   $test_bias_ambiguous_ema_struct_clashr      sA    ',Ry1!ea#go1',Q{3!ea#go34F 3v;'	) 	 AY!c&k8I!vVWyF3qsCKM+B$CDtKF3qsCKM+B$CDtK )D )
 
d	B"A V V$ VDUDUV V VOUvV V=U=U  V VLUI  V VLUI  V VLUI "% V VDUDU
"166(&1C1C0DC}UV V VBUBUV V
'xva6H6H5IQRQ\Q\P]^_ 23)s   H7H<BIc                 H   t        d       t                t                t                t	                t                t                t                t                t                t                t                t                t                t                t        d       y)Nztest_regime_bias.pyzALL 14 TESTS PASSEDr   )r   rB   rG   rJ   rN   rQ   rT   rX   rf   rx   r   r   r   r   r   r   r   r   mainr      sk    	
   %'!#$&!(*%'%'%'(*&((*	
 r   __main__)r   strreturnNone)r   ztuple[str, str, list[str]])r   int)1__doc__
__future__r   builtinsr6   _pytest.assertion.rewrite	assertionrewriter4   syspathlibr   pathinsertr   __file__resolveparentanalysis.biasr   r   analysis.regimer   tests._fixtures.barsr   r	   r
   r   r   r   r   r#   rB   rG   rJ   rN   rQ   rT   rX   rf   rx   r   r   r   r   r   r   __name__exitr   r   r   <module>r      s   	 #   
  3tH~--/66==> ? 5 , (<<30955J$Q4R(
75`:( zCHHTV r   