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 ddlmZ ddlm	Z	 ddl
Z
e
 d¡ ddlmZ edƒZej deeƒ¡ ddlmZ ddlZe	d	ƒZed
 d d Zed
 d ZddddœZdd„ Zdd„ Zddd„Zdd„ Zedkr|eƒ  dS dS )al  
bb_pattern_search.py -- [2026-09-30] The user: "look back 50 days and try to identify trades
that had a similar pattern as BB today, so we can have an idea how often we will see that
pattern". First version of the user's matching idea (whole day from 9:30, all main measures).

For every stock-day on the saved lists in the last 50 trading days (bars/ + 14-day reference):
per minute from 9:30, forward-filled
   p   price vs the open, %
   w   price vs VWAP, %
   x   log(1 + volume vs its 14-day normal for that minute)
distance to BB 9/30 over a window = RMS(p diff) + RMS(w diff) + 0.5 * RMS(x diff)
windows: MORNING 9:30-9:48 (what was known at the suggested buy, 8.79)
         TO 12:50  (through BB's climb, up to its 12:46 volume-spike top)
         FULL DAY
Outcomes after 9:48 for the morning matches: best gain afterwards, time of the peak,
+2% before -1%, close.
é    N)Údatetime)ÚPath)ÚZoneInfoÚAggz/var/www/screener/trade)Ú
get_clientzAmerica/New_YorkÚreportsÚopen_windowÚbarsÚplaybooké   éÈ   é�  )úMORNING (9:30-9:48)zTO 12:50úFULL DAYc              	   C   sÀ  i }| D ]4}t |d tƒst |d t¡n|d  t¡}|jd d |j d }d|  kr2dk r8n q|||< q|s=dS |t|ƒ d }g g g g g g f\}}}	}
}}|dd}}}tdƒD ]v}| 	|¡}d}|r—|d	 }|d
 }||d |d  |d	  d | 7 }||7 }| 
|d ¡ | 
|d ¡ n
| 
|¡ | 
|¡ |
 
|¡ |r¬|| n|}| 
|| d d ¡ | 
|| d d ¡ |	 
t |t|d | dƒ ¡¡ q_||||	|
||dœS )z1rows: [[ts, o, h, l, c, v], ...] regular session.r   é	   é<   é   é†  Né   g        é   é   é   é   éd   Úvol_per_min)ÚoÚPÚWÚXÚCÚHÚL)Ú
isinstancer   ÚfromtimestampÚETÚ
astimezoneÚhourÚminuteÚminÚrangeÚgetÚappendÚmathÚlog1pÚmax)ÚrowsÚrefÚbyÚbÚtÚmr   r   r   r   r   r    r!   ÚlastÚpvÚcvÚvÚvw© r:   ú?/var/www/screener/trade/reports/playbook/./bb_pattern_search.pyÚpaths)   s8   ,€
$
$r<   c                    sš   t  t‡ ‡fdd„t|d ƒD ƒƒ|d  ¡}t  t‡ ‡fdd„t|d ƒD ƒƒ|d  ¡}t  t‡ ‡fdd„t|d ƒD ƒƒ|d  ¡}|| d|  S )Nc                 3   ó,   � | ]}ˆ d  | ˆd  |  d V  qdS )r   r   Nr:   ©Ú.0Úk©Úar2   r:   r;   Ú	<genexpr>J   ó   €* zdist.<locals>.<genexpr>r   c                 3   r=   )r   r   Nr:   r>   rA   r:   r;   rC   K   rD   c                 3   r=   )r   r   Nr:   r>   rA   r:   r;   rC   L   rD   g      à?)r,   ÚsqrtÚsumr)   )rB   r2   ÚnÚrpÚrwÚrxr:   rA   r;   ÚdistI   s   ...rK   c                    sÐ   ˆ d | }t t|d dƒ‡ fdd„d�}d}t|d dƒD ]}ˆ d | |d	 kr.d
} nˆ d | |d kr<d} nqˆ d | | d d dd| d  › dd| d d›�ˆ d d | d d |dœS )Nr   r   i‚  c                    s   ˆ d |  S )Nr    r:   )r@   ©Úsr:   r;   Ú<lambda>R   s    zafter.<locals>.<lambda>©ÚkeyÚtimer!   g®Gáz®ï?Ústopr    gR¸…ëQð?Útargetr   r   r   r   ú:Ú02dr   )ÚbestÚpeak_tÚcloseÚfirst)r.   r)   )rM   r4   ÚeÚhi_krY   r@   r:   rL   r;   ÚafterP   s   þ8ÿr\   c                     s"  d} t  | ¡jtd�}tƒ jd|jddd�|jdd�d	d
�}tdd„ |D ƒt | d¡ƒ‰ t	t
 d¡ƒdd … }g }|D ]P}t t |d¡¡}|d D ];}|d | krW|dkrWqJt |d |¡}|d  |i ¡ dg ¡}	|rst|	ƒdk rtqJt|	|ƒ}
|
r…| |d ||
f¡ qJtj ¡  q;tt|ƒ› d|d jdd… › d|d jdd… › dt|ƒ› d�ƒ i }t ¡ D ]…\}‰t	‡ ‡fdd„|D ƒdd „ d!�}|||< d"d„ |D ƒ}td#|› d$|d d%›d&|t|ƒd'  d%›d(|t|ƒd)  d%›�ƒ |d d*… D ]>}t|d+ ƒ}td,|d- › d.|d) d/›d0|d d%›d1|d+ d2 d3 d4›d5|d6 d4›d7|d8 › d9|d: › d;|d< d4›d=�ƒ qúq´|d> }d?|d d@… fdAtt|ƒd' ƒ dB |d t|ƒd' … ffD ]b\}}	dCd„ |	D ƒ}tdDd„ |D ƒƒ}tdEd„ |D ƒƒ}tdF|› dG|› dHt|ƒ› d|t|ƒ dI dJ›dK|› dLtdMd„ |D ƒƒt|ƒ dN›dOtdPd„ |D ƒƒt|ƒ dQ›dRt|	ƒt|ƒ dS›�ƒ �q\tˆ ƒ}tdT|d6 dN›d7|d8 › dU|d: › d;|d< dN›d=�	ƒ tjd)d-dVdW�\}}t|dXƒD ]”\}}|jtdYƒˆ d2 dZd[d\d]� || d d^… D ]'}|jtdYƒ|d+ d2 d-d_|d) › d.|d- dd … › d`|d d%›dB�da� �q|  db¡�rM|j!dcddded_df� |j"dg| #¡ d- dh didjdk� | $g dl¢¡ | %g dm¢¡ |j&ddddndo� | 'dp¡ |j(dq|› dr�dsdk� |j)dtd)du� |j*dvdw� �qít +¡  tj,t-dx dydz� d S ){Nz
2026-09-30)ÚtzinfoÚBBr   r   )r&   r'   é   )r&   iè  )ÚstartÚendÚlimitc              	   S   s<   g | ]}|j t|jƒt|jƒt|jƒt|jƒt|jƒg‘qS r:   )Ú	timestampÚfloatÚopenÚhighÚlowrX   Úvolume)r?   r2   r:   r:   r;   Ú
<listcomp>c   s   < zmain.<locals>.<listcomp>zbars_20*.json.gziÎÿÿÿÚrtÚtop30_currentÚdateÚsymbolsr	   r   z stock-days, r   r   é   z .. éÿÿÿÿz (z days)
c                 3   s*   � | ]\}}}t ˆ |ˆƒ|||fV  qd S )N)rK   )r?   ÚdayrM   Úx©ÚbbrG   r:   r;   rC   w   s   €( zmain.<locals>.<genexpr>c                 S   s   | d S )Nr   r:   )Úrr:   r:   r;   rN   w   s    zmain.<locals>.<lambda>rO   c                 S   s   g | ]}|d  ‘qS )r   r:   ©r?   rt   r:   r:   r;   ri   y   s    z=== z: distance to BB  best z.2fz
  5th pct é   z	  median r   é   r   z   r   ú Ú5z dist z | open->close r   r   z+5.1fz% | after 9:48: best rV   z% (peak rW   z), +2% before -1%: rY   z, close rX   ú%r   z
closest 25é   zclosest 5% (ú)c                 S   s   g | ]}t |d  ƒ‘qS )r   )r\   ru   r:   r:   r;   ri   ‚   s    c                 s   ó   � | ]	}|d  dkV  qdS )rY   rS   Nr:   ©r?   rB   r:   r:   r;   rC   ƒ   ó   € c                 s   r}   )rY   rR   Nr:   r~   r:   r:   r;   rC   „   r   z
MORNING matches, z: +2% before -1% ú/r   z.0fz%), -1% first z, avg best after c                 s   ó   � | ]}|d  V  qdS )rV   Nr:   r~   r:   r:   r;   rC   †   ó   € z+.1fz%, avg close c                 s   r�   )rX   Nr:   r~   r:   r:   r;   rC   †   r‚   z+.2fz%, per day z.1fz
BB itself after 9:48: best z), )é   é   )Úfigsize)r   r   r   Úblackgš™™™™™@zBB 9/30)ÚcolorÚlwÚlabelé   gš™™™™™é?z (d )rˆ   Úalphar‰   ÚMORNINGr   Úgreyz--)r‡   Úlsrˆ   é   gÍÌÌÌÌÌì?z9:48r„   )Úfontsize)r   r   éZ   é–   éÒ   i  iJ  i…  )z9:30z10:00z11:00z12:00z13:00z14:00z15:00z16:00g333333ã?)r‡   rˆ   zprice vs open %z$BB 9/30 vs its 6 closest matches -- z (last 50 trading days)é
   é   )r�   Úncolg333333Ó?)r‹   z!BB_2026-09-30_pattern_matches.pngés   )Údpi).r   ÚfromisoformatÚreplacer$   r   Úget_minute_barsr<   ÚREFÚloadÚsortedÚBARSÚglobÚjsonÚgzipre   r*   Úlenr+   Ú_CACHEÚclearÚprintÚnameÚWINÚitemsr\   ÚstrrF   ÚpltÚsubplotsÚzipÚplotr)   Ú
startswithÚaxvlineÚtextÚget_ylimÚ
set_xticksÚset_xticklabelsÚaxhlineÚ
set_ylabelÚ	set_titleÚlegendÚgridÚtight_layoutÚsavefigÚOUT)Úday0ÚdÚrawÚfilesÚcandsÚpÚddrM   r0   r/   rq   Úresr§   ÚdsÚallvrt   rB   Úcut_nameÚAr3   ÚspÚbb_aÚfigÚaxsÚaxr:   rr   r;   Úmain_   sŒ   &
ÿ
€D BFÿÿÿþD4ÿÿþ6L
rÎ   Ú__main__)r   ) Ú__doc__r¢   r¡   r,   Úsysr   Úpathlibr   Úzoneinfor   Ú
matplotlibÚuseÚmatplotlib.pyplotÚpyplotr«   ÚTRADEÚpathÚinsertrª   Úalpaca_clientr   Ú	referencerœ   r$   rŸ   r¼   r¨   r<   rK   r\   rÎ   Ú__name__r:   r:   r:   r;   Ú<module>   s4    
 
?
ÿ