+
    1j7?              
         R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIHtHt ^ RIHt ]! ]4      P!                  4       P"                  P"                  t]	P&                  P)                  ^ ]! ]4      4       . R-Ot. R.OtRR
RRRRRRR	R	/t]R,          R,          R,          t]R,          R,          R,          t]P7                  4       '       d	   ]! ]4      M]	P8                  tR R ltR R ltR/R R llt R R lt!R/R R llt"R R lt#R0R  R! llt$R" R# lt%R$ R% lt&R& R' lt'R( R) lt(R* R+ lt)]*R,8X  d
   ])! 4        R# R# )1u  
MLP training orchestrator — trains N seeds per asset/TF combo, sweeps thresholds,
optionally regenerates Pine presets and sends ntfy notification.

Replaces the ad-hoc shell scripts written to /tmp/ each session.

Usage:
    # Train BTC all TFs, 3 seeds, sweep + promote + notify
    python3 tools/run_mlp_train.py --assets COINBASE_BTCUSD --seeds 3 --sweep --promote --notify

    # Train all 4 assets, 4H only, 6 seeds, then generate presets
    python3 tools/run_mlp_train.py --tfs 4H --seeds 6 --sweep --promote --presets --notify

    # Extra seeds 404-606 for BTC 6H and 8H (specific seeds)
    python3 tools/run_mlp_train.py --assets COINBASE_BTCUSD --tfs 6H 8H --seed-start 404 --seeds 3

    # Dry run — show what would be launched without running
    python3 tools/run_mlp_train.py --assets COINBASE_BTCUSD --seeds 3 --dry-run

    # All 4 assets, all TFs, 3 seeds, full pipeline
    python3 tools/run_mlp_train.py --seeds 3 --sweep --promote --presets --table --notify
)annotationsN)datetimetimezone)Path4H6H8H12H1D240360480720
strategiesparamsmlpz.venvbinpython3c                    V ^8  d   QhRRRR/# )   msgstrreturnNone )formats   ">/Users/jameslopez/projects/TradingBot25/tools/run_mlp_train.py__annotate__r   0   s     T TS TT T    c                    \        R \        P                  ! \        P                  4      P                  R4       RV  2RR7       R# )[z%H:%M:%Sz] T)flushN)printr   nowr   utcstrftime)r   s   &r   logr&   0   s2    	Ahll8<<(11*=>b
FdSr   c               $    V ^8  d   QhRRRRRR/# )r   assetr   tfr   r   r   )r   s   "r   r   r   4   s!     < <S <c <d <r   c                ^    \         V,          p\        R ,          R,          V  RV R2,          # )datar   z, z.csv)	TF_PERIODREPO)r(   r)   periods   && r   	data_pathr/   4   s,    r]F&=5 eWBvhd#;;;r   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	r   r(   r   r)   seedinttagr   r   r   )r   s   "r   r   r   9   s6     K K K# KS Ks K Kr   c           
     6    \         R V  RV RV RV R2	,          # )mlp_weights___seedz.json)WEIGHTS_DIR)r(   r)   r1   r3   s   &&&&r   artifact_pathr9   9   s(    <wat1SEtfEJJJr   c               $    V ^8  d   QhRRRRRR/# )r   
seed_startr2   n_seedsr   	list[int]r   )r   s   "r   r   r   =   s!     : :3 : : :r   c                \    \        V4       Uu. uF  q V^e,          ,           NK  	  up# u upi )zAGenerate seeds as seed_start, seed_start+101, seed_start+202, ...)range)r;   r<   is   && r   
seed_rangerA   =   s(    */.9.QS  .999s   )c               (    V ^8  d   QhRRRRRRRR/# )r   r(   r   r)   r3   r   r=   r   )r   s   "r   r   r   B   s(     	 	# 	3 	S 	i 	r   c           	        . p\         P                  RV  RV RV R24       F@  p \        VP                  P	                  R4      R,          4      pVP                  V4       KB  	  \        V4      #   \         d     K]  i ; i)zBReturn sorted list of seeds already trained for this asset/TF/tag.r5   r6   _seed*.jsonr7   )r8   globr2   stemsplitappend
ValueErrorsorted)r(   r)   r3   seedspss   &&&   r   existing_seedsrO   B   s~    EUG1RD#kJK	AFFLL)"-.ALLO L %=  		s   <A11B ?B c               (    V ^8  d   QhRRRRRRRR/# )r   r3   r   regimeinput_structurer   r   )r   s   "r   r   r   N   s(     9 9 9S 93 93 9r   c                    VR8X  d   V R9   d   \        RV  R24      hVR8w  d   V R8X  d   V  RV 2p VR8X  d   V # V  RV 2# )	zDKeep non-dense experiments out of the production ``bb50`` namespace.hybrid_groupedzArtifact tag 'zp' is reserved by an existing input-structure experiment; use an isolated hybrid tag such as 'hybrid_grouped_v1'.densebb50r6   all>   
grouped_v1bb50_groupedrandom_sparse_v1bb50_random_sparse)rJ   )r3   rQ   rR   s   &&&r   effective_artifact_tagr\   N   sv    **s 7 0 SE "F F
 	
 '!cVmQ'(E/38#ax'88r   c               P    V ^8  d   QhRRRRRRRRRRR	R
RRRRRRRRRRRRRRRR/# )r   r(   r   r)   r1   r2   hiddenr=   fold_objectivel2float
es_workerses_generationsr3   dry_runboolrQ   rR   	mask_seedz
int | Noner   tuple[str, bool, str]r   )r   s   "r   r   r   \   s     .$ .$S .$c .$ .$i .$!.$',.$:=.$!.$(+.$6:.$ .$ 58.$ $	.$ 0E	.$r   c                j   \        WW(4      p\        W4      pV  R V RV 2pVP                  4       '       g	   VRRV 23# \        RR\	        V4      RV RVRVR	\	        V4      R
.V Uu. uF  p\	        V4      NK  	  upORN\	        V4      NRN\	        V4      NRN\	        V4      NRN\	        V4      NpV
R8w  d   VRV
.,          pVR8w  d   VRV.,          pVR8X  d   Vf   VRR3# VR\	        V4      .,          pV	'       d#   \        RR P                  V4       24       VRR3# \        RV  RV RV R24      p\        P                  ! 4       p \        VR4      ;_uu_ 4       p\        P                  ! VVV\	        \        4      R7      pRRR4       \        \        P                  ! 4       V,
          4      pXP                  ^ 8w  d   VRR VP                   R!V R"V 23# VRV R#VP                   23# u upi   + '       g   i     Lw; i  \          d   pTR\	        T4      3u Rp?# Rp?ii ; i)$ z seedFzdata file missing: ztools/train_mlp.pyz--data--assetz--tf--fold-objective--l2--hiddenz--seed--es-workers--es-generationsz--outrW   --regimerU   --input-structurerandom_sparseNz"random_sparse requires a mask seedz--mask-seed  [dry-run] Tdry-runz/tmp/mlp_train_r6   r7   .logwstdoutstderrcwdexit  after 
   s — see u   s → )r9   r/   existsPYTHONr   r"   joinr   timeopen
subprocessrunr-   r2   
returncodename	Exception)r(   r)   r1   r^   r_   r`   rb   rc   r3   rd   rQ   rR   rf   outr+   labelhcmdlog_patht0fresultelapsedes   &&&&&&&&&&&&&           r   	train_oner   \   sy   
 4
-CUDgQrd%v&E;;==e24&999 	$#d)5&"NB '--fc!ff- 	 d) 	 J 	  / 	 SC 
F##'!#_55/)%!EEEs9~..SXXc]O,-dI%%oeWAbTtfDABH	B$(C  A^^C!TKF !diikB&'!%5):):(;77):V^U_!```dwivchhZ8885 .* !   $eSV##$sC   (G7H %(G<AH #H <H	H H2H-'H2-H2c               4    V ^8  d   QhRRRRRRRRRRR	RR
R/# )r   r(   r   r)   r3   samplesr2   promotere   rd   r   rg   r   )r   s   "r   r   r      s?     $ $S $c $ $c $D $$ 5$r   c                d   V  R V 2p\        \        P                  RV  RV RV R24      4      pV'       g   VRR3# \        RRV RVR	\	        V4      R
.	V Uu. uF  p\	        V4      NK  	  upOp	V'       d   V	P                  R4       V'       d#   \        RR P                  V	4       24       VRR3# \        RV  RV R24      p
\        P                  ! 4       p \        V
R4      ;_uu_ 4       p\        P                  ! WV\	        \        4      R7      pRRR4       \        \        P                  ! 4       V,
          4      pXP                  ^ 8w  d   VRRVP                   RV RV
 23# VRV R23# u upi   + '       g   i     Lk; i  \          d   pTR\	        T4      3u Rp?# Rp?ii ; i)ri   r5   r6   rD   Fzno artifacts to sweepztools/run_mlp_deep_sweep.pyrj   z--timeframes	--samplesz--extra-weights	--promoters   Trt   z/tmp/mlp_sweep_ru   rv   rw   Nr{   r|   r}   rN   )listr8   rF   r   r   rI   r"   r   r   r   r   r   r   r-   r2   r   r   )r(   r)   r3   r   r   rd   r   extrasr   r   r   r   r   r   r   s   &&&&&&         r   	sweep_oner      s   gQrdOE+""\%"Qse;#OPQFe444 	-5S\
 .44VSVV4C 

;SXXc]O,-dI%%oeWAbT67H	B$(C  A^^C!TKF !diikB&'!%5):):(;77):V^U_!```dwiqM))# 5 !   $eSV##$sC   E4F /'E9AF ,F 9F		F F/F*$F/*F/c                    V ^8  d   QhRRRR/# )r   rd   re   r   r   )r   s   "r   r   r      s     " " "$ "r   c                r   V '       d   \        R 4       R# \        P                  ! \        R.\	        \
        4      RRR7      p\        VP                  P                  4       4       VP                  ^ 8w  d4   \        VP                  P                  4       \        P                  R7       VP                  ^ 8H  # )z6  [dry-run] python3 tools/generate_pine_mlp_presets.pyTz"tools/generate_pine_mlp_presets.pyrz   capture_outputtext)file)r"   r   r   r   r   r-   rx   stripr   ry   sys)rd   r   s   & r   run_presetsr      s    FG^^	56IdF 
&--


 Afmm!!##**5!!r   c               $    V ^8  d   QhRRRRRR/# )r   assetsz	list[str]rd   re   r   r   r   )r   s   "r   r   r      s!      i $ 3 r   c                   V'       d   \        R 4       R# . pV  F[  p\        P                  ! \        RRV.\	        \
        4      RRR7      pVP                  VP                  P                  4       4       K]  	  RP                  V4      # )z5  [dry-run] python3 tools/mlp_results_table.py --save tools/mlp_results_table.pyrj   Tr   
)
r"   r   r   r   r   r-   rI   rx   r   r   )r   rd   linesr(   r   s   &&   r   	run_tabler      sr    EFE19eDD	$T
 	V]]((*+  99Ur   c               $    V ^8  d   QhRRRRRR/# )r   titler   r   r   r   r   )r   s   "r   r   r      s!      s   r   c           	     h    \         P                  ! \        R VRV RR.\        \        4      RR7       R# )ztools/ntfy.pyz--titlez
--priorityhighTrz   r   N)r   r   r   r   r-   )r   r   s   &&r   send_notifyr      s)    NN	#y%vNIdr   c                   V ^8  d   QhRR/# )r   r   r   r   )r   s   "r   r   r      s     _ _d _r   c                 :   \         P                  ! R \         P                  \        R7      p V P	                  RR\
        \
        RRR7       V P	                  RR\        \        RR	R7       V P	                  R
\        ^RR7       V P	                  R\        ^eRR7       V P	                  RRRR7       V P	                  RRRR7       V P	                  R\        R^^.R7       V P	                  RR. RoOR7       V P	                  R\        RR7       V P	                  R\        ^R R7       V P	                  R!\        R"R7       V P	                  R#\        ^ R$R7       V P	                  R%RR&R7       V P	                  R'\        R(R)R7       V P	                  R*RR+R7       V P	                  R,RR-R7       V P	                  R.RR/R7       V P	                  R0RR1R7       V P	                  R2RR3R7       V P	                  R4. RpOR5R6R77       V P	                  R8. RqOR9R;R77       V P	                  R<\        R=R>7       V P                  4       pVP                  R:8X  d    VP                  f   V P                  R@4       \        VP                  VP                  VP                  4      pW!P                  8w  d*   \!        RAVP                   RBVP                   RCV RD24       VP"                   UUu. uF  q1P$                   F  qCV3NK  	  K  	  ppp\'        VP(                  VP*                  4      pVP                  R:8X  d    \'        VP                  \-        V4      4      MR?.\-        V4      ,          pV UUUU	u. uF  w  r4\/        Wg4       F	  w  rW4W3NK  	  K  	  p
pppp	\!        RE\-        VP"                  4       RF\-        VP$                  4       RG\-        V4       RH\-        V
4       RI2	4       VP0                  '       dW   V
 UUUU	u. uF,  w  r4r\3        W4W4      P5                  4       '       d   K(  W4W3NK.  	  p
pppp	\!        RJ\-        V
4       RK24       VP6                  '       d   \!        RL4       \8        P8                  ! 4       pVP:                  ^ 8  d   VP:                  M\=        ^\-        V
4      4      p. p\>        P@                  PC                  VRM7      ;_uu_ 4       pV
 UUUU	u/ uFy  w  r4rVPE                  \F        W4WPH                  VPJ                  VPL                  VPN                  VPP                  VVP6                  VP                  VP                  V	4      W4V3bK{  	  ppppp	\>        P@                  PS                  V4       FW  pVPU                  4       w  pppV'       d   RNMROp\!        RPV RQV RRV 24       V'       d   KA  VPW                  V RRV 24       KY  	  R?R?R?4       \!        RS\        \8        P8                  ! 4       V,
          4       RT\-        V
4      \-        V4      ,
           RU\-        V
4       RV24       V'       d)   \!        RWRXPY                  RY V 4       4      ,           4       VPZ                  '       d   \!        RZ4       . pVP"                   F  pVP$                   Ft  p\]        VWBVP^                  VP`                  VP6                  4      w  pppV'       d   RNMROp\!        RPV R[V RRV 24       V'       d   K^  VPW                  V RRV 24       Kv  	  K  	  V'       d)   \!        R\RXPY                  R] V 4       4      ,           4       VPb                  '       d:   \!        R^4       \e        VP6                  4      p\!        RPV'       d   RNMRO R_24       R`pVPf                  '       d8   \!        Ra4       \i        VP"                  VP6                  4      p\k        V4       MSVP6                  '       gB   VP"                   F1  p\l        Pn                  ! \p        RbRcV.\s        \t        4      RdRe7       K3  	  VPv                  '       d   VP6                  '       g   \-        V
4      \-        V4      ,
          pV RU\-        V
4       Rf2pVPZ                  '       d
   VRg,          pVPb                  '       d
   VRh,          pV'       d^   VPy                  4        Uu. uF  pRiV9   g
   RjV9   g   K  VNK  	  ppV'       d'   VRXRXPY                  VRk,          4      ,           ,          p\{        RlV4       \!        Rm4       \!        Rn4       \|        P~                  ! ^ 4       R?# u uppi u up	pppi u up	pppi u up	pppi   + '       g   i     EL; iu upi )rzMLP training orchestrator)descriptionformatter_classepilogz--assets+ASSETz Assets to train (default: all 4))nargsdefaultchoicesmetavarhelpz--tfsTFzTimeframes (default: all 5)z--seedsz&Number of seeds per combo (default: 3))typer   r   z--seed-startz8First seed value; subsequent seeds += 101 (default: 101)z--skip-existing
store_truez6Skip training if artifact already exists for that seed)actionr   z--tagrV   z.Artifact name tag, e.g. 'bb50' (default: bb50))r   r   rm   )r   r   r   rk   robust)r   r   rl   g{Gz?)r   r   rn   zWCMA-ES worker processes per training job (default: 2, keeps headroom for parallel jobs)ro   i,  z--parallel-jobsz<Max parallel training jobs (default: 0 = all combos at once)z--sweepz"Run threshold sweep after trainingr   i8 z%Sweep samples per TF (default: 80000)r   z(Promote sweep winners (requires --sweep)z	--presetsz#Regenerate Pine presets after sweepz--tablez"Print regression table after sweepz--notifyz Send ntfy notification when donez	--dry-runz#Print commands without running themrp   rW   zmFilter Phase-1 training to MVRV regime bars (requires mvrv_regime column). Auto-appends regime suffix to tag.)r   r   r   rq   rU   rr   zBPass the first-layer connectivity experiment to each training run.z--random-mask-seed-startz~Required with random_sparse; one explicit mask seed per training seed, incremented by 101 in the same order as training seeds.)r   r   NzI--random-mask-seed-start is required with --input-structure random_sparsezregime=z: tag auto-suffixed 'u   ' → ''zPlan: u    assets × u    TFs × z	 seeds = z training jobsz  After skipping existing: z jobs remainingu    DRY RUN — no commands executed)max_workersu   ✅u   ❌  ri   z: zTraining done in u   s — /z
 succeededz
Failures:
r   c              3  ,   "   T F
  pR V 2x  K  	  R# 5ir   Nr   .0r   s   & r   	<genexpr>main.<locals>.<genexpr>;  s     &BAA3x   z3Starting threshold sweeps (sequential per combo)...z sweep zSweep failures:
c              3  ,   "   T F
  pR V 2x  K  	  R# 5ir   r   r   s   & r   r   r   J  s     /Q.Q"QC.r   zRegenerating Pine presets...z Pine presetsr   zRunning regression table...r   rj   Tr   z trainedz + sweptz
 + presetsOOS%:N   NzTradingBot25 MLPz	ntfy sentzDone.)meanminmean_minr   )bullbearsidewaysrW   )rU   groupedrT   rr   )@argparseArgumentParserRawDescriptionHelpFormatter__doc__add_argument
ALL_ASSETSALL_TFSr2   ra   
parse_argsrR   random_mask_seed_starterrorr\   r3   rQ   r&   r   tfsrA   r;   rL   lenzipskip_existingr9   r~   rd   r   parallel_jobsmax
concurrentfuturesThreadPoolExecutorsubmitr   r^   r_   r`   rb   rc   as_completedr   rI   r   sweepr   r   r   presetsr   tabler   r"   r   r   r   r   r-   notify
splitlinesr   os_exit)parserargseffective_tagar)   combosrL   
mask_seedsr1   rf   jobsrN   t_trainr   failurespoolr   futr   okdetailstatussweep_failuresr(   table_outputn_okr   l	oos_liness                                r   mainr	     s   $$/ <<F
 
#z: '.P  R
sGW $+H  J
	QE  G
S#W  Y
),U  W
M  O 
C"aI
*H E  G
UD9
S!A  B *cB
)Q[  ] 	,A  C
#uD  F
LG  I
LB  D
	,A  C

<?  A
LB  D

,OY^a  b +5lv}a  c
2W  X D.43N3N3V`a +488T[[$BVBVWM gdkk]"7zWXYZ#{{>{!XXr"gXg{F>4E))_< T88#e*ECG&3u:BU  EA3u3I 
 3I 	! 	 
 &T[[!"+c$((m_HSZL QYK~	' (AE H*=!$QA=DDF &% H)#d)ODE|||./ iikG(,(:(:Q(>$$$C3t9DUKH				.	.;	.	G	G4
 (,	
 (,#q KK	1![[$:M:M$2E2E}dkk43G3GTVW]^U_` (,	 	 
 %%227;C #

E2v UeF"VHAeWBvh/025'F8 45 < 
H 
C		G 345Vt9S]"
#1SYKz	; < kTYY&B&BBBC zzzAB[[Ehh$-eR.2llDLL$,,%X!r6"$%bwb9:r"))UG2fX*>?  ! #dii/Q./Q&QQR |||*+&b"%(67 Lzzz)* dll;l\\\[[ENN5y%HId ! {{{4<<<TS]*63t9+X.::::C<<<<C$0$;$;$=X$=q!sVWx$=IXtdii	"666&,KLHHQKA ?H
 
H	G	GB YsJ   !e&,#e,
=%e4
'e4
f"A?e<!A ff!f6f<ff	__main__)COINBASE_BTCUSDCOINBASE_ETHUSDBINANCE_SOLUSDBINANCE_LINKUSD)r   r   r   r	   r
   )rV   )rW   rU   N)+r   
__future__r   r   concurrent.futuresr   jsonr   r   r   r   r   r   pathlibr   __file__resolveparentr-   pathinsertr   r   r   r,   r8   VENV_PYTHONr~   
executabler   r&   r/   r9   rA   rO   r\   r   r   r   r   r   r	  __name__r   r   r   <module>r     s  . #    	  
  ' H~&&-- 3t9 X
,E4eUE4N	\!H,u4Wnu$y0"-"4"4"6"6c+CNNT<
K:
	9.$b$D"_D zF r   