
    ܸ9jU                        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	m	Z	 dZ
dZdZdZdZd	gZg d
ZdZddiZg dZh dZh dZh dZdedefdZdedefdZdedefdZdededefdZdedefdZdefdZdefdZ d(de!fdZ"d)de!fdZ#d*de!fd Z$d!edefd"Z%d#ed$e&ddfd%Z'g a(g a)d& Z*e+d'k(  r e*        yy)+aB  
Generate Pine Script preset block for strategy_mlp_scores.pine from trained MLP artifacts.

Reads strategies/params/mlp/mlp_weights_COINBASE_BTCUSD_{TF}.json and
optionally results/winners/optimization_winner_strategy_mlp_scores_COINBASE_BTCUSD_{TF}.csv
(for post-sweep thresholds; falls back to artifact's recommended_thresholds if missing).

Rewrites the auto-generated sentinel block inside strategy_mlp_scores.pine in-place.

Usage:
    python3 tools/generate_pine_mlp_presets.py [--dry-run]

After running, paste strategy_mlp_scores.pine into TradingView to compile-test.
    N)datetimez#strategies/strategy_mlp_scores.pinezstrategies/params/mlpzresults/winnersu$   // ── AUTO-GENERATED MLP PRESETSu   // ── END AUTO-GENERATEDCOINBASE_BTCUSD)4H6H8H12H1DzCOINBASE_BTCUSD 12HzCOINBASE_BTCUSD 1D)!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_thresholdi_regime_windowi_regime_entry_min_scorei_mvrv_suppress_beari_exit_score_windowi_entry_score_window>   r   r   r   >   r   r   r   >   % In MarketTotal P&L %Calmar RatioP&L/DD RatioSharpe RatioTotal TradesSortino RatioMax Drawdown %verified	CPU_Score	Composite	GPU_Score	WFO_Scorecomposite_scoreWFO_Fold_Calmars_pnl_dd_percentilesubperiod_consistentvreturnc                 (    | d}d|vr	d|vr|dz  }|S )zFormat float to 7 significant figures for Pine weight literals.
    Matches float32 training precision; ~3 fewer digits/weight vs prior 10g format.
    z.7g.e.0 )r&   ss     J/Users/jameslopez/projects/TradingBot25/tools/generate_pine_mlp_presets.py
fmt_float9r/   N   s(     S'A
!|1	T	H    namec           	      2   | t         v rFt        |t              r$|j                         j	                         dv rdS dS t        |      dkD  rdS dS | t        v r&t        t        t        t        |                        S t        |      d}d|vr	d|vr|dz  }|S )	zIFormat threshold param value as Pine literal (4-sig float, int, or bool).)true1yesr3   falseg      ?z.4gr)   r*   r+   )	_BOOL_PARAMS
isinstancestrstriplowerfloat_INT_PARAMSintround)r1   r&   r-   s      r.   fmt_thresholdr@   X   s    |aWWY__.2FF6SGSqCv4W4{3uU1X'((8C.A
!|1	T	Hr0   c                 (    | t         v ry| t        v ryy)Nboolr>   r<   )r7   r=   )r1   s    r.   	pine_typerC   f   s    |{r0   assettfc                     |  d| S )N r,   )rD   rE   s     r.   
preset_keyrH   n   s    WAbT?r0   pathc                     	 t        | d      5 }t        j                  |j                               j	                         d d cd d d        S # 1 sw Y   y xY w# t
        $ r Y yw xY w)Nrb   z????????)openhashlibsha256read	hexdigestOSError)rI   fs     r.   _sha8rT   r   sR    $>>!&&(+557;  s.   A 4A	A AA A 	A$#A$c                  X   ddl } ddlm} i }i }t        j                  d      }t
        j                  j                  t              rt        t        j                  t                    D ]  }|j                  |      }|s|j                  d      |j                  d      }}|t        vs|t        vrJt
        j                  j                  t        |      }	t!        |	d      5 }
t#        t%        j&                  |
            }ddd       s|d   j)                         D ci c]  \  }}|t*        vs|| }}}||t-        ||      <    t        D ](  }t        D ]  }t-        ||      }t
        j                  j                  t.        d	| d
| d      }||v r\||   j1                  dd      j3                         }|r7t
        j                  j5                  |      r|}t6        j9                  |d       t
        j                  j5                  |      s#t;        d| d| dt<        j>                         	  ||      }i }|d   j1                  di       j1                  di       }||v rx||   }tB        D ci c]%  }||j1                  ||j1                  |d            ' }}t;        d| dt
        j                  jE                  |       t<        j>                         ny|rDtB        D ci c]  }||j1                  |d       }}t;        d| dt<        j>                         n3tB        D ci c]  }|d }}t;        d| dt<        j>                         ||d   |d   |tG        |      d||<    + t        D ]E  }t        D ]:  }t-        ||      |vst;        dt-        ||       d t<        j>                         < G |S # 1 sw Y   xY wc c}}w # t@        $ r-}t;        d| d| dt<        j>                         Y d}~d}~ww xY wc c}w c c}w c c}w )!z
    Returns {preset_key: {"thresholds": {...}, "layers": [(W,b),...], "arch": [...],
                           "artifact_path": str, "artifact_sha8": str}} for found presets.
    r   N)load_mlp_artifactzHoptimization_winner_strategy_mlp_scores_([A-Z0-9_]+)_([A-Z0-9HD]+)\.csv$       )newlinemlp_weights__z.jsonmlp_weights_filez  WARNING: no artifact for z (u   ) — skippingfilez  WARNING: cannot load z: u    — skippingmetatrainingrecommended_thresholds        z  z): using winner CSV thresholds + artifact z': using artifact recommended_thresholdsu%   : no thresholds found — using zeroslayersarch)
thresholdsrd   re   artifact_pathartifact_sha8z  WARNING: preset z will use fallback defaults)$numpystrategies.strategy_mlp_scoresrV   recompileosrI   isdirWINNERS_DIRsortedlistdirmatchgroup_ASSETS_TFSjoinrM   listcsv
DictReaderitems_METRIC_COLSrH   WEIGHTS_DIRgetr:   exists_PRESET_WEIGHT_ALIASESpopprintsysstderr	Exception_THRESHOLD_PARAMSbasenamerT   )nprV   presetswinner_thresholdswinner_patternfnamemrD   rE   fpathrS   rowskr&   rowkeyrg   csv_weightsartr*   thrrecw_rowps                           r.   load_presetsr   |   s   
 @G ZZSN 
ww}}[!BJJ{34E$$U+A
AGGAJ2EG#r~GGLLe4EeR(ACNN1-. )$(GMMOMODAqq7L1a4OCM7:j34 5 $BUB'C GGLLUG1RDPU6VWM''/4889KRPVVX277>>+#>$/M +..sD977>>-03C5=/X::''6 Cf+//*b1556NPRSC'')#.ARSARAq%))Aswwq#77ARS3%HIYIYZgIhHij::'3DE3Daq#''!S/)3DE3%FGcjjY'89'8!q#v'893%DECJJW "h-F!.!&}!5GCLS  d B%$G3*:eR+@*AA\]::'   N )( N0  /b=Q::' T F :sB   %O%O6O=O$=*P2P"6
P'O	$	P-"PPc                 >    ddj                  d | D              z   dz   S )z0Emit a list of floats as Pine array.from() call.zarray.from(, c              3   D   K   | ]  }t        t        |              y wN)r/   r<   ).0r&   s     r.   	<genexpr>z_row_literal.<locals>.<genexpr>   s     $J6aZa%96s    ))rv   )valuess    r.   _row_literalr      s!    499$J6$JJJSPPr0   c                    g }|j                  | d       |j                  | ddj                  d | D                      t        t        |       dz
        D ]X  }| |   | |dz      }}|j                  | d|dz    d||z   d|dz    d	| d
| d       |j                  | d|dz    d| d       Z |j                  d       |S )zrEmit 'var float[]' declarations for all weight/bias arrays (must appear before any if-block that assigns to them).zP// MLP weight arrays (populated on barstate.isfirst from the preset block below)z// Architecture: u    → c              3   2   K   | ]  }t        |        y wr   r9   r   ds     r.   r   z(emit_var_declarations.<locals>.<genexpr>   s     9O$Q#a&$   rW   zvar float[] _wz = array.new_float(z, 0.0)  // Wz [   ×]zvar float[] _bz, 0.0)rY   )appendrv   rangelen)re   indentlinesin_inn_outs         r.   emit_var_declarationsr      s    E	LLF8klm	LLF8,W\\9O$9O-O,PQR3t9q=!1gtAE{ex~acU2Eedl^S_`abc`c_ddfglfmmoptouuvwxx~acU2EeWFST " 
LLLr0   c           	         ddl }|j                  | |j                        } | dg}| j                  dk(  s!| j                  dk(  rB| j                  d   dk(  r0| j                         }|j                  | t        |              |S | j                  d   }|j                  | dt        | d                 |j                  | dt        | d                 |j                  | d	       t        d|      D ]8  }|j                  | d
t        | |                 |j                  | d	       : |j                  | d       |S )uL  
    Emit a Pine named function that builds ONE weight matrix or bias vector and returns it.
    Moving data into functions keeps the main script body small (Pine's main-body size limit
    is separate from per-function limits).

    The function has no arguments and returns the array — caller does:
        _w1 := fn_name()
    r   Ndtypez() =>rW   rX   float[] _tw = float[] _tr = array.concat(_tw, _tr)_tr := _tw)	ri   asarrayfloat64ndimshaperavelr   r   r   )arrfn_namer   r   r   r   r   row_is           r.   emit_weight_fnr      s@    
**S

*
+CyE
xx1}Q399Q<1+<iikxS 1234 L 		!x~l3q6.B-CDEx~l3q6.B-CDEx5671e_ELLF87<E
+C*DEFLLF8#9:; % 	xs^$Lr0   c           
         ddl }g }d}d}t        |       D ]  \  }\  }}	|j                  ||j                        }|j                  |	|j                        }	|j                  \  }
}d|dz    }d|dz    }|
dk(  r&|j                  | | dt        |d                 n|r#|j                  | d	t        |d                 n$|j                  | d
t        |d                 d}|
dkD  r|r#|j                  | dt        |d                 n$|j                  | dt        |d                 d}|j                  | d       t        d|
      D ]8  }|j                  | dt        ||                 |j                  | d       : |j                  | | d       |j                  | | dt        |	               |S )a{  
    Return list of Pine lines that initialize _w1/_b1/.._b3 from the given layers.

    Uses row-by-row array.from() calls with array.concat() to build each W matrix,
    avoiding any single very-large array.from() call.

    _tw/_tr are declared with 'float[]' only on first use; subsequent layers reuse
    them with ':=' to avoid duplicate-declaration errors in Pine v6.
    r   NFr   _wrW   _bz := z_tw := r   Tr   r   r   rX   z := _tw)ri   	enumerater   r   r   r   r   r   )rd   re   r   r   r   tw_declaredtr_declaredliWbr   r   w_varb_varr   s                  r.   emit_weight_initr   
  s    EKK'
FQJJq

J+JJq

J+ggtRTFRTFA:LLF8E7$|AaD/A.BCD xw|AaD/A.BCDx~l1Q46H5IJK"qyLLF87<!3E2F!GHLLF8>,qt:L9M!NO"&Kx'=>?"1e_ELLF87<%3I2J!KLLLF8+A!BC - LLF8E7'23 	xwd<?*;<=? (B Lr0   r   c                    t        j                         j                  d      }t        D cg c]  }t        D ]  }t        ||        }}}|D cg c]	  }|| v s| }}g }|j                  t         d       |j                  d       |j                  d| dt        |       dt        |       d       |j                  d       |j                  d	       |j                  d
       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       t        D cg c]  }t        D ]  }t        ||        }}}ddj                  d |D              z   dz   }	|j                  d       |j                  d|	 d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       t        }
|
| vr|r|d   }
|
| v r| |
   d   nt        D ci c]  }|d c}}t        D ]  }t        |      }t        ||j                  |d            }|j                  | d| d       |D ]`  }|| v st        || |   d   j                  |d            }t        j                  |      }|rd | nd}|j                  d!| d"| |        b |j                  d#| d$|
        |j                  d        |r| |d      d%   ng d&}g }|D ]e  }| |   d%   |k7  rGt!        d'| d(| |   d%    d)| d*dj                  d+ |d,d- D               t"        j$                  .       U|j                  |       g |j'                  t)        |             dd l}|D ]  }||vr|t        v r| |   }|j-                  dd/      }t/        |d%         }|d0   }|j                  d1| d2| d3|        t1        |d4         D ]  \  }\  }}|j'                  t3        |j5                  |      d5| d6|d,z                 |j                  d       |j'                  t3        |j5                  |      d5| d7|d,z                 |j                  d         i }t        j7                         D ]&  \  }}|j9                  |g       j                  |       ( |D ]   }||vr	|t        v r|j-                  dd/      }t        | |   d4         } |j                  |g       }!d8| d9g|!D "cg c]  }"d8|" d9
 c}"z   }#d:j                  |#      }$t        |#      d,kD  rd;|$ d<n|$}%|j                  d=|%        t;        |       D ]D  }|j                  d>|d,z    d?| d6|d,z    d@       |j                  dA|d,z    d?| d7|d,z    d@       F |j                  d        |j                  t<         dB       dCj                  |      dCz   S c c}}w c c}w c c}}w c c}w c c}"w )DNz%Y-%m-%d %H:%Mu    — do not edit manually ──────────────────────────────────────────zV// Run tools/generate_pine_mlp_presets.py to regenerate from trained weight artifacts.z// Last generated: z  |  /z presets foundrY   u}   // ── Preset auto-detection from chart symbol + timeframe ─────────────────────z2_tf_secs  = timeframe.in_seconds(timeframe.period)z&_tf_label = _tf_secs == 86400 ? "1D" :z'             _tf_secs == 14400 ? "4H" :z'             _tf_secs == 21600 ? "6H" :z'             _tf_secs == 28800 ? "8H" :z+             _tf_secs == 43200 ? "12H" : ""z["", r   c              3   (   K   | ]
  }d | d   yw)"Nr,   )r   r   s     r.   r   z!generate_block.<locals>.<genexpr>V  s     %H1!Ahs   r   zCi_preset_override = input.string("", "Force preset (blank = auto)",z    options=,zC    group=group_neural_activation_thresholds, display=display.none)zC_auto_key = syminfo.prefix + "_" + syminfo.ticker + " " + _tf_labelzC_preset   = i_preset_override != "" ? i_preset_override : _auto_keyu   // ─────────────────────────────────────────────────────────────────────────────r   rf   rc   rG   z = switch _presetz#  // thresholds: own CSV, weights: z    "z" => z    => z  // fallback: re   )1      rL   rW   z  WARNING: skipping u
    — arch z != ref z. Retrain with --hidden c              3   2   K   | ]  }t        |        y wr   r   r   s     r.   r   z!generate_block.<locals>.<genexpr>  s     1Q.Q#a&.r   rW   r^   r\   rh   z// z  arch: z  artifact: rd   _fw_r   r   z_preset == "r   z or (r   zif barstate.isfirst and z    _wz := _fw_z()z    _bu    ─────────────────────────────────────────────────────────────────────
)r   nowstrftimert   ru   rH   r   SENTINEL_STARTr   rv   _FALLBACK_PRESETr   rC   r@   r}   r   r   r   r   extendr   ri   replacer9   r   r   r   rz   
setdefaultr   SENTINEL_END)&r   	timestamparE   ordered_keysr   present_keysr   all_option_keysoptions_strfallback_keyr   fallback_thrparamptypefb_valr   val
weight_src
alias_noteref_archarch_ok_keysr   safearch_strsha8r   r   r   alias_reverse	alias_key
target_keyn_layersextra_aliasesak
cond_partscondcond_strs&                                         r.   generate_blockr   @  s   ''(89I/6Fw!2Jq"%%wLF+<|!qG|A|L<E	LLN#  $|  }  ~	LLik	LL&yks<7H6I3|K\J]]klm	LL 
LL  Q  R	LLEF	LL9:	LL:;	LL:;	LL:;	LL>?	LL29I'QDbz!R(D('OIDII%H%HHH3NK	LLVX	LL<}A./	LLVX	LL	LLVW	LLVW	LL  ~  	LL $L7"|#A:F':Q7<(6hyWzhycdXY[^X^hyWzL"% ul&6&6uc&BCwaw&789Cg~#E73<+E+I+I%QT+UV377<
S]B:,Oce
uSEseJ<@A   	wvhol^DER # 4@w|A'/^H
 L3<8+&se:gcl66J5K8T\S] ^)),1Q(1R.1Q)Q(RTZZ $  
LL&x01 l"((CL{{3$qy>!s3%xzdVDE#AhK0JBALL

1dV2bdV7LMNLLLL

1dV2bdV7LMNLL	 1 $ +-M!7!=!=!?	:  R077	B "@ l"(({{3$ws|H-.%))#r2$SE+,}/]},rd!0D}/]]
{{:&"%j/A"5QtfA;4/z:;/BLL6"Q$xvR1vR@ALL6"Q$xvR1vR@A " 	R! $ 
LLL>  "r  s  t99Ud""k G<$ J  X{N 0^s#   X5	X;X;Y 
YYblockdry_runc           
         t         j                  j                  t              st	        j
                  dt                t        t              5 }|j                         }d d d        j                  t              }|j                  t              }|dk(  s|dk(  r+t	        j
                  dt         dt         dt         d       |t        t              z  }|t        |      k  r"||   dv r|dz  }|t        |      k  r||   dv r|j                  d	|j                  t                    }|dk7  r|dz   }nt        |      }|d | | z   ||d  z   }|r"t        d
       t        |        t        d       y t        t        d      5 }|j                  |       d d d        t        dt         dt        t               dt        t               d       t        d       t        d       y # 1 sw Y   xY w# 1 sw Y   `xY w)NzPine file not found: r   zSentinel markers not found in z. Expected 'z' and 'z'.u    -─	rW   r   u9   ── DRY RUN — would write the following block ──u&   ── (Pine file not modified) ──wu   ✅ Rewrote z  (r   z	 presets)z-   Next step: paste into TradingView and run:z/       python3 tools/check_pine.py --mark-valid)rm   rI   r~   	PINE_FILEr   exitrM   rP   findr   r   r   r   writepresent_keys_globalall_keys_global)r  r  rS   content	start_idxend_idxnlnew_contents           r.   rewrite_piner    s   77>>)$(45	iA&&( 
 ^,I\*GB'R-1) =,-W\N"F 	G s<  G
CL
 WW%5%B1 CL
 WW%5%B 
dGLL6	7B	Rxq&g,*9%-0AAKIJe68)S!QGGK  "YKs3/B+C*DAc/FZE[[def=??AA 
8 "!s   G*G7*G47H c            
      T   t        j                  d      } | j                  ddd       | j                         }t        j
                  j                  dt        j
                  j                  t        j
                  j                  t        j
                  j                  t                                 t        dt        j                  	       t               }t        D cg c]  }t        D ]  }t!        ||        c}}at"        D cg c]	  }||v s| c}a|s0t        d
t        j                  	       t	        j&                  d       t        dt)        t$               dt        j                  	       t+        |      }t-        ||j.                         y c c}}w c c}w )Nz7Regenerate MLP preset block in strategy_mlp_scores.pine)descriptionz	--dry-run
store_truez1Print generated block without modifying Pine file)actionhelpr   zLoading MLP artifacts...r^   u+   No artifacts found — nothing to generate.rW   z
Generating block for z preset(s)...)argparseArgumentParseradd_argument
parse_argsr   rI   insertrm   dirnameabspath__file__r   r   r   rt   ru   rH   r
  r	  r  r   r   r  r  )parserargsr   r   rE   r   r  s          r.   mainr     s1    $$MOF
LP  RD HHOOArwwrwwrwwx7P'QRS	
$3::6nG4;KGqdAr*d*GKO&5Fog1oF;#**M	#C(;$<#=]
KRUR\R\]7#E% LFs   $F	F%F%__main__)rY   )z    )z        ),__doc__r  rx   rN   jsonmathrm   rk   r   r   r  r|   ro   r   r   rt   ru   r   r   r   r7   r=   r{   r<   r9   r/   r@   rC   rH   rT   dictr   r   rw   r   r   r   r   rB   r  r	  r
  r   __name__r,   r0   r.   <module>r'     s    
    	 	 
  5	& 7/ 

)(  / 
  iQ% C  3 C C c s s   Wd WxQC Q

d 
4 @1 1lw#D w#S w#x#B #Bd #Bt #BL  &6 zF r0   