a
    ˜¸kjC  ã                   @   s’   d Z ddlZddlZddlZddlZddlmZ ej 	dd¡ ej 	dd¡ ddl
ZddlZddlmZ dZdZd	d
„ Zdd„ ZedkrŽeƒ  dS )a,  What would the DECAYING-ARM policy have earned on a past day?

Compares three policies on the same logged quotes and the same real trade tape:

  A  FIXED arm, no concede      -- what actually ran for most of 2026-07-29
  B  FIXED arm + concede at T-60
  C  DECAYING arm + concede     -- the current policy

C is what we want to price. B is the control that isolates how much of C's gain
comes from conceding rather than from the decay itself; without it, the decay
would get credit for the concede's work.

Every policy is scored with the SAME queue-aware fill model used live: a fill
requires cumulative volume at or above our price, since we last (re)posted, to
exceed the depth resting there when we posted. Above the touch that depth is 0
(nobody else quotes there), so stepping down through high rungs costs no queue
position; joining the touch does.

Book outcomes follow the live stack: 3 legs -> natural; 2 -> cross the last into
the bid; 1 -> buy it back flat; 0 -> no position.

CAVEAT the numbers cannot escape: our own orders are not in the tape. If we had
actually rested at these prices, some of the volume we count would have traded
against US and not printed at all, and other makers would have reacted. This is
a replay, not a counterfactual market.

Usage:  python research\decay_backtest.py [YYYY-MM-DD]
é    N)ÚdefaultdictzE:\soccer\mainzE:\soccer\research)Útrades_sizedé
   gìQ¸…ë±?c           (         s  d } } }}d}|   ¡ D �]Ö\}}	t|	ƒdkr4qi i  ‰ }
|	  ¡ D �]²\}\}}t |d d ¡}| |g ¡}tt|d d ƒd t|d d ƒd  ƒ}d}d}d}d}d}t|ƒD �]\}}t |d	 ¡}|du sâ||krè �qÄ||  ¡ d
 }t|d ƒ}zt|d ƒ}W n t	t
f�y0   Y qºY n0 |dk�rLt |||¡}n|}|dv �rj|dk�rj|}n t|t |¡d  ||d  ƒ}t t|d dƒ¡d }|du �sº||d k �r |du�rÈd}|}| d¡}|�pÞd ¡ �rü||d k�rüt|ƒnd}|d t|ƒk �r(t ||d  d	 ¡n|}|du �s@||k�rD|}|t|ƒk �r´|| d |k �r´|| \} }!}"|d7 }| |k�rˆ�q´|!|d k�rD||"7 }||k�rD|}�q´�qD|durº �qÄqº|du�rÖ|ˆ |< t|d d ƒt|d d ƒf|
|< qFtˆ ƒdk�r,|d7 }|tˆ  ¡ ƒd t 7 }qtˆ ƒdk�r–‡ fdd„|	D ƒd }#|
|# d }$tˆ  ¡ ƒ|$ }%|d7 }||%d t|$ d|$   t 7 }qtˆ ƒdk�rìtˆ ƒd }&|
|& d }'|d7 }||'ˆ |&  t|' d|'    t 7 }q|d7 }q|||||fS )z2policy: 'fixed', 'fixed_concede', 'decay_concede'.r   g        é   ÚkickoffÚour_askéd   Úk_askNÚtsg      ¬@Úpin_fairÚdecay_concede)Úfixed_conceder   g      ð?g      Y@é   g•Ö&è.>Zask_sizeÚ é   éÿÿÿÿZk_bidé   c                    s   g | ]}|ˆ vr|‘qS © r   )Ú.0Ús©Zfilledr   ú$E:\soccer\research\decay_backtest.pyÚ
<listcomp>r   ó    zsimulate.<locals>.<listcomp>)ÚitemsÚlenÚSÚ_ptÚgetÚroundÚfloatÚ	enumerateZtotal_secondsÚ	TypeErrorÚ
ValueErrorÚQZarm_forÚminZ
margin_forÚmathZceilÚstripÚsumÚvaluesÚSIZEÚTAKERÚlist)(Zlegs_by_bookÚtradesÚpolicyÚnatZcompZflatÚnoneÚtotalZevZlegsZlastÚsideÚtkÚrsÚkoZtrZarm0Zcur_pxZqueueZcumZhit_pxZtiÚiÚrÚtZhrsZmktZfairZarmZwantZaszZnxtZttÚtpZtcZmissZbidZcollZs0Zaskr   r   r   Úsimulate-   s˜    
,

 


ÿÿ, 


&"(
r:   c                     s   t tjƒdkrtjd nd} ttƒ}tddd��d}t |¡D ]H}|d d d… | kr<| d¡r<| d	¡r<| d
¡r<||d   	|¡ q<W d   ƒ n1 sš0    Y  tt
ƒ}| ¡ D ]8\}}|jdd„ d� ||f||d d  |d d < q´t| › dt |ƒ› dt |ƒ› d�ƒ i }| ¡ D ]F\}}t |d d ¡‰ ‡ fdd„t|t |d d ¡ƒD ƒ||< �qtddd›ddd›ddd›ddd›dd d!›dd"d#›�ƒ d$D ]Z\}}	t|||ƒ\}
}}}}td|	d›d|
d%›d|d%›d|d%›d|d&›d|d'›d(�ƒ �q d S ))Nr   z
2026-07-29z&E:\soccer\research\mm_paper_quotes.csvzutf-8)Úencodingr
   r   r   r	   r   Z
leg_tickerc                 S   s   | d S )Nr
   r   )Úxr   r   r   Ú<lambda>‹   r   zmain.<locals>.<lambda>)Úkeyr   Zeventr2   z: z legs across z books
r   c                    s$   g | ]\}}}|ˆ k r|||f‘qS r   r   )r   r8   ÚpÚc©r5   r   r   r   ’   s   ÿzmain.<locals>.<listcomp>z  r.   Z26sú r/   z>4sz2/3z1/3r0   z>5szP&Lz>9s))ZfixedzA fixed arm, no concede)r   zB fixed arm + concede)r   zC DECAY + concedeZ4dZ5dz+8.2fú$)r   ÚsysÚargvr   r,   ÚopenÚcsvZ
DictReaderr   ÚappendÚdictr   ÚsortÚprintr   r   r   r:   )ZdayZrowsZfhr7   Zbyr3   r4   r-   ZpolZlblÚnr@   ÚfÚzr8   r   rA   r   Úmain�   s.    (ÿ2""
ÿ8rO   Ú__main__)Ú__doc__rG   ZdatetimeZdtr&   rD   Úcollectionsr   ÚpathÚinsertZ	mm_settler   Z	mm_quoterr$   Zqueue_aware_fillr   r*   r+   r:   rO   Ú__name__r   r   r   r   Ú<module>   s    T