o
    >j)                     @   sz   d Z ddlZddlZddlmZmZmZmZmZm	Z	 ddl
mZmZ ddl
mZmZ ddlmZmZmZ G dd	 d	ZdS )
u  
V12 — Executor: taker orders para momentum.

Live mode:
  - GTC aggressive limit (al ask + AGGRESSIVE_BUMP) — V12: reducido de +0.02 a +0.01
  - Verificación de fill vía CLOB get_trades API (V12: reemplaza positions API rota)
  - Balance check antes de operar
  - Cancel de órdenes pendientes si no se llenan

V12 fix crítico: verify_fill usa client.get_trades(asset_id) en vez de
data-api.polymarket.com/positions. La positions API tiene latencia de minutos
y nunca muestra fills recientes, causando que TODOS los trades caigan al path
FILL TRUST (que creaba trades fantasma). get_trades devuelve fills CONFIRMED
con transaction_hash — es la fuente de verdad on-chain.
    N   )ConfigHOSTCHAIN_ID
MIN_SHARESPAPER_SLIPPAGE
snap_price)
ClobClientSide)BalanceAllowanceParams	AssetType)ApiCredsOrderArgsV2TradeParamsc                   @   s   e Zd ZdefddZddedefddZd	ed
ededede	eeef f
ddZ
	dd	edededB fddZdedefddZdefddZdS )Executorcfgc                 C   s   || _ d | _d| _d| _|jrUtdd dd}tdd }t	tdtdtdd	}t
tt||d
|d| _|  }td|j  d| d|d d S td|j  d d S )N        PK 0x
POLY_PROXYPOLY_API_KEYPOLY_API_SECRETPOLY_API_PASSPHRASE)api_key
api_secretapi_passphrase   )hostchain_idkeycredssignature_typefunderz[*] Executor TAKER LIVE [z
] | proxy=z | balance=$z.4fz[*] Executor TAKER PAPER [])r   client_balance_cache_balance_tsliveosgetenvstripreplacer   r	   r   r   get_balanceprintassetupper)selfr   pkproxyr!   bal r5   0/var/www/html/MetaHedge/POLYBOT1/v12/executor.py__init__   s.   zExecutor.__init__F	use_cachereturnc                 C   s   | j jr| js	dS |rt | j dk r| jS z| jttj	d}t
|ddd }|| _t | _|W S  tyK   | jdkrG| j Y S d Y S w )Ng    @   )
asset_typebalancer   g    .Ar   )r   r(   r%   timer'   r&   get_balance_allowancer   r   
COLLATERALintget	Exception)r1   r8   rr4   r5   r5   r6   r-   3   s   

zExecutor.get_balancetoken_idpricesizelabelc                 C   s  t |}tt|dt}| jjr| jsDt |t }dtt		  d| }t
d| d|dd|dd|d	d
|| d
 d||dfS || }|  }||d k rdt
d| d|dd|dd dS t || jj }	zt||	|dd}
| jj|
dd}t|trd|d}|dd}|dp|dpd}|dp|dpd}|dpd }|s|d v rt|d!pd"}|d"kr|n|}t
d#| d|	dd$|d	d%t|d&d'  d(	 dt||	dfW S |d)v rt
d*| d|	dd$|d	d+| d,t|d&d'  d( dt||	d-fW S t
d.| d/|p|p|  W d0S  tyG } zt
d1| d/t|d&d2   W Y d&}~d0S d&}~ww )3z
        Place a taker BUY order at the ask price.
        Returns (success, order_id, fill_price).
        Paper: simulates fill at ask + slippage.
        Live: GTC aggressive limit, then verify fill via positions.
        r   paper__z  [PAPER TAKE] z @ z.2fz (ask=z) x z.1fz sh = $Tmatchedg?z  [TAKE SKIP] z: balance $z	 < cost $z	 + margen)Fr   r   BUY)rD   rE   rF   sideGTC)
order_args
order_type)successorderIDrP   FrQ   order_idr   errorMsg	error_msgstatus)rJ   filledtakingAmountr   z  [TAKE FILLED] z x z
 sh | oid=N   z...)r(   openz  [TAKE PENDING] z sh | status=z | oid=pendingz  [TAKE FAIL] : )Fr   r   r   z  [TAKE ERR] P   )r   maxroundr   r   r(   r%   r   r@   r=   r.   r-   aggressive_bumpr   create_and_post_order
isinstancestrrA   lowerfloatrB   )r1   rD   rE   rF   rG   
fill_priceoidcostr4   aggressive_priceargsresprP   err_msgrU   takingactual_sizeer5   r5   r6   place_taker_orderE   sz   





  zExecutor.place_taker_orderr   order_tsNc              
   C   sP  | j jr| js	dS tdd  }|sdS |dkr|d ntt d }z| jj	t
|ddd	}W n tyN } ztd
|  W Y d}~dS d}~ww d}d}	g }
|D ]}|dp_d }|dkrgqW|dd |kr|ddkrt|dd|krt|dd}t|dd}|dkr|dkr||7 }|	|| 7 }	|dd}|r|
| |dg D ]Q}|dd |krqt|dd}||krqt|dd}t|dd}|dkr|dkr||7 }|	|| 7 }	|dd}|r||
vr|
| qqW|dkrdS |dkrt|	| dnd}t|d||
dS )a  Verify fill via CLOB get_trades API.

        Busca trades CONFIRMED donde nuestra address aparece como maker
        en maker_orders para el asset_id dado, desde order_ts en adelante.

        Returns {"size": float, "avg_price": float, "tx_hashes": list} or None.

        V12: Reemplaza la positions API (data-api.polymarket.com/positions)
        que tiene latencia de minutos y nunca mostraba fills recientes,
        causando trades fantasma via FILL TRUST.
        Nr   r   r   <   x   )afterT)only_first_pagez  [verify] get_trades error: r   rU   	CONFIRMEDmaker_addresstrader_sideTAKERasset_idrF   rE   transaction_hashmaker_ordersmatched_amount      )rF   	avg_price	tx_hashes)r   r(   r%   r)   r*   r+   rc   r@   r=   
get_tradesr   rB   r.   rA   r0   rb   rd   appendr^   )r1   sessionrD   rp   r3   after_tstradesrn   
total_sizeweighted_pricer   trU   szpxtx_hmomo_assetr   r5   r5   r6   verify_fill   sr    



zExecutor.verify_fillrR   c              
   C   s  | j jr| js	dS z<| j|}t|tr"d| v p d| v W S t|trC|ddp2|dd}|s@dt| v r@W dS |W S W dS  t	y } z0t| }d|v s[d|v rbW Y d }~dS t
d|d d  d	t|d d
   W Y d }~dS d }~ww )NTcanceledz	not foundFrP   alreadyz  [CANCEL ERR] rX   r[   rq   )r   r(   r%   cancel_orderra   rb   rc   dictrA   rB   r.   )r1   rR   rj   	cancelledrn   errr5   r5   r6   r      s*   

(zExecutor.cancel_orderc              
   C   s   | j jr| js	dS z*| j }t|tr|dg ng }t|tr%t|nd}|r1t	d| d |W S  t
yS } zt	dt|d d   W Y d }~dS d }~ww )Nr   r   z  [CANCEL ALL] z ordenes canceladasz  [CANCEL ALL ERR] rq   )r   r(   r%   
cancel_allra   r   rA   listlenr.   rB   rb   )r1   rj   r   nrn   r5   r5   r6   r      s   
zExecutor.cancel_all)F)r   )__name__
__module____qualname__r   r7   boolrd   r-   rb   tuplero   r@   r   r   r   r   r5   r5   r5   r6   r      s     
J
Ur   )__doc__r)   r=   configr   r   r   r   r   r   py_clob_client_v2r	   r
   r   r   py_clob_client_v2.clob_typesr   r   r   r   r5   r5   r5   r6   <module>   s     