o
    ª»j  ã                   @   s\  d Z ddlZddlZddlmZ ddlZe d¡ ddlmZ ddl	m
Z ej dd¡ ej dd¡ ddlZddlZdZdd„ ZdBd
d„Zdd„ Zedk�r*ejd Zejdd… D ]ÐZeeeƒ\ZZeeeeeƒ ed d Zede› ded›ded›dee d d d›d�	ƒ dD ]AZeeeƒD ]9Zede ¡ d›ded › d ed d›d!ed" d›d#ed$ d%›d&e  d'¡p»dd%›d(ed) d›d*ed+ d›d,�ƒ q”q�d-d.„ eD ƒZ!d/d.„ eD ƒZ"d0d1„ Z#ed2e$e!ƒ› dd3 %e&d4d5„ e!D ƒƒ¡› d6e#e!d+ƒd7›d8e#e"d+ƒd7›d9�	ƒ ed:e'd;d<„ eD ƒƒd%›d=e'd>d<„ eD ƒƒd%›d?ed d@ d%›dA�ƒ q[dS dS )Ca¨  
speed_check.py -- [2026-09-28] Speed / shape measures (after the AGEN check) on any
stock-day, with three signals fixed BEFORE looking at new stocks:

  TURN   (entry)   15-bar acceleration >= 0.5 ATR, straightness >= 0.6, 15-bar R^2 >= 0.7,
                   15-min volume >= 2x its 14-day normal, price above VWAP but <= 2% above
  SMOOTH (hold)    30-bar R^2 >= 0.8 (steady climb)
  CLIMAX (avoid)   5-bar acceleration >= 1.5 ATR, 15-min volume >= 5x normal,
                   >= 4% above VWAP, move from the open >= 3x its normal

For each signal: what price did afterwards (best in the next 60 min, and to the close).
    python3 speed_check.py 2026-09-28 TGB IMMX NWL SG
é    N)ÚdatetimeÚAggz/var/www/screener/tradez$/var/www/screener/trade/reports/agenc                    s¬  t  | |¡‰ˆd u r't jt | ¡ ¡ |gdd� t j | |fd ¡ t  | |¡‰dd„ t 	|| ¡D ƒd d… }dd„ |D ƒ‰dd„ |D ƒ}dd„ |D ƒ}d	d„ |D ƒ‰d
d„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ‰t
|d d ƒ}d gt|ƒ d ‰ }tdt|ƒƒD ]4}	t||	 ||	  t||	 ˆ|	d   ƒt||	 ˆ|	d   ƒƒ}
|d u r¨|
n||
| d  }|ˆ |	< q€‡ ‡‡‡‡fdd„}g }tt|ƒƒD �]	}	tˆ|	 dƒ}||	 ˆ|	 ||	 ˆ|	 ||	  d d tˆ|	 | d ƒd tˆd | dƒ tˆd |	d … ƒtˆd | dƒ dœ}dD ]‰||	ˆƒ}|�r(| ‡fdd„| ¡ D ƒ¡ �qˆ|	d |	d … }|�rCt|ƒˆ|	  d d nd |d< ˆd ˆ|	  d d |d< t| d ¡d u�o‹|d  d!k�o‹|d" d#k�o‹|d$ d%k�o‹|d& �pydd'k�o‹d|d(   k�o‰d'kn  ƒ|d)< t| d*¡d u�o�|d* d+kƒ|d,< t| d-¡d u�oÈ|d- d.k�oÈ| d&¡�p¸dd/k�oÈ|d( d0k�oÈ|d1 d2kƒ|d3< | |¡ qÇ||fS )4NF)Úverbosec                 S   s   g | ]
}|d  dkr|‘qS )ÚsessionÚreg© ©Ú.0Úrr   r   ú5/var/www/screener/trade/reports/agen/./speed_check.pyÚ
<listcomp>%   ó    zmeasures.<locals>.<listcomp>é†  c                 S   ó   g | ]}t |d  ƒ‘qS )Úclose©Úfloatr   r   r   r   r   &   ó    c                 S   r   )Úhighr   r   r   r   r   r   '   r   c                 S   r   )Úlowr   r   r   r   r   r   (   r   c                 S   r   )Úvolumer   r   r   r   r   r   )   r   c                 S   r   )Úvwap_regularr   r   r   r   r   r   *   r   c                 S   s   g | ]}|d  ‘qS )Útime_etr   r   r   r   r   r   +   s    c                 S   s8   g | ]}t |d d… ƒd d t |dd … ƒ d ‘qS )Né   é	   é<   é   é   )Úint©r	   Úxr   r   r   r   ,   s   8 r   Úopené   é   c                    sÂ  | |k sˆ|  s
d S ˆ| | | d … ‰ ‡ fdd„t |ƒD ƒ}ˆ d ˆ d  tdd„ |D ƒƒ}}|d tˆ ƒtˆ ƒ ‰‰t‡fd	d„t tˆ ƒƒD ƒƒ}t‡‡fd
d„tˆ ƒD ƒƒ| ‰t‡fdd„ˆ D ƒƒ}t‡‡‡fdd„tˆ ƒD ƒƒ}|rd||  ndˆdkr†dnd }|d }	t||	d … ƒt||	d … ƒ t|d |	… ƒ|	  ˆ|   }
t‡fdd„ˆ| | d | d … D ƒƒ}|rÆ|| nd||
|rÝtˆ| | d | d … ƒ| dœS d dœS )Nr"   c                    s    g | ]}ˆ |d   ˆ |  ‘qS )r"   r   ©r	   Úk)Úcsr   r   r   8   ó     z)measures.<locals>.win.<locals>.<listcomp>éÿÿÿÿr   c                 s   s   � | ]}t |ƒV  qd S ©N)Úabs)r	   Úsr   r   r   Ú	<genexpr>9   s   € z(measures.<locals>.win.<locals>.<genexpr>r   c                 3   ó   � | ]	}|ˆ  d  V  qdS ©r   Nr   r$   )Úxmr   r   r,   ;   ó   € c                 3   s$   � | ]\}}|ˆ  |ˆ  V  qd S r)   r   ©r	   r%   Úy)r/   Úymr   r   r,   <   ó   €" c                 3   r-   r.   r   )r	   r2   )r3   r   r   r,   =   r0   c                 3   s,   � | ]\}}|ˆˆ |ˆ    d  V  qdS r.   r   r1   )Úsloper/   r3   r   r   r,   >   s   €* c                 3   s$   � | ]}|d k rˆ d | V  qdS )r   Úvol_per_minNr   )r	   Úm)Úrefr   r   r,   B   r4   )ÚeffÚr2ÚaccÚvrel)ÚrangeÚsumÚlenÚ	enumerate)ÚiÚnÚstepsÚnetÚpathÚsxxÚsstÚssrr:   Úhalfr;   Únorm)ÚatrÚcÚidxr8   Úv)r&   r5   r/   r3   r   Úwin4   s&   $ $<*"ÿÿzmeasures.<locals>.wini…  éd   Úabs_move_pctg�íµ ÷Æ°>Úcum_vol)ÚtrL   ÚvwapÚvwap_pctÚnoiseÚrvol)é   é   r   c                    s   i | ]\}}|› ˆ › �|“qS r   r   )r	   r%   r    )rB   r   r   Ú
<dictcomp>O   s    zmeasures.<locals>.<dictcomp>é=   Úfwd60r(   Úto_closeÚacc15ç      à?Úeff15ç333333ã?Úr215gffffffæ?Úvrel15r   rU   ÚturnÚr230çš™™™™™é?ÚsmoothÚacc5g      ø?rX   é   rV   r   Úclimax)ÚREFÚloadÚbuildr   ÚfromisoformatÚdateÚ_CACHEÚpopÚ
day_reportÚload_minutesr   r?   r=   Úmaxr*   Úminr>   ÚupdateÚitemsÚboolÚgetÚappend)ÚdayÚsymÚBÚhÚlÚvwrS   ÚoÚarA   ÚtrrO   Úrowsr7   r
   ÚwÚfutr   )rK   rL   rM   rB   r8   rN   r   Úmeasures   s`   @
(($þ
€&<ÿÿ$6
ÿ
ÿr‡   rY   c                 C   sB   g d}}t | ƒD ]\}}|| r|| |kr| |¡ |}q	|S )zOFirst minute of each cluster of a signal (clusters separated by `gap` minutes).iüÿÿ)r@   rz   )r„   ÚkeyÚgapÚoutÚlastrA   r
   r   r   r   Úfirsts\   s   

€rŒ   c              
      sú  ‡ fdd„ˆD ƒ}‡fdd„}t jddddd	g d
¢id�\}}|d j||dƒdddd� |d j||dƒdddd� dD ]A\}}	}
tˆ|ƒD ]6}t ˆ d |d  d¡}|d j|g|d g|	ddd� |d j|
› d|d › �||d fddd|	d� qGq=dd„ t|ˆƒD ƒ}|D ]}|d j	||d d!d"� q‹|d j
|› dˆ › d#�d$d%� |d jdd&d'� |d jd(d)� |d j||d*ƒd dd+� |d jd,d-d.d/� |d  d0d¡ |d jd1d2d%� |d3 j||d4ƒd5dd6d� |d3 j||d7ƒd8d9d:d� |d3 jdd.d;d+� |d3 jd<d2d%� |d3 jd=d%� |d> j||d?ƒd@ddAd� |d> j||dBƒdCddDd� |d> jdd-d.d/� |d> jd=d%� |dd … D ]	}|jd(d)� �qL|d> j t dE¡¡ t  ¡  t› dF|› dGˆ › dH�}t j|dIdJ� t  ¡  |S )KNc                    s$   g | ]}t  ˆ d  |d  d¡‘qS )ú rS   ú%Y-%m-%d %H:%M)r   Ústrptimer   )r{   r   r   r   h   s   $ zchart.<locals>.<listcomp>c                    s   ‡ fdd„ˆD ƒS )Nc                    s   g | ]}|  ˆ ¡‘qS r   ©ry   r   ©r%   r   r   r   i   s    z+chart.<locals>.<lambda>.<locals>.<listcomp>r   r‘   )r„   r‘   r   Ú<lambda>i   s    zchart.<locals>.<lambda>ri   r"   )é   g      !@TÚheight_ratios)r   çš™™™™™ñ?r•   r•   )ÚfigsizeÚsharexÚgridspec_kwr   rL   z#1f3a5fÚprice)ÚcolorÚlwÚlabelrT   z#c0392bÚVWAP))rd   ÚgreenÚTURN)rj   ÚpurpleÚCLIMAXr�   rS   rŽ   é#   rX   )rš   r+   Úzorder)ri   é   zoffset pointsé   )ÚxytextÚ
textcoordsÚfontsizerš   c                 S   s   g | ]
\}}|d  r|‘qS ©rg   r   )r	   Úxxr
   r   r   r   r   r   r   z#2a78d6g{®Gáz´?)rš   Úalphau?    â€” TURN (green), CLIMAX (purple), SMOOTH trend (blue shading)é
   )r¨   z
upper left)r¨   Úlocg333333Ó?)r«   re   )rš   r›   rf   ú:Úgray)Úlsrš   r(   u   smoothness
30-bar RÂ²é   r   r^   z#eb6834z15-barrh   z#999ra   z5-barr_   Úaccelerationr¤   r   rc   z#0ca30cz15-min vol vs normalrV   z#6b3fa0zmove vs normalz%H:%Mú/Ú_speed_shape_z.pngén   )Údpi)ÚpltÚsubplotsÚplotrŒ   r   r�   ÚscatterÚannotateÚzipÚaxvspanÚ	set_titleÚlegendÚgridÚaxhlineÚset_ylimÚ
set_ylabelÚxaxisÚset_major_formatterÚmdÚDateFormatterÚtight_layoutÚOUTÚsavefigr   )r{   r|   r„   r�   r    ÚgÚfigÚaxrˆ   ÚcolÚlabr
   ÚtmÚsmrª   r‚   Úpr   )r{   r„   r   Úchartg   sL     2ýrÓ   Ú__main__r"   r   r(   rL   z
=== z: open z.2fz close z (rP   z+.1fz%))rd   rj   z  Ú6r�   rS   z @ z	  vsVWAP rU   z%  move/normal rV   z.1fz  vol15 rc   zx  -> best next 60m r\   z%, to close r]   ú%c                 C   s   g | ]}|d  r|‘qS r©   r   r   r   r   r   r   š   r   r   c                 C   s&   g | ]}|d  s|  d¡dur|‘qS )rg   re   Nr�   r   r   r   r   r   ›   s   & c                    s2   t ‡ fdd„| D ƒƒtdt‡ fdd„| D ƒƒƒ S )Nc                 3   s$   � | ]}|ˆ  d ur|ˆ  V  qd S r)   r   r   r‘   r   r   r,   œ   r4   z<lambda>.<locals>.<genexpr>r"   c                    s   g | ]
}|ˆ  d ur|‘qS r)   r   r   r‘   r   r   r   œ   r   z<lambda>.<locals>.<listcomp>)r>   rt   r?   )ÚLr%   r   r‘   r   r’   œ   s   2 r’   z  SMOOTH minutes: z, c                 C   s    h | ]}|d  dd… d ’qS )rS   Nr   z:00r   r   r   r   r   Ú	<setcomp>�   r'   rØ   z%); avg to-close from a smooth minute z+.2fz% vs z% otherwisez  RVOL so far: 9:45 c                 c   ó$   � | ]}|d  dkr|d V  qdS )rS   z09:45rW   Nr   r   r   r   r   r,   Ÿ   r4   r,   z	x, 11:00 c                 c   rÙ   )rS   z11:00rW   Nr   r   r   r   r   r,   Ÿ   r4   z	x, close rW   r    )rY   )(Ú__doc__ÚjsonÚsysr   Ú
matplotlibÚuseÚmatplotlib.datesÚdatesrÆ   Úmatplotlib.pyplotÚpyplotr·   rE   Úinsertrr   Ú	referencerk   rÉ   r‡   rŒ   rÓ   Ú__name__Úargvr{   r|   r„   r�   ÚclÚprintrˆ   r
   Úupperry   rÑ   ÚnsÚavgr?   ÚjoinÚsortedÚnextr   r   r   r   Ú<module>   sX    

=
(
4>ÿÿÿÿ(
ÿ

ÿHð