
    뒇j,                       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mZ ddl	Z
ddlZ ee      j                         j                  j                  Zej"                  j%                  d ee             ddlmZmZmZmZ ddlmZ dZdZdd	Zdd
ZddZddZ ddddZ!efddZ"dddddd	 	 	 	 	 	 	 	 	 ddZ#d dZ$d!dZ%d"ddZ&d#dZ'e(dk(  r e) e'             y)$zCausal, non-promoting MLP score-peak deterioration event study.

The only model inputs are the local TradingView export and the current winner
CSV for the requested asset/timeframe.  This script never writes either.
    )annotationsN)Path)	OOS_STARTSCORE_START	TRAIN_END	WFO_FOLDS)generate_signals)            )   r      c                .    t         dz  dz  d|  d| dz  S )Nresultswinners(optimization_winner_strategy_mlp_scores__.csv)REPO)assettfs     O/Users/jameslopez/projects/TradingBot25/tools/run_mlp_score_peak_event_study.py_winner_pathr      s-    )i',TUZT[[\]_\``d*eee    c                ^    dddddd}t         dz  dz  |  d	||j                             d
z  S )N2403604807201D)4H6H8H12Hr!   datamlpz, r   )r   upper)r   r   minutess      r   
_data_pathr*      s?    %uU$OG&=5 eWBwrxxz/B.C4#HHHr   c                   t        | |      j                         5 }t        t        j                  |            }d d d        h d}t        j                               D ]-  \  }}|j                  d      s||v r|dv n
t        |      ||<   / t        t        |d               }|j                         s(t        dz  t        |      j                  dd      d   z  }t        |      |d<   |S # 1 sw Y   xY w)	N>   i_mvrv_suppress_beari_use_long_exit_confirmationi_use_long_entry_confirmationi_>   1Truetruemlp_weights_file
strategieszstrategies/r
   )r   opennextcsv
DictReaderlistitems
startswithfloatr   strexistsr   split)r   r   handlerowbooleanskeyvalueweight_paths           r   _load_winnerrG   $   s    	eR	 	%	%	'63>>&)* 
(hH399;'
U>>$9<u 55eTYlCH ( s31234K\)C,<,B,B=RS,TUW,XX!+.CJ 
(	's   C..C7c                J   g }t        |t        |       |z
        D ]  }| |   }t        j                  |      s| ||z
  | | |dz   ||z   dz    }}t        j                  ||kD        sMt        j                  ||k\        sf|j                  |||z   t        |      f        |S )aJ  Return (pivot index, confirmation index, score), with no future access.

    At ``confirmation`` the complete [pivot-left, pivot+right] window is
    closed. Strict comparison on the left and non-strict on the right makes a
    flat top deterministic: its first bar is not selected before a later bar
    could invalidate it.
    r
   )rangelennpisfiniteallappendr=   )scoresleftrightresultpivotrE   beforeafters           r   confirmed_pivot_highsrV   2   s     FtS[501u{{5!ut|E2F519UU]UVEV4W66%&.!bffUe^&<MM5%%-u>? 2 Mr   r   )horizonc                  g }| D ]S  \  }}}| D ]H  \  }}}||z
  }	d|	cxk  rdk  sn |dk  s||dz
  kD  s|d|z  kD  r0|j                  |||||||d       J U |j                  d        g }
d	}t               }|D ]D  }t        |d
         }||v s||k  r|
j                  |       |j	                  |       ||z   dz   }F |
S )zHFind qualifying second peaks, deduping chronologically by event horizon.   (   ,     333333?)first_pivot_indexfirst_confirmation_indexfirst_scoresecond_pivot_indexevent_indexevent_scoresecond_scorec                <    t        | d         t        | d          fS )Nrb   r_   intevents    r   <lambda>z-detect_deterioration_events.<locals>.<lambda>U   s!    s5+?'@3uMgGhCiBi&jr   rD   r5   rb   r
   )rN   sortsetrg   add)pivotsrW   
candidatessecond_pivotsecond_confirmrd   first_pivotfirst_confirmr`   spacingacceptednext_allowedseen_eventsri   indexs                  r   detect_deterioration_eventsrz   E   s   /1J6<2nl7=3K$}4G&B&S L;3D$DWY\gWgHgK]j.9Q].<\/;= > 8> 7= OOjOk-/HLEKE-()K5<#7w*  Or   c                   t        | |         }i }|D ]  }| |dz   ||z   dz    }t        |      |k7  sBt        j                  |      r-|dk(  s(t        j                  t        j                  |            sbdt        |d         |z  dz
  z  t        ddt        t        j
                  |            |z  dz
  z        d||<    |S )Nr
   r   d   r5   g        )
return_pctmae_pct)r=   rJ   rK   rL   rM   min)closesrb   horizonsentryoutputrW   paths          r   forward_metricsr   c   s    &%&E*,FkAokG&;a&?@t9r{{5'9UaZrvvVXVaVabfVgOh),d2h%0G!0K)L '*#seBFF4L6IE6QTU6U/V&WYw	  Mr   g     b@   )rW   
score_bandregion_daysallowed_indicesforbidden_eventsc                  t        j                  | d         }| d   j                  t              ||n|}|D 	ch c]3  }t	        t        |d         t        |d         |z   dz         D ]  }	|	 5 }
}}	t               }g }t        |d       D ]  }t        |d         t        |d         cg }t	        t        |       |z
        D ]w  }|||vr
||
v s||v st        |   z
        |kD  r't        |j                  |   |j                     z
        t        j                  |      kD  rg|j                  |       y |st        |fd	      }|j                  |       |j                  |        |S c c}	}w )
aL  One deterministic, without-replacement control per event.

    Candidates share the event's +/- ``region_days`` calendar region and have
    score within ``score_band`` points. All event action bars and forward
    horizon bars are excluded. Ties choose smallest score distance, then
    nearest timestamp, then earliest index.
    timeactivation_scorerb   r
   c                    t        | d         S Nrb   rf   )rE   s    r   rj   z match_controls.<locals>.<lambda>   s    #eM6J2Kr   rk   rc   )daysc                D    t        |    z
        t        | z
        | fS N)abs)	candidatery   scorerO   s    r   rj   z match_controls.<locals>.<lambda>   s*    #fY>ORW>W:XZ]^gjo^oZpr{9|r   )pdto_datetimeto_numpyr=   rI   rg   rm   sortedrJ   r   iloc	TimedeltarN   r   rn   )frameeventsrW   r   r   r   r   timesri   idx	forbiddenusedselectedrp   r   bestry   r   rO   s                   @@@r   match_controlsr   q   s    NN5=)E%&//6F!1!9v?O"2 g"2!#eM&:";S}AU=VY`=`cd=deS e "2I gUDH$KL5/0%m8L2Mu
s5zG34I*y/OI%d):c&BSV[B[>\_i>i5::i(5::e+<<=R]@^^i( 5 z'|}DOOD!HHTN M O'gs   8Fc                0   t        |       i d}| D cg c]  }t        ||       }}t        D ]K  }|D cg c]  }|j                  |       }}|D cg c]  }||	 }}t	        j
                  |D cg c]  }|d   	 c}t              }	t	        j
                  |D cg c]  }|d   	 c}t              }
t        |	      si nt        |	      t        t	        j                  |	            t        t	        j                  |	            t        dt	        j                  |	dk        z        t        t	        j                  |
            t        t	        j                  |
            d|d   t        |      <   N |S c c}w c c}w c c}w c c}w c c}w )	N)countr   r}   )dtyper~   r|   r   )nmedian_return_pctmean_return_pctnegative_return_pctmedian_mae_pctmax_mae_pctr   )rJ   r   HORIZONSgetrK   arrayr=   medianmeanr   r>   )indicesr   r   ry   metrics_by_indexrW   metricsvaluesrE   returnsmaess              r   
_summarizer      s[   *-g,B GFDKLG56GL86FG6F7'++g&6FG%+AVEu/@%VA((VDVEE,/VDERxxv>vey)v>eL58\2WE"))G:L4Mbghjhohopwhxby#(rwww{/C)C#DX]^`^g^ghl^mXn .H
z3w<(  M MGAD>s"   E?FF	F	5F
!F
c           
     f   t        j                  | d         }t        t        j                  |t        j
                  |      k\  |r|t        j
                  |      k  ndz              D ch c]  t        fdt        D              s  }}|D cg c]  }t        |d         |v s| }}t        | |||      }	| d   j                  t              }
t              t        |D cg c]  }t        |d          c}|
      t        |	|
      t        |	      dS c c}w c c}w c c}w )Nr   Tc              3  ,   K   | ]  }|z   v   y wr    ).0rW   ry   valid_positionss     r   	<genexpr>z _study_window.<locals>.<genexpr>   s     A}t|ip%'/UdBdt|s   rb   )r   r   close)barsr   controlscontrol_count)r   r   rm   rK   flatnonzero	TimestamprM   r   rg   r   r   r=   rJ   r   )r   r   startenddatesry   usable_positionsri   local_eventsr   r   r   s        `     @r   _study_windowr      s#   NN5=)E"..%2<<3F*FknEUWUaUabeUfLftx)yz{O ,;~?%cA}t|A}>}?~'-_veU=5I1JN^1^EvL_ e\CS/57H7^$$U+F(Jgs?tgs^cE-DX@Ygs?tv|4}"8V4s8}V V _ @us   1D$D$D)0D)0D.
c                L   t        j                  t        | |            }|j                  j                  j                         j                  j                         |_        t        j                  |d   d      j                  j                  d       |d<   t        | |      }t        |d<   t        |fi |j                  d      }|d   j                  t              }i }t         D ]   }t#        t%        |||            || d| <   " |j'                         D 	cg c]  }|D ]  }	|	  }
}}	|
j)                  d 	       g }d
}|
D ]6  }	t+        |	d         |kD  s|j-                  |	       t+        |	d         dz   }8 ||d<   | |dddddgdddd|j/                         D ci c]W  \  }}|t1        ||t        t2              t1        ||t4        d       t6        D ci c]  \  }}}|t1        ||||       c}}}dY c}}}}}dS c c}	}w c c}}}w c c}}}}}w )Nr   T)utc_pine_time_start)dropr   /c                    t        | d         S r   rf   rh   s    r   rj   zrun.<locals>.<lambda>   s    U=%9!:r   rk   r5   rb   r   z!combined (union of 2/2, 3/3, 4/4)r[   r\   r]   rY   rZ      r   )first_peak_mindecline_minsecond_to_first_maxconfirmation_spacing_barsdedup_horizon_barscontrol_score_bandcontrol_region_days)ISOOSWFO)r   	timeframedefinitionsstudies)r   read_csvr*   columnsr>   lowerstripr   dttz_localizerG   r   r	   reset_indexr   r=   PIVOT_WIDTHSrz   rV   r   rl   rg   rN   r;   r   r   r   r   )r   r   r&   paramsscoredrO   
all_eventswidthr   ri   unioncombinedlocked_untilnamer   r   r   s                    r   runr      sD   ;;z%,-D<<##))+//557DL>>$v,D9<<HHNDL%$F!,Fd-f-99t9DF&'007F:<J)DEZ[achjoEp)q
eWAeW%&  ",!2!2!4I!4v&U&U!4EI	JJ:J;-/HLu]#$|3OOE"u]34r9L  7?J23scf  @B*+Rbe  B=C
 -7,<,<,>@ -?LD& ]66;PY%Z'4VVYPT'Unw'xnw]j]^`egj}VVUTW/X(Xnw'xz z -?@A A J (y@s   H+9H$H">	HHc                    t        j                  t              } | j                  dd       | j                  dd       | j                  dt        d	       | j                         }t        |j                  |j                  j                               }t        j                  |d
      }t        |       |j                  rE|j                  j                  j                  dd       |j                  j!                  |dz          y)N)descriptionz--assetCOINBASE_BTCUSD)defaultz--tfr#   z--outputz:Write machine-readable JSON (safe outside tracked inputs).)typehelpr   )indentT)parentsexist_ok
r   )argparseArgumentParser__doc__add_argumentr   
parse_argsr   r   r   r(   jsondumpsprintr   parentmkdir
write_text)parserargsrR   texts       r   mainr	     s    $$9F
	+<=
-

4pqDTWW]]_-F::fQ'D	$K{{   =td{+r   __main__)r   r>   r   r>   returnr   )r   r>   r   r>   r  dict[str, object])rO   
np.ndarrayrP   rg   rQ   rg   r  list[tuple[int, int, float]])ro   r  rW   rg   r  list[dict[str, float | int]])r   r  rb   rg   r   ztuple[int, ...]r  zdict[int, dict[str, float]])r   pd.DataFramer   r  rW   rg   r   r=   r   rg   r   zset[int] | Noner   z#list[dict[str, float | int]] | Noner  	list[int])r   r  r   r  r  r  )
r   r  r   r  r   r>   r   z
str | Noner  r  )r   r#   )r  rg   )*r   
__future__r   r   r8   r   syspathlibr   numpyrK   pandasr   __file__resolver  r   r   insertr>   configr   r   r   r   strategies.strategy_mlp_scoresr	   r   r   r   r*   rG   rV   rz   r   r   r   r   r   r	  __name__
SystemExitr   r   r   <module>r     s  
 #  
  
   H~&&-- 3t9  ? ? ;fI
& Y[ < W_  ac',6:KO!$!;>!$3! &I! U^!H V A< z
TV
 r   