a
    àgej¹  ã                   @   sb   d Z ddlZddlZddlZddlZddlmZ dZdZ	dd„ Z
dd	„ Zd
d„ Zedkr^eƒ  dS )a  
Analyse the market-maker feasibility data collected by mm_feasibility.py.
(read-only, trades nothing)

THE HEADLINE NUMBER IS NOT THE NOTIONAL-WEIGHTED ROI. On the first 40 events the
notional-weighted figure was +7.88% while only 19/40 events were profitable and
the MEDIAN event was -1.25%. A few large matches carried the whole result. So
this reports per-event distribution first and the aggregate second.

MAPPING (verified against our own fills, which are all buys carrying
book_side='bid', is_taker=true):
    taker_book_side == 'bid'  -> taker BOUGHT  -> MAKER SOLD
    taker_book_side == 'ask'  -> taker SOLD    -> MAKER BOUGHT
An earlier version had this inverted and confidently reported market making as a
-5% loser. If takers do not come out as net BUYERS (~4:1), the mapping is wrong.

WHAT IT STILL CANNOT TELL YOU: queue priority. These are the fills makers DID
get in aggregate; you would win some fraction of them, and plausibly the worse
fraction. Treat every number here as a CEILING.

Usage:  python research\mm_analyse.py
é    N)Údefaultdictz E:\soccer\research\mm_trades.csvz&E:\soccer\research\kalshi_backfill.csvc                  C   sž   i } z‚t tddd��`}t |¡D ]D}z$tj |d  dd¡¡| |d < W q  tt	fyb   Y q Y q 0 q W d   ƒ n1 sz0    Y  W n t
y˜   Y n0 | S )NÚ úutf-8©ÚnewlineÚencodingZkickoffÚZú+00:00Zevent)ÚopenÚBACKFILLÚcsvÚ
DictReaderÚdtÚdatetimeÚfromisoformatÚreplaceÚ
ValueErrorÚKeyErrorÚFileNotFoundError)ÚoutZfhÚr© r   ú E:\soccer\research\mm_analyse.pyÚkickoffs!   s    ÿ.r   c                 C   s   d  |  d¡d d… ¡S )Nú-é   )ÚjoinÚsplit©Útickerr   r   r   Úevent_of0   s    r    c                     s¬   t ƒ ‰ tt ttddd�¡ƒ‰ttˆƒd›dtdd„ ˆD ƒƒ› d�ƒ ‡ fd	d
„‰‡fdd„} | dd„ dƒ | ‡fdd„dƒ | ‡fdd„dƒ tdƒ tdƒ tdƒ d S )Nr   r   r   ú,z trades across c                 S   s   h | ]}t |d  ƒ’qS r   )r    )Ú.0r   r   r   r   Ú	<setcomp>7   ó    zmain.<locals>.<setcomp>z events
c                    s\   t | d ƒ}|ˆ vs| d s dS z"tj | d  dd¡¡ˆ | k W S  tyV   Y dS 0 d S )Nr   ZtsFr   r	   )r    r   r   r   r   r   )r   Úe)Úkor   r   Úpre9   s    "zmain.<locals>.prec                    s¬  t dd„ ƒ}t tƒ‰ d }}ˆD ]ü}| |ƒs.q t|d ƒt|d ƒt|d ƒ  }}}t|d ƒ}	|d d	krÀ||	 d
  || ||  7  < ||	 d  || 7  < ˆ |	  |7  < ||7 }q |d dkr ||	 d
  || ||  7  < ||	 d  || 7  < ˆ |	  |8  < ||7 }q dd„ | ¡ D ƒ}
t|
ƒdk �rZt|› dt|
ƒ› d�ƒ d S dd„ |
D ƒ}tdd„ | ¡ D ƒƒ}tdd„ | ¡ D ƒƒ}t 	|¡t
 t|ƒ¡ }tdd„ |D ƒƒ}t|› ƒ tdt|
ƒd›d|d›d|t|
ƒ d d›dt |¡d›dt |¡d›d t |¡| d!›�ƒ td"|| d d#›d$|d%›d&|t|dƒ d'›d(�ƒ ‡ fd)d„|D ƒ}td*td+d„ |D ƒƒ› d,t|ƒ› d-t |¡d%›d.�ƒ tƒ  d S )/Nc                   S   s   ddgS )Nç        r   r   r   r   r   Ú<lambda>C   r$   z&main.<locals>.report.<locals>.<lambda>r(   ÚpriceÚcountZ
result_yesr   Ztaker_book_sideZbidr   é   Zaskc                 S   s4   g | ],}|d  dkr|d |d   d |d  f‘qS )r,   iè  r   éd   r   ©r"   Úvr   r   r   Ú
<listcomp>U   r$   z(main.<locals>.report.<locals>.<listcomp>é
   z: only z events -- too fewc                 S   s   g | ]}|d  ‘qS )r   r   ©r"   Úxr   r   r   r0   Y   r$   c                 s   s   | ]}|d  V  qdS )r   Nr   r.   r   r   r   Ú	<genexpr>Z   r$   z'main.<locals>.report.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS )r,   Nr   r.   r   r   r   r4   [   r$   c                 s   s   | ]}|d krdV  qdS ©r   r,   Nr   r2   r   r   r   r4   ]   r$   z
   events Z4dz   profitable z (r-   z.0fz%)   median z+7.2fz	%   mean z%   t=z+5.2fz   notional-weighted z+.2fz%   on $z,.0fz   taker buy:sell z.1fz:1c                    s   g | ]}ˆ | ‘qS r   r   )r"   r%   ©Zshortr   r   r0   d   r$   z   maker ends net SHORT on c                 s   s   | ]}|d krdV  qdS r5   r   r2   r   r   r   r4   e   r$   ú/z events, median z
 contracts)r   ÚfloatÚintr    ÚvaluesÚlenÚprintÚsumÚ
statisticsZpstdevÚmathZsqrtZmedianZmeanÚmax)ZselZlabelZbyZsoldZboughtr   ÚpÚcÚresr%   ZevZroiZtotZnotiZseÚposÚns)Úrowsr6   r   ÚreportB   sV    ( 
 

,
ÿ
ÿþÿ
"
ÿ
zmain.<locals>.reportc                 S   s   dS )NTr   ©r   r   r   r   r)   i   r$   zmain.<locals>.<lambda>z
ALL tradesc                    s(   ˆ | ƒo&dt | d ƒ  ko"dkS   S )Ngš™™™™™©?r*   gffffffî?©r8   rH   ©r'   r   r   r)   j   r$   zPRE-KICKOFF, 5c-95cc                    s(   ˆ | ƒo&dt | d ƒ  ko"dkS   S )Ng333333Ã?r*   g333333ë?rI   rH   rJ   r   r   r)   l   r$   z5PRE-KICKOFF, 15c-85c   <-- the market you would quotez?READ: the per-event MEDIAN and t are the honest numbers. A highzDnotional-weighted ROI with a negative median means a few big matchesz$carried it, which is not a business.)r   Úlistr   r   r
   ÚTRADESr<   r;   )rG   r   )r&   r'   rF   r   Úmain4   s    (	'ÿÿrM   Ú__main__)Ú__doc__r   r?   r>   r   r   Úcollectionsr   rL   r   r   r    rM   Ú__name__r   r   r   r   Ú<module>   s   @