
    8j4+              	          d Z ddlZddlZddlZddlZddlmZ ddlZddl	Z
 ee      j                         j                  j                  Zej                  j!                  d ee             ddlmZ ddlmZmZmZ ddlmZ ddZdedz  d	efd
Zdededed	e
j:                  fdZde
j:                  ded	e
j:                  fdZdde
j:                  dede d	e
j:                  fdZ!d Z"e#dk(  r e"        yy)uu  
MLP Parity Checker — Python vs TradingView
==========================================

Compares Python mlp_forward scores against the mlp_score column exported from
TradingView, to verify that the Pine float literals and forward-pass loop
reproduce the same values as the Python implementation.

Pass criteria
-------------
  - max |Δ| < 0.01  (9-sig-digit literals + summation drift ≈ 1e-3 on ±1000 scale)
  - zero threshold-side disagreements (no bar where Python and TV sit on opposite
    sides of entry OR exit threshold)

Warns on bars where |score − threshold| < 0.05 (fragile, could flip on next export).

Usage
-----
    python tools/check_mlp_parity.py \
        --data  data/COINBASE_BTCUSD-6H.csv \
        --weights strategies/params/mlp/mlp_weights_COINBASE_BTCUSD_6H.json \
        [--params results/winners/optimization_winner_strategy_mlp_scores_COINBASE_BTCUSD_6H.csv] \
        [--date  2024-01-15]  # show bar-level detail around this date \
        [--max-delta N]       # show top-N worst-delta bars (default 10) \
        [--crossunders-only]  # only show entry/exit bars \
        [--export /tmp/parity.csv]
    N)Path)TRAIN_START)load_mlp_artifactmlp_forwardFEATURE_COLS)_prepare_featuresc                     t        | |      S )zAWrapper that uses artifact feature_cols when provided (MLP path).feature_cols)_prepare_features_base)dfr   s     A/Users/jameslopez/projects/TradingBot25/tools/check_mlp_parity.pyr   r   0   s    !"<@@    params_pathreturnc                    | rt         j                  j                  |       si S | j                  d      r]t	        j
                  |       j                  d   j                         }h d}|j                         D ci c]  \  }}||vs|| c}}S | j                  d      rt        |       5 }t        j                  |      }d d d        i }j                         D ]J  \  }}t        |t              r0d|v r|j                  dd g      d   n|j                  dd      ||<   F|||<   L |S i S c c}}w # 1 sw Y   rxY w)Nz.csvr   >   % In MarketTotal P&L %Calmar RatioP&L/DD RatioSharpe RatioTotal TradesSortino RatioMax Drawdown %verified	CPU_Score	Composite	GPU_Score	WFO_Scorecomposite_scoreWFO_Fold_Calmars_pnl_dd_percentilesubperiod_consistentz.jsonvaluesstart)ospathexistsendswithpdread_csvilocto_dictitemsopenjsonload
isinstancedictget)r   rowdropkvfrawflats           r   load_paramsr<   7   s   bggnn[9	F#kk+&++A.668
 "%>A1>>G$+!))A,C IIKDAq!T"8@A!%%4&1!4155QXZ[K\QQ	  
 I ?s   <D/	D/.D55D>	data_pathweights_pathparamsc                    t        |      }|d   }t        j                  |       }|j                  j                  j                         j                  j                         |_        t        j                  |d   d      j                  j                  d      |d<   |j                  |d   t        j                  t              k\     j                         j                  d      }|d   }t        ||      }t!        ||      }t#        d	 |j                  D        d      }	|	r||	   j$                  n,t'        j(                  t+        |      t&        j,                        }
||
z
  }d
dlm}  ||j                         fi |}|dg   j                         }||d<   |
|d<   ||d<   |j3                  dt        j4                  d|j6                              |d<   |j3                  dt        j4                  d|j6                              |d<   |S )u+  
    Returns a DataFrame with one row per bar (from TRAIN_START onward) containing:
      py_score  — Python mlp_forward score
      tv_score  — TV-exported mlp_score column (NaN if column missing)
      delta     — py_score - tv_score
      execute_entry, execute_exit — Python signals
    layerstimeT)utcN)r6   r   r
   c              3   *   K   | ]  }|d v s|  yw))	mlp_scoremlp_score_pocN ).0cs     r   	<genexpr>zrun_parity.<locals>.<genexpr>j   s     FJq!'E"EJs   	r   )generate_signalspy_scoretv_scoredeltaexecute_entryFindexexecute_exit)r   r*   r+   columnsstrlowerstripto_datetimedttz_localizeloc	Timestampr   copyreset_indexr   r   nextr$   npfulllennanstrategies.strategy_mlp_scoresrK   r4   SeriesrQ   )r=   r>   r?   artrA   r   art_colsX	py_scorestv_col	tv_scoresrN   rK   sigsresults                  r   
run_parityrm   S   s    L
)C]F	Y	B%%'++113BJ6
588DDTJBvJ	6
bll;77	8	=	=	?	K	KQU	K	VB >"H"84AAv&I FBJJFF &,6
!!R"&&1II	!E @BGGI00D\ F&F:&F:"F7O"hh		%rxx8XYF?"hh~		%rxx8XYF>Mr   rl   c                    t        |j                  dd            }t        |j                  dd            }| j                  dg      }|d   |k\  }|d   |k\  }|d   |k\  }|d   |k\  }||k7  ||k7  z  }	||	   j                         S )z
    Returns rows where Python and TV sit on opposite sides of entry OR exit threshold.
    A NaN tv_score is skipped (TV column not present).
    !i_long_entry_activation_threshold         i_long_exit_activation_thresholdrM   subsetrL   )floatr4   dropnar\   )
rl   r?   	entry_threxit_thrvalidpy_above_entrytv_above_entrypy_above_exittv_above_exitdisagrees
             r   threshold_disagreementsr~      s    
 fjj!DcJKIfjj!CcJKHMM*M.E :&)3N:&)3N:&(2M:&(2M.0]m5STH?!!r   marginc                    t        |j                  dd            }t        |j                  dd            }t        |j                  dd            }t        j                  | d   |z
        |k  t        j                  | d   |z
        |k  z  t        j                  | d   |z
        |k  z  }| |   j	                         S )z=Bars where |py_score - threshold| < margin for any threshold.ro   rp   rq   -i_long_exit_activation_confirmation_thresholdrL   )rt   r4   r_   absr\   )rl   r?   r   rv   rw   conf_thrnears          r   fragile_barsr      s    fjj!DcJKIfjj!CcJKHfjj!PRUVWH	z"Y.	/&	8	z"X-	.&	8	:	z"X-	.&	8	: 	
 $<r   c                  <
   t        j                  d      } | j                  ddd       | j                  ddd       | j                  d	d d
       | j                  dd d       | j                  ddt        d       | j                  ddt        d       | j                  ddd       | j                  dd d       | j	                         }t        |j                        }t        d|j                          t        d|j                          |j                  rt        d|j                          t        |j                  |j                  |      }t        |      }|d   j                         j                         }t        d| d | d!       |d"k(  r+t        d#       t        d$       t        j                  d%       |j!                  dg&      }|d'   j#                         }|j%                         }|j'                         }	|j)                  d(      }
t        d)       t        d*|d+       t        d,|	d+       t        d-|
d+       t+        ||      }t        |      }|r/t        d.|        t        |g d/   j-                  d01             nt        d2       t/        ||      }t        |      rGt        d3t        |       d4       t        |g d5   j1                  d6      j-                  d01             |d7k  xr |d"k(  }t        d8|rd9nd: d;|d+d<|d7k  rd=nd> d?| d@	       |j2                  d"kD  r`|j5                  |j2                  d'      }t        |      r9t        dA|j2                   dB       t        |g d/   j-                  d01             |j6                  r	t9        j:                  |j6                        }|dC   |t9        j<                  |j>                  D      z
  k\  |dC   |t9        j<                  |j>                  D      z   k  z  }||   jA                         }|jB                  r||dE   |dF   z     }t        |      rGt        dG|j6                   dH|j>                   dI       t        |g dJ   j-                  d01             nt        dK|j6                          |jD                  r5|jG                  |jD                  d01       t        dL|jD                          t        j                  |rd"       y d%       y )MNz,Check Python vs TradingView MLP score parity)descriptionz--dataTzPath to TV-exported CSV)requiredhelpz	--weightszPath to MLP artifact JSONz--paramsz*Winner CSV or params JSON (for thresholds))defaultr   z--datez3Show bar-level detail around this date (YYYY-MM-DD)z--window   z$Bars each side of --date (default 5))r   typer   z--max-delta
   z(Show top-N worst-delta bars (default 10)z--crossunders-only
store_truez)Only show entry/exit bars in --date table)actionr   z--exportzExport full result to CSVzLoading artifact:  zLoading data:      zLoading params:    rM   z
Bars compared: /z have TV score exportedr   u*   
⚠️  No mlp_score column found in CSV.zQ   Re-export from TradingView with the MLP strategy active and mlp_score plotted.   rr   rN   gffffff?z
Score delta (py - tv):u     max  |Δ| = z.6fu     mean |Δ| = u     p95  |Δ| = u#   
❌ THRESHOLD-SIDE DISAGREEMENTS: )rB   rL   rM   rN   FrP   u&   
✅ Zero threshold-side disagreementsu	   
⚠️  z+ fragile bars (|score - threshold| < 0.05):)rB   rL   rN      g{Gz?
u   ✅ PASSu   ❌ FAILu    — max|Δ|= <z>=z 0.01, z side-disagreementsz
Top z worst-delta bars:rB   )daysrO   rR   z
Bar detail around u    (±z days):)rB   rL   rM   rN   rO   rR   z 
No bars found in window around z
Full result exported to )$argparseArgumentParseradd_argumentint
parse_argsr<   r?   printweightsdatarm   ra   notnasumsysexitru   r   maxmeanquantiler~   	to_stringr   head	max_deltanlargestdater*   r[   	Timedeltawindowr\   crossunders_onlyexportto_csv)apargsr?   rl   n_totalhas_tvrx   deltasr   
mean_delta	p95_delta	disagrees
n_disagreefragspassedworstcentremask	window_dfs                      r   mainr      s   		 	 -[	\BOOH$>WOXOOK$>YOZOOJ>jOkOOH>sOtOOJcHnOoOOMcHrOsOO(ItOuOOJ>YOZ==?D%F	~
./			{
+,{{#DKK=12		4<<8F&kGZ &&(,,.F	fXQwi/F
GH{;<abMM*M.E7^!FIJ&I	$&	N9S/
*+	N:c*
+,	N9S/
*+ (7IYJ4ZLABiABLLSXLYZ79 (E
5z
3u:,&QRSe1277;EEEERS 1*/F	BVz4M)CPQYbeiYiRUosQtt{L+- . ~~t~~w7u:F4>>**<=>%ABLLSXLYZ yydii(.FR\\t{{-K$KK.FR\\t{{-K$KKM4L%%'	  !)O"<y?X"XYIy>(4}GLM) ? @@I	PU	@VX 5dii[AB {{dkk/*4;;-89HH&Q a r   __main__)N)g?)$__doc__r   r0   r&   r   pathlibr   numpyr_   pandasr*   __file__resolveparentREPOr'   insertrT   configr   rc   r   r   r   %strategies.strategy_activation_scoresr   r   r3   r<   	DataFramerm   r~   rt   r   r   __name__rG   r   r   <module>r      s  8   	 
   H~&&-- 3t9    ^AS4Z D 8(# (S ($ (2<< (Z"BLL "$ "2<< ",
 
t 
U 
bll 
Y!x zF r   