o
    îU¹jö  ã                   @   sÖ   d Z ddlZddlZddlZddlZddlmZmZmZ ddl	m
Z
 ej dee
eƒ ¡ jd ƒ¡ ddlmZ e
dƒZe
eƒ d d	 ƒZeƒ d
 d Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedkrieƒ  dS dS )aî  
check_entry_rules.py -- [2026-09-27] Verifies an entry_rules simulation run:
  1. every pick's saved indicator values really clear every threshold
  2. key indicators recomputed independently from Alpaca's official 1-min
     bars (bar RVOL, price vs VWAP, 5-bar change, relative strength vs
     SPY/IWM) agree with what entry_rules saw at the pick
  3. when in the day each stock first passed
Usage: python3 sim/analysis/check_entry_rules.py data/simulations/entry_rules_21d.json [date ...]
é    N)ÚdatetimeÚ	timedeltaÚtimezone)ÚPathé   )Ú
get_configz0/var/www/screener/trade/reports/open_window/barsÚ	simulatorÚ	cache_dirÚentry_rulesÚrulesc                 C   s*  dd„ |   d¡p	i  ¡ D ƒ}dtd  | d d uo | d td kdtd  | d	 d uo2| d	 td kd
td  | d d uoD| d td kdtd  | d d uoV| d td kdt|ƒdkodt|ƒtd kd| d dvi}t  d¡rŒ|   d¡rŒ| d   d¡rŒ| d   d¡du |dtd  < dd„ | ¡ D ƒS )Nc                 S   s   g | ]}|d ur|‘qS ©N© ©Ú.0Úxr   r   ú:/var/www/screener/trade1/sim/analysis/check_entry_rules.pyÚ
<listcomp>   ó    zrule_check.<locals>.<listcomp>Úrel_strength_pctzvas>=%sÚmin_vasÚvaszimbalance>=%sÚmin_imbalanceÚ	imbalancezbar_rvol>=%sÚmin_bar_rvolÚbar_rvolz
spread<=%sÚmax_spread_pctÚ
spread_pctzbeats SPY and IWMr   Úmin_rel_strength_pctznot deceleratingÚ
trend_3bar)ÚDECELERATINGÚINSUFFICIENTÚvolume_rising_barsÚvolume_risingÚbarsÚokTzvolume rising %s barsc                 S   s   g | ]\}}|s|‘qS r   r   )r   Úkr$   r   r   r   r   %   r   )ÚgetÚvaluesÚRÚlenÚminÚitems)ÚindÚrsÚchecksr   r   r   Ú
rule_check   s   $$$$ú"r/   c                 C   s€   t d| › d� }ttdƒsi t_| tjvr)| ¡ r$t t |d¡¡d ni tj| < tj|   	|i ¡ 	d¡}|r>dd„ |D ƒS d S )	NÚbars_z.json.gzÚcÚrtÚsymbolsr#   c                 S   s.   g | ]}t  |d  tj¡g|dd… ¢R ‘qS ©r   é   N)r   Úfromtimestampr   Úutc©r   Úbr   r   r   r   /   s   . zofficial.<locals>.<listcomp>)
ÚBARSÚhasattrÚofficialr1   ÚexistsÚjsonÚloadÚgzipÚopenr&   )ÚdayÚsymÚpÚblr   r   r   r<   (   s   

(r<   c                 C   s8   t |  d|› d� }| ¡ rdd„ t | ¡ ¡D ƒS d S )NÚbench_z.jsonc                 S   s*   g | ]}t  |d  ¡g|dd… ¢R ‘qS r4   )r   Úfromisoformat)r   Úrr   r   r   r   4   s   * zbench.<locals>.<listcomp>)ÚCACHEr=   r>   ÚloadsÚ	read_text)rB   rC   rD   r   r   r   Úbench2   s   $rL   c                    s&  t | |ƒ}|s	d S ‡ fdd„|D ƒ}t|ƒdk rd S dd„ |D ƒ}|dd… }tdd„ |D ƒƒ}|t|ƒ }	|d d	 |d
 d	  d d }
i }dD ],}‡ fdd„t| |ƒpWg D ƒ}t|ƒdkrr|
|d d	 |d
 d	  d d  nd ||< qJ|d t|ƒt|ƒ  ||	 d d |
|d |d dœS )Nc                    ó&   g | ]}|d  t dd� ˆ kr|‘qS ©r   r5   )Úminutes©r   r8   ©Útr   r   r   ;   ó   & zrecompute.<locals>.<listcomp>é   c                 S   s   g | ]}|d  ‘qS )é   r   r8   r   r   r   r   >   s    iëÿÿÿéÿÿÿÿc                 s   s4   � | ]}|d  |d  |d  d |d  V  qdS )r   é   é   rU   Nr   r8   r   r   r   Ú	<genexpr>@   s   €2 zrecompute.<locals>.<genexpr>rX   iúÿÿÿr5   éd   )ÚSPYÚIWMc                    rM   rN   rP   r8   rQ   r   r   r   E   rS   é   r[   r\   ©r   Úprice_vs_vwap_pctÚown_change_5bar_pctÚrs_SPYÚrs_IWM)r<   r)   ÚsumrL   )rB   rC   rR   ÚpricerE   ÚdoneÚvÚbaseÚpvÚvwapÚownr-   ÚbsymÚbbr   rQ   r   Ú	recompute7   s$   
 :$ÿrm   c                     sÞ  t  ttjd ƒ¡} tjdd … pt| d ƒ}g dd„ dD ƒd}}}g }|D ]�}| d  |i ¡ dg ¡D ]€}|d7 }|d	 d
 }t|ƒ}	|	rR| ||d |	f¡ t	 
|d ¡}
| |
|
jddddd�  ¡ d ¡ t||d |
|d ƒ}|r¶|d |d |d |d p†i  d¡|d pŽi  d¡dœ}|D ]‰ |ˆ  d urµ|ˆ  d urµ|ˆ   |ˆ  |ˆ  ||d f¡ q–q6q(t|› dt|ƒ› d�ƒ td|t|ƒ › d|› d�ƒ |d d… D ]}td|ƒ qÙtdƒ | ¡ D ]D\‰ }|sðqéd d!„ |D ƒ}d"d!„ |D ƒ}t‡ fd#d$„ˆ dk�r|n|D ƒƒ}td%ˆ d&›d't|ƒd(›d)t |¡d*›d+|› d,t|ƒ› �
ƒ qét|d d-d.„ d/�d d0… }td1d2d!„ |D ƒƒ td3ƒ t|ƒ}d4D ]‰td5ˆd6›d7t‡fd8d$„|D ƒƒ› d,t|ƒ› �ƒ �qPd S )9Nr5   r   Údaysc                 S   s   i | ]}|g “qS r   r   )r   r%   r   r   r   Ú
<dictcomp>N   s    zmain.<locals>.<dictcomp>r^   r   ÚtradesÚplanÚ
indicatorsÚsymbolÚ
entry_timeé   é   )ÚhourÚminuteÚsecondÚmicrosecondé<   Úentry_pricer   r_   r`   r   r[   r\   z picks checked over z day(s)
z1. Threshold check: z of z picks clear all six rulesé   z	   FAILS:zG
2. entry_rules value vs independent recompute from official 1-min barsc                 S   s   g | ]^}}}t || ƒ‘qS r   )Úabs©r   Úar9   Ú_r   r   r   r   i   s    zmain.<locals>.<listcomp>c                 S   s,   g | ]^}}}t || ƒtt |ƒd ƒ ‘qS )ç•Ö&è.>©r~   Úmaxr   r   r   r   r   j   ó   , c                 3   s(   � | ]}ˆ d kr|dkn|dkV  qdS )r   g      Ð?g      à?Nr   r   )r%   r   r   rY   k   s   €& zmain.<locals>.<genexpr>z   Ú20z n=Ú4z  median gap z.3fz  close agreement ú/c                 S   s$   t | d | d  ƒ t| d dƒ S )Nr   r5   r‚   rƒ   )r   r   r   r   Ú<lambda>m   s   $ zmain.<locals>.<lambda>)ÚkeyrU   z3   biggest bar_rvol gaps (entry_rules vs official):c                 S   s,   g | ]\}}}}||t |d ƒt |d ƒf‘qS )r   )Úround)r   r€   r9   ÚdÚsr   r   r   r   n   r…   z2
3. When stocks first passed (minutes after 9:30):)é
   é   rv   r{   éx   i†  z   by Ú3z min: c                 3   s   � | ]}|ˆ kV  qd S r   r   r   )Úlimr   r   rY   r   s   € )r>   r?   rA   ÚsysÚargvÚsortedr&   r/   Úappendr   rG   ÚreplaceÚtotal_secondsrm   Úprintr)   r+   rc   ÚstÚmedian)Úresrn   ÚbadÚdiffsÚnÚ
first_passrB   rR   r,   ÚfailsÚetÚrcÚminer9   rf   rŒ   ÚrelÚagreeÚworstÚfpr   )r%   r’   r   ÚmainK   sV   $ þ"€ñ$<6ÿr©   Ú__main__)Ú__doc__r@   r>   Ú
statisticsrš   r“   r   r   r   Úpathlibr   ÚpathÚinsertÚstrÚ__file__ÚresolveÚparentsÚconfig_loaderr   r:   rI   r(   r/   r<   rL   rm   r©   Ú__name__r   r   r   r   Ú<module>   s(    	 
*
ÿ