+
    ;j  c                       R t ^ RIt^ RIHu Ht ^ RIt^ RI	t
^ RIt^ RIHt ]
P                  ! R4      tR tR tR tR tR tR# )	u  
RED→GREEN acceptance test for the trailing-stop time-gating parity fix.

Pine gates BOTH `strategy.close` calls (score-exit and trailing-stop) on
`timeCondition = time >= startDate and time <= endDate`. So a position that is
open when the window ends is held open to the chart end — Pine cannot close it
after `endDate`.

Python's `_apply_trailing_stop` previously fired the trailing stop regardless of
the time window, so a trade open across `endDate` would trail-out in OOS while
TV held it open (the 4H "TV#106 open trade" parity break).

Given/When/Then:
  Given a trade entered just before `endDate` whose price drops below the trail
        stop only on bars AFTER `endDate`,
  When  the signals are generated with a Pine time gate (`_pine_time_end`),
  Then  no exit (trail or score) fires after `endDate` — the position is held
        open, matching Pine.

A second case (no time gate) asserts the trailing stop still fires normally, so
the fix does not disable the trail inside the trading window.
N)_score_to_signalsz
2026-02-28c            
      $   \         P                  ! R ^RR7      p \        P                  ! . RO\        R7      p\        P                  ! . R	O\        R7      p\        P                  ! . R	O\        R7      p\         P
                  ! RV RVRVRV/4      # )
z
2026-02-24D)periodsfreqdtypetimeactivation_scoreclosehigh)
      (   r   r   r   r   r   )2   r   <   r   d   F   r   r   )pd
date_rangenparrayfloat	DataFrame)timesscorer
   r   s       I/Users/jameslopez/projects/TradingBot25/tests/test_mlp_trail_time_gate.py_fixture_dfr   "   ss     MM,<EHH=UKE HH=UKE88<EJD<<(:E %7 8 8    c                  &    R RRRRRRRRRR	R
R^R^/# )!i_long_entry_activation_thresholdg      Y@ i_long_exit_activation_thresholdg      I@-i_long_exit_activation_confirmation_thresholdi_use_long_exit_confirmationg      ?i_use_long_entry_confirmationFi_trailing_stop_thresholdg      4@i_exit_score_windowi_entry_score_windowg      r'   r   r   _base_paramsr(   1   s6     	,U*D7&'#Tq	 	r   c           
      (   \        4       p\        P                  ! \        V4      \        P                  R 7      p\        WVVR,          P                  \        P                  R 7      VR,          P                  \        P                  R 7      4      pV# )r   r
   r   )r   r   zeroslenfloat64r   to_numpy)paramsdf
stoch_peakouts   &   r   _runr2   @   si    	B#b'4J

J
72::.
6
"**-C
 Jr   c            	        \        4       p \        P                  ! R4      V R&   \        V R&   \	        V 4      pVR,          P
                  ^,          q"'       gZ   \        P                  ! R4      R,           R\        P                  ! V4      /,          p\        \        P                  ! V4      4      hRpVR	,          \        8  pVP                  VR
3,          q"P                  qU! 4       qf'       * qw'       g   \        P                  ! R4      R,           R\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V4      /,          p\        \        P                  ! V4      4      hR;p;p;rgVR,          P
                  R,          p^qV	8H  qU'       g   \        P                  ! RV3RW)34      R\        P                  ! V4      R\        P                  ! V	4      /,          p
\        P                  ! R4      R,           RV
/,          p\        \        P                  ! V4      4      hR;p;rYR# )z?Given a Pine time gate, the trailing stop must NOT fire in OOS.z
2017-12-01_pine_time_start_pine_time_endexecute_entryexpected entry at idx2
>assert %(py1)spy1Nr   execute_exitu}   trailing stop fired after endDate — Python should hold the position open to match Pine's timeCondition-gated strategy.closezD
>assert not %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.any
}()
}py3py5positionpy4z(position should remain open past endDate
>assert %(py6)spy6==z%(py1)s == %(py4)s)r(   r   	TimestampENDr2   iloc
@pytest_ar_format_assertmsg	_safereprAssertionError_format_explanationlocany_call_reprcompare)r.   r1   @py_assert0@py_format2	after_end@py_assert2@py_assert4@py_assert6@py_format7@py_assert3@py_format5s              r   6test_trail_does_not_fire_after_endDate_when_time_gatedrY   K   s   ^F!#l!;F"F
v,C $$Q'A'AA)AAAAA'AAAAAA Fc!Iwwy.01 55 57 7 7  	B   1   5   7      
 z?#TqTq(TTTT#TTT#TTTqTTTT*TTTTTTTTTr   c                    \        4       p \        V 4      pVR,          P                  ^,          q"'       gZ   \        P                  ! R4      R,           R\        P
                  ! V4      /,          p\        \        P                  ! V4      4      hRpVR,          P                  ^,          q"'       gZ   \        P                  ! R4      R,           R\        P
                  ! V4      /,          p\        \        P                  ! V4      4      hRpVR,          P                  R,          p^ qBV8H  qU'       g   \        P                  ! RV3RW$34      R\        P
                  ! V4      R	\        P
                  ! V4      /,          p\        P                  ! R
4      R,           RV/,          p\        \        P                  ! V4      4      hR;p;rTR# )zFSanity: without a time gate, the trailing stop fires normally at idx5.r6   r7   r8   r9   Nr:   z5trailing stop should fire at idx5 without a time gater=   r>   z/position should be closed after the trail firesr?   r@   rA   rB   rD   )	r(   r2   rG   rH   rI   rJ   rK   rL   rO   )r.   r1   rP   rQ   rW   rS   rX   rV   s           r   *test_trail_still_fires_when_not_time_gatedr[   _   s   ^F
v,C$$Q'A'AA)AAAAA'AAAAAA~##A&_&__(_____&______z?#[q[q([[[[#[[[#[[[q[[[[*[[[[[[[[[r   )__doc__builtins@py_builtins_pytest.assertion.rewrite	assertionrewriterH   numpyr   pandasr   pyteststrategies.strategy_mlp_scoresr   rE   rF   r   r(   r2   rY   r[   r'   r   r   <module>rf      sH   .      < 	ll< 8U(\r   