+
    9j2!  c            
          R t ^ RIt^ RIHu Ht ^ RIt^ RIt	^ RI
t^ RIt^ RIHt ^ RIHtHtHtHtHt ]P,                  P/                  ]P,                  P1                  ]4      RRRR4      tRtRt]P:                  ! RR	7      R
 4       tR R ltR t RRRRRRRRRR/t!R t" ! R R4      t# ! R R4      t$ ! R R4      t% ! R R4      t&R# )!u  
TDD tests for strategy_mlp_scores.generate_signals.

Core guarantee under test (linear degeneracy): an MLP constructed to be an
(arbitrarily good) linear approximation of the existing perceptron score must
reproduce the existing strategy's behaviour — near-perfect score correlation
and identical entry/exit bars when thresholds are scaled by the same factor.
This pins the new module's crossunder/trailing/position logic to the old one.
N)FEATURE_COLSFEATURE_WEIGHT_PARAMS_score_to_signalsgenerate_signalssave_mlp_artifactz..datamlpzCOINBASE_BTCUSD, 360.csvgMbP?module)scopec                     \         P                  ! \        4      p V P                  P                  P                  4       P                  P                  4       V n        \         P                  ! V R ,          RR7      P                  P                  R4      V R &   V P                  RR4      V R&   V P                  RR4      V R&   V P                  R	4      P                  RR
7      # )timeT)utcNqqq_spy_roc_sign        	sopr_normfear_greed_normcvd_normi  )drop)pdread_csvDATA_CSVcolumnsstrlowerstripto_datetimedttz_localizegettailreset_index)dfs    A/Users/jameslopez/projects/TradingBot25/tests/test_mlp_signals.pydf_realr"       s    	X	B%%'++113BJ6
588DDTJBvJ ff/5B{OVV-s3BzN774=$$$$//    c                   ^ RI p\        VP                  4      p\        P                  P                  V 4      pVP                  R^dVR7      pRV\        P                  ! V4      R8  &   \        \        VP                  V4      4      p\        P                  ! \         Uu. uF  pWe9   g   K  WV,          NK  	  up4      pWu3# u upi )uE  Random nonzero weight per feature for the 49 features shared with the perceptron.

Uses only the params that the perceptron strategy actually reads (config.WEIGHT_COLS).
bb_pct_b_norm (col 49) is MLP-only and excluded so both strategies normalise by
the same denominator — keeping the linear-degeneracy equivalence intact.
N)sizeg      @i)configlenWEIGHT_COLSnprandomdefault_rnguniformabsdictziparrayr   )seedr&   nrngww_paramsparam
artifact_ws   &       r!   _perceptron_weightsr8   .   s     FA
))


%CD#A&AAbffQi#oC**A./H**E 	* J
 s    C-Cc                   ^ RI p\        \        4       UUu. uF.  w  r4V\        VP                  4      9   g   K!  \
        V,          NK0  	  ppp\        V4      p\        V4      qvV8H  q'       Eg   \        P                  ! RV3RWg34      RR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRRR\        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      /,          p	\        P                  ! R	\        V4       R
V 24      R,           RV	/,          p
\        \        P                  ! V
4      4      hR;rV\         P"                  ! \         P$                  ! V4      4      ,          p\         P&                  ! ^V34      p\(        V,          VR&   \         P&                  ! ^4      p\         P*                  ! \,        \(        ,          R..4      p\         P&                  ! ^4      p\/        V R,          4      p\1        VW3W3.RRVR7       V# u uppi )u  [N, 2, 1] MLP that linearises to DELTA * perceptron score.

Uses the same N features as the perceptron (config.WEIGHT_COLS) so normalisation
denominators match.  bb_pct_b_norm (col 49) is excluded — the artifact saves
its own feature_cols list so generate_signals uses the right subset.

Hidden unit 0 = tanh(EPS * x.w_hat) ~ EPS * s  (w_hat = w / sum|w|, s in [-1,1])
Output       = tanh((DELTA/EPS) * h0) ~ DELTA * s
=> mlp_score ~ DELTA * 1000 * s = DELTA * perceptron_score
Npy0r2   py2r'   py3r4   py5zweight vector length z != feature subset length z
>assert %(py7)spy7r   zmlp_weights_DEGEN_6H.jsonTEST6H)asset	timeframefeature_cols==)z0%(py0)s == %(py5)s
{%(py5)s = %(py2)s(%(py3)s)
})    :NNN)r&   	enumerater   setr(   r   r'   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationr)   sumr-   zerosEPSr0   DELTAr   r   )tmp_pathr4   r&   ip	feat_colsr2   @py_assert4@py_assert1@py_format6@py_format8w_hatW1b1W2b2paths   &&               r!   _degenerate_artifactrd   C   s    -67L-M 2-MTQV//00 !a-MI 2IAAU;UUUU1UUUUUU1UUUU1UUUUUUUUUUUUUUUUUUAUUUUAUUUUUUU/Ax7QRSQTUUUUUUUUrvvay!!E	1a&	BU{BtH	!B	ECK%&	'B	!Bx556DdbXx0$#,.K2s
   KK!i_long_entry_activation_threshold      Y@ i_long_exit_activation_thresholdg     a@-i_long_exit_activation_confirmation_thresholdg      >@i_use_long_exit_confirmation      ?i_use_long_entry_confirmationFc                  j    \        \        4      p R F  p\        V,          \        ,          W&   K  	  V # )re   )re   rg   rh   )r.   
THRESHOLDSrU   )outks     r!   _scaled_thresholdsrp   h   s1    
z
C? A&? Jr#   c                   ,   a  ] tR t^qt o R tR tRtV tR# )TestLinearDegeneracyc                :   \        4       w  r4\        W4      p\        P                  ! VP	                  4       3/ / VC\
        CB p\        VP	                  4       3R V/\        4       B p\        P                  ! VR,          VR,          4      R,          pRqV	8  q'       g   \        P                  ! RV
3RW34      RR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V	4      /,          pRRV/,          p\        \        P                   ! V4      4      hR;r\        P"                  P%                  VR	,          P&                  VR	,          P&                  4       \        P"                  P%                  VR
,          P&                  VR
,          P&                  4       \        P"                  P%                  VR,          P&                  VR,          P&                  4       R# )mlp_weights_fileactivation_scoreg!?r:   corrr<   zassert %(py5)sr=   Nexecute_entryexecute_exitposition)rF      )>)z%(py0)s > %(py3)s)r8   rd   
perceptronr   copyrm   rp   r)   corrcoefrI   rJ   rK   rL   rM   rN   rP   rQ   testingassert_array_equalvalues)selfrV   r"   r4   r5   artifactoldnewrv   @py_assert2r[   @py_format4r\   s   &&&          r!   +test_score_correlation_and_identical_trades@TestLinearDegeneracy.test_score_correlation_and_identical_tradesr   s\   )+'4))',,.W<Vx<V:<VWw||~aaL^L`a{{312C8J4KLTRhttth


%% ''_)=)D)D	F


%%&&N(;(B(B	D


%%c*o&<&<c*o>T>TUr#   c                z   \        ^R7      w  r4\        W4      pRR/p\        P                  ! VP	                  4       3/ / VC\
        CVCB p\        VP	                  4       3RV// \        4       CVCB p\        P                  P                  VR,          P                  VR,          P                  4       \        P                  P                  VR,          P                  VR,          P                  4       \        P                  P                  VR,          P                  VR,          P                  4       R# )	   )r1   i_trailing_stop_thresholdg      $@rt   ry   rw   rx   N)r8   rd   r|   r   r}   rm   rp   r)   r   r   r   )	r   rV   r"   r4   r5   r   trailr   r   s	   &&&      r!   #test_trailing_stop_path_equivalence8TestLinearDegeneracy.test_trailing_stop_path_equivalence   s   )r2'4,d3))',,.`<_x<_:<_Y^<_`w||~ D D!B$6$8!BE!BD 	

%%c*o&<&<c*o>T>TU


%% ''_)=)D)D	F


%%&&N(;(B(B	Dr#    N)__name__
__module____qualname____firstlineno__r   r   __static_attributes____classdictcell____classdict__s   @r!   rr   rr   q   s     V D Dr#   rr   c                   ,   a  ] tR t^t o R tR tRtV tR# )TestParamValidationc                    \         P                  ! \        R R7      ;_uu_ 4        \        VP	                  4       3/ \
        B  RRR4       R#   + '       g   i     R# ; i)rt   matchN)pytestraises
ValueErrorr   r}   rm   )r   r"   s   &&r!    test_missing_weights_file_raises4TestParamValidation.test_missing_weights_file_raises   s7    ]]:-?@@W\\^:z: A@@@s   AA	c                   \        VR ,          4      p\        P                  ! R4      \        P                  ! ^4      3\        P                  ! R4      \        P                  ! ^4      3.p\        W4. ROR7       \        P
                  ! \        RR7      ;_uu_ 4        \        VP                  4       3RV/\        B  RRR4       R#   + '       g   i     R# ; i)	zmlp_weights_BAD_6H.json)rC   rC   r   rt   N)      )rz   r   )abc)
r   r)   rS   r   r   r   r   r   r}   rm   )r   rV   r"   rc   layerss   &&&  r!   #test_mismatched_feature_cols_raises7TestParamValidation.test_mismatched_feature_cols_raises   s    877888F#RXXa[1BHHV4Dbhhqk3RS$_E]]:^<<W\\^QdQjQ =<<<s   !C		C	r   N)r   r   r   r   r   r   r   r   r   s   @r!   r   r      s     ;R Rr#   r   c                   &   a  ] tR t^t o R tRtV tR# )TestPineTimeGatec                   \         P                  ! R \         P                  ! . RO4      R. ROR. ROR. RO/4      pRRRRR	RR
RRRRR/p\        VP	                  4       V\
        P                  ! \        V4      4      VR,          P                  \
        P                  4      VR,          P                  \
        P                  4      4      pVR,          qDP                  qU! 4       p. ROqvV8H  q'       g   \        P                  ! RV3RWg34      R\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V4      /,          p	RRV	/,          p
\        \        P                  ! V
4      4      hR;p;p;p;rVR,          qDP                  qU! 4       p. ROqvV8H  q'       g   \        P                  ! RV3RWg34      R\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V4      /,          p	RRV	/,          p
\        \        P                  ! V
4      4      hR;p;p;p;rR# ) r   2017-12-01 08:00ru   closerf   highre   rg   g      @rh   ri   rj   rk   F_pine_time_startrw   py1r<   r=   py8zassert %(py10)spy10Nry   )z2017-11-30 16:00z2017-12-01 00:00r   z2017-12-01 16:00)      i@      I@r   r   )rf   g     @Y@g     Y@g     Y@g      )FFFTrD   )zE%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.tolist
}()
} == %(py8)s)rF   rF   rF   rz   )r   	DataFramer   r   r}   r)   rS   r'   to_numpyfloat64tolistrI   rJ   rN   rP   rQ   )r   r    paramssignals@py_assert0r   rZ   @py_assert7@py_assert6@py_format9@py_format11s   &          r!   0test_pre_start_crossunder_does_not_open_positionATestPineTimeGate.test_pre_start_crossunder_does_not_open_position   s   \\BNN $   :10

 
 0.;V*C+U 2
 $GGIHHSWwK  ,vJ

+
 'O..O.0O4OO4OOOOOO0OOO'OOO.OOO0OOO4OOOOOOOOOz";));)+;|;|;;;;;+;;;";;;);;;+;;;|;;;;;;;;;r#   r   N)r   r   r   r   r   r   r   r   s   @r!   r   r      s     < <r#   r   c                   ,   a  ] tR t^t o R tR tRtV tR# )TestFeatureWeightParamsc                4
   \        \        4      p^2q!V8H  q3'       Eg%   \        P                  ! RV3RW34      RR\        P
                  ! 4       9   g!   \        P                  ! \         4      '       d   \        P                  ! \         4      MRRR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR	;p;r2\        \        4      p^7q!V8H  q3'       Eg%   \        P                  ! RV3RW34      RR\        P
                  ! 4       9   g!   \        P                  ! \         4      '       d   \        P                  ! \         4      MRRR
\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MR
R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR	;p;r2R \         4       p\        V4      qw'       g   RRR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V4      R\        P                  ! V4      /,          p\        \        P                  ! V4      4      hR	;rg\        \        4      p\        V4      p^2qV	8H  q'       Eg   \        P                  ! RV
3RW)34      RR\        P
                  ! 4       9   g!   \        P                  ! \         4      '       d   \        P                  ! \         4      MRRR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V4      R\        P                  ! V4      R\        P                  ! V	4      /,          pRRV/,          p\        \        P                  ! V4      4      hR	;p;p;rR	# )2   r:   r'   r   r   r<   py6zassert %(py8)sr   Nr   c              3   B   "   T F  qP                  R 4      x  K  	  R# 5i)i_w_N)
startswith).0rX   s   & r!   	<genexpr>ETestFeatureWeightParams.test_one_param_per_feature.<locals>.<genexpr>   s     G1FA<<''1Fs   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr;   py4rH   py9zassert %(py11)spy11rD   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)s)zN%(py6)s
{%(py6)s = %(py0)s(%(py4)s
{%(py4)s = %(py1)s(%(py2)s)
})
} == %(py9)s)r'   r   rI   rJ   rK   rL   rM   rN   rP   rQ   r   r   rH   )r   r   @py_assert5rZ   @py_format7r   r[   @py_assert3@py_format5@py_assert8r   @py_format10@py_format12s   &            r!   test_one_param_per_feature2TestFeatureWeightParams.test_one_param_per_feature   sz   
 ()/R/R/////)//////s////s///////(////(///)///R////////< &B&B&&&&& &&&&&&s&&&&s&&&&&&&<&&&&<&&& &&&B&&&&&&&&G1FGGsGGGGGGGGGGsGGGGsGGGGGGGGGGGGGG,-4s-.4"4"44444.444444s4444s44444443444434444444,4444,444-444.444"44444444r#   c                l   ^ RI pVP                  p\        V4      q3P                  p\        \        4      qT! V4      qf'       Eg   RRR\
        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\
        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      R\        P                  ! V4      R	\        P                  ! V4      R
R\
        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\
        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V4      R\        P                  ! V4      /	,          p\        \        P                  ! V4      4      hR;p;p;p;rVR# )rF   Nzassert %(py13)s
{%(py13)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.WEIGHT_COLS
})
}.issubset
}(%(py11)s
{%(py11)s = %(py8)s(%(py9)s)
})
}r:   rH   r   r&   r<   r=   r>   r   r   r   r   py13)r&   r(   rH   issubsetr   rK   rL   rI   rM   rN   rP   rQ   )r   r&   r   rZ   r   @py_assert10@py_assert12@py_format14s   &       r!   !test_config_weight_cols_is_subset9TestFeatureWeightParams.test_config_weight_cols_is_subset   s"    	%%Ks%&K//K4I0JK/0JKKKKKKKKKsKKKKsKKKKKKK6KKKK6KKK%KKK&KKK/KKKKKKKKKKKKKKKKK4IKKKK4IKKK0JKKKKKKKKKKKr#   r   N)r   r   r   r   r   r   r   r   r   s   @r!   r   r      s     5L Lr#   r   )   )'__doc__builtinsrK   _pytest.assertion.rewrite	assertionrewriterI   osnumpyr)   pandasr   r   %strategies.strategy_activation_scoresstrategy_activation_scoresr|   strategies.strategy_mlp_scoresr   r   r   r   r   rc   joindirname__file__r   rT   rU   fixturer"   r8   rd   rm   rp   rr   r   r   r   r   r#   r!   <module>r      s     	    :  77<<14Hbc  h
0  
0 *: (&3T"C#U
D DB
R 
R< <DL Lr#   