a
    ®Ã�jø  ã                   @   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ej dd¡ ej dd¡ ddl	Z
ddlZddlmZmZmZ dd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zedkr²eƒ  dS )a¥  Does selecting volatile, liquid books raise BOOK COMPLETION?

Everything so far about volatility and volume is per LEG (2.9% -> 20.1%). A book
only pays when all three legs fill, and the number the strategy lives or dies on
is book completion -- 3.7% under gate+ratchet, queue-aware, in
mm_ratchet_backtest.py.

Legs inside one book are not independent: a volatile liquid book should have all
three legs moving and trading together, so completion ought to rise by more than
the cube of the leg rate. Ought to. This measures it.

Same machinery as the ratchet backtest -- real Kalshi trade prints, queue-aware
fills, the entry gate and the ratchet -- with books additionally split by their
own pre-quote volatility (from live_data) and their volume (from the Kalshi
market at post time).

The comparison that matters is completion AND total P&L against "no selection".
A filter can only remove books, so it must earn its lost volume.
é    NzE:\soccer\mainzE:\soccer\research)Ú	load_legsÚload_movementÚCACHEc              	   C   s(   z
t | ƒW S  ttfy"   Y d S 0 d S ©N)ÚfloatÚ	TypeErrorÚ
ValueError)Úx© r
   ú+E:\soccer\research\mm_selection_backtest.pyÚ_f   s    
r   c                  C   s¢   i } t dddd��|}t |¡D ]`}| d¡}|r|| v s| d¡pDd ¡ sLqt| d¡ƒ}|rd	|  k rrd
k rn q|| |< qW d  ƒ n1 s”0    Y  | S )af  {leg: market ask at first quote}. The live maker rests AT the touch;
    the paper maker's our_ask sits 0-5c above it on a price ladder. Since cents
    above the touch is the single strongest fill killer measured (AUC 0.690),
    scoring the ladder prices answers a different question and is not comparable
    to the 3.7% baseline from mm_ratchet_backtest.ú&E:\soccer\research\mm_paper_quotes.csvúutf-8Úreplace©ÚencodingÚerrorsÚ
leg_tickerÚask_sizeÚ Zk_askr   é   N©ÚopenÚcsvZ
DictReaderÚgetÚstripr   )ÚoutÚfhÚrÚtÚar
   r
   r   Ú
load_touch$   s    ÿ
(r!   c                  C   s�   i } t dddd��j}t |¡D ]N}| d¡}|r|| v s| d¡pDd ¡ sLqt| d¡ƒpft| d	¡ƒ| |< qW d   ƒ n1 s‚0    Y  | S )
Nr   r   r   r   r   r   r   Z
volume_24hZvolumer   )r   r   r   r   r
   r
   r   Úload_volume7   s    ÿ
@r"   c           
      C   s˜   || vrd S d}| | D ]z\}}}t  |¡}	|	s4 q”|	jd u |jd u krd|	jrV|	 ¡ n|	j|jd�}	|	|krp q”||d kr||7 }||kr dS qdS )Nç        )Útzinfog•Ö&è.>TF)ÚSZ_ptr$   Z
astimezoner   )
ÚtradesÚkeyZpriceÚqueueÚkoZcumZts_sÚpÚcÚtsr
   r
   r   ÚfilledC   s     
r-   c                 C   sh   | sd S dd„ | D ƒ}dd„ |D ƒ}|t | ƒt |ƒdt |ƒ t | ƒ |rVt |¡d ndt|ƒd dœS )Nc                 S   s   g | ]}|d  r|‘qS )Úcompleter
   ©Ú.0Úbr
   r
   r   Ú
<listcomp>Y   ó    zscore.<locals>.<listcomp>c                 S   s   g | ]}|d  ‘qS )Únetr
   r/   r
   r
   r   r2   Z   r3   ç      Y@éd   r#   )ÚlabelÚnÚdoneÚrateÚmeanÚtotal)ÚlenÚ
statisticsr;   Úsum)Úbooksr7   r9   r4   r
   r
   r   ÚscoreV   s    
ýrA   c                     sd  t ƒ } t| ƒ‰tƒ ‰
tƒ ‰	t ttdd�¡}t 	t
¡}|  ¡ D ]$\}}| dd¡\‰}||ˆ |< q>g }| ¡ D �]Â\‰}t|ƒdkrˆqpt‡‡‡
fdd„|D ƒƒs¢‡fdd	„|D ƒ‰t‡‡fd
d„|D ƒƒsÎqp‡‡
fdd„|D ƒ}tdd„ |D ƒƒröqpt‡‡	fdd„|D ƒƒ�sqp‡‡	fdd	„|D ƒ}	t |	i ¡}
|
d dk�rBqpi }|D ]H}|| }ˆ| › d|d  ¡ › �}t|||	| |d |d ƒ||< �qJtdd„ | ¡ D ƒƒ�r®qpt| ¡ ƒ}t|	 ¡ ƒ}tdd„ |	 ¡ D ƒƒ}| ˆ||�rö|| d ndt ‡‡fdd„|D ƒ¡t |¡tdd„ | ¡ D ƒƒdœ¡ qpt|ƒdk �r\tdt|ƒ› d�ƒ d S t|d ƒ}tt|ƒ› d!�ƒ td"d#›d$d%d&›d$d'd(›d$d)d*›d$d+d(›d$d,d(›�ƒ d-d.„ }||ƒ t d/d„ |D ƒ¡‰t d0d„ |D ƒ¡‰|t‡fd1d„|D ƒd2ƒƒ |t‡fd3d„|D ƒd4ƒƒ |t‡‡fd5d„|D ƒd6ƒƒ |t‡‡fd7d„|D ƒd8ƒƒ td9d„ |D ƒƒtt|ƒd: ƒ ‰td;d„ |D ƒƒtt|ƒd: ƒ ‰|t‡‡fd<d„|D ƒd=ƒƒ td>ƒ d?|fd6‡‡fd@d„|D ƒfdA‡‡fdBd„|D ƒffD ]\\}}|�s�qút dCd„ |D ƒ¡‰ t|ƒ‰tdD|dE›dF�dD ‡ ‡fdGd„dHD ƒ¡ ƒ �qútdIƒ d S )JNr   )r   ú-r   é   c                 3   s(   | ] }|ˆv oˆ › d |› �ˆv V  qdS )rB   Nr
   )r0   r   )ÚevÚmvÚvolsr
   r   Ú	<genexpr>r   r3   zmain.<locals>.<genexpr>c                    s   i | ]}|ˆ › d |› �“qS )rB   r
   )r0   Úleg)rD   r
   r   Ú
<dictcomp>t   r3   zmain.<locals>.<dictcomp>c                 3   s   | ]}ˆ| ˆ v V  qd S r   r
   ©r0   Úl©rE   Útickr
   r   rG   u   r3   c                    s   g | ]}ˆ  ˆ | ¡‘qS r
   ©r   rJ   )rM   rF   r
   r   r2   w   r3   zmain.<locals>.<listcomp>c                 s   s   | ]}|d u V  qd S r   r
   )r0   r	   r
   r
   r   rG   x   r3   c                 3   s   | ]}ˆ | ˆv V  qd S r   r
   rJ   ©rM   Útouchr
   r   rG   {   r3   c                    s   i | ]}|ˆˆ |  “qS r
   r
   rJ   rO   r
   r   rI   }   r3   ZdecisionZgateú|r,   r(   r)   c                 s   s   | ]}|d u V  qd S r   r
   ©r0   r   r
   r
   r   rG   ˆ   r3   c                 s   s   | ]}t  |¡V  qd S r   )ÚMLZ	maker_fee)r0   r    r
   r
   r   rG   �   r3   g      ð?r#   c                 3   s   | ]}ˆ ˆ|  d  V  qdS ©ÚsdNr
   rJ   rL   r
   r   rG   ‘   r3   c                 s   s   | ]}|rd V  qdS )r   Nr
   rR   r
   r
   r   rG   “   r3   )rD   r.   r4   rU   ÚliqÚlegs_filledé(   zonly z" books survive the join -- too fewzgate+ratchet, no selectionz. books past the entry gate, queue-aware fills
Z	selectionú>34ú r@   ú>6r.   ú>9r:   z>7znet/bookr<   c                 S   sX   | rTt | d d›d| d d›d| d d›d| d d	›d
| d d›d| d d›d�ƒ d S )Nr7   rY   rZ   r8   r[   r9   r\   r:   z>6.1fz% r;   z>8.2fzc r<   z>8.1fr+   )Úprint)Úsr
   r
   r   ÚshowŸ   s    2ÿÿzmain.<locals>.showc                 s   s   | ]}|d  V  qdS rT   r
   r/   r
   r
   r   rG   ¥   r3   c                 s   s   | ]}|d  V  qdS ©rV   Nr
   r/   r
   r
   r   rG   ¦   r3   c                    s   g | ]}|d  ˆ kr|‘qS )rU   r
   r/   )Úsd_medr
   r   r2   §   r3   zvolatile halfc                    s   g | ]}|d  ˆ kr|‘qS )rV   r
   r/   )Úlq_medr
   r   r2   ¨   r3   zliquid halfc                    s(   g | ] }|d  ˆkr|d ˆ kr|‘qS ©rU   rV   r
   r/   ©rb   ra   r
   r   r2   ©   r3   zvolatile AND liquidc                    s(   g | ] }|d  ˆkr|d ˆ kr|‘qS rc   r
   r/   rd   r
   r   r2   «   r3   zcalm AND thin (the dregs)c                 s   s   | ]}|d  V  qdS rT   r
   r/   r
   r
   r   rG   ¯   r3   g      è?c                 s   s   | ]}|d  V  qdS r`   r
   r/   r
   r
   r   rG   °   r3   c                    s(   g | ] }|d  ˆks |d ˆ kr|‘qS rc   r
   r/   )Úlq_qÚsd_qr
   r   r2   ±   r3   ztop quartile on eitherz(
=== how far books get, by selection ===Úallc                    s(   g | ] }|d  ˆkr|d ˆ kr|‘qS rc   r
   r/   rd   r
   r   r2   ·   r3   zcalm AND thinc                    s(   g | ] }|d  ˆkr|d ˆ kr|‘qS rc   r
   r/   rd   r
   r   r2   ¹   r3   c                 s   s   | ]}|d  V  qdS )rW   Nr
   r/   r
   r
   r   rG   ¼   r3   z  z>20z: c                 3   s0   | ](}|› d dˆ   |d¡ ˆ d›d�V  qdS )z/3 r5   r   z>4.0fú%NrN   )r0   Úk)ÚdÚtotr
   r   rG   ¾   s   )r   r   é   rC   z@
A filter can only REMOVE books, so judge it on TOTAL, not rate.)r   r   r"   r!   ÚjsonÚloadr   r   ÚcollectionsÚdefaultdictÚdictÚitemsÚrsplitr=   rg   ÚanyrS   Zbook_budgetZ	isoformatr-   Úvaluesr?   Úappendr>   Zmedianr]   rA   ÚsortedÚintÚCounterÚjoin)Zlegsr&   Zby_bookr   ÚvrH   r@   ZlsZvvZasksr1   ÚresrK   r'   r.   ZcollZfeesÚbaser_   ZlabZselr
   )rj   rD   rb   re   rE   ra   rf   rM   rk   rP   rF   r   Úmaina   s®    
$û

"ÿÿÿÿ""ÿÿÿýÿr~   Ú__main__)Ú__doc__r   ro   rm   Úosr>   ÚsysÚpathÚinsertZ	mm_settler%   Zmm_maker_liverS   Zmm_volatility_cleanr   r   r   r   r!   r"   r-   rA   r~   Ú__name__r
   r
   r
   r   Ú<module>   s   0c