o
    ©¹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 ej 	dej 
ej e¡¡¡ ddlmZ dZdd„ Zdd	d
„Zdd„ Zdd„ Zdd„ Zdd„ ZedkrSeƒ  dS dS )a„  
first_reversal.py -- [2026-09-27] At the FIRST REVERSAL after a pick went
positive, do the eventual winners and losers look different?

First reversal = the first finished 1-min bar (after the buy, after price
has been above the buy price) that CLOSES at least 1 x 1-min ATR(14) below
the highest price since the buy. Measured at the end of that bar.
Winner / loser = price at 15:55 above / below the buy price.
Uses Alpaca's official 1-min bars (bars1m_*, bench_*) and the tick cache
(buy pressure, Lee-Ready: trade at/above ask = buy, at/below bid = sell).
Usage: python3 sim/analysis/first_reversal.py data/simulations/entry_rules_21d.json
é    N)ÚdatetimeÚ	timedelta)Úaucz./var/www/screener/trade/data/simulations/cachec              
   C   s*   dd„ t  tt› d| › d|› d�ƒ¡D ƒS )Nc              	   S   s<   g | ]}t  |d  ¡|d |d |d |d |d dœ‘qS )r   é   é   é   é   é   )ÚtÚoÚhÚlÚcÚv)r   Úfromisoformat)Ú.0Úr© r   ú7/var/www/screener/trade1/sim/analysis/first_reversal.pyÚ
<listcomp>   s    4ÿzload_bars.<locals>.<listcomp>ú/ú.json)ÚjsonÚloadÚopenÚCACHE)ÚdayÚnamer   r   r   Ú	load_bars   s   ÿr   é   c                 C   sx   d }t | | dd … ƒD ].\}}t|d |d  t|d |d  ƒt|d |d  ƒƒ}|d u r1|n||| |  }q|S )Nr   r   r   r   )ÚzipÚmaxÚabs)ÚbarsÚnÚaÚpÚbÚtrr   r   r   Úatr   s
   8r)   c                 C   s"   |   |¡ |r|  ¡  |  ¡ }|S ©N)ÚseekÚreadline)ÚfÚoffÚliner   r   r   Ú_line_at&   s
   
r0   c                 C   s  t j | ¡}t| dƒ�s}d|}}|tdd�  ¡  ¡ }|| dkrF|| d }t||ƒ}	|	r;|	ddt|ƒ … |kr>|}n|}|| dks"| 	|¡ |rQ| 
¡  g }
|D ]}	t |	¡\}}}}t |¡}||krk n
|
 ||||f¡ qU|
W  d  ƒ S 1 s�w   Y  dS )zJTrades+quotes in [t0 - 5 s, t1] via binary search on the time-sorted file.Úrbr   r	   ©Úsecondsi   r   N)ÚosÚpathÚgetsizer   r   Ú	isoformatÚencoder0   Úlenr+   r,   r   Úloadsr   r   Úappend)r5   Út0Út1Úsizer-   ÚloÚhiÚtargetÚmidr/   ÚoutÚtsÚkindr%   r'   r
   r   r   r   Úticks_between.   s.   

ú

$ìrF   c                 C   s¾   d\}}}| D ]I\}}}}	|dkr||	f}q||t |d� krP|rP|\}
}||kr.||	7 }q||
kr7||	7 }q||
| d krD||	7 }q||
| d k rP||	7 }q|| r]|| ||  S d S )N)Nç        rG   Úquoter2   r   ©r   )Úevr=   ÚsecsÚqÚbuyÚsellr
   rE   r%   r'   ÚbidÚaskr   r   r   Ú	imbalanceH   s    




€rQ   c            .         s4  t  ttjd ƒ¡} g d}}t| d  ¡ ƒD �]o\‰}‡fdd„dD ƒ}|d D �]S}|d |d	 }}t |d
 ¡}t	ˆd|› �ƒ}	|j
ddddd�}
|j
ddd�tdd� ‰|dd }}}t|	ƒD ]D\}}|d ˆk sz|d tdd� |
kr{qet||d ƒ}|p‰|d |k}t|	td|d ƒ|d … ƒ}|r©|r©|d || kr©|} nqe|d u r³|d7 }q)|	| }|d tdd� ‰ |	d |d … }dd„ |D ƒ}tdd„ |D ƒƒt|ƒ }‡fdd„|D ƒ}tdd„ |D ƒƒ}tdd„ |D ƒƒ}t|dd … ƒ}t|ƒdk�r|d d |d  d  d d! nd }g }| ¡ D ]/\}}‡ fd"d„|D ƒ}t|ƒdk�rL|d u�rL| ||d d |d  d  d d!  ¡ �q‡ fd#d„|d$ D ƒ}tt› d%ˆ› d%|› d&�ˆ td'd(� ˆ ƒ}i d)|| d d! “d*ˆ |  ¡ d' “d+|d | d d! “d,|�r—||d  | nd “d-|d | d d! “d.||d/ k�rº|d |d/  ||d/   nd “d0|d | d d! “d1|d |	d d2  d d! “d3|d td4d„ |D ƒƒ d d! “d5t|ƒd6k�r|d t|d7d… ƒt|d7d… ƒ  nd “d8|�r|| nd “d9t|ƒdk�r1t|d d:… ƒ�r1t|d:d … ƒt|d d:… ƒ nd “d;|�r?||d  d! nd “d<|�rIt|ƒnd “d=|�r_|d d |d d2  d d! nd “d>t|ˆ dƒ“d?t|ˆ d'ƒ“}| ˆ||d@ dk|f¡ q)tˆdAtjdBdC� qdDd„ |D ƒ}dEd„ |D ƒ} tt|ƒ› dFt|ƒ› dGt| ƒ› dH|› dI�ƒ tdJdK„ |D ƒƒ}!t|!d t|!ƒdL … ƒ‰tdMdN›dOdP›dQdR›dSdT›dUdV›dWdV›�ƒ g }"|d dX D ]^‰‡fdYd„|D ƒ}‡fdZd„| D ƒ}‡‡fd[d„|D ƒ}#‡‡fd\d„|D ƒ}$‡‡fd]d„|D ƒ}%‡‡fd^d„|D ƒ}&t||ƒ}'|" t|'d_ ƒˆt |¡t |¡|'t|#|$ƒt|%|&ƒf¡ �qßt|"dBd`�D ]A\}(‰})}*}'}+},|+d_ |,d_  dk�rjtt|+d_ ƒt|,d_ ƒƒdak�rjdbndc}-tˆdN›|)dd›|*de›|'df›|+dg›|,dg›|-› �ƒ �qDt j|ttjd  
dhdi¡djƒtdk� d S )lNr   r   Údaysc                    s   i | ]}|t ˆ d |› �ƒ“qS )Úbench_)r   )r   Ús)r   r   r   Ú
<dictcomp>^   s    zmain.<locals>.<dictcomp>)ÚSPYÚIWMÚtradesÚsymbolÚentry_priceÚ
entry_timeÚbars1m_é   é7   )ÚhourÚminuteÚsecondÚmicrosecond)ra   rb   ©ÚminutesFr
   r   é   r   c                 S   s   g | ]}|d  ‘qS )r   r   ©r   Úzr   r   r   r   u   ó    zmain.<locals>.<listcomp>c                 s   s4   � | ]}|d  |d  |d  d |d  V  qdS )r   r   r   r   r   Nr   rf   r   r   r   Ú	<genexpr>v   s   €2 zmain.<locals>.<genexpr>c                    s   g | ]
}|d  ˆ kr|‘qS )r
   r   rf   )Ú
first_fullr   r   r   w   ó    c                 s   s(   � | ]}|d  |d kr|d V  qdS ©r   r   r   Nr   rf   r   r   r   ri   x   ó   €& c                 s   s(   � | ]}|d  |d k r|d V  qdS rl   r   rf   r   r   r   ri   y   rm   iáÿÿÿé   éÿÿÿÿiúÿÿÿéd   c                    ó&   g | ]}|d  t dd� ˆ kr|‘qS ©r
   r   rc   rI   rf   ©ÚTr   r   r   ~   ó   & c                    rq   rr   rI   rf   rs   r   r   r   �   ru   rW   r   z.jsonlé<   r2   Ú
run_up_pctÚminutes_since_buyÚpullback_from_high_pctÚpullback_in_atrÚprice_vs_buy_pctÚprice_vs_stop_RÚ
stop_priceÚvs_vwap_pctÚvs_open_pctr   Úvs_day_high_pctc                 s   s   � | ]}|d  V  qdS )r   Nr   rf   r   r   r   ri   Œ   s   € Úreversal_bar_vol_x_avgr	   iëÿÿÿÚdown_vol_vs_up_vol_since_buyÚvol_last3_vs_prev3éýÿÿÿÚ
atr_1m_pctÚrel_strength_min_5barÚiwm_from_open_pctÚbuy_pressure_30sÚbuy_pressure_60sÚ
pl_dollarsÚdoneT)ÚfileÚflushc                 S   s   g | ]
�^ }}}|r|‘qS r   r   ©r   Ú_Úokr-   r   r   r   r   ˜   rk   c                 S   s   g | ]
�^ }}}|s|‘qS r   r   rŽ   r   r   r   r   ™   rk   z picks had a first reversal (z ended up, z ended down); z never did
c                 S   s   h | ]^}}|’qS r   r   )r   Údr�   r   r   r   Ú	<setcomp>›   rh   zmain.<locals>.<setcomp>r   zat the first reversalÚ32zended upz>10z
ended downz>11ÚAUCz>6z1st halfz>9z2nd halfr   c                    ó    g | ]}|ˆ  d ur|ˆ  ‘qS r*   r   ©r   r-   ©Úkr   r   r       ó     c                    r•   r*   r   r–   r—   r   r   r   ¡   r™   c                    s4   g | ]\}}}}|r|ˆ v r|ˆ d ur|ˆ ‘qS r*   r   ©r   r‘   rT   r�   r-   ©Úh1r˜   r   r   r   ¢   ó   4 c                    s4   g | ]\}}}}|s|ˆ v r|ˆ d ur|ˆ ‘qS r*   r   rš   r›   r   r   r   £   r�   c                    s4   g | ]\}}}}|r|ˆ vr|ˆ d ur|ˆ ‘qS r*   r   rš   r›   r   r   r   ¤   r�   c                    s4   g | ]\}}}}|s|ˆ vr|ˆ d ur|ˆ ‘qS r*   r   rš   r›   r   r   r   ¥   r�   g      à?)Úreversegš™™™™™©?z  <- consistentÚ z10.3fz11.3fz6.2fz9.2fr   z_first_reversal.jsonÚw)Údefault) r   r   r   ÚsysÚargvÚsortedÚitemsr   r   r   Úreplacer   Ú	enumerater!   r)   Úsumr9   r;   rF   r   Útotal_secondsÚminrQ   ÚprintÚstderrÚsetr   r"   ÚstÚmedianÚdumpÚstr).ÚresÚrowsÚneverÚxÚbenchr(   ÚsymÚeÚetr#   Úeodr@   Úwent_upÚrevÚir'   r%   r‹   r   ÚvwapÚsinceÚupvÚdnvÚown5ÚrsrT   ÚblÚbbÚiwmrJ   r-   ÚWÚLrR   rC   Úa1Úb1Úa2Úb2ÚAr�   ÚmaÚmbÚA1ÚA2Úflagr   )rt   r   rj   rœ   r˜   r   ÚmainZ   sÆ   
"€2*€(ÿþýüû.úùø"	÷:
öõDôóò*ñðï,,
<>4(rÓ   Ú__main__)r   )Ú__doc__r   r4   Ú
statisticsr®   r¢   r   r   r5   ÚinsertÚdirnameÚabspathÚ__file__Ú
separationr   r   r   r)   r0   rF   rQ   rÓ   Ú__name__r   r   r   r   Ú<module>   s$    
T
ÿ