
    $yj2              	           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dddddZ"deded	e#eeef   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     o/Users/jameslopez/projects/TradingBot25/.worktrees/experiment-mlp-extreme-event-study/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)N.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)r7   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_scoresrL   r5   SeriesrR   )r>   r?   r@   artrB   r   art_colsX	py_scorestv_col	tv_scoresrO   rL   sigsresults                  r   
run_parityrn   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   rm   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_thresholdrN   subsetrM   )floatr5   dropnar]   )
rm   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.rp   rq   rr   -i_long_exit_activation_confirmation_thresholdrM   )ru   r5   r`   absr]   )rm   r@   r   rw   rx   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   2403604807201D)4H6H8H12Hr   assettfc                    t         j                  |j                               }|(t        j                  d| dt        t                       t        dz  dz  |  d| dz  }|j                         st        j                  d| d       t        d	z  d
z  d|  d|j                          dz  }|j                         st        j                  d|  d| d|        t        j                  |      j                  d   d   }t        |      j                         st        j                  d|        t        |      |t        |      fS )zVReturn (data_path, weights_path, params_path) from asset+TF using project conventions.zUnknown TF 'z'. Choices: datamlpz, r   zData file not found: z1
Re-export from TradingView and save to data/mlp/resultswinners(optimization_winner_strategy_mlp_scores__zNo winner CSV for  z: r   mlp_weights_filez(Weights file from winner CSV not found: )_TF_TO_MINUTESr5   uppersysexitlistREPOr)   r+   r,   r-   r   rU   )r   r   minutesr   
params_csvweightss         r   _auto_resolver      s3     ,G<t<^0D/EFG&=5 eWBwit#<<D;;=(.`ab	!I-2Z[`Zaabceckckcmbnnr0ssJ%eWAbTJ<@Akk*%**1-.@AG=!;G9EFt9gs:..r   c                     t        j                  dd      } | j                  ddd       | j                  dd	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	                         }|j
                  |j                  ct        |j                  |j                        \  }}}|j
                  xs ||_        |j                  xs ||_        |j                  xs ||_
        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/|d0       t        d1|d0       t        d2|d0       t1        ||      }t        |      }|r/t        d3|        t        |g d4   j3                  d56             nt        d7       t5        ||      }t        |      rGt        d8t        |       d9       t        |g d:   j7                  d;      j3                  d56             |d<k  xr |d'k(  }t        d=|rd>nd? d@|d0dA|d<k  rdBndC dD| dE	       |j8                  d'kD  r`|	j;                  |j8                  d,      }t        |      r9t        dF|j8                   dG       t        |g d4   j3                  d56             |j<                  r	t?        j@                  |j<                        }|dH   |t?        jB                  |jD                  I      z
  k\  |dH   |t?        jB                  |jD                  I      z   k  z  }||   jG                         }|jH                  r||dJ   |dK   z     }t        |      rGt        dL|j<                   dM|jD                   dN       t        |g dO   j3                  d56             nt        dP|j<                          |jJ                  r5|jM                  |jJ                  d56       t        dQ|jJ                          t#        j$                  |rd'       y d*       y )RNz,Check Python vs TradingView MLP score parityzFWith no --data/--weights, pass --asset and --tf to auto-resolve paths.)descriptionepilogz--assetCOINBASE_BTCUSDz Asset (default: COINBASE_BTCUSD))defaulthelpz--tfr   zTimeframe (default: 6H)z--datazDPath to TV-exported CSV (auto-detected from --asset/--tf if omitted)z	--weightszFPath to MLP artifact JSON (auto-detected from --asset/--tf if omitted)z--paramszFWinner CSV or params JSON (auto-detected from --asset/--tf if omitted)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:    rN   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.   rs   rO   gffffff?z
Score delta (py - tv):u     max  |Δ| = z.6fu     mean |Δ| = u     p95  |Δ| = u#   
❌ THRESHOLD-SIDE DISAGREEMENTS: )rC   rM   rN   rO   FrQ   u&   
✅ Zero threshold-side disagreementsu	   
⚠️  z+ fragile bars (|score - threshold| < 0.05):)rC   rM   rO      g{Gz?
u   ✅ PASSu   ❌ FAILu    — max|Δ|=r   <z>=z 0.01, z side-disagreementsz
Top z worst-delta bars:rC   )daysrP   rS   z
Bar detail around u    (±z days):)rC   rM   rN   rO   rP   rS   z 
No bars found in window around z
Full result exported to )'argparseArgumentParseradd_argumentint
parse_argsr   r   r   r   r   r@   r=   printrn   rb   notnasumr   r   rv   r   maxmeanquantiler   	to_stringr   head	max_deltanlargestdater+   r\   	Timedeltawindowr]   crossunders_onlyexportto_csv)apargs	auto_dataauto_weightsauto_paramsr@   rm   n_totalhas_tvry   deltasr   
mean_delta	p95_delta	disagrees
n_disagreefragspassedworstcentremask	window_dfs                         r   mainr      s    		 	 BW
B OOI):AcOdOOFAZO[OOH5{O|OOK5}O~OOJ5}O~OOH>sOtOOJcHnOoOOMcHrOsOO(ItOuOOJ>YOZ==?DyyDLL0/<TZZ/Q,	<yy0y	||3|{{2{%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   r1   r'   r   pathlibr   numpyr`   pandasr+   __file__resolveparentr   r(   insertrU   configr   rd   r   r   r   %strategies.strategy_activation_scoresr   r   r4   r=   	DataFramern   r   ru   r   r   tupler   r   __name__rH   r   r   <module>r      sH  8   	 
   H~&&-- 3t9    ^AS4Z D 8(# (S ($ (2<< (Z"BLL "$ "2<< ",
 
t 
U 
bll 
 U%TR/ /# /%S#*> /&d!N zF r   