a
    ÕœgjÓ  ã                   @   sr   d Z ddlZddlZddlZddlmZ dZdZdZ	dZ
dd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zedkrneƒ  dS )aÐ  Charging more, tested CAUSALLY off the trade tape.

WHY THIS REPLACES mm_charge_more_history.py: that version priced our offer from
kalshi_backfill's ask, which is snapped at KICKOFF, then counted trades from the
hours BEFORE it. Any leg whose price drifted down therefore scored a guaranteed
fill against a price it only reached later. It reported 90% fills at +5c and
E[net] rising monotonically to +14.7c/book -- which is self-evidently broken,
because the three legs sum to ~100c and cannot all trade 5c above their asks.

The fix is ordering: our posting price must be fixed from information available
BEFORE the trades that fill it.

  T_post = kickoff - POST_H
  level  = each leg's LAST trade price at or before T_post   (known at T_post)
  our ask = level + k
  fill    = a maker-sell trade (taker_book_side='bid') in (T_post, kickoff)
            printing at or above our ask

Everything used to decide is in the past; everything used to fill is in the
future. Sample is the whole 2.28M-row tape, not just the backfill snapshots.

Remaining caveats, stated rather than buried:
  - last-trade price is a noisy stand-in for the ask (trades print on both
    sides), so `level` is biased slightly low vs a true ask. That inflates
    fills at every k equally; it does not manufacture the k-slope, which is
    what this test is about.
  - queue priority is still ignored, but posting ABOVE the touch makes us the
    only offer at that price, so k>0 is the least distorted region.
é    N)Údefaultdictz&E:\soccer\research\kalshi_backfill.csvz E:\soccer\research\mm_trades.csvg      @é   c                 C   s   d|  d|   d S )NgìQ¸…ë±?é   éd   © )Úpr   r   ú+E:\soccer\research\mm_charge_more_causal.pyÚ<lambda>'   ó    r	   c              	   C   sL   zt j |  dd¡¡}W n ttfy0   Y d S 0 |jr<|S |jt jjd�S )NÚZz+00:00)Útzinfo)	ÚdtÚdatetimeZfromisoformatÚreplaceÚ
ValueErrorÚAttributeErrorr   ÚtimezoneZutc)ÚsÚdr   r   r   Ú_pt*   s
    r   c                  C   sh   i } t tdd��D}t |¡D ](}t|d ƒ}|r||d f| |d < qW d   ƒ n1 sZ0    Y  | S )Núutf-8©ÚencodingZkickoffÚdivZevent)ÚopenÚBACKFILLÚcsvÚ
DictReaderr   )ÚoutÚfhÚrÚkor   r   r   Úkickoffs2   s    4r"   c           
   
   C   s*  t dd„ ƒ}ttdd��Ì}t |¡D ]°}|d }| d¡}|dk rDq$|d|… }|| vrZq$t|d	 ƒ}|du s$|| | d kr€q$zt|d
 ƒ}W n ty¦   Y q$Y n0 || ||d d…   	|||d dkf¡ q$W d  ƒ n1 sê0    Y  |D ],}|| D ]}	|| |	 j
dd„ d� �qqø|S )z8event -> leg suffix -> [(ts, price, maker_sold)] sorted.c                   S   s   t tƒS )N)r   Úlistr   r   r   r   r	   >   r
   ztape.<locals>.<lambda>r   r   Ztickerú-r   NZtsZpricer   Ztaker_book_sideZbidc                 S   s   | d S )Nr   r   )Úxr   r   r   r	   R   r
   )Úkey)r   r   ÚTRADESr   r   Úrfindr   Úfloatr   ÚappendÚsort)
ÚkosÚlegsr   r    ZtkÚiÚevÚtr   r   r   r   r   Útape<   s,    

Lr1   c                     s  t ƒ } t| ƒ}g }| ¡ D ]ê\}}t|ƒdkr0q| | d }|tjtd� ‰i i  }}d}| ¡ D ]P\}	}
‡fdd„|
D ƒ}‡fdd„|
D ƒ}|r–|sžd} q´|d	 ||	< |||	< qb|sºqt| ¡ ƒd
 }d|  k rÞdk sâq q| 	|| | d |||d
 dœ¡ qt
t|ƒ› dtd›d�ƒ t
dt dd„ |D ƒ¡d›d�ƒ t
ddd›ddd›ddd›ddd›ddd›dd d!›�ƒ tdtd ƒD �]t}g g  }}|D ]À}d}|d"  ¡ D ]F\}	}||d#  ‰ t‡ fd$d%„|d& |	 D ƒƒ}| 	|¡ ||7 }�q°|d' d|  }|dk�r|}n0|d(k�rD|| d) tt|d"  ¡ ƒƒ }nd*}| 	|||d+œ¡ �qœt|ƒ}t
d|d,›dt|ƒt|ƒ d
 d-›d.td/d%„ |D ƒƒ| d
 d0›d.td1d%„ |D ƒƒ| d
 d0›d.t d2d„ |D ƒ¡d3›d4t d5d„ |D ƒ¡d6›d7�ƒ �qˆt
d8ƒ t
d9ƒ d S ):Né   r   )ZhoursTc                    s   g | ]\}}}|ˆ kr|‘qS r   r   )Ú.0r0   r   Ú_©Útpr   r   Ú
<listcomp>b   r
   zmain.<locals>.<listcomp>c                    s"   g | ]\}}}|ˆ kr||f‘qS r   r   )r3   r0   r   Úmr5   r   r   r7   c   r
   Féÿÿÿÿr   éZ   ép   r   )r/   r   ÚlvÚfutÚgross0z books with a clean Úgzh-pre-KO level on all 3 legszmedian gross at k=0: c                 S   s   g | ]}|d  ‘qS )r>   r   )r3   Úbr   r   r   r7   q   r
   z+.2fzc
z  Úkz>3sú z
leg fill %z>11szall-3 %z>9sz2-of-3 %z
mean grosszE[net]/bookz>12sr<   g      Y@c                 3   s"   | ]\}}|o|ˆ d  kV  qdS )g•Ö&è.>Nr   )r3   r   r8   )Úourr   r   Ú	<genexpr>{   r
   zmain.<locals>.<genexpr>r=   r>   é   g      ð?g        )ÚnfÚnetÚgrossZ3dz10.1fz% c                 s   s   | ]}|d  dkrdV  qdS )rF   r2   r   Nr   ©r3   r%   r   r   r   rD   ˆ   r
   z8.1fc                 s   s   | ]}|d  dkrdV  qdS )rF   rE   r   Nr   rI   r   r   r   rD   ‰   r
   c                 S   s   g | ]}|d  ‘qS )rH   r   rI   r   r   r   r7   Š   r
   z10.2fzc c                 S   s   g | ]}|d  ‘qS )rG   r   rI   r   r   r   r7   ‹   r
   z11.2fÚczD
SANITY: all three legs cannot rise together (they sum to ~100c), sozHall-3 fill % MUST fall steeply in k. If it does not, the test is broken.)r"   r1   ÚitemsÚlenr   Z	timedeltaÚPOST_HÚsumÚvaluesr*   ÚprintÚ
statisticsZmedianÚrangeÚMAX_KÚanyÚFEEÚminZmean)r,   r-   Zbooksr/   Zsidesr!   r<   r=   Zokr   ZrowsZpastZafterZtotrA   ZlfZperr@   rF   ÚlevelZhitrH   rG   Únr   )rC   r6   r   ÚmainV   sz    

ÿ
"$ÿÿ



"$ÿþýürY   Ú__main__)Ú__doc__r   r   r   rQ   Úcollectionsr   r   r'   rM   rS   rU   r   r"   r1   rY   Ú__name__r   r   r   r   Ú<module>   s   
;