a
    D(Vj^!  ã                   @   s¾   d 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 d¡ dZ	d\Z
Zg d¢Zd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zddd„Zdd„ Zdd„ Zedkrºeƒ  dS ) at	  
Does xlow survive Kalshi-only execution (Polymarket geo-restricted)?  YES,
if you keep Poly as the confirming SIGNAL and reroute execution to Kalshi
for every bet -- NOT if you only take the bets where Kalshi was already
the cheap leg.

Question (2026-07-13): user is geo-restricted from trading Polymarket. Two
readings tested:

  A) SKIP Poly-cheap signals entirely (only act when Kalshi is the cheap leg)
  B) KEEP all signals (Poly still just watched for confirmation, never
     traded) but REROUTE every execution to Kalshi's ask, even on the 136
     bets where Poly was actually the cheaper book.

RESULTS on poly_backfill (286 strict-xlow bets, same rule/band as the live
forward tracker):
  Reference -- both books tradable (design as frozen):
    n=286  +24.7% gross ROI  z+2.59 p=0.005  fee-adj net (Kalshi legs only,
    Poly fee-free) +19.3%  bootstrap 90% CI [+8.3%,+42.8%] P(>0)=100%

  A) SKIP Poly-cheap (Kalshi-only OPPORTUNITY SET, n=150, 52% of signals):
    +29.2% gross -> +23.7% fee-adj net.  z+1.72 p=0.043.  Per-bet edge
    actually similar-or-better than blended (Kalshi legs always ran hotter
    than Poly legs individually) but n HALVES -> the n>=100 forward
    checkpoint takes ~2x as long to reach at current stamp rate.

  B) REROUTE Poly-cheap to Kalshi execution (n=286, FULL sample kept):
    +23.2% gross -> +17.8% fee-adj net.  z+2.41 p=0.008.  bootstrap 90% CI
    [+7.3%,+40.5%] P(>0)=99%.  Avg price markup paying Kalshi instead of
    Poly on the 136 rerouted bets: only +0.83c (Kalshi, as the "confirming"
    book, sits near fair -- not cheap, but not wildly expensive either; it
    was never missing a tradeable price on those 136 bets: 0/136).
    Isolating just the 136 rerouted bets: TRAIN -4.4% / TEST +47.4% (noisier,
    front-loaded into the back half) -- but pooled with the 150 Kalshi-
    native bets this barely moves the total (TRAIN +11.9%->+10.7%).

VERDICT: (B) is the right answer for geo-restricted execution. Keep watching
ALL xlow alerts regardless of which book the signal names, execute every one
at Kalshi's current ask. Costs ~1-2pp of ROI and a touch of significance
(p .005->.008) but loses ZERO sample size and stays clearly profitable/
significant/robust. (A) is dominated -- same downside, worse (halved n,
slower path to the n>=100 forward-validation checkpoint).

Read-only, backtest only. Mirrors kalshi_poly_pure_deviation.py conventions.
é    N)Údatetime)Údefaultdicté   zE:\soccer\poly_backfill)çš™™™™™©?g¸…ëQ¸¾?)z%Y-%m-%d %H:%M:%Sz%m/%d/%Y %H:%Mz%m/%d/%Y %H:%M:%Sz%Y-%m-%d %H:%Mc              
   C   s8   t D ].}zt | |¡W   S  ttfy0   Y q0 qd S ©N)Ú_FMTSr   ÚstrptimeÚ
ValueErrorÚ	TypeError)ÚsÚf© r   ú+E:\soccer\research\kalshi_only_execution.pyÚ_pts7   s    r   c              	   C   s(   z
t | ƒW S  ttfy"   Y d S 0 d S r   )Úfloatr
   r	   )Úxr   r   r   Ú_f<   s    r   c                 C   s8   t | ƒD ]*}| d¡pd ¡  ¡ }|dv r|  S qd S )NÚftrÚ )ÚHÚDÚA)ÚreversedÚgetÚupperÚstrip)ÚrowsÚrÚvr   r   r   Ú_result?   s    r   c                    s(   dd„ | D ƒ}t |ƒ‰ ‡ fdd„|D ƒS )Nc                 S   s   g | ]}d | ‘qS )g      ð?r   ©Ú.0r   r   r   r   Ú
<listcomp>E   ó    zfair_mult.<locals>.<listcomp>c                    s   g | ]}|ˆ  ‘qS r   r   )r!   Zri©r   r   r   r"   E   r#   )Úsum)Úor   r   r$   r   Ú	fair_multD   s    r'   c                 C   s(   | dk rdS | dk rdS | dk r$dS dS )Nr   gú~j¼t“h?g      Ð?g{®Gázt?gffffffÖ?gš™™™™™™?g{®Gáz”?r   )Úmidr   r   r   Úhalf_spreadF   s    r)   c            
   	   C   s  t tƒ} t t› d�¡D ]h}t|ddd��F}t |¡D ]*}| | d¡| d¡| d¡f  |¡ q6W d   ƒ q1 sv0    Y  qg }|  	¡ D ]^\}}|d }|s¤qŽt
d	d
„ |D ƒdd„ d�}t|ƒ}	|rŽ|	rŽ| t||	dd
„ |D ƒd�¡ qŽ|jdd„ d� |S )Nz\*_polybackfill.csvr   zutf-8)ÚnewlineÚencodingZ	game_dateÚhomeÚawayr   c                 S   s>   g | ]6}|  d ¡pd ¡ dkrt|d ƒrt|d ƒ|f‘qS )Zstatusr   ZPREZ	timestamp)r   r   r   )r!   r   r   r   r   r"   V   s   "ÿzload.<locals>.<listcomp>c                 S   s   | d S )Nr   r   )Útr   r   r   Ú<lambda>X   r#   zload.<locals>.<lambda>©Úkeyc                 S   s   g | ]\}}|‘qS r   r   )r!   Ú_r   r   r   r   r"   [   r#   )Úgdr   Úprec                 S   s   | d S ©Nr3   r   )r   r   r   r   r/   \   r#   )r   ÚlistÚglobÚDIRÚopenÚcsvZ
DictReaderr   ÚappendÚitemsÚsortedr   ÚdictÚsort)
ZfixturesÚpathZfhr   Úoutr1   r   r3   r4   r   r   r   r   ÚloadL   s"    Hþ rB   c                 C   sl  | d D �]\}t | d¡ƒt | d¡ƒt | d¡ƒ  }}}d|||fv s|dkr|dkr|dksdqt|||fƒ}g }dD �]Ð\}}t | d|› d	�¡ƒ}	t | d|› d
�¡ƒ}
t | d|› d�¡ƒ}|	du sz|du szd|	  k rêdk rzn qzd|  k �rdk �s
qz qz|	|k�rPd|	|
�r>d|
  k �r6dk �r>n n|
n|	|f\}}}}nd||t|ƒ |	f\}}}}|| | ||  }|| | ||  }||k rzt|  k�r´tk �s¸qz qzt|  k�rÐtk �rÖqz nqz| d dk�rî|dk�p| d dk�o|dk}|
�r*d|
  k �r"dk �r*n n|
n|	}| t||||| d |d�¡ qz|rt|dd„ d�  S qdS )z×Strict xlow (same as forward_test_unique_book.fire_xlow). Also records
    the Kalshi ask for the picked side at the firing snapshot regardless of
    which book qualified, so rerouted-execution scoring is possible.r4   Zpin_homeZpin_drawZpin_awayNé   ))r,   r   )r-   é   Zkalshi_Z_midZ_askZpoly_Z_pricer   ÚkalshiÚpolyr   r   r,   r   r-   r3   )ÚclvÚpxÚbookÚwonr3   Ú
kalshi_askc                 S   s   | d S )NrG   r   )Údr   r   r   r/   s   r#   zxlow.<locals>.<lambda>r0   )	r   r   r'   r)   ÚLOÚHIr;   r>   Úmax)Zfxr   ZphZpd_ZpaZpfZcandsZsideZsiZkmZkaZpmrI   r(   rH   ÚotherrG   ZoclvrJ   Zkalshi_ask_herer   r   r   Úxlow_   s$    .(,DF($.* rQ   Tc                 C   sè  t | ƒ}|dk rd S tdd„ | D ƒƒ}tdd„ | D ƒƒ}|rNtdd„ | D ƒƒnd}tdd„ | D ƒƒ}tdd„ | D ƒƒ}|dkr�|| t |¡ nd}d	t |t d
¡ ¡ }	t|d ƒ}
dd„ }ttƒ}| D ]}||d   |¡ qÌt| 	¡ ƒ}g }t
dƒD ]:}g }t
t |ƒƒD ]}| t |¡¡ �q| ||ƒ¡ qü| ¡  t|||| d || d || d ||| | d ||	|| d |
… ƒ|| |
d … ƒ|t |ƒd
  |tdt |ƒ ƒ |tdt |ƒ ƒ tdd„ |D ƒƒt |ƒ d d�S )Nr   c                 s   s   | ]}|d  V  qdS )rJ   Nr   ©r!   Úbr   r   r   Ú	<genexpr>y   r#   zmetrics.<locals>.<genexpr>c                 s   s.   | ]&}|d  r"d|d  |d  ndV  qdS ©rJ   rC   rH   éÿÿÿÿNr   rR   r   r   r   rT   z   r#   c                 s   s   | ]}d d|d   V  qdS )gìQ¸…ë±?rC   rH   Nr   rR   r   r   r   rT   {   r#   r   c                 s   s   | ]}|d  V  qdS )rH   Nr   rR   r   r   r   rT   |   r#   c                 s   s"   | ]}|d  d|d    V  qdS )rH   rC   Nr   rR   r   r   r   rT   |   r#   g      à?rD   g333333ã?c                 S   s&   | r"t dd„ | D ƒƒt| ƒ d S dS )Nc                 s   s.   | ]&}|d  r"d|d  |d  ndV  qdS rU   r   rR   r   r   r   rT   €   r#   z'metrics.<locals>.roi.<locals>.<genexpr>éd   r   )r%   Úlen)Zxsr   r   r   Úroi€   r#   zmetrics.<locals>.roir3   iÐ  rW   r   gffffffî?c                 s   s   | ]}|d krdV  qdS )r   rC   Nr   r    r   r   r   rT   �   r#   )ÚnÚwÚwrÚiwrrY   ÚnetÚnet_feeÚzÚpÚtrainÚtestÚboot_medÚboot_loÚboot_hiÚppos)rX   r%   ÚmathZsqrtZerfcÚintr   r6   r;   ÚvaluesÚrangeÚextendÚrandomZchoicer?   r>   )r<   Úfee_adjrZ   r[   r^   ZfeesZmuÚvarr`   ra   ZcutrY   ZdaysrS   ZdlZroisr2   Zpoolr   r   r   Úmetricsv   s0    $$& .ürp   c                 C   s*  |st d| › d�ƒ d S t d| › d�ƒ t d|d › d|d › d|d |d  › d	|d
 d›d|d d›d|d
 |d  d›d�ƒ t d|d d›d|d d›d|d d›d�ƒ t d|d d›d|d d›d|d d›d |d! d›d�	ƒ t d"|d# d›d$|d% d›d&|d' d›d(|d) d*›d�	ƒ d S )+Nz  z: (n<5)z
--- z ---z  n=rZ   r[   zW-zL  WR=r\   z.1fz% (impl r]   z%, edge z+.1fzpp)z  gross ROI=rY   z%  net=r^   zu  |  fee-adj NET=r_   ú%z  z=r`   z+.2fz  p=ra   z.4fz  TRAIN=rb   z%  TEST=rc   z  bootstrap: median=rd   z
%  90%CI=[re   z%,rf   z
%]  P(>0)=rg   z.0f)Úprint)ZlabelÚmr   r   r   Úline�   s    \.:rt   c                  C   s   t ƒ } dd„ dd„ | D ƒD ƒ}|jdd„ d� dd„ |D ƒ}d	d„ |D ƒ}d
d„ |D ƒ}t|| dd„ d�}tdt|ƒ› d�ƒ tdt|dd�ƒ tdt|ƒƒ tdt|ƒƒ tdt|ƒƒ dd„ t||ƒD ƒ}tdt|ƒt|ƒ d d›d�ƒ tdd„ |D ƒƒ}td|› dt|ƒ› �ƒ d S )Nc                 S   s   g | ]}|r|‘qS r   r   rR   r   r   r   r"   ™   r#   zmain.<locals>.<listcomp>c                 s   s   | ]}t |ƒV  qd S r   )rQ   )r!   r   r   r   r   rT   ™   r#   zmain.<locals>.<genexpr>c                 S   s   | d S r5   r   ©rS   r   r   r   r/   š   r#   zmain.<locals>.<lambda>r0   c                 S   s   g | ]}|d  dkr|‘qS )rI   rE   r   rR   r   r   r   r"   ›   r#   c                 S   s   g | ]}|d  dkr|‘qS )rI   rF   r   rR   r   r   r   r"   œ   r#   c                 S   s   g | ]}t ||d  d�‘qS )rK   ©rH   )r>   rR   r   r   r   r"   �   r#   c                 S   s   | d S r5   r   ru   r   r   r   r/   ž   r#   zTotal strict xlow universe: z bets
z1REFERENCE: both books tradable (design as frozen)F)rn   z/A) SKIP Poly-cheap: Kalshi-only opportunity setz>B1) the 136 Poly-cheap bets, rerouted to Kalshi ask (isolated)z6B) FULL 286, all rerouted to Kalshi execution (pooled)c                 S   s    g | ]\}}|d  |d   ‘qS rv   r   )r!   ÚoldÚnewr   r   r   r"   ¦   r#   zC
avg price markup paying Kalshi instead of Poly on rerouted bets: +rW   z.2fÚcc                 s   s4   | ],}|d  r(d|d    k r&dk sn dV  qdS )rK   r   rC   Nr   rR   r   r   r   rT   ©   r#   z.rerouted bets with NO tradeable Kalshi price: z of )	rB   r?   r=   rr   rX   rt   rp   Úzipr%   )ÚFZbetsZkalshi_nativeZ	poly_origZpoly_reroutedZall_reroutedZdiffsZmissingr   r   r   Úmain—   s$    ÿ
r|   Ú__main__)T)Ú__doc__r:   r7   rh   rm   r   Úcollectionsr   Zseedr8   rM   rN   r   r   r   r   r'   r)   rB   rQ   rp   rt   r|   Ú__name__r   r   r   r   Ú<module>   s&   - 

