Ë
    Š_±ja  ã                  óü  — U d Z ddlm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 ddlmZmZ ddlmZmZ ddlmZ ddlmZ  ee«      j/                  «       j0                  j0                  Ze	j4                  j7                  d ee«      «       g d	¢Zg d
¢Zdddddd
œZedz  dz  dz  Z edz  dz  Z!edz  dz  Z"edz  dz  dz  Z#e#jI                  «       r ee#«      ne	jJ                  Z&da'de(d<   d0d1d„Z)d2d„Z*d3d„Z+d4d„Z,d5d„Z-d6d „Z.d3d!„Z/d7d"„Z0d8d#„Z1d9d:d$„Z2d;d%„Z3e G d&„ d'«      «       Z4	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d<d(„Z5	 	 	 	 	 	 	 	 	 	 	 	 d=d)„Z6d>d*„Z7d?d+„Z8d@d,„Z9dAd-„Z:dBd.„Z;e<d/k(  r e;«        yy)Cu  
Adaptive MLP training loop with convergence detection.

Trains seed batches per timeframe round-by-round, measures whether the winner
Calmar improved, and retires timeframes that have stopped benefiting.  When a
TF plateaus on all-regime seeds, it switches to --regime bull as an
intervention before retiring permanently.

State machine per TF:
    ACTIVE (phase=all)  â†’  no improvement Ã— convergence_rounds  â†’  ACTIVE (phase=bull)
    ACTIVE (phase=bull) â†’  no improvement Ã— convergence_rounds  â†’  RETIRED
    RETIRED             â†’  skipped for all future rounds

All console output is tee'd to results/adaptive_logs/run_<timestamp>.log so the
full run history is available for later review.

Usage:
    # Run with defaults (BTC all TFs, 3 seeds/round, up to 10 rounds)
    python3 tools/run_mlp_adaptive.py --notify

    # Specific TFs, smaller batches
    python3 tools/run_mlp_adaptive.py --tfs 6H 12H 1D --seeds-per-round 2 --notify

    # Preview plan without executing
    python3 tools/run_mlp_adaptive.py --dry-run
é    )ÚannotationsN)Údefaultdict)Ú	dataclassÚfield)ÚdatetimeÚtimezone)ÚPath)ÚIO)ÚCOINBASE_BTCUSDÚCOINBASE_ETHUSDÚBINANCE_SOLUSDÚBINANCE_LINKUSD)Ú4HÚ6HÚ8HÚ12HÚ1DÚ240Ú360Ú480Ú720r   Ú
strategiesÚparamsÚmlpÚresultsÚwinnersÚadaptive_logsz.venvÚbinÚpython3zIO[str] | NoneÚ	_log_filec                ó°   — t        | d¬«       t        �.	 t        j                  | dz   «       t        j                  «        yy# t        t
        f$ r Y yw xY w)z4Write a line to stdout and the current run log file.T)ÚflushNÚ
)Úprintr    Úwriter"   ÚOSErrorÚ
ValueError)Úlines    úA/Users/jameslopez/projects/TradingBot25/tools/run_mlp_adaptive.pyÚteer*   =   sO   € ä	ˆ$�dÕÜÐð	Ü�O‰O˜D 4™KÔ(Ü�O‰OÕð øô œÐ$ò 	Ùð	ús   •,A ÁAÁAc                ó†   — t        dt        j                  t        j                  «      j                  d«      › d| › �«       y )NÚ[z%H:%M:%Sz] )r*   r   Únowr   ÚutcÚstrftime)Úmsgs    r)   Úlogr1   H   s0   € Üˆ!ŒH�L‰LœŸ™Ó&×/Ñ/°
Ó;Ð<¸B¸s¸eÐDÕEó    c                ó"   — t         d| › d|› d�z  S )NÚ(optimization_winner_strategy_mlp_scores_Ú_ú.csv)Ú
WINNER_DIR©ÚassetÚtfs     r)   Úwinner_pathr;   N   s   € ÜÐBÀ5À'ÈÈ2È$ÈdÐSÑSÐSr2   c                ó    — ddl m}  || |«      S )zIReplay the current incumbent; missing or invalid evidence stops the loop.r   )Úreplay_incumbent)Útools.run_mlp_deep_sweepr=   )r9   r:   r=   s      r)   Úread_winner_evidencer?   R   s   € å9Ù˜E 2Ó&Ð&r2   c                ó2   — t        t        | |«      d   «      S )NúCalmar Ratio)Úfloatr?   r8   s     r)   Úread_winner_calmarrC   X   s   € ÜÔ% e¨RÓ0°Ñ@ÓAÐAr2   c                ó‚  ‡ — ‰ j                   rt        ˆ fd„||fD «       «      rt        ‰ j                  › d�«      ‚d„ ||fD «       \  }}t	        d„ ||‰ j
                  fD «       «      st        ‰ j                  › d�«      ‚t        j                  |‰ j
                  dd¬«      st        ‰ j                  › d�«      ‚||z
  S )	zJNever count a changed measurement context or failed replay as convergence.c              3  óZ   •K  — | ]"  }|j                  d «      ‰j                  k7  –— Œ$ y­w)ÚComparison_FingerprintN)ÚgetÚcomparison_fingerprint)Ú.0ÚrowÚstates     €r)   Ú	<genexpr>z#comparison_delta.<locals>.<genexpr>^   s.   øè ø€ ð /á"ˆCð 	�‰Ð(Ó)¨U×-IÑ-IÕIÙ"ùs   ƒ(+z6: comparison fingerprint changed; restart with replaysc              3  ó8   K  — | ]  }t        |d    «      –— Œ y­w)rA   N)rB   )rI   rJ   s     r)   rL   z#comparison_delta.<locals>.<genexpr>c   s   è ø€ ÐG±°”�s˜>Ñ*×+±ùs   ‚c              3  óF   K  — | ]  }t        j                  |«      –— Œ y ­w©N)ÚmathÚisfinite)rI   Úvalues     r)   rL   z#comparison_delta.<locals>.<genexpr>d   s   è ø€ ÐPÑ1O¨Œt�}‰}˜U×#Ñ1Oùs   ‚!z!: incumbent Calmar must be finiteg»½×Ùß|Û=)Úrel_tolÚabs_tolz&: incumbent baseline did not reproduce)rH   Úanyr'   r:   ÚallÚlast_calmarrP   Úisclose)rK   ÚbeforeÚafterÚpreÚposts   `    r)   Úcomparison_deltar]   \   sº   ø€ à×'Ò'¬3ó /à˜E‘?ó/ô ,ô ˜EŸH™H˜:Ð%[Ð\Ó]Ð]ÙG¸À±ÓG�I€CˆÜÑP°#°t¸U×=NÑ=NÑ1OÓPÔPÜ˜EŸH™H˜:Ð%FÐGÓHÐHÜ�<‰<˜˜U×.Ñ.¸ÀuÕMÜ˜EŸH™H˜:Ð%KÐLÓMÐMØ�#‰:Ðr2   c                ó:   — t         dz  dz  | › dt        |   › d�z  S )NÚdatar   ú, r6   )ÚREPOÚ	TF_PERIODr8   s     r)   Ú	data_pathrc   k   s'   € Ü�&‰=˜5Ñ  e W¨B¬y¸©}¨o¸TÐ#BÑBÐBr2   c           	     óð   — g }t         j                  d| › d|› d|› d�«      D ]9  }	 |j                  t        |j                  j                  d«      d   «      «       Œ; t        |«      S # t        $ r Y ŒRw xY w)NÚmlp_weights_r5   z_seed*.jsonÚ_seedéÿÿÿÿ)ÚWEIGHTS_DIRÚglobÚappendÚintÚstemÚsplitr'   Úsorted)r9   r:   ÚtagÚseedsÚps        r)   Úexisting_seedsrr   o   sz   € Ø€EÜ×Ñ ¨U¨G°1°R°D¸¸#¸¸kÐJÖKˆð	Ø�L‰Lœ˜QŸV™VŸ\™\¨'Ó2°2Ñ6Ó7Õ8ð Lô
 �%‹=Ðøô ò 	Ùð	ús   ¦6A)Á)	A5Á4A5c                ó@   — t        | ||«      }|rt        |«      dz   S dS )z=First seed not yet trained for this asset/TF/tag combination.ée   )rr   Úmax)r9   r:   ro   rp   s       r)   Únext_seed_startrv   y   s&   € ä˜5 " cÓ*€EÙ!&ŒC�‹J˜ÑÐ/¨CÐ/r2   c                ó   — | dk(  r|S |› d| › �S )NrV   r5   © )ÚphaseÚbase_tags     r)   Ú	phase_tagr{      s   € Ø ’~ˆ8Ð@¨h¨Z°q¸¸Ð+@Ð@r2   c                ó   — | dk(  rdS | S )NrV   rx   )ry   s    r)   Úphase_regimer}   ƒ   s   € Ø˜U’Nˆ5Ð-¨Ð-r2   c                  ó–   — e Zd ZU ded<   dZded<   dZded<   dZded<   dZd	ed
<   dZded<   dZ	ded<   dZ
ded<   dZd	ed<   dZd	ed<   y)ÚTFStateÚstrr:   Ú rH   Úincumbent_identityrV   ry   r   rk   Úno_improve_roundsg        rB   rW   Úinitial_calmarõ   â€”Ú	phase_wonÚrounds_usedrt   Ú	next_seedN)Ú__name__Ú
__module__Ú__qualname__Ú__annotations__rH   r‚   ry   rƒ   rW   r„   r†   r‡   rˆ   rx   r2   r)   r   r   ‰   sd   … àƒGØ"$Ð˜CÓ$Ø Ð˜Ó Ø€Eˆ3ÓØÐ�sÓØ€K�ÓØ€N�EÓØ€IˆsÓØ€K�ÓØ€IˆsÔr2   r   c
                ó  ‡ ‡‡‡‡‡‡	— g }
|D ]l  }t        |j                  |«      }t        |j                  «      }t        |«      D ]1  }|
j	                  |j
                  |j                  |dz  z   ||f«       Œ3 Œn |
sydj                  d„ |D «       «      }t        dt        |«      › d|› dt        |
«      › d|› d	�	«       t        t        «      }|
D ]  ^}}||xx   d
z  cc<   Œ t        t        «      }dˆ ˆ	ˆˆˆˆˆfd„}t        j                  j                  t!        d
t        |
«      «      ¬«      5 }|
D ����ci c]  \  }}}}|j#                  |||||«      ||f“Œ! }}}}}t        j                  j%                  |«      D ]Ê  }|j'                  «       \  }}}}||   j	                  |||f«       t        ||   «      ||   k(  sŒDt)        ||   d„ ¬«      }t+        d„ |D «       «      }dj                  d„ |D «       «      }dj                  d„ |D «       «      }|||   k(  rdn|dkD  rdnd}t        d|› d|› d|› d||   › d|› d|› d	�«       ŒÌ 	 ddd«       |D ]  }|xj                  |dz  z  c_        Œ yc c}}}}w # 1 sw Y   Œ1xY w)z—Train seeds_per_round new seeds for each active TF (all in parallel).

    Prints one summary line per TF when all its seeds finish, not per seed.
    rt   Nr`   c              3  óR   K  — | ]  }|j                   › d |j                  › �–— Œ! y­w)Ú=N)r:   ry   ©rI   Úss     r)   rL   ztrain_round.<locals>.<genexpr>³   s$   è ø€ ÐI¹=°a §¡  a¨¯© yÔ1¹=ùs   ‚%'z
Training: u    TFs Ã— z	 seeds = z jobs [Ú]é   c                ót  •— t         d‰› d| › d|› d|› d�	z  }t        ‰| «      }|j                  «       s| |ddfS t        ddt	        |«      d	‰d
| d‰dt	        ‰«      dg‰D �cg c]  }t	        |«      ‘Œ c}¢d‘t	        |«      ‘d‘t	        ‰«      ‘d‘t	        ‰«      ‘d‘t	        |«      ‘}|dk7  r|d|gz  }‰r#t        ddj                  |«      › �«       | |ddfS t        d‰› d| › d|› d|› d�	«      }t        j                  «       }		 t        |d«      5 }
t        j                  ||
|
t	        t        «      ¬«      j                  }d d d «       | |dk(  t        t        j                  «       |	z
  «      fS c c}w # 1 sw Y   Œ5xY w# t        $ r' | |dt        t        j                  «       |	z
  «      fcY S w xY w)Nre   r5   rf   z.jsonFr   ztools/train_mlp.pyz--dataú--assetz--tfú--fold-objectiveú--l2ú--hiddenz--seedú--es-workersú--es-generationsz--outrV   z--regimeú  [dry-run] Ú Tz/tmp/mlp_train_ú.logÚw©ÚstdoutÚstderrÚcwd)rh   rc   ÚexistsÚPYTHONr€   r*   Újoinr	   ÚtimeÚopenÚ
subprocessÚrunra   Ú
returncoderk   Ú	Exception)r:   Úseedro   ÚregimeÚoutr_   ÚhÚcmdÚlog_pÚt0ÚfhÚrcr9   Údry_runÚes_generationsÚ
es_workersÚfold_objectiveÚhiddenÚl2s               €€€€€€€r)   Ú
_train_oneztrain_round.<locals>._train_one½   s  ø€ Ü˜|¨E¨7°!°B°4°q¸¸¸UÀ4À&ÈÐNÑNˆÜ˜ Ó#ˆØ�{‰{Œ}Ø�t˜U AÐ%Ð%ô Ð(Ø”c˜$“iØ�u˜f bØ Ø”C˜“GØð
ñ +1Ó1©& Qœ#˜a�&¨&Ñ1ð
ð ð
ô ˜$“ið
ð ð
ô   
›Oð
ð ð
ô !$ NÓ 3ð
ð ð
ô ˜“Xð
ˆð �UŠ?Ø�J Ð'Ñ'ˆCáÜ�,˜sŸx™x¨›}˜oÐ.Ô/Ø�t˜T 1Ð$Ð$ä� u g¨Q¨r¨d°!°C°5¸¸d¸VÀ4ÐHÓIˆÜ�Y‰Y‹[ˆð	:Ü�e˜SÔ! RÜ—^‘^ C°¸2Ä3ÄtÃ9ÔM×XÑX�÷ "à�t˜R 1™W¤c¬$¯)©)«+¸Ñ*:Ó&;Ð;Ð;ùò% 2÷  "Ð!ûô ò 	:Ø�t˜U¤C¬¯	©	«°bÑ(8Ó$9Ð9Ò9ð	:ús0   Á"E6Ä
F Ä1E;Å.F Å;FÆ F Æ-F7Æ6F7©Úmax_workersc                ó   — | d   S )Nr“   rx   )Úxs    r)   Ú<lambda>ztrain_round.<locals>.<lambda>è   s   € ¸aÀºdr2   )Úkeyc              3  ó.   K  — | ]  \  }}}|sŒ
d –— Œ y­w)r“   Nrx   )rI   Úokr5   s      r)   rL   ztrain_round.<locals>.<genexpr>é   s   è ø€ Ð>±¡H B¨¨1º2œa±ùs   ‚Žc              3  ó.   K  — | ]  \  }}}d |› �–— Œ y­w)r¬   Nrx   )rI   r5   r‘   s      r)   rL   ztrain_round.<locals>.<genexpr>ê   s   è ø€ Ð#F¹g±7°1°a¸ d¨1¨#¤J¹gùó   ‚Ú+c              3  ó.   K  — | ]  \  }}}|› d �–— Œ y­w)r‘   Nrx   )rI   r5   Úes      r)   rL   ztrain_round.<locals>.<genexpr>ë   s   è ø€ Ð"B¹'©w¨q°!°Q a S¨¤7¹'ùrÅ   õ   âœ…r   õ   âš ï¸�õ   â�Œú  rœ   ú: Ú/z trained  (z) [)
r:   r€   r¬   rk   ro   r€   r­   r€   Úreturnztuple[str, int, bool, int])r{   ry   r}   Úrangerj   r:   rˆ   r¥   r1   Úlenr   rk   ÚlistÚ
concurrentÚfuturesÚThreadPoolExecutorru   ÚsubmitÚas_completedÚresultrn   Úsum) r9   Úactive_statesÚseeds_per_roundrz   r¹   r¸   rº   r·   r¶   rµ   ÚjobsrK   ro   r­   ÚiÚphase_summaryÚseeds_per_tfr:   r5   Ú	completedr»   Úpoolr¬   rÔ   ÚfutrÃ   Úelapsedr   Ún_okÚidsÚtimesÚicons    `   ``````                      r)   Útrain_roundrè   ™   s™  þ€ ð  -/€DÛˆÜ˜5Ÿ;™;¨Ó1ˆÜ˜eŸk™kÓ*ˆÜ�Ö'ˆAØ�K‰K˜Ÿ™ 5§?¡?°Q¸±WÑ#<¸cÀ6ÐJÕKñ (ð ñ Øà—I‘IÑI¹=ÓIÓI€MÜˆ*”S˜Ó'Ð(¨°Ð0AÀÌ3ÈtË9È+ð VØˆ?˜!ð	ô ô œsÓ#€LÛˆˆˆQØ�RÓ˜AÑÔð ô 9DÄDÓ8I€I÷ :ó  :ôD 
×	Ñ	×	.Ñ	.¼3¸qÄ#ÀdÃ)Ó;LÐ	.Ô	MÐQUñ *.ö
á)-Ñ%��D˜#˜vð �K‰K˜
 B¨¨c°6Ó:¸RÀ¸JÑFØ)-ð 	ó 
ô ×%Ñ%×2Ñ2°7Ö;ˆCØ$'§J¡J£LÑ!ˆB��b˜'Ø�b‰M× Ñ  " d¨GÐ!4Ô5Ü�9˜R‘=Ó! \°"Ñ%5Ó5Ü  ¨2¡±NÔC�ÜÑ>±Ó>Ó>�ØŸ)™)Ñ#F¹gÓ#FÓF�ØŸ(™(Ñ"B¹'Ó"BÓB�Ø#'¨<¸Ñ+;Ò#;™%ÈdÐUVÊhÁ(Ð\a�Ü�b˜˜˜a ˜t 2 d V¨1¨\¸"Ñ-=Ð,>¸kÈ#ÈÈcÐRWÐQXÐXYÐZÕ[ñ <÷ 
Nó  ˆØ�Š˜?¨SÑ0Ñ0Žñ ùõ
÷ 
NÐ	Mús&   Ä3JÄ;$I9ÅA'JÇB	JÉ9JÊJ
c           
     óˆ  ‡ ‡‡‡‡— t        |«      }t        j                  «       xs d}t        d||z  «      Št	        d|› d‰› d�«       dˆ ˆˆˆˆfd„}g }t
        j                  j                  |¬«      5 }	|D �
ci c]  }
|	j                  ||
«      |
j                  “Œ! }}
t
        j                  j                  |«      D ]G  }|j                  «       \  }}}t	        d|rd	nd
› d|› d|› �«       |rŒ2|j                  |› d|› �«       ŒI 	 ddd«       |rt        ddj                  |«      z   «      ‚yc c}
w # 1 sw Y   Œ.xY w)zÓSweep all active TFs in parallel, each with an equal share of CPU cores.

    Always passes all seed artifacts for this TF (all tags) so the best
    historical weight can still win with updated thresholds.
    é   r“   z
Sweeping: z TFs in parallel (z workers each) ...c                ó¶  •— t        t        j                  d‰
› d| j                  › d‰› d�«      «      }|s| j                  ddfS t        dd‰
d| j                  d	t        ‰«      d
t        ‰«      dg|D �cg c]  }t        |«      ‘Œ c}¢d‘d‘| j                  ‘d‘| j                  ‘}‰r,t        ddj                  |«      › �«       | j                  ddfS t        d‰
› d| j                  › d�«      }t        j                  «       }	 t        |d«      5 }t        j                  |||t        t        «      ¬«      j                   }d d d «       t#        t        j                  «       |z
  «      }dk7  r| j                  dd|› d|› d|› �fS | j                  d|› d�fS c c}w # 1 sw Y   Œ]xY w# t$        $ r"}	| j                  dt        |	«      fcY d }	~	S d }	~	ww xY w)Nre   r5   z*_seed*.jsonFzno artifacts foundztools/run_mlp_deep_sweep.pyr•   z--timeframesú	--samplesz	--workersz--extra-weightsz	--promotez!--expected-comparison-fingerprintz--expected-incumbent-identityr›   rœ   Tzdry-runz/tmp/mlp_sweep_r�   rž   rŸ   r   zexit z after u
   s â€” see r‘   )rn   rh   ri   r:   r¤   r€   rH   r‚   r*   r¥   r	   r¦   r§   r¨   r©   ra   rª   rk   r«   )rK   ÚextrasrÈ   r°   r±   r²   r³   r´   rã   Úexcr9   rz   rµ   ÚsamplesÚworkers_per_sweeps             €€€€€r)   Ú
_sweep_onezsweep_round.<locals>._sweep_one  sð  ø€ Üœ×(Ñ(Ø˜5˜'  5§8¡8 *¨A¨h¨Z°|ÐDó
ó ˆñ Ø—8‘8˜UÐ$8Ð8Ð8ô Ð1Ø�uØ˜EŸH™HØœ˜W›ØœÐ.Ó/Øð

ñ 28Ó 8±¨A¤ Q¥°Ñ 8ð

ð ð

ð 0ð

ð 27×1MÑ1Mð

ð ,ð

ð .3×-EÑ-Eð

ˆñ Ü�,˜sŸx™x¨›}˜oÐ.Ô/Ø—8‘8˜T 9Ð,Ð,ä� u g¨Q¨u¯x©x¨j¸Ð=Ó>ˆÜ�Y‰Y‹[ˆð	-Ü�e˜SÔ! RÜ—^‘^ C°¸2Ä3ÄtÃ9ÔM×XÑX�÷ "äœ$Ÿ)™)›+¨Ñ*Ó+ˆGØ�QŠwØ—x‘x ¨%°¨t°7¸7¸)À:ÈeÈWÐ(UÐUÐUØ—8‘8˜T g Y¨a =Ð0Ð0ùò% !9÷ "Ð!ûô ò 	-Ø—8‘8˜U¤C¨£HÐ,Õ,ûð	-úsC   Á5FÄF- Ä1F!ÅAF- Æ
F- Æ!F*Æ&F- Æ-	GÆ6GÇGÇGr¼   rÌ   rÉ   rË   z sweep rÍ   Nz(Sweep failed; convergence not measured: z; )rK   r   rÏ   ztuple[str, bool, str])rÑ   ÚosÚ	cpu_countru   r1   rÓ   rÔ   rÕ   rÖ   r:   r×   rØ   rj   ÚRuntimeErrorr¥   )r9   rÚ   rz   rï   rµ   Ún_tfsró   rñ   Úfailuresrá   rK   rÔ   râ   r:   rÃ   Údetailrð   s   ` ```           @r)   Úsweep_roundrø   õ   s@  ü€ ô �Ó€EÜ—‘“Ò# !€IÜ˜A˜y¨EÑ1Ó2Ðäˆ*�U�GÐ-Ð.?Ð-@Ð@RÐSÔT÷!-ñ !-ðF €HÜ	×	Ñ	×	.Ñ	.¸5Ð	.Ô	AÀTÙIVÓWÉÀ�4—;‘;˜z¨5Ó1°5·8±8Ñ;ÈˆÐWÜ×%Ñ%×2Ñ2°7Ö;ˆCØ ŸZ™Z›\‰NˆB��FÜ�"™b‘U eÐ,¨G°B°4°r¸&¸ÐBÔCÚØ—‘ 2 $ b¨¨Ð 1Õ2ñ	 <÷ 
Bñ ÜÐEÈÏ	É	ÐRZÓH[Ñ[Ó\Ð\ð ùò X÷ 
BÐ	Aús%   Á6D8Á;$D3ÂAD8Ã2D8Ä3D8Ä8Ec                óö  — t        «        t        d› «       t        dd›ddd›ddd›dd	d
›ddd›d�
«       t        d› «       d}|j                  «       D ]€  \  }}|j                  }||j                  z
  }|dkD  rd|d›�n|d›}|dkD  }|rdnd}	|rd}t        |	› d|d›d|j                  d›d|d›d|d
›d|j                  d›d|j
                  › �«       Œ‚ t        d› «       |st        d«       t        «        y)z1Print before/after Calmar comparison for each TF.uÃ   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ÚTFz<6rœ   zCalmar Beforez>14zCalmar Afterz>13ÚDeltaz>8rÌ   z	Phase Wonz<12z RoundsFg-Cëâ6?rÆ   ú.4fú+.4frÉ   Tz<5z>14.4fz>13.4fuE     No Calmar improvements â€” all TFs at architecture/feature ceiling.N)r*   ÚitemsrW   r„   r†   r‡   )
r9   ÚstatesÚany_improvedr:   rK   rZ   ÚdeltaÚ	delta_strÚimprovedrç   s
             r)   Úprint_comparison_tabler  8  s*  € ä„EÜˆ8ˆ*ÔÜˆ4�ˆ)�1�_ SÐ)¨¨>¸#Ð*>¸aÀÈ¸|È2ÈkÐZ]ÐM^Ð^eÐfÔgÜˆ8ˆ*ÔØ€LØ—\‘\–^‰	ˆˆEØ×!Ñ!ˆØ˜×,Ñ,Ñ,ˆØ',¨v¢~�a˜˜c�{‘O¸eÀD¸\ˆ	Ø˜F‘NˆÙ%‘E¨3ˆÙØˆLÜˆtˆf�A�b˜�W˜A˜e×2Ñ2°6Ð:¸!¸EÀ&¸>ÈÈ9ÐUWÈ.ÐXZØ�‰˜sÐ# 1 U×%6Ñ%6Ð$7ð9õ 	:ð $ô ˆ8ˆ*ÔÙÜÐSÔTÜ…Er2   c                ó’  — | rt        d«       yt        j                  t        dgt	        t
        «      dd¬«      }|j                  j                  «       r#t        |j                  j                  «       «       |j                  dk7  r3t        |j                  j                  «       t        j                  ¬«       |j                  dk(  S )Nz6  [dry-run] python3 tools/generate_pine_mlp_presets.pyTz"tools/generate_pine_mlp_presets.py©r¢   Úcapture_outputÚtextr   ©Úfile)r*   r¨   r©   r¤   r€   ra   r    Ústriprª   r$   r¡   Úsys)rµ   rØ   s     r)   Úrun_presetsr  O  s”   € ÙÜÐDÔEØÜ�^‰^Ü	Ð5Ð6Ü”‹I d°ô€Fð ‡}�}×ÑÔÜˆF�M‰M×ÑÓ!Ô"Ø×Ñ˜AÒÜˆf�m‰m×!Ñ!Ó#¬#¯*©*Õ5Ø×Ñ Ñ!Ð!r2   c                ó’   — t        j                  t        dd| gt        t        «      dd¬«      }|j
                  j                  «       S )Nztools/mlp_results_table.pyr•   Tr  )r¨   r©   r¤   r€   ra   r    r  )r9   rØ   s     r)   Úrun_results_tabler  ^  s=   € Ü�^‰^Ü	Ð-¨y¸%Ð@Ü”‹I d°ô€Fð �=‰=×ÑÓ Ð r2   c           	     ód   — t        j                  t        d|d| ddgt        t        «      d¬«       y )Nztools/ntfy.pyz--titlez
--priorityÚhighT)r¢   r  )r¨   r©   r¤   r€   ra   )Útitler0   s     r)   Úsend_notifyr  f  s)   € Ü‡N�NÜ	� # y°%¸ÀvÐNÜ”‹I dör2   c                 óð  — t        j                  dt         j                  t        ¬«      } | j	                  dddgt
        dd¬«       | j	                  d	dt        t        d
d¬«       | j	                  dt        dd¬«       | j	                  dt        dd¬«       | j	                  dt        dd¬«       | j	                  dt        dd¬«       | j	                  ddd¬«       | j	                  dt        dd¬«       | j	                  dt        dd d!g¬"«       | j	                  d#d$g d%¢¬&«       | j	                  d't        d(¬)«       | j	                  d*t        d+d,¬«       | j	                  d-t        d.¬)«       | j	                  d/d0d1d2¬3«       | j	                  d4d5d6d7¬8«       | j	                  d9d0d:¬;«       | j	                  d<d0d=¬;«       | j                  «       }t        |j                  «      d>kD  r0t        d?t        j                  ¬@«       t        j                  d>«       |j                  dA   }|j                   sƒt"        j%                  d1d1¬B«       t'        j(                  t*        j,                  «      j/                  dC«      }t"        dD|› dE�z  }t1        |dF«      at5        dG|j7                  t8        «      › �«       i }|j:                  D ]N  }t=        ||«      }t        |dH   «      }t?        |||j@                  «      }	tC        |dI|dJ   |dK   |||	¬L«      ||<   ŒP tE        dM|› dNt        |«      › dO�«       tE        dP|jF                  › dQ|jH                  › dR|jJ                  › dS|jL                  › �«       tE        dT«       |jO                  «       D ]U  \  }}
t        tQ        |||j@                  › dU�«      «      }tE        dV|› dW|
jR                  dX›dY|
jT                  › dZ|› d[�	«       ŒW d\}dA}tW        jV                  «       }||jH                  k  �rª|jY                  «       D �
cg c]  }
|
jZ                  d]k7  sŒ|
‘Œ }}
|stE        d^«       �nn|d>z  }tE        d_d`› �«       tE        da|› db|jH                  › dNt        |«      › dcddj]                  de„ |D «       «      › �«       tE        d`› «       |D �
ci c]#  }
|
j^                  t=        ||
j^                  «      “Œ% }}
|D ]`  }ta        |||j^                     ||j^                     «       ||j^                     dK   |jb                  k7  sŒJte        |j^                  › df�«      ‚ |jO                  «       D ��ci c]  \  }}||dH   “Œ }}}tg        |||jF                  |j@                  |jh                  |jj                  |jl                  |jn                  |jp                  |j                   «
       ts        |||j@                  |jt                  |j                   «       |j                   rtE        dg«       �n¬tE        dh«       d\}|D �];  }|xjv                  d>z  c_;        t=        ||j^                  «      }ta        |||j^                     |«      }t        |dH   «      }||_)        |dK   |_1        ||jL                  k\  }|r\dA|_<        |jZ                  |_=        d1}d1}tE        di|j^                  › dj||j^                     dX›dk|dX›dl|dX›dm|jZ                  › dn�«       ŒÕ|xjx                  d>z  c_<        |jx                  |jJ                  k\  rdondp}tE        dV|› dq|j^                  › dj||j^                     dX›dk|dX›dr|ds›dt|jx                  › db|jJ                  › du|jZ                  › dn�«       |jx                  |jJ                  k\  s�Œ~|jZ                  dIk(  r�dv|_-        dA|_<        t?        ||j^                  |j@                  › dU�«      |_*        t        tQ        ||j^                  |j@                  › dU�«      «      }tE        dw|j^                  › dx|› dy|jT                  › d[�«       �Œd]|_-        tE        dz|j^                  › d{�«       �Œ> |rK|j|                  r?|j                   s3tE        d|«       t        |j                   «      }tE        dV|rd}nd~› d�«       ||jH                  k  r�Œªt        tW        jV                  «       |z
  «      }tE        d_d`› �«       tE        d€|› d�|d‚z  › dƒ|d‚z  › d„�«       tE        d`› «       t5        d…«       t�        ||«       |j                   sJtE        d†«       tƒ        |«      }t5        «        |j…                  «       D ]  }t5        |«       Œ t5        «        |j†                  ræ|j                   sÚ|jO                  «       D ��
cg c]O  \  }}
|
jR                  |
jˆ                  z
  d‡kD  r.|› dq|
jˆ                  dˆ›d‰|
jR                  dˆ›dr|
jz                  › d[�‘ŒQ }}}
dŠ|› d‹|d‚z  › dƒ�g}|r*|j‹                  dŒ«       |j�                  d�„ |D «       «       n|j‹                  dŽ«       t�        d�d_j]                  |«      «       tE        d�«       t2        �Pt‘        t2        j’                  «      j7                  t8        «      } t2        j•                  «        d at5        d‘| › �«       tE        d’«       t—        j˜                  dA«       y c c}
w c c}
w c c}}w c c}
}w )“Nz5Adaptive MLP training loop with convergence detection)ÚdescriptionÚformatter_classÚepilogz--assetsrÆ   r   ÚASSETzHAsset to train (default: COINBASE_BTCUSD; multi-asset not yet supported))ÚnargsÚdefaultÚchoicesÚmetavarÚhelpz--tfsrú   z&Timeframes to include (default: all 5)z--seeds-per-roundé   z0New seeds to train per TF per round (default: 3))Útyper  r  z--max-roundsé
   z&Hard cap on total rounds (default: 10)z--improvement-thresholdg{®Gáz”?z;Min Calmar improvement to count as progress (default: 0.02)z--convergence-roundszAConsecutive non-improving rounds before phase change (default: 2)z--tagÚbb50z>Artifact tag prefix; bull suffix auto-appended (default: bb50))r  r  rì   i€8 z/Sweep candidate samples per TF (default: 80000)r˜   é   é   )r  r  r  r–   Úrobust)ÚmeanÚminÚmean_minr$  )r  r  r—   g{®Gáz„?)r  r  r™   é   z,CMA-ES workers per training job (default: 2)rš   i,  z	--presetsÚ
store_trueTz?Regenerate Pine presets after any promotion round (default: on))Úactionr  r  z--no-presetsÚpresetsÚstore_falsezDSkip Pine preset regeneration (use for intermediate training passes))Údestr*  r  z--notifyz Send ntfy notification when done)r*  r  z	--dry-runz Print commands without executingr“   u>   ERROR: multi-asset not yet supported â€” pass a single --assetr	  r   )ÚparentsÚexist_okz%Y-%m-%dT%H%M%SÚrun_r�   rž   zLog: rA   rV   rF   ÚEvaluation_Key)r:   ry   rH   r‚   rW   r„   rˆ   u   Adaptive MLP â€” u    â€” z TFszConfig: z seeds/round, max z rounds, convergence=z rounds, threshold=zStarting Calmar per TF:Ú_bullrÌ   z	: Calmar=rü   z  next_seed=z (bull seeds already trained: Ú)FÚretiredu   All TFs retired â€” stopping.r#   u´   â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�zRound rÎ   z active TFs: r`   c              3  ó4   K  — | ]  }|j                   –— Œ y ­wrO   )r:   r�   s     r)   rL   zmain.<locals>.<genexpr>Ê  s   è ø€ Ð.¡v !˜Ÿ�¡vùs   ‚z-: incumbent changed outside this adaptive runz6Dry-run complete; no progress or convergence measured.zImprovement check:u     âœ… rÍ   u    â†’ z (+z
)  [phase=r’   rÊ   r…   rœ   z (rý   z)  no_improve=z [phase=Úbullu     ðŸ”„ uD   : plateau in all-regime â†’ switching to bull (existing bull seeds: z, next: seedu     ðŸš« z*: RETIRED (converged in all + bull phases)zRegenerating Pine presets...rÉ   rË   z Pine presetsu   ADAPTIVE LOOP COMPLETE â€” z rounds in é<   Úmr‘   z
Calmar improvement summary:zRunning mlp_results_table...gü©ñÒMbP?z.3fu   â†’u   Adaptive loop done â€” z	 rounds, z	Promoted:c              3  ó&   K  — | ]	  }d |› �–— Œ y­w)rÌ   Nrx   )rI   r(   s     r)   rL   zmain.<locals>.<genexpr>+  s   è ø€ ÐB±\¨T˜r $ œ[±\ùs   ‚u%   No promotions â€” all TFs at ceiling.zTradingBot25 MLP Adaptivez	ntfy sentz
Full log: zDone.)MÚargparseÚArgumentParserÚRawDescriptionHelpFormatterÚ__doc__Úadd_argumentÚ
ALL_ASSETSÚALL_TFSrk   rB   Ú
parse_argsrÑ   Úassetsr$   r  r¡   Úexitrµ   ÚLOG_DIRÚmkdirr   r-   r   r.   r/   r§   r    r*   Úrelative_tora   Útfsr?   rv   ro   r   r1   rÛ   Ú
max_roundsÚconvergence_roundsÚimprovement_thresholdrþ   rr   rW   rˆ   r¦   Úvaluesry   r¥   r:   r]   r‚   r'   rè   r¹   r¸   rº   r·   r¶   rø   rï   r‡   rƒ   r†   r+  r  r  r  Ú
splitlinesÚnotifyr„   rj   Úextendr  r	   ÚnameÚcloserò   Ú_exit)!ÚparserÚargsr9   Úrun_tsÚlog_pathrÿ   r:   ÚevidenceÚcalmarÚnxtr‘   Úbull_nÚany_promotedÚ	round_numÚt_startÚactiveÚpre_evidencerK   rJ   Úpre_calmarsÚpromoted_this_roundÚpost_evidencer  Úpost_calmarr  rç   rÃ   rã   Útable_outputr(   Úimproved_tfsÚ	msg_linesÚlog_path_displays!                                    r)   Úmainrg  o  s§
  € Ü×$Ñ$ØKÜ ×<Ñ<Üô€Fð
 ×Ñ˜
¨#Ð8IÐ7JÔT^Ø 'Øgð ô ið ×Ñ˜ s´GÄWÐVZØEð ô Gà
×ÑÐ+´#¸qØOð ô Qà
×Ñ˜¬S¸"ØEð ô Gà
×ÑÐ1¼ÀtØZð ô \à
×ÑÐ.´SÀ!Ø`ð ô bà
×Ñ˜¨Ø]ð ô _à
×Ñ˜¬#°uØNð ô Pð ×Ñ˜
¬°CÀ"ÀaÀÐÔIØ
×ÑÐ*°HÚ Eð ô Gà
×Ñ˜¤U°DÐÔ9Ø
×Ñ˜¬S¸!ØKð ô Mà
×ÑÐ*´¸cÐÔBà
×Ñ˜¨LÀ$Ø^ð ô `à
×Ñ˜¨Y¸}Øcð ô eà
×Ñ˜
¨<Ø?ð ô Aà
×Ñ˜¨LØ?ð ô Aà×ÑÓ€Dä
ˆ4�;‰;Ó˜!ÒÜÐNÔUX×U_ÑU_Õ`Ü�‰�ŒØ�K‰K˜‰N€Eð �<Š<Ü�‰˜d¨TˆÔ2Ü—<‘<¤§¡Ó-×6Ñ6Ð7HÓIˆÜ˜t F 8¨4Ð0Ñ0ˆÜ˜ 3Ó'ˆ	Üˆe�H×(Ñ(¬Ó.Ð/Ð0Ô1ð "$€FØ�hŒhˆÜ'¨¨rÓ2ˆÜ�x Ñ/Ó0ˆÜ  ¨¨D¯H©HÓ5ˆÜØ˜°xÐ@XÑ7YØ'Ð(8Ñ9Ø¨vØô	
ˆˆrŠ
ð	 ô Ð
˜E˜7 %¬¨F« }°DÐ9Ô:Üˆ(�4×'Ñ'Ð(Ð(:¸4¿?¹?Ð:Kð LØ×.Ñ.Ð/Ð/BÀ4×C]ÑC]ÐB^ð	`ô aäÐ!Ô"Ø—‘–‰ˆˆAÜ”^ E¨2°$·(±(°¸5Ð/AÓBÓCˆÜˆb���I˜aŸm™m¨CÐ0°¸Q¿[¹[¸Mð J,Ø,2¨8°1ð6õ 	7ð  ð
 €LØ€IÜ—9‘9“;€Gà
�d—o‘oÓ
%Ø#Ÿ]™]œ_ÓE™_˜°·±¸9Ó0D’!˜_ˆÐEÙÜÐ/Ô0Ùà�Q‰ˆ	Üˆb��
ˆOÔÜˆf�Y�K˜q §¡Ð 1°´s¸6³{°mÀ=Ø�y‰yÑ.¡vÓ.Ó.Ð/ð1ô 	2äˆxˆjÔáIOÓPÉÀA˜Ÿ™Ô2°5¸!¿$¹$Ó?Ñ?ÈˆÐPÛˆEÜ˜U L°·±Ñ$:¸LÈÏÉÑ<RÔSØ˜EŸH™HÑ%Ð&6Ñ7¸5×;SÑ;SÓSÜ  E§H¡H :Ð-ZÐ![Ó\Ð\ð ð ?K×>PÑ>PÔ>RÔSÑ>R±7°2°s�r˜3˜~Ñ.Ñ.Ð>RˆÑSô 	Ø�6˜4×/Ñ/°·±Ø�K‰K˜×,Ñ,¨d¯g©gØ�O‰O˜T×0Ñ0°$·,±,ô	
ô 	�E˜6 4§8¡8¨T¯\©\¸4¿<¹<ÔHà�<Š<ÜÐHÔIÙô 	Ð Ô!Ø#ÐÜˆEØ×Ò Ñ"ÕÜ0°¸¿¹ÓAˆMÜ$ U¨L¸¿¹Ñ,BÀMÓRˆEÜ ¨nÑ =Ó>ˆKØ +ˆEÔØ'4Ð5EÑ'FˆEÔ$Ø 4×#=Ñ#=Ñ=ˆHáØ*+�Ô'Ø*/¯+©+�”Ø*.Ð#Ø*.�Ü�f˜UŸX™X˜J b¨°U·X±XÑ)>¸sÐ(CÀ5ÈÐUXÐHYð ZØ˜s˜ :¨e¯k©k¨]¸!ð=õ >ð ×'Ò'¨1Ñ,Õ'Ø#(×#:Ñ#:¸d×>UÑ>UÒ#U‘xÐ[`�Ü�b˜˜˜a §¡˜z¨¨K¸¿¹Ñ,AÀ#Ð+FÀeÈKÐX[ÐK\ð ]Ø˜d�| >°%×2IÑ2IÐ1JÈ!ÈD×LcÑLcÐKdð eØ#Ÿk™k˜]¨!ð-ô .ð ×*Ñ*¨d×.EÑ.EÔEØ—{‘{ eÒ+Ø06˜œØ23˜Ô/Ü0?ÀÀuÇxÁxÐTX×T\ÑT\ÐS]Ð]bÐQcÓ0d˜œÜ03´NÀ5È%Ï(É(ÐW[×W_ÑW_ÐV`Ð`eÐTfÓ4gÓ0h˜Ü˜g e§h¡h Zð 05Ø5;°H¸LÈÏÉÐHYÐYZð\ö ]ð '0˜œÜ˜g e§h¡h ZÐ/YÐZÖ[ðC ñF  4§<¢<¸¿ºÜÐ.Ô/Ü˜TŸ\™\Ó*ˆBÜ�"™b‘U eÐ,¨MÐ:Ô;ðU �d—o‘oÔ
%ôZ ”$—)‘)“+ Ñ'Ó(€GÜˆ"ˆXˆJˆÔÜÐ
% i [°¸GÀR¹K¸=ÈÈ'ÐRTÉ*ÈÐUVÐWÔXÜˆ8ˆ*ÔäÐ'Ô(Ü˜5 &Ô)ð �<Š<ÜÐ*Ô+Ü(¨Ó/ˆÜŒØ ×+Ñ+Ö-ˆDÜ��Ið .äŒð ‡{‚{˜4Ÿ<š<ð  Ÿ™œô
á'‘��AØ�}‰}˜q×/Ñ/Ñ/°%Ò7ð ˆd�!�A×$Ñ$ SÐ)¨¨Q¯]©]¸3Ð,?¸rÀ!Ç+Á+ÀÈaÒPØ'ð 	ñ 
ð & i [°	¸'À2¹+¸ÀaÐHð
ˆ	ñ Ø×Ñ˜[Ô)Ø×ÑÑB±\ÓBÕBà×ÑÐDÔEÜÐ/°·±¸9Ó1EÔFÜˆKÔäÐÜ¤	§¡Ó/×;Ñ;¼DÓAÐÜ�‰ÔØˆ	ÜˆlÐ+Ð,Ð-Ô.äˆ„LÜ‡H�HˆQ…Kùòm Fùò Qùó
 Tùó^
s   Ðk"Ð4k"Ò,(k'Õk,æ$Ak2Ú__main__)r�   )r(   r€   rÏ   ÚNone)r0   r€   rÏ   ri  )r9   r€   r:   r€   rÏ   r	   )r9   r€   r:   r€   rÏ   Údict)r9   r€   r:   r€   rÏ   rB   )rK   z	'TFState'rY   rj  rZ   rj  rÏ   rB   )r9   r€   r:   r€   ro   r€   rÏ   ú	list[int])r9   r€   r:   r€   ro   r€   rÏ   rk   )r!  )ry   r€   rz   r€   rÏ   r€   )ry   r€   rÏ   r€   )r9   r€   rÚ   úlist[TFState]rÛ   rk   rz   r€   r¹   rk  r¸   r€   rº   rB   r·   rk   r¶   rk   rµ   ÚboolrÏ   ri  )r9   r€   rÚ   rl  rz   r€   rï   rk   rµ   rm  rÏ   ri  )r9   r€   rÿ   zdict[str, TFState]rÏ   ri  )rµ   rm  rÏ   rm  )r9   r€   rÏ   r€   )r  r€   r0   r€   rÏ   ri  )rÏ   ri  )=r=  Ú
__future__r   r:  Úconcurrent.futuresrÓ   rP   rò   r¨   r  r¦   Úcollectionsr   Údataclassesr   r   r   r   Úpathlibr	   Útypingr
   Ú__file__ÚresolveÚparentra   ÚpathÚinsertr€   r?  r@  rb   rh   r7   rD  ÚVENV_PYTHONr£   Ú
executabler¤   r    rŒ   r*   r1   r;   r?   rC   r]   rc   rr   rv   r{   r}   r   rè   rø   r  r  r  r  rg  r‰   rx   r2   r)   Ú<module>r{     s0  ðòõ6 #ã Û Û Û 	Û Û 
Û Ý #ß (ß 'Ý Ý áˆHƒ~×ÑÓ×&Ñ&×-Ñ-€Ø ‡�‡��‘3�t“9Ô âX€
Ú,€Ø ¨e¸EÈÑN€	à�\Ñ! HÑ,¨uÑ4€Ø�YÑ Ñ*€
Ø�YÑ Ñ0€Ø�W‰n˜uÑ$ yÑ0€Ø"-×"4Ñ"4Ô"6‰c�+Ô¸C¿N¹N€à €	ˆ>Ó  ô
óFóTó'óBóóCóó0ôAó.ð ÷
ð 
ó ð
ðW1ØðW1à ðW1ð ðW1ð ð	W1ð
 ðW1ð ðW1ð 	ðW1ð ðW1ð ðW1ð ðW1ð 
óW1ðx>]Øð>]à ð>]ð ð>]ð ð	>]ð
 ð>]ð 
ó>]óF
ó."ó!óóIðX ˆzÒÙ…Fð r2   