a
    ñÀ�jx  ã                   @   s²   d Z ddlZddlZddlZddlZddlZddlZddlZddlZ	ej
 dd¡ ej
 dd¡ ddlZdZdZdZdd	d
dœZdd„ Zdd„ Zdd„ Zdd„ Zedkr®eƒ  dS )a„  Does pre-quote volatility predict fills? Clean version.

The first pass (mm_volatility_fill.py) found +5pp for the wildest quartile but
could not be trusted, because both halves of the test came from the same file.
The paper log marks a leg filled when a trade printed at or above our ask, so a
leg whose price moves more mechanically generates more qualifying prints -- the
instrument was biased in exactly the direction of the hypothesis.

This separates the two sides completely:

  MOVEMENT  from live_data -- the snapshot feed the xlow/xhigh strategies run on.
            93 days of it, written by a different process for a different
            purpose, and measured over the window BEFORE the maker ever quoted
            the leg, so no fill can be inside it.

  FILL      from real Kalshi trade prints, queue-aware: filled only once
            cumulative volume at or above our price exceeds the depth that was
            already resting there when we posted. Not "a print happened".

If the effect survives that, it is a fact about the market. If it vanishes, the
first result was an artifact of the fill model and the hypothesis is unproven.
é    NzE:\soccer\mainzE:\soccer\researchz&E:\soccer\research\mm_paper_quotes.csvz%E:\soccer\research\.trades_cache.jsonzE:\soccer\live_dataZkalshi_home_midZkalshi_draw_midZkalshi_away_mid)ÚhomeZdrawÚawayc              	   C   sH   z*t | ƒ}d|  k rdk r&n n|nd W S  ttfyB   Y d S 0 d S )Nr   é   )ÚfloatÚ	TypeErrorÚ
ValueError)ÚxÚv© r
   ú)E:\soccer\research\mm_volatility_clean.pyÚ_f$   s
    "r   c                  C   s  i } t tddd��Ú}t |¡D ]¾}| d¡}|r|| v r:q| d¡pFd ¡ sNqt| d¡ƒ| d¡| d	¡  }}}|r|r|s‚q|t|d ƒt 	|¡t 	|¡| d
¡| d¡| d¡pºd 
¡ | d	¡pÊddd… dœ| |< qW d  ƒ n1 sò0    Y  dd„ |  ¡ D ƒS )zCFirst quote per leg: price, queue depth, kickoff, fixture identity.úutf-8Úreplace©ÚencodingÚerrorsZ
leg_tickerZask_sizeÚ Úour_askÚtsZkickoffr   r   ÚsideNé
   )r   Úqueuer   Úkor   r   r   Úgdc                 S   s2   i | ]*\}}|d  r|d r|d t v r||“qS )r   r   r   )ÚSIDE_COL)Ú.0Útr	   r
   r
   r   Ú
<dictcomp>>   s   ÿzload_legs.<locals>.<dictcomp>)ÚopenÚQUOTESÚcsvÚ
DictReaderÚgetÚstripr   r   ÚSÚ_ptÚlowerÚitems)ÚfirstÚfhÚrr   Úar   r   r
   r
   r   Ú	load_legs,   s$    
&ü*r,   c                    sö  t  t¡}|  ¡ D ](\}}||d |d |d f  |¡ qtdd„ |D ƒƒ}t  t¡}|D ]è}tj t	|› d�¡}tj 
|¡s‚q\t|ddd	��¢}t |¡D ]†}	|	 d
¡|	 d¡|	 d¡f}
|
|vrÆqœt |	 d¡¡}|sÜqœ||
 D ]<}t| | d  }t|	 |¡ƒ}|durä||  ||f¡ qäqœW d  ƒ q\1 �s:0    Y  q\i }| ¡ D ]ž\}}| | d }|j�r~| ¡ jdd�n|‰ ‡ fdd„t|ƒD ƒ}t|ƒdk �rª�qRt |¡t|ƒt|ƒt|ƒ tdd„ t||dd… ƒD ƒƒdœ||< �qR|S )zH{leg: stdev of the leg's mid BEFORE we first quoted it}, from live_data.r   r   r   c                 S   s   h | ]}|d  ’qS )r   r
   )r   Úkr
   r
   r   Ú	<setcomp>H   ó    z load_movement.<locals>.<setcomp>z.csvr   r   r   Z	game_dateZ	timestampr   Nr   ©Útzinfoc                    s.   g | ]&\}}|j r|jd d�n|ˆ k r|‘qS )Nr0   )r1   r   )r   r   Úm©Zcutnr
   r   Ú
<listcomp>e   s   ÿz!load_movement.<locals>.<listcomp>é   c                 s   s&   | ]\}}t || ƒd krdV  qdS )ç•Ö&è.>r   N)Úabs)r   r+   Úbr
   r
   r   Ú	<genexpr>k   s   
ÿz load_movement.<locals>.<genexpr>r   )ÚsdÚnÚrangeÚchanges)ÚcollectionsÚdefaultdictÚlistr'   ÚappendÚsortedÚosÚpathÚjoinÚLIVE_DIRÚexistsr   r    r!   r"   r$   r%   r   r   r1   Ú
astimezoner   ÚlenÚ
statisticsZpstdevÚmaxÚminÚsumÚzip)ÚlegsZwantr   r	   ZdatesZseriesÚdrD   r)   r*   Úkeyr   Úcolr2   ÚoutZptsZcutZprer
   r3   r   Úload_movementB   sD    
"
8þrT   c                     s>  t j t¡stdƒ d S t ttdd�¡} tƒ }tt	|ƒ› dt	| ƒ› d�ƒ t
|ƒ}tt	|ƒ› d�ƒ g }| ¡ D ]ö\}}||vr„qr|› d|d  ¡ › �}|| vr¤qrd	\}}| | D ]–\}	}
}t |	¡}|sÒ �qL|d
 }|jd u |jd u k�r|jrþ| ¡ n|j|jd�}||k�r �qL|
|d d kr´||7 }||d kr´d} �qLq´| t|| t|ƒ|d�¡ qrt	|ƒdk �r�tdt	|ƒ› d�ƒ d S dtdd„ |D ƒƒ t	|ƒ }tdt	|ƒ› d|d›d�ƒ dD �]h\‰}t‡fdd„|D ƒƒ‰‡fdd„dD ƒ}d |d! d"f|d! |d# d$f|d# d%d&fg}td'|› d(�ƒ g }|D ]š\‰‰ }‡ ‡‡fd)d„|D ƒ}t	|ƒd*k �rv�qDtd+d„ |D ƒƒ}| |d| t	|ƒ f¡ td,|d-›d.t	|ƒd/›d0|d1›d2d| t	|ƒ d3›d4�	ƒ �qDt	|ƒd5k�r0td6|d  d! › d7|d! d! › d8|d  d# |d! d#  d9›d:�ƒ tƒ  �qÎd S );Nz3no trades cache -- run mm_ratchet_backtest.py firstr   )r   z legs with depth logged; z tickers in the trade cachez3 of those have pre-quote price history in live_dataú|r   )g        Fr   r0   r   r6   r   T)ÚfilledZtickeré(   zonly z. legs join across all three sources -- too fewg      Y@c                 s   s   | ]}|d  V  qdS ©rV   Nr
   ©r   r*   r
   r
   r   r9   ˜   r/   zmain.<locals>.<genexpr>Ú
z: legs with movement AND queue-aware fills, base fill rate z.1fz%
))r:   zpre-quote stdev)r=   zprice changes)r<   zpre-quote rangec                 3   s   | ]}|ˆ  V  qd S )Nr
   rY   )Úmetricr
   r   r9   ž   r/   c                    s    g | ]}ˆ t |tˆ ƒ ƒ ‘qS r
   )ÚintrI   )r   Úp)Úvalsr
   r   r4   Ÿ   r/   zmain.<locals>.<listcomp>)g      à?g      è?éÿÿÿÿr   z	calm halfr   z3rd quartileg    eÍÍAzwildest 25%z  by ú:c                    s,   g | ]$}ˆ|ˆ   kr ˆ k rn q|‘qS r
   r
   rY   )ÚhiÚlor[   r
   r   r4   ¥   r/   é   c                 s   s   | ]}|d  V  qdS rX   r
   rY   r
   r
   r   r9   ¨   r/   z    z>14ú z>5z legs  z>4z	 filled  z>6.1fú%é   z    -> z vs z: z+.1fZpp)rC   rD   rG   ÚCACHEÚprintÚjsonÚloadr   r,   rI   rT   r'   Z	isoformatr$   r%   r1   rH   r   rA   Údictr\   rM   rB   )ZtradesrO   ZmvZrowsr   r	   rQ   ZcumrV   Zts_sr]   Úcr   r   ÚbaseZlabelÚqZbucketsZgotÚnameZselÚfr
   )ra   rb   r[   r^   r   Úmainp   s|    
ÿ
ÿ
ÿ ÿ ÿ
rq   Ú__main__)Ú__doc__r    r>   Zglobri   rC   rJ   ÚsysZdatetimeZdtrD   ÚinsertZ	mm_settler$   r   rg   rF   r   r   r,   rT   rq   Ú__name__r
   r
   r
   r   Ú<module>   s    @ÿ.B