a
    o€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mZ ddlm	Z	 ej
 dd¡ ej
 dd¡ e	dƒZe	dƒZg d	¢Zd
dddœZe d¡Ze d¡Zd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Ú  Score the Poly-US paper market maker.

WHY THIS EXISTS. mm_quoter_polyus.py has been quoting since 2026-07-29 and
writing mm_polyus_quotes.csv, but nothing ever read that file back. The Kalshi
book has mm_settle.py; this side had no scorer at all, so ~460k quote rows
across 264 books sat unmeasured -- on the one venue that CREDITS the maker
(MAKER_THETA = 0.0125 x p(1-p)).

SCORE BOOKS, NOT LEGS. A leg is not the unit of risk here. The quoter takes two
terminal actions that a leg-by-leg reading misses entirely, and an earlier
version of this file missed both:

  COMPLETE_AT_BID -- two legs have sold, so cross into the bid on the third
    near kickoff. The book is then short all three outcomes, exactly one of
    which pays: the P&L is LOCKED and outcome-independent. Holding these to
    settlement scores a position that was already closed.
  FLATTEN_1OF3 -- only one leg sold, so buy it back rather than carry a naked
    position into the match. Also closed before kickoff, also not a settlement.

Both write their realised per-contract economics into `reason` at the moment
they fire, computed with the live fee schedule. This reads those numbers rather
than recomputing them, for the same reason it reads `rebate_c` off the row: a
second implementation of the fee model is a second thing to drift.

WHAT A PASSIVE FILL MEANS, and why it is a CEILING. Poly-US exposes no trade
tape; `last_px` is a LEVEL sampled every 20s. A level already above our ask when
we start quoting is not evidence anyone traded with us, so a fill counts only
when last_px CHANGES to a value at or above our resting ask. Still optimistic --
it assumes we held queue priority for that print. Same caveat mm_settle carries.

Usage:  python main\mm_settle_polyus.py
é    N)Údefaultdict)ÚPathzE:\soccer\mainzE:\soccer\researchz'E:\soccer\research\mm_polyus_quotes.csvz(E:\soccer\research\mm_polyus_results.csv©Ú
event_slugÚdivÚmatchÚkickoffZ	legs_soldÚoutcomeZpnl_c_per_contractZ	contractsÚpnl_dollarsÚrebate_cÚregimeÚHÚDÚA)ÚhomeZdrawÚawayz#=>\s*([+-]?[\d.]+)c/contract lockedz#=>\s*cost\s*([+-]?[\d.]+)c/contractc              	   C   s*   z
t | ƒW S  ttfy$   | Y S 0 d S )N)ÚfloatÚ	TypeErrorÚ
ValueError)ÚxÚd© r   ú"E:\soccer\main\mm_settle_polyus.pyÚ_f6   s    
r   c                  C   s¢   t t ¡ ƒd } t t| ¡ ttƒ}| jdddd��<}t	 
|¡D ] }| d¡r@||d   |¡ q@W d  ƒ n1 sv0    Y  | ¡ D ]}|jdd	„ d
� qˆ|S )zÕRows grouped by leg, timestamp-ordered. Snapshotted first: the quoter
    holds the real file open and polls every 20s, and a partial read of a 96MB
    CSV mid-write is a silent wrong answer rather than an error.zmm_polyus_quotes.snap.csvÚ úutf-8Úreplace)ÚnewlineÚencodingÚerrorsZmarket_slugNc                 S   s   |   d¡pdS )NZtsr   )Úget)Úrr   r   r   Ú<lambda>I   ó    zload_quotes.<locals>.<lambda>©Úkey)r   ÚtempfileZ
gettempdirÚshutilZcopyfileÚQUOTESr   ÚlistÚopenÚcsvZ
DictReaderr    ÚappendÚvaluesÚsort)ÚtmpÚby_legÚfhr!   Úvr   r   r   Úload_quotes=   s    
2r3   c               	   C   sb   dd l } i }| jdd�D ]D}|d r0|d d ni }|d ||d |d | d¡| d	¡f< q|S )
Nr   T)Zrequire_resultZpreÚftrÚgdZleaguer   r   )Zforward_test_unique_bookZload_fixturesr    )ÚFÚoutZfxÚr0r   r   r   Úresults_mapM   s    *r9   c           	      C   sZ  d}d}d}| D �],}|  d¡p"d}d|v rdt |¡}dt|  d¡ƒ|rXt| d¡dƒnd|f  S d	|v r¤t |¡}d
t|  d¡ƒ|r˜t| d¡dƒnd|f  S t|  d¡ƒt|  d¡ƒ }}|du �r2|du�r2|du�r2d|  k rödk �r2n n8|du�r2||k�r2||k�r2|}t|  d¡dƒ�p0d}|dur|}q|du�rVd|d|fS dS )zÃ(state, price, per_contract_c, rebate_c) for one leg.

    state is 'completed' (crossed into the bid), 'flattened' (bought back),
    'sold' (passive fill, still open at kickoff) or 'none'.
    Nç        Úreasonr   ZCOMPLETE_AT_BIDÚ	completedZour_aské   ZFLATTEN_1OF3Ú	flattenedZlast_pxr   r   Úsold)ZnoneNNr:   )r    Ú	RE_LOCKEDÚsearchr   ÚgroupÚRE_COST)	ÚrowsZsold_pxÚrebÚprevr!   r;   ÚmZaskZlpr   r   r   Ú	leg_stateV   s&    

.
.8rH   c                  C   s8  t ƒ } tƒ }ttƒ}|  ¡ D ]$\}}||d  d¡  ||f¡ qg d }}| ¡ D �]j\}}|d d d }	|	 d¡pzdd d… }
| |
|	 d¡p–d ¡ |	 d¡|	 d	¡f¡}i }|D ]*\}}|d  d
¡pÐd ¡ }t	|ƒ||< q¸dd„ | 
¡ D ƒ}t|ƒ}dd„ | 
¡ D ƒ}tdd„ | 
¡ D ƒƒ}|�s4|�s4qT|dv�rT|�sT|�sT|d7 }qTt|	 d¡dƒ�phd}tdd„ | 
¡ D ƒƒ}tdd„ |D ƒƒ}|�r´tdd„ | 
¡ D ƒƒ}d}n’|�rÒ|dk�rÒ|| }d}ntd}| ¡ D ]N\}}|d dk�rÞ|d d u�rÞ||d t |¡|k�rdnd d 7 }�qÞ||| 7 }d|› d�}|t|t|ƒ dƒ }| ||	 d¡|	 d¡› d|	 d	¡› �|	 d¡||t|dƒ|t|| d dƒt|dƒ|	 d ¡d!œ¡ qTtjd"dd#d$��<}tj|td%�}| ¡  |D ]}| |¡ �qîW d   ƒ n1 �s0    Y  tt|t|ƒ|ƒƒ d S )&Nr   r   r=   r   r   é
   r   r   r   Úsidec                 S   s   g | ]}|d  dv r|‘qS )r   )r?   r<   r   ©Ú.0Úsr   r   r   Ú
<listcomp>„   r#   zmain.<locals>.<listcomp>c                 S   s   g | ]}|d  dkr|‘qS )r   r>   r   rK   r   r   r   rN   †   r#   c                 s   s   | ]}|d  dkV  qdS )r   r<   Nr   rK   r   r   r   Ú	<genexpr>‡   r#   zmain.<locals>.<genexpr>)r   r   r   Úsizeg      $@c                 s   s   | ]}|d  V  qdS )é   Nr   rK   r   r   r   rO   �   r#   c                 s   s   | ]}|d  pd V  qdS )é   r:   Nr   rK   r   r   r   rO   ™   r#   c                 s   s"   | ]}|d  dkr|d V  qdS )r   r<   rR   Nr   rK   r   r   r   rO   ›   r#   Úcompleter>   r:   r?   g      Y@zopen z/3z vs rQ   é   r   r   Úwr   )r   r   )Z
fieldnames)r3   r9   r   r)   Úitemsr    r,   ÚupperÚlowerrH   r-   ÚlenÚanyr   ÚsumÚnextÚSIDE_WINÚmaxÚroundÚRESULTSr*   r+   Z
DictWriterÚFIELDSZwriteheaderZwriterowÚprintÚ	summarise)r0   ÚresÚbooksZslugrD   r7   Ú
unresolvedZevZlegsr8   r5   r4   ZstatesrJ   r?   Zn_soldZflatr<   rP   rE   Zflat_pnlZperr	   rM   Zctsr1   rU   Úor   r   r   Úmainq   sn    
ÿ
,


ú
.rh   c                    s  dd|› dt | ƒ› d|› d�dg}| s6d |dg ¡S tdd	„ | D ƒƒ}|d
t | ƒ› �d|d›d�dg7 }tdd„ ƒ‰ | D ]L}|d dv r’|d n|d }ˆ | d  d7  < ˆ | d  |d 7  < qz|ddddd›ddd›ddd›ddd›�g7 }tˆ ‡ fdd„d�D ]>}ˆ | \}}| |d›d|d›d|d ›d|| d!›�¡ �q
| d¡ td"d„ ƒ}	| D ]:}|	|d#  d  d7  < |	|d#  d  |d 7  < �qd|g d$¢7 }t|	 ¡ d%d„ d�D ]>\}
\}}| d&|
d'›d|d(›d)|d*›d+|| d,›d-�	¡ �qÀ|g d.¢7 }d |¡S )/Nz(POLY-US PAPER MARKET MAKER  (book-level)r   z books in the quote log, z  that traded and can be scored (z traded but unsettled)Ú
znothing scoreable yetc                 s   s   | ]}|d  V  qdS )r
   Nr   )rL   rg   r   r   r   rO   Á   r#   zsummarise.<locals>.<genexpr>z  books scored        : z  TOTAL P&L           : z+,.2fz dollarsc                   S   s   ddgS ©Nr   r:   r   r   r   r   r   r"   Å   r#   zsummarise.<locals>.<lambda>r	   )rS   r>   r   r=   r
   ú>--------------------------------------------------------------zBY HOW THE BOOK ENDEDZ12ú re   z>6zP&L $z>10zper bookc                    s   ˆ |  d  S ©Nr=   r   )r   ©Zgrpr   r   r"   Ì   r#   r$   z>10,.2fz>10,.3fc                   S   s   ddgS rj   r   r   r   r   r   r"   Ñ   r#   r   )rk   z	BY LEAGUEr   c                 S   s   | d d  S rm   r   )Zkvr   r   r   r"   Ö   r#   z  Z6sz>4z books  z+8,.2fz $  z+7.3fz $/book)r   zAComplete books are OUTCOME-INDEPENDENT -- locked at the moment wezCcrossed. Flattened books are closed positions. Only "open n/3" rowszCcarry match risk. Passive fills assume queue priority, so those arez)a CEILING, same caveat mm_settle carries.)rY   Újoinr[   r   Úsortedr,   rV   )r7   Z
books_seenrf   ÚLZtotrg   ÚkÚnÚpZby_divr   r   rn   r   rc   º   sB    ÿþÿ ÿ0
  4rc   Ú__main__)N)Ú__doc__r+   Úrer'   Úsysr&   Úcollectionsr   Úpathlibr   ÚpathÚinsertr(   r`   ra   r]   Úcompiler@   rC   r   r3   r9   rH   rh   rc   Ú__name__r   r   r   r   Ú<module>   s.    


	I%