o
    yÀj37  ã                   @   s  d Z ddlmZmZ ddlmZ ddlZddlmZ edƒZi dd“d	d
“dd“dd“dd“dd“dd“dd“dd
“dd“dd“dd“dd“dd“d d“d!d"“d#d“d$dddd%d&d
dddd'œ
¥Z	d(e
fd)d*„Zd+d,„ Zd:d.d/„Z	d;d0ed1ed2ed3ed4ed5ed6ed7ed(efd8d9„ZdS )<ar  
entry_v2.py -- [2026-09-28] The user's entry rules v2 (dictated 9/28 evening), a
switchable alternative to setup J's smart_engine (config smart_engine.entry_mode:
"j" = smart_engine as before, "v2" = this). Exits are unchanged (J's).

Checked every poll, in the user's order (all must pass):
  0. timing      >= min_bars finished 1-min bars today (15 -> no buys before ~9:45)
  1. volume      RVOL so far (today's volume / 14-day average volume by this same
                 minute) >= min_rvol; and the last 15 minutes' volume is not a spike
                 (<= max_vol15_x its 14-day normal for those minutes)
  2. resistance  room to the nearest 14-day resistance band >= min_room_pct, or price
                 is above the 14-day high (breakout)
  3. buy vs sell buy share = buy / (buy + sell) over the last 15 minutes >= min_buy_share;
                 and not "falling on net selling" (price down >= 1% in 30 min with
                 net selling)
  4. steady rise 15-bar smoothness (R^2 of closes, rising) >= min_r2 and straightness
                 (net move / path, 15 bars) >= min_eff
  spread         bid/ask spread <= max_spread_pct of the mid (as setup J; no quote -> passes)
  position       price above VWAP but no more than max_vwap_pct above it
  don't buy      5-bar acceleration >= max_acc5 x 1-min ATR (spike), or stretched:
                 move from the open >= stretch_move_x its 14-day normal AND >= 4% over VWAP
  confirm        all of the above on `confirm_checks` polls in a row (~15 s)
Stop: under the nearest 14-day support band (its low - 1c), at least min_stop_pct
below the price and at most max_stop_pct; otherwise min_stop_pct.

The 14-day reference comes from reference.py (data/reference/<date>/<SYM>.json).
Returns smart_engine.SmartEngineDecision so monitor.py / simulate.py handle it
exactly like setup J's decisions (metrics["stage3"]["stop"], metrics["price"]).
é    )ÚdatetimeÚtimezone)ÚZoneInfoN)ÚSmartEngineDecisionzAmerica/New_YorkÚmin_barsé   Úmin_rvolg      ø?Úmax_vol15_xg      @Úmin_room_pctg      ð?Úmin_buy_sharegš™™™™™á?Úmin_r2gffffffæ?Úmin_effç      à?Úmax_vwap_pctg       @Úmax_acc5Ústretch_move_xg      @Ústretch_vwap_pctg      @Úconfirm_checksé   Úmin_stop_pctÚmax_stop_pctÚmax_spread_pctÚday_high_ceilingFÚday_high_min_ageg333333Ó?é   é   )
Úday_high_tol_pctÚday_high_min_roomÚmax_range_posÚmax_above_open_pctÚbreakout_confirm_barsÚbreakout_recent_minÚbreakout_max_above_pctÚbreakout_level_ageÚblock_climax_volxÚblock_climax_barsÚreturnc                 C   s"   |   t¡}|jd d |j d S )Né	   é<   r   )Ú
astimezoneÚETÚhourÚminute)ÚtsÚt© r/   ú#/var/www/screener/trade/entry_v2.pyÚ_minute_indexU   s   
r1   c                    sþ   t ˆ ƒ}|d d tˆ ƒ| ‰‰t‡fdd„t|ƒD ƒƒ}t‡‡fdd„tˆ ƒD ƒƒ| ‰t‡fdd„ˆ D ƒƒ}|rNdt‡‡‡fdd„tˆ ƒD ƒƒ|  nd}‡ fd	d
„t|d ƒD ƒ}tdd„ |D ƒƒ}|ˆdkrmdnd |r|ˆ d ˆ d  | fS dfS )Né   r   c                 3   ó   � | ]	}|ˆ  d  V  qdS ©r   Nr/   )Ú.0Úk)Úxmr/   r0   Ú	<genexpr>]   ó   € z_r2_eff.<locals>.<genexpr>c                 3   s$   � | ]\}}|ˆ  |ˆ  V  qd S ©Nr/   ©r5   r6   Úy)r7   Úymr/   r0   r8   ^   s   €" c                 3   r3   r4   r/   )r5   r<   )r=   r/   r0   r8   _   r9   c                 3   s,   � | ]\}}|ˆˆ |ˆ    d  V  qdS r4   r/   r;   )Úsloper7   r=   r/   r0   r8   `   s   €* g        c                    ó    g | ]}ˆ |d   ˆ |  ‘qS ©r2   r/   ©r5   Úi)Úclosesr/   r0   Ú
<listcomp>a   ó     z_r2_eff.<locals>.<listcomp>c                 s   s   � | ]}t |ƒV  qd S r:   )Úabs)r5   Úsr/   r/   r0   r8   b   ó   € r   éÿÿÿÿ)ÚlenÚsumÚrangeÚ	enumerate)rC   ÚnÚsxxÚsstÚr2ÚstepsÚpathr/   )rC   r>   r7   r=   r0   Ú_r2_effZ   s    .2rT   é   c                 C   sx   d }t | | dd … ƒD ].\}}t|d |d  t|d |d  ƒt|d |d  ƒƒ}|d u r1|n||| |  }q|S )Nr2   ÚhÚlÚc)ÚzipÚmaxrF   )ÚbarsÚperiodÚaÚpÚbÚtrr/   r/   r0   Ú_atrf   s
   8ra   Úsymbolr[   ÚrefÚflow15ÚpersistenceÚas_ofÚcfgÚquotec           @         s  i t ¥|pi ¥}|pt tj¡}	t| d�}
g g }}|r"|d d nd}|ddœ}||
_i |
_|dd… }|du sAt|ƒ|d k rTd|
_	t|ƒ› d	|d › d
�g|
_
|
S ˆs_d|
_	dg|
_
|
S ttt|d d ƒdƒdƒ}|d d }tdd„ |D ƒƒ}tdd„ |D ƒƒ}|r‹|| n|}|| d d }|jt|dƒt|dƒd� |tˆd | dƒ }|dd… }t‡fdd„|D ƒƒ}|rËtdd„ |D ƒƒ| nd}|j||ˆd | t|ƒt|dƒ|duræt|dƒndd� ||d k rÿ| d|d›d |d › d!�¡ |du�r||d" k�r| d#|d$›d%|d" › d!�¡ ˆ d&¡�r,t ˆ d&¡�p)i |¡ni }| d'¡}t| d(¡ƒ}||d&< |�sf|du�rf||d) k �rf| d*|d›d+|d, d- d›d.|d, d/ › d0�¡ td1d„ |D ƒƒ‰td2d„ |D ƒƒ}td3ˆ|d4  d ƒ‰t‡‡fd5d„|D ƒƒ}|d d |  ¡ d6 d }ˆ| d d } ˆ|k�r²|| ˆ|  nd}!|jˆt|ƒt| dƒ|!du�rÈt|!dƒndd7� |d8 du�r×|d8 n|d) }"|d9 �r||d: k�rd|   k�ró|"k �rn n| d*| d›d;ˆd›d.|d<›d=�¡ |d> du�r.|!du�r.|!|d> k�r.| d?|!d d<›d@|d> d d<›dA�¡ |\}#}$|#|$ �r=|#|#|$  nd}%t|ƒdBk�rR||dC d  d d nd}&|j|#|$|%du�rbt|%dƒnd|&du�rmt|&dƒnddD� |%du �s}|%|dE k �r™| dF|%du �r‡|%nt|%d ƒ› dG|dE d d<›dA�¡ |&du�r²|&dk�r²|%du�r²|%dHk �r²| dI¡ tdJdK„ |dd… D ƒƒ\}'}(|jt|'dƒt|(dƒdL� |'|dM k �rã| dN|'d›dO|dM › �¡ |(|dP k �rø| dQ|(d›dO|dP › �¡ || d d })t|)dƒ|dR< |dS du�rÐ|)|dS k�rÐt|dT ƒt|dU ƒ}*}+t|dV ƒ},g }-ˆ dW¡�r9|- dXˆdW f¡ t|ƒ|,k�rW|- dY|,› dZ�td[d„ |d|, … D ƒƒf¡ d}.|-D ]O\}/‰ ||* d… }0t|ƒ|*k�ru||+ |* … ng }1t|0ƒ|*k�r©t‡ fd\d„|0D ƒƒ�r©t‡ fd]d„|1D ƒƒ�r©|ˆ d|d^ d   k�r©|/ˆ f}. n�q[|.�rº|.d t|.d dƒd_œnd|d`< |.�sÐ| da|)db›dc|dS › dd�¡ |de �rNt|df ƒ}2ttdt|ƒ|2 ƒt|ƒƒD ]d}3||3 }4t|4d ƒ}5d|5  k�rdgk �rLn �qé|4dh tˆdi |5 dƒ |de k�rL|4dj tdkd„ |d|3… D ƒƒk�rL| dl|4dh tˆdi |5 dƒ d<›dm|4dj d›d.t|4d ƒ› dn�¡  n�qé|�rª| do¡�rª| dp¡�rª|dp |do   k�rmdk�rªn n;|do |dp  dq }6|dp |do  |6 d }7|j|do |dp t|7dƒdr� |7|ds k�rª| dt|7d›du|ds › dA�¡ d|  k�r¸|dv k�sÈn | dw|dx›dy|dv › dz�¡ t|dCd… ƒ}8d{dK„ |d|d… D ƒ‰|8�rtˆƒd}k�r‡fd~dK„tdƒD ƒ}9t|9dqd… ƒd t|9ddq… ƒdq  |8 }:t|:dƒ|d€< |:|d� k�r| d‚|:d›dƒ�¡ || d d tˆd„ | d…ƒ };|jt|;dƒ|ˆd„ | d†� |;|d‡ k�rZ||dˆ k�rZ| d‰|;d$›dŠ|db›d‹�¡ |d|dŒ d   }<| d�¡}=|=�rŠ|=d- dŽ }>|d|d� d   |>  k�r†|<k�rŠn n|>}<d�t|<dƒi|d‘< |�ržd’|
_	||
_
|
S |�p¢i  d“d¡d }?d“|?i|
_d”|d$›d•|�r¸d–n|du�rÃ|d$›dA�nd—› d˜|%d d<›d™|'d›dš|(d›d›|db›dœ|<d›�g}||
_|?|d� k �rùd|
_	dž|?› dŸ|d� › �g|
_
|
S d |
_	d¡|
_|
S )¢z¥bars: today's 1-min bars incl. the forming one ({"t","o","h","l","c","v"});
    ref: reference.load(...) for today; flow15: (buy_vol, sell_vol) over the last 15 min.)rb   rI   rX   NÚv2)ÚpriceÚ
entry_moder   ÚWAITz of z barszno 14-day reference filer.   r   é…  Úoc                 s   s4   � | ]}|d  |d  |d  d |d  V  qdS )rV   rW   rX   r   ÚvNr/   ©r5   r_   r/   r/   r0   r8   …   s   €2 zevaluate.<locals>.<genexpr>c                 s   ó   � | ]}|d  V  qdS ©ro   Nr/   rp   r/   r/   r0   r8   †   rH   r2   éd   é   r   )ÚvwapÚvwap_pctÚcum_voliñÿÿÿc                 3   s0   � | ]}ˆ d  t tt|d ƒdƒdƒ V  qdS )Úvol_per_minr.   r   rm   N)ÚminrZ   r1   rp   )rc   r/   r0   r8   Ž   s   €. c                 s   rq   rr   r/   rp   r/   r/   r0   r8   �   rH   )r,   Ú	vol_todayÚref_cum_volÚ	ref_vol15Ú
rvol_sofarÚvol15_xr   z1 volume: RVOL so far z.2fzx < Úxr	   z1 volume: last-15-min spike z.1fzx > Úsr14Údist_to_resistance_pctÚabove_14d_highr
   z2 resistance: only z% to Ú
resistanceÚloz (Útouchesz	 touches)c                 s   rq   ©rV   Nr/   rp   r/   r/   r0   r8   ¡   rH   c                 s   rq   )rW   Nr/   rp   r/   r/   r0   r8   ¢   rH   g{®Gáz”?r   c                 3   s(   � | ]}|d  ˆ ˆ kr|d V  qdS )rV   r.   Nr/   rp   )Úday_hiÚtolr/   r0   r8   ¤   s   €& r(   )Úday_highÚday_high_age_minÚroom_day_high_pctÚ	range_posr   r   r   z% to today's high z.0fz	 min old)r   z2 resistance: z% of today's range > ú%r   iâÿÿÿ)Ú	buy_vol15Ú
sell_vol15Úbuy_share15Úret30r   z3 buy/sell: buy share z% < r   z"3 buy/sell: falling on net sellingc                 S   ó   g | ]}|d  ‘qS ©rX   r/   rp   r/   r/   r0   rD   ¼   ó    zevaluate.<locals>.<listcomp>)Úr2_15Úeff15r   z4 steady rise: smoothness z < r   z4 steady rise: straightness Úext_open_pctr   r    r!   r#   Ú	prev_highzyesterday's highztoday's high z	+ min agoc                 s   rq   r†   r/   rp   r/   r/   r0   r8   Í   rH   c                 3   s   � | ]	}|d  ˆ kV  qdS ©rX   Nr/   rp   ©ÚLr/   r0   r8   Ò   r9   c                 3   s   � | ]	}|d  ˆ kV  qdS r™   r/   rp   rš   r/   r0   r8   Ó   r9   r"   )Úlevelrj   Úbreakoutz
extended: z+.1fz% over the open (max z% unless a confirmed breakout)r$   r%   i†  ro   rx   rV   c                 s   rq   r†   r/   )r5   r   r/   r/   r0   r8   ã   rH   zB1: zx volume bar at the day's high z min) -- no buy into a climaxÚbidÚaskr   )rž   rŸ   Ú
spread_pctr   zspread: z% > r   zVWAP: z+.2fz% (needs 0 to +z%)c                 S   r’   r“   r/   rp   r/   r/   r0   rD   ö   r”   iúÿÿÿé   c                    r?   r@   r/   rA   )Úcsr/   r0   rD   ø   rE   é   Úacc5r   zwarning: acceleration spike z ATRÚabs_move_pctgš™™™™™©?)Úmove_xÚday_openÚref_abs_move_pctr   r   zwarning: stretched (zx normal move, z% over VWAP)r   Úsupportg{®Gáz„?r   ÚstopÚstage3ÚREJECTÚokz	v2: RVOL zx, room zabove 14d highzn/az, buy share z%, smoothness z, straightness z, VWAP z%, stop r   zconfirming ú/ÚBUYT) ÚDEFAULTSr   Únowr   Úutcr   Úmetricsre   rJ   ÚstateÚreasons_againstry   rZ   r1   rK   ÚupdateÚroundÚappendÚgetÚ
volatilityÚsr_positionÚboolÚnextÚtotal_secondsrT   ÚintÚallÚanyrL   ra   Úreasons_forÚshould_enter)@rb   r[   rc   rd   re   rf   rg   rh   rX   r±   ÚdÚagainstÚfor_rj   ÚmÚdoneÚmir§   ÚpvÚvolru   rv   ÚrvolÚlast15Únorm15r~   ÚspÚroomÚ
above_highÚday_loÚfirst_touchÚhi_ageÚroom_dayrŒ   Úneed_dayÚbvÚsvÚsharer‘   rQ   ÚeffÚext_openÚn_cÚrecÚageÚlevelsÚ	confirmedÚnameÚlast_nÚwindowÚnbr6   r_   ÚmkÚmidr    ÚatrrR   r¤   r¦   rª   ÚsupÚcandrN   r/   )r›   r¢   r‡   rc   rˆ   r0   Úevaluaten   sH  


ÿ(


ÿÿ4$&(*ÿ8(
."&ÿ€&
 B$$ÿ

ÿ€B,"
,
0ÿÿÿÿÿrê   )rU   )NNN)Ú__doc__r   r   Úzoneinfor   rº   Úsmart_enginer   r*   r°   r¿   r1   rT   ra   ÚstrÚlistÚdictÚtuplerê   r/   r/   r/   r0   Ú<module>   s‚    ÿþýüûúùø	÷
öõôóòñêéÕ/
	ÿÿÿÿÿ