
    j              	       \   d Z ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZmZ ddlZddlZe
j$                  j'                  ej$                  j)                  ej$                  j+                  ej$                  j-                  e      d                   ddlZddlmZmZmZmZ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l)m*Z* dd	l+m,Z,m-Z- d
Z.dZ/dZ0dZ1dZ2dZ3da4d Z5d Z6d Z7	 d"dZ8d"dZ9d"dZ:d Z;d Z<d Z=	 d#dZ>d Z?d Z@d ZA	 d#dZBd$dZCd ZDd  ZEeFd!k(  r eE        yy)%u  
Two-phase trainer for the MLP activation-score strategy (strategy_mlp_scores).

Phase 1 — supervised pretrain (PyTorch):
    Target: y_t = tanh( scale * (k-bar forward log return / k) / rolling_vol_t )
    where rolling_vol is past-only (shifted) so there is no lookahead leakage.
    Temporal split: train on bars up to the last WFO fold's IS end, early-stop
    on the last fold's OOS span. (Full per-epoch expanding-window CV across all
    folds was deliberately simplified away — Phase 2 does the real fold-averaged
    model selection on the actual backtest metric.)

Phase 2 — CMA-ES fine-tune (cma):
    Parameter vector = flattened MLP weights + [entry, exit, exit_conf, trail]
    thresholds. Fitness = -(mean per-fold OOS Calmar across config.WFO_FOLDS,
    invalid folds scoring 0, >= WFO_MIN_VALID_FOLDS valid folds required)
    + lambda * mean squared deviation from the pretrained weights (L2 anchor).
    `--fold-objective robust` keeps the same WFO-only training boundary but
    subtracts penalties for high fold drawdown, zero P&L/DD, low fold trade
    coverage, negative folds, and threshold fragility.
    Per-fold Calmar matches the existing WFO rescore convention in
    auto_optimize_loop.py (composite_score's 1000% P&L gate is meaningless on
    ~1-year folds, so Calmar is the per-fold metric).

Usage:
    python3 tools/train_mlp.py --data data/COINBASE_BTCUSD-6H.csv         [--hidden 16 8] [--target-k 10] [--phase1-epochs 300]         [--es-generations 300] [--es-popsize 32] [--es-sigma 0.05] [--l2 1e-3]         [--fold-objective mean|robust] [--es-workers 0]         [--seed 42] [--smoke] [--skip-phase2] [--out PATH]

Output: strategies/params/mlp/mlp_weights_{ASSET}_{TF}.json
    N)datetimetimezone..)ACTIVATION_NAMEFEATURE_COLS_score_to_signalscalculate_metricsmlp_forwardsave_mlp_artifact)_prepare_features)grouped_first_layer_maskgrouped_structure_metadatahybrid_grouped_first_layer_mask!hybrid_grouped_structure_metadatarandom_sparse_first_layer_mask random_sparse_structure_metadata)inject_temporal_features)DEFAULT_WORKER_FRACTIONresolve_worker_count<   g       @      Y@g      I@皙?      ?c                     t        j                  dt        j                  j	                  |             }|st        d|        |j                  d      |j                  d      fS )Nz ([A-Z0-9_!]+)-([0-9]+[HDW])\.csvz&Cannot derive ASSET/TF from filename:       )rematchospathbasename
ValueErrorgroup)	data_pathms     :/Users/jameslopez/projects/TradingBot25/tools/train_mlp.pyderive_asset_tfr'   R   sS    
4bgg6F6Fy6QRAA)MNN771:qwwqz!!    c                    t        j                  |       }|j                  j                  j	                         j                  j                         |_        t        j                  |d   d      j                  j                  d       |d<   |d   t        j                  k\  |d   t        j                  k  z  }|j                  |   j                  d      S )NtimeT)utcdrop)pdread_csvcolumnsstrlowerstripto_datetimedttz_localizeconfigTRAIN_START	TRAIN_ENDlocreset_index)r$   dfmasks      r&   	load_datar>   Y   s    	Y	B%%'++113BJ6
588DDTJBvJvJ&,,,Fv?O?O1OPD66$<###..r(   c                    t        j                  | d   j                  j                  t         j                              }t        j                  t        j                  ||d               }|j                  t              j                         j                  d      j                  }t        j                  t        |       t         j                        }||d |d|  z
  |z  |d|  t        j                  t         |z  |dz   z        }t        j"                  |       }|| d   t$        j&                  k\  j                  z  }||fS )zJtanh-squashed vol-normalised k-bar forward log return. Returns (y, valid).closer   )prependr   Nư>r*   )nplogvaluesastypefloat64r.   Seriesdiffrolling
VOL_WINDOWstdshiftfulllennantanhTARGET_SCALEisnanr7   SCORE_START)r<   k	log_closeret1volfwdyvalids           r&   build_targetr\   a   s    r'{))00<=I99RWWY	!=>D
,,z
"
&
&
(
.
.q
1
8
8C
''#b'266
"C!"	#A2.!3C!H
s"cDj12AXXa[LE	bjF...666Ee8Or(   c                 	   #$ dd l $$j                  j                         rdn'$j                  j                  j                         rdnd#$j                  |       t        j                  j                  |        j                  d   gt        |      z   dgz   }g }g }t        t        |      dz
        D ]W  }$j                  j                  ||   ||dz            }||$j                  j                         gz  }|j!                  |       Y  $j                  j"                  | j%                  #      }d }|
W$j'                  |
$j(                  #      }$j+                         5  |d   j,                  j/                  | d       d d d        |||k\  j0                  z  ||k  j0                  z  }|||k  j0                  z  } |	d# d	| d
|j3                          d|j3                                  #$fd} ||      \  }} ||      \  }}$j4                  j7                  |j9                         dd      }$j                  j;                         }t        j<                  d ddf\  }}}}t        |      D ]  }|j?                          |jA                           | ||      |      } | jC                          |jE                          |9$j+                         5  |d   j,                  j/                  | d       d d d        | jG                         }!|jI                          $j+                         5  t        |      rtK         | ||      |            n|!}"d d d        "|dz
  k  r|"d}}|D cg c]  }|j,                  jM                         jO                         jQ                         jS                         jU                         |jV                  jM                         jO                         jQ                         jS                         jU                         f }}n|dz  }||k\  r |	d| d|dd        n |dz  dk(  s |	d| d|!dd|"d        |#|dz   |tY        |j3                               tY        |j3                               dfS # 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   ZxY wc c}w )Nr   cudampscpur   dtypedevice        zphase1: device=z arch=z train_bars=z
 val_bars=c                     j                  |    j                        j                  |    j                        j                  d      fS )Nra   r   )tensorfloat32	unsqueeze)mask_arrXrc   torchrZ   s    r&   tenszpretrain.<locals>.tens   sO    Qx[fMQx[fMWWXYZ\ 	\r(   g{Gz?g-C6?)lrweight_decay   rB   zphase1: early stop at epoch z (best val MSE z.5f)2   zphase1: epoch z train=z val=)rc   arch
epochs_runbest_val_mse
train_barsval_bars)-rk   r^   is_availablebackendsr_   manual_seedrC   randomseedshapelistrangerO   nnLinearTanhappend
Sequentialtorf   boolno_gradweightmasked_fill_rE   sumoptimAdam
parametersMSELossinftrain	zero_gradbackwardstepitemevalfloatdetachr`   doublenumpycopybiasint)%rj   rZ   r[   timeshiddenepochsr{   	val_startval_endrD   first_layer_maskrr   layers_tmodulesilinmodelmask_tval_mask
train_maskrl   XtrytrXvayvaoptloss_fnbest_val
best_statepatience
since_bestepochloss
train_lossval_lossrc   rk   s%   ``                                 @@r&   pretrainr   s   s@   

//1f!NN..;;=5  
dIINN4GGAJ<$v,&!,DHG3t9q=!hhood1gtAE{3C)) "  EHH),,V4EF#.ejjP]]_QK++VGS9  *222ew6F5N5NNH%)+333J/&v\*..:J9K LLLN#	% &\ JHCH~HC
++

5++-$T

JChh G13r11D.Hj(JvuSz3'
""//= !YY[


]]_:=c(uWU3Z56
H ho%#+QjH &./%-c ::,,.224;;=CCEJJL88??,00299;AACHHJL%-  / !OJX%25'RUVWXY2:?.wz#.>eHS>RS1 4 &$eai(0&)*..*:&;$'$79 9 9[ _4 ! _/s+   ,!R#&!R0?&R==B+S
#R-0R:	=S	c                    |-| D cg c]   \  }}t        j                  |t              " }}}t        j                  t	        | |      D cg c]V  \  \  }}}t        j                  t        j
                  |      |   t        j
                  |      j                         g      X c}}}      S c c}}w c c}}}w )zEFlatten trainable weights, omitting structurally blocked connections.rb   )rC   	ones_liker   concatenatezipasarrayravel)layersweight_masksW_br=   s         r&   flatten_layersr      s    @FG1Qd3G>>55LFQD 	

1d+RZZ]-@-@-BCD5   Hs   %B3AB9c           
      N   g d}}t        t        |      dz
        D ]  }||dz      ||   }}|t        j                  ||ft              nt        j
                  ||   t              }|j                  ||fk7  r t        d| d|j                   d||f       t        j                  ||ft        j                        }	t        |j                               }
| |||
z    |	|<   ||
z  }| |||z    }||z  }|j                  |	|f        |t        |       k7  rt        d      |S )Nr   r   r   zWeight mask z has shape z; expected z=Parameter vector length does not match architecture and masks)r~   rO   rC   onesr   r   r|   r"   zerosrG   r   r   r   )thetarr   r   r   r   lin_outn_inr=   r   n_activer   s               r&   unflatten_layersr      s)   AAFCIM"26lDHt6B6JT2ZZR 0= 	::%&|B4{4::,kSXZ^R_Q`abbHHeT]"**5txxz?!h,'$h!AIU
q!f # 	CJXYYMr(   c                 :   |dk(  rt        t        j                  |             S |dk(  rt        t        j                  |             S |dk(  rCdt        t        j                  |             z  dt        t        j                  |             z  z   S t	        d|       )Nmeanminmean_mingffffff?333333?zUnknown fold objective: )r   rC   r   r   r"   )calmars	objectives     r&   aggregate_fold_scorer      s    FRWWW%&&ERVVG_%%JU2777+,,sU266'?5K/KKK
/	{;
<<r(   c           	      r   t        j                  |d d t         j                        }t        |      dk(  ryt        j                  | t         j                        } t        j                  t        j
                  | d d d f   |d d d f   z
        d      }t        t        j                  ||k              S )N   r   r   r   )axis)rC   r   rG   rO   r   absr   r   )scores
thresholdsmargindists       r&   threshold_fragility_countr      s    JrN"**=J
:!ZZbjj1F66"&&4:dAg+>>?aHDrvvdVm$%%r(   c           	      B   t        | d      }t        |dz   t        t        j                  |dz                    }t        dt        |            }d}d}	d}
d}|D ]  }t        |j                  dd            }t        t        |j                  dd                  }t        |j                  d	d            }t        |j                  d
d            }|t        d|t        z
        t        z  z  }|dk  r|	dz  }	|
t        d||z
        |z  z  }
|t        dt        d|             z  } ||z  }|	|z  }	|
|z  }
||z  }t        ||t              }t        ||t              }d|z  t        d|dz        z   }||	|
|||||d}d|z  d|	z  z   d|
z  z   d|z  z   |z   }||z
  |fS )Nr      g      ?r   rd   Total Tradesr   Max Drawdown %P&L/DD RatioCalmar Ratio      $r   r   g     @@)drawdown_penaltypnl_dd_penaltytrade_penaltynegative_fold_penaltyfragility_penaltyfragile_0_05fragile_1_0trade_targetg?g      ?r   )r   maxr   rC   ceilrO   getr   r   ROBUST_DRAWDOWN_TARGETr   r   ROBUST_FRAGILITY_TIGHT_MARGINROBUST_FRAGILITY_WIDE_MARGIN)r   fold_metricsr   r   min_fold_tradesbaser   n_foldsr   r   r   neg_fold_penaltymetricstradesdrawdownpnl_ddcalmarfragile_tightfragile_wider   	penaltiespenaltys                         r&   robust_objective_scorer     s   4D*C#8M0N,OPL!S&'GNMW[[34uW[[)93?@Aw{{>378w{{>59:CX0F%FGJ```S=c!NS,"78<GGCSvg%677   gNWM-fjB_`M,VZA]^L-S,:N1OO -(&!1.%#$	I 	

	

	 !
!	" 		  '>9$$r(   c
                    | ddg   j                         | d   j                         | d   j                  j                  t        j                        | d   j                  j                  t        j                        |d d df   |t        |      t        j                  |t        j                        t        |      |||||	dS )Nr*   r@   high	   r   )base_dfr   	close_arrhigh_arrstoch_peak_arrrj   rr   theta0_wfoldsr   min_valid_foldsl2fold_objectiver   )r   rE   rF   rC   rG   r}   r   )
r<   rj   rr   r  r  r   r  r  r  r   s
             r&   make_fitness_contextr     s     vw'(--/F"[''..rzz:vJ%%,,RZZ8AqD'T
JJxrzz:e**($ r(   c           
      V   t        j                  | t         j                        } |d   }t        |      }t	        | d | |d   |d         }t        j
                  | |d  t        z  g dg d      }t        |d   |      }|d   j                         }||d	<   |d
   |d<   |d   |d   |d   ddt        d|d         d}t        |||d   |d   |d
         }g g d}}
}	|d   }|d   }|d   D ]  \  }}}|j                  ||k\  ||k  z     }t        |      dk  r(|
j                  ddddd       |	j                  d       Ut        ||      }|
j                  |       |d   dk  s|d   |k  r|	j                  d       |	j                  |d          |dz  } d|i}|d    }|d!k(  r3t        |	|
|||      \  }}|j                  |       t!        |	d"      |d#<   n||d$   k  rd}nt!        |	|      }|d%   t#        t        j$                  | d | |z
  dz              z  }| |z   |	||fS )&Nr   r  rr   r   )      r  r  rd   )      @r  r  g      >@rj   r  activation_scorer	  r  r   r   r   r   Frd   r   )!i_long_entry_activation_threshold i_long_exit_activation_threshold-i_long_exit_activation_confirmation_thresholdi_use_long_exit_confirmationi_use_long_entry_confirmationi_trailing_stop_thresholdr
  r  r   r   r  
   r   )r   r   r   r   )
min_tradesr   r   valid_foldsr  robustr   base_fold_scorer  r  )rC   r   rG   rO   r   clipTHRESHOLD_SCALEr
   r   r   r   r:   r   r	   r  updater   r   r   )r   contextr  n_wr   r   r   dparamsr   r   r[   r   r   r   	oos_startoos_endslr   diagnosticsr  scorer  anchors                           r&   evaluate_thetar-  4  s   JJuBJJ/Ez"H
h-CeDSk76?GN<STFcdo%%#J v.F	!A"A
#AfI-7],6qM9CA(+).%(jm%<F 		 !
	A $&r15\GGE/0O!(!19gUUEY&5G+;<=r7R<E14!M NNN3#B?CG$>"e+w~/F/XNN3NN7>23QJE "2 !%(K-.N!1
y 	9%)=gz)R%&	*+	+$Wn=T]U277E$3K(,Bq+H#IJJF8fgz;>>r(   c                     | a y N)_FITNESS_CONTEXT)r#  s    r&   init_fitness_workerr1  z  s    r(   c                 "    t        | t              S r/  )r-  r0  )r   s    r&   evaluate_theta_workerr3    s    %!122r(   c
                 Z   
 t        | |||||||||	
      

fd
_        i _        S )Nc                 >    t        |       \  }}}}|_        |||fS r/  )r-  last_diagnostics)r   fitr   r   r*  r#  fitnesss        r&   r8  zmake_fitness.<locals>.fitness  s-    0>ug0N-Wj+#. GZ''r(   )r  r#  r6  )r<   rj   rr   r  r  r   r  r  r  r   r#  r8  s             @@r&   make_fitnessr9    s>    "
AtXuoG
(
 GO!GNr(   c                 4    dd l }|j                  ||||dd      t        dt                    t        j
                  |d d i dfdfd}	dk(  rF d        fd	}
t              D ])  } |	||
       j                         s d
|         S  S t         dd       }|t        d       d d       t        j                  d      }	 t        j                  j                  |t        |f      5 t              D ]+  } |	|fd       j                         s  d
|         n d d d        S # 1 sw Y   S xY w# t         t"        f$ r)} d| d       t%         ||||d      cY d }~S d }~ww xY w)Nr   i)popsizer{   verboser   r7  r   r   thrr*  workersc                     |\  }}}}|j                  |       |d   k  r4|t        j                  |       j                         ||t	        |      dy y )Nr7  r=  )r   rC   r   r   dict)	solutionresultfitsfr   r>  r*  bestr?  s	          r&   observe_solutionz!run_cma.<locals>.observe_solution  s\    '-$7CAtE{?H-224"#K0"D r(   c                    
j                         D cg c]'  }t        j                  |t        j                        ) }} ||      }g }t	        ||      D ]  \  }} |||        
j                  ||       | dz  dk(  s| dz
  k(  r8 d|  d d	d   d	d
	d   xs g D cg c]  }t        |d       c}        y y c c}w c c}w )Nr   r  r   r   zphase2: gen /z best_fitness=r7  .4f fold_calmars=r   r   )askrC   r   rG   r   tellround)gen	evaluators	solutionsresultsrD  rB  rC  crF  esgenerationsrD   rG  s            r&   run_generationzrun_cma.<locals>.run_generation  s    >@ffhGhRZZ4h	GI& #Iw 7HfXvt4 !8
	4 8q=C;?2,se1[MUC?P Q 7;I7L"7L N7Lq!7L NOQ R 3 H !Os   ,C'C
z1phase2: evaluating CMA-ES population sequentiallyc                     g }| D ]7  } |      \  }}}|j                  |||t        t        di             f       9 |S )Nr6  )r   rA  getattr)rR  outrB  rE  r   r>  r8  s         r&   sequential_evaluatorz%run_cma.<locals>.sequential_evaluator  sT    C%")("37C

Aw 2Db!IJL M & Jr(   z phase2: CMA-ES converged at gen r#  z*Parallel CMA-ES requires a fitness contextz*phase2: evaluating CMA-ES population with z worker processesspawn)max_workers
mp_contextinitializerinitargsc                 B    t        j                  t        |             S r/  )r}   mapr3  )rR  pools    r&   <lambda>zrun_cma.<locals>.<lambda>  s    d488DY[d;e6fr(   z!phase2: worker pool unavailable (z(); falling back to sequential evaluation)r?  )cmaCMAEvolutionStrategyr   r   rC   r   r~   stoprY  r"   mpget_context
concurrentfuturesProcessPoolExecutorr1  OSErrorPermissionErrorrun_cma)r8  theta0sigma0r;  rV  r{   rD   r?  re  rW  r[  rO  r#  r^  excrF  rU  rG  rc  s   `   ` ``       @@@@r&   ro  ro    s   		!	!&&.5tPR"S
UB!S\"G66FtD'3D	R 	R !|?@	 %C3 45wwy6se<= &
 gy$/GEFF
4WI=NOP(J\33!+Z	 4 

 [)s$fg779:3%@A	 *
 K
 K _% \/u4\]^wdCYZ[[\sB   &(E +E:EE EE E F.FFFc                    ddl m} |j                  xs	 d| d| d} |d|        t        j                  |      }|j
                  d   j                         } |d        || j                         fi |}	|	d   j                  }
|
j                  t        j                        }t        j                  t        |
      t        j                  	      }d}t        t        |
            D ]$  }|
|   dkD  rt        |d
z  d      ||<   |dz  }#d}& || d<   || d<   t!        |j#                               }t%        |j'                               } |d| dt        |        d|dd|dz  dd	       t(        ddgz   S )a  Compute in_long_position + bars_held_norm from the current winner policy.

    One-cycle circularity (documented in roadmap): the position state used for
    training comes from the OLD model's decisions, not the new model.  This is
    acceptable for the first retrain; a second retrain with the new policy's
    state would converge.

    Mutates df in-place, adding columns 'in_long_position' and 'bars_held_norm'.
    Returns the extended feature_cols list.
    r   )generate_signalsz8results/winners/optimization_winner_strategy_mlp_scores_r   z.csvz'approach-b: loading winner params from zNapproach-b: running generate_signals with old policy to get position state ...positionr   r   r   r   in_long_positionbars_held_normu+   approach-b: position features injected — rI  z& bars in-position, max bars_held_norm=z.3fz (=d   .0fz bars))strategies.strategy_mlp_scoresrt  approach_b_paramsr.   r/   ilocto_dictr   rE   rF   rC   rG   r   rO   r~   r   r   r   r   r   r   )r<   assettfargsrD   _gen_signalsparams_path	params_dfr&  signalsru  in_long	bars_heldbars_inr   n_in_posmax_helds                    r&   _inject_position_featuresr    s    P 	 	WEeWAbTQUV  
1+?@K(I^^A&&(FXY2779//Gz"))Hoobjj)GXbjj9IG3x=!A;?w4IaLqLGG " %B$B7;;=!HY]]_%H
5hZqR	 J&s^3x|C.@	H I -/?@@@r(   c                  l   t        j                  d      } | j                  dd       | j                  dt        ddd	g
       | j                  dt        d       | j                  dt        d       | j                  dt        d       | j                  dt        d       | j                  dt        d       | j                  dt        d       | j                  dg ddd       | j                  dt        dd       | j                  d t        t
        d!       | j                  d"t        d#       | j                  d$d%d&'       | j                  d(d%)       | j                  d*d+,       | j                  d-d.,       | j                  d/d0,       | j                  d1d%d2'       | j                  d3d4,       | j                  d5d%d6'       | j                  d7g d8d9d:       | j                  d;t        d<=       | j                  d>g d?d@dA       | j                         }|j                  dBk(  r|j                  | j                  dC       |j                  dDk(  r|j                  | j                  dE       |j                  r|j                  | j                  dF       t        j                         }dG }|j                  r%|j                  r|j                  |j                  }}nt        |j                         \  }}t#        |j                         }|j$                  r|j'                  dH      j)                  dI      }|j                  d9k(  r	d	dJg|_        t-        |j.                  dK      |_        t-        |j0                  dL      |_        t-        |j2                  d	      |_        |dM   j4                  t        t7        |      dNz           }d t9        |j;                               t9        |dM   j4                  dO   j;                               fg}dP\  }	}
|}nKt<        j>                  }t<        j@                  }	t<        jB                  }
tE        jF                  |dO   dQ         }tI        |jJ                  |j2                  |jL                        |_%        |dM   j4                  dO   } |dR| dS| dTt7        |       dU|dM   j4                  d   j;                          dV|dM   j4                  dO   j;                          dW|j*                          |jN                  rtQ        |||||      }ntR        }|j                  r4g |tU        |      } |dXt7        |      t7        tR              z
   dY       d }|j                  dZk(  r"tW        ||j*                  d         } |d[       n|j                  dDk(  r=tY        ||j*                  d         } |d\t        |j[                                d]       nb|j                  dBk(  rSt]        ||j*                  d   |j                        } |d^|j                   d_t        |j[                                       t_        ||      }ta        ||jb                        \  }}dQdOdd`}|jd                  d@k7  r||jd                     }da|jf                  v r|da   jh                  |k(  }t        |j[                               }||z  }t        |j[                               tk        dQ|      z  dbz  } |dc|jd                   dd| det        |j[                                df|dgdh	       n |di|jd                   dj       tm        ||||dM   |j*                  |j.                  |jn                  ||||      \  }}|dk   }i ||jb                  tp        tr        t9        |      t9        |      gdl|j                   tu        jv                  ty        |j                   dm      j{                               j}                         t9        |dM   j4                  d   j;                               t9        |dM   j4                  dO   j;                               g|jn                  |jd                  |j                  dZk(  rt        ||j*                  d         n^|j                  dDk(  rt        ||j*                  d         n6|j                  dBk(  r$t        ||j*                  d   |j                        ndnd9it        j                  t        j                        j                  dop      dq}t        ||      }t        j                  t        j                  |dr      t        j                  |ds      t        j                  |dt      dug      } |dv|j-                         dwdx|jk                         dwdy|d   dwdz|dQ   dwd{|d|   dw
       |j                  sd }|N|gt        dQt7        |      dQz
        D cg c](  }t        j                  ||dQz      ||   ft        }      * c}z   }t        ||      }t        j                  ||t        z  g      } t        ||||||	|
|j                  |j                  |
      }! |!|       \  }"}#}$ |d~|"dd|#D %cg c]  }%t        |%d|       c}%        t        |!| |j                  |j2                  |j0                  |jn                  ||jJ                        }&t7        |      }'t        |&d   d |' ||      }|&d   }|j2                  |j                  |j0                  |j                  |&j                  d|jJ                        |j                  |&d   |&d   t	        t        j                  |&d               t	        t        j,                  |&d               d
|d<   |j                  dk(  r|&j                  di       |d   d<   t	        |d         t	        |dQ         t	        |d|         t	        |d         ddd|d<   |j                  xs) t        j                  j                  dddd| d| d      }(t        |(|||||        |d|( dt        j                         |z
  dgd        |d|d           y c c}w c c}%w )NzTwo-phase MLP trainer)descriptionz--dataT)requiredz--hidden+      )typenargsdefaultz
--target-kr  )r  r  z--phase1-epochsi,  z--es-generationsz--es-popsize    z
--es-sigmar   z--l2gMbP?z--fold-objective)r   r   r   r  r   zPhase-2 fold aggregation: mean matches legacy behavior; min emphasizes worst fold; mean_min blends 70%% mean / 30%% min; robust subtracts drawdown, P&L/DD, trade-count, negative-fold, and threshold-fragility penalties.)choicesr  helpz--es-workersr   zWorker processes for parallel CMA-ES population evaluation. Use 0 for auto, currently 50%% of logical CPUs capped by popsize; use 1 for sequential evaluation.)r  r  r  z--worker-fractionz.Logical CPU fraction used when --es-workers=0.z--seed*   z--smoke
store_truez/Tiny run on recent bars for plumbing validation)actionr  z--skip-phase2)r  z--outzArtifact path override)r  z--assetzHAsset override (e.g. COINBASE_BTCUSD) when filename format doesn't matchz--tfz?Timeframe override (e.g. 4H) when filename format doesn't matchz--approach-bzProbe: inject in_long_position + bars_held_norm (cols 50-51) computed from the current winner artifact's position state (one-cycle circularity per roadmap). Output artifact will have 52 features.z--approach-b-paramszMWinner CSV to derive position state from (default: auto-detect from asset/tf)z--temporal-featureszLExperiment: append causal 3- and 12-bar EMA companions for ten fast signals.z--input-structure)densegroupedhybrid_groupedrandom_sparser  zFirst-layer connectivity: dense is the production baseline; grouped routes each of the 16 first-layer units to one logical signal family; hybrid_grouped keeps eight family specialists plus eight dense rows; random_sparse is the matched seeded control.z--mask-seedzERequired with random_sparse; seed for the auditable first-layer mask.)r  r  z--regime)bullbearsidewaysallr  zFilter Phase-1 supervised training to MVRV regime bars only (requires mvrv_regime column). Phase-2 CMA-ES always uses all IS bars.r  z<--mask-seed is required with --input-structure random_sparser  zQ--out is required with --input-structure hybrid_grouped to protect live artifactsz<--temporal-features requires --out to protect live artifactsc                 P    t        dt        j                  d       d|  d       y )N[z%H:%M:%Sz] T)flush)printr*   strftime)msgs    r&   rD   zmain.<locals>.logR  s#    $--
+,Bse4DAr(   i   r,      ro   r   r*   g      ?)r   r   r   zasset=z tf=z bars=z window=r   z hidden=ztemporal-features: appended z causal EMA companionsr  zTinput-structure=grouped: first-layer units are restricted to logical signal familiesz]input-structure=hybrid_grouped: eight family specialists plus eight dense rows (active_edges=rp   z+input-structure=random_sparse: seeded mask=z active_edges=)r  r  r  mvrv_regimerx  zregime=z: Phase-1 training bars u    → z (ry  z%)zWARNING: --regime=z0 requested but mvrv_regime not in data; ignoringrr   )target_k
vol_windowtarget_scaleval_spanrbnameseconds)timespec)phase1	data_filedata_sha256train_windowr{   regime_filterinput_structurecreatedr   K      rd   zphase2: score range [z.1fz, z], seed thresholds entry=z exit=z conf=r   r   z"phase2: pretrain baseline fitness=rJ  rK  r   r>  r?  r7  r   )

es_popsizees_sigmaes_generations	l2_anchor
es_workersr  best_fitnessfold_calmarsfold_mean_calmarfold_min_calmarphase2r  r*  robust_diagnosticsr   r   F)r  r  r  r  r  r  recommended_thresholds
strategiesr&  mlpmlp_weights_r   z.json)r~  	timeframetrainingfeature_colszartifact written: z  (zs total)zrecommended thresholds: )_argparseArgumentParseradd_argumentr   r   r   
parse_argsr  	mask_seederrorrZ  temporal_featuresr*   r~  r  r'   datar>   smoketailr;   r   r   phase1_epochsr  r  r|  rO   r1   dater7   	WFO_FOLDSWFO_MIN_OOS_TRADESWFO_MIN_VALID_FOLDSr.   	Timestampr   r  worker_fraction
approach_br  r   r   r   r   r   r   r   r\   r  regimer0   rE   r   r   r{   rK   rR   hashlibsha256openread	hexdigestr   r   r   r   nowr   r+   	isoformatr
   rC   array
percentileskip_phase2r~   r   r   r   r   r!  r9  r  r  rN  ro  r  r   r   r   r   r    joinr   ))pr  t0rD   r~  r  r<   t75r  r   r  r   r   r  r   rj   rZ   r[   _REGIME_INT
regime_intregime_maskbeforepctr   p1_metarr   training_metascores0r   r   r   r  rp  r8  f0calmars0r   rT  rF  r$  rZ  s)                                            r&   mainr    s   ,CDANN8dN+NN:CsRGNDNN<c2N6NN$3N<NN%CN=NN>RN8NN<eTN:NN6tN4NN%/T!=  > NN>Q;  < NN&U<SH  JNN8#rN2NN9\I  KNN?<N8NN7!9N:NN9#mNnNN6#dNeNN>,O  P NN(l  nNN(f  hNN&0gqxG  H
 NN=s_  aNN:'JTYa  b <<>D.4>>3I	NO//DHH4D	cd$(("2	NO	BB zzdggJJr#DII.	r	499	BzzWWS\%%4%07*a&DK !3!3R8!$"5"5q9dooq1jooc#b'D.12CHHJRZ__R-@-E-E-G)HIJ+/(	   33 44LLr1.	*4??DOOTMaMabDOjoob!G&tB4vc"gYhf:??1""$
%R6
(;(@(@(B'C8DKK=	Z [ 0UBcJ#EE(@(DE*3|+<s<?P+P*QQghiy(3L$++a.Qbc			!1	1:<UVX  !1!5!5!789< 	=				09$++a.$..
 	9$..9I J 0 4 4 678: 	; 	"l+AB.HAu ba8K{{e -
BJJ&]+22j@K%FK'Eeiik"SF^3c9C'$++&>vheCPUPYPYP[L\K]]_`cdg_hhjkl$T[[M1abc q!UBvJ#11499iRU/1OFG 6?D?W ?$--!+\ #IG=? YY~~d499d&;&@&@&BCMMORZ__Q/4467RZ__R=P=U=U=W9XY		 ##y0 '|T[[^D ##'77 3<QP ##6 2,APTP^P^_'"<<-777K%M. !V$G
gr"
gr"
gr"	 J 
c2"W[[]34G H!!+As 36*Q-9L M1c"	$ %
 ',-EJ1cRViZ[mE\1E\a!ed1g.d;E\1 L "&,7:+G HIr1dHe.#22LB "&/Ha0C 92:;(QU1a[(;<> 	?wt**DIIsDOOM(m!$w-"5t\J%[
//t}}"11((9doo>"11 K O %bggd9o&> ?$RVVDO%<=	#
h (*<@HH]TV<WM(#$89 .3:a=-A,1*Q-,@9>z!}9M%*:a=%9(+)./M*+ (( Ebggll<5%1%"U#CECc6",<I
SETYY[2%5c$:(CD
"=1I#J"KLMW1 <s   -r,*r1__main__r/  )r   N)r   )G__doc__r  concurrent.futuresrj  r  jsonmultiprocessingrh  r   r   sysr*   r   r   r   rC   pandasr.   r    r   abspathr  dirname__file__r7   rz  r   r   r   r	   r
   r   %strategies.strategy_activation_scoresr   strategies.mlp_feature_groupsr   r   r   r   r   r    strategies.mlp_temporal_featuresr   tools.worker_utilsr   r   rK   rR   r!  r   r   r   r0  r'   r>   r\   r   r   r   r   r   r  r  r-  r1  r3  r9  ro  r  r  __name__ r(   r&   <module>r
     s<  @      	 	 
  '   RWW__X-F MN O   D  F L
  $ "  "/& #E9X$=&/%f >B(C?L
3
 6:"I`-AhYNx zF r(   