o
    8
úhõ)  ã                   @   sb  d Z ddlZddlZddlmZmZmZ ddlmZm	Z	 ddl
m
Z
 ddlZddlmZ e e¡ZeG dd„ dƒƒZG d	d
„ d
ƒZdad+dededefdd„Zedkr­ejejd� eddƒZejdddddddddddd �Zed!ƒ e ¡ Ze ¡ D ]\ZZ ed"e› d#e › �ƒ q{ed$ƒ e !¡ D ]Z"ed%e"j#› d&e"j$› d'e"j%r£d(nd)› d*e"j&› �ƒ q’dS dS ),u~   
Position Manager - Tracking local des positions en temps rÃ©el
Sauvegarde les positions au fur et Ã  mesure que le bot trade
é    N)ÚDictÚListÚOptional)Ú	dataclassÚasdict)Údatetime)ÚRLockc                   @   sæ   e Zd ZU dZeed< eed< eed< eed< eed< eed< eed< eed	< eed
< eed< eed< eed< eed< dZ	eed< dZ
ee ed< dZee ed< dZee ed< dZee ed< dZee ed< dZee ed< dS )ÚPositionu   Position tradÃ©eÚ
trade_hashÚtx_hashÚsymbolÚpair_addressÚis_longÚmarginÚleverageÚentry_priceÚqtyÚ	stop_lossÚtake_profitÚ	opened_atÚblock_numberÚOPENÚstatusNÚ	closed_atÚclose_tx_hashÚ
exit_priceÚpnlÚpnl_pctÚclose_reason)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__ÚboolÚfloatÚintr   r   r   r   r   r   r   r   © r(   r(   úL/var/www/html/HyperOracle/crypto_trader/apollo_degen_bot/position_manager.pyr	      s,   
 r	   c                   @   s   e Zd ZdZd+dedefdd„Z			d,ded	ed
edededededededededede	fdd„Z
		d-dedededededee	 fdd„Zdee	 fdd„Zdee	 fdd „Zdedee	 fd!d"„Zdee	 fd#d$„Zdefd%d&„Zd'd(„ Zd)d*„ ZdS ).ÚPositionManageru]   
    Gestionnaire de positions local
    Enregistre et suit les positions en temps rÃ©el
    úpositions.jsonÚwallet_addressÚstorage_filec                 C   s>   || _ || _i | _tƒ | _|  ¡  t dt| jƒ› d�¡ d S )Nu"   ðŸ“Š PositionManager initialisÃ©: u    positions chargÃ©es)	r,   r-   Ú	positionsr   ÚlockÚloadÚloggerÚinfoÚlen)Úselfr,   r-   r(   r(   r)   Ú__init__1   s   zPositionManager.__init__r   r
   r   r   r   r   r   r   r   r   r   r   r   Úreturnc                 C   s´   | j �M t|||||||||	|
|t ¡  ¡ |dd�}|| j|< |  ¡  t d|› d|r-dnd› d|› d|d›d	�	¡ t d
|dd… › d�¡ |W  d  ƒ S 1 sSw   Y  dS )u�  
        Ajoute une nouvelle position ouverte

        Args:
            trade_hash: Hash unique de la position (depuis l'event)
            tx_hash: Hash de la transaction
            symbol: Symbole tradÃ© (BTCUSD_DEGEN, ETH, etc.)
            pair_address: Adresse du pair token
            is_long: True si long, False si short
            margin: Montant de margin en USDT
            leverage: Leverage utilisÃ©
            entry_price: Prix d'entrÃ©e
            qty: QuantitÃ©
            stop_loss: Prix de stop loss
            take_profit: Prix de take profit
            block_number: NumÃ©ro du block

        Returns:
            Position crÃ©Ã©e
        r   )r
   r   r   r   r   r   r   r   r   r   r   r   r   r   u   âœ… Position ajoutÃ©e: Ú ÚLONGÚSHORTzx (margin: $ú.2fú)z   Trade hash: Né   ú...)	r/   r	   r   ÚnowÚ	isoformatr.   Úsaver1   r2   )r4   r
   r   r   r   r   r   r   r   r   r   r   r   Úpositionr(   r(   r)   Úadd_position<   s6   !
ò
ÿ
ÿ$çzPositionManager.add_positionNr   r   r   c           	      C   sV  | j �ž || jvrt d|dd… › d�¡ 	 W d  ƒ dS | j| }|du rC|jdkrC||j }|js8| }||j |j |j }|jdkrO||j d nd}d|_t	 
¡  ¡ |_||_||_||_||_|  ¡  t d|j› d	|jrwd
nd› �¡ t d|jd›d|d›�¡ t d|d›d|d›d�¡ |W  d  ƒ S 1 s¤w   Y  dS )uŽ  
        Ferme une position

        Args:
            trade_hash: Hash de la position Ã  fermer
            close_tx_hash: Hash de la transaction de fermeture
            exit_price: Prix de sortie
            pnl: PnL rÃ©alisÃ© (optionnel, sera calculÃ© si non fourni)
            block_number: NumÃ©ro du block

        Returns:
            Position mise Ã  jour ou None si non trouvÃ©e
        u.   âš ï¸�  Position non trouvÃ©e pour fermeture: Nr<   r=   r   éd   ÚCLOSEDu   âœ… Position fermÃ©e: r7   r8   r9   z   Entry: $r:   u    â†’ Exit: $z	   PnL: $z (z+.2fz%))r/   r.   r1   Úwarningr   r   r   r   r   r   r>   r?   r   r   r   r   r   r@   r2   r   )	r4   r
   r   r   r   r   rA   Úprice_changer   r(   r(   r)   Úclose_positionx   s0   
ý

"$âzPositionManager.close_positionc                 C   ó>   | j � dd„ | j ¡ D ƒW  d  ƒ S 1 sw   Y  dS )z&Retourne toutes les positions ouvertesc                 S   ó   g | ]	}|j d kr|‘qS )r   ©r   ©Ú.0Úpr(   r(   r)   Ú
<listcomp>®   ó    z6PositionManager.get_open_positions.<locals>.<listcomp>N©r/   r.   Úvalues©r4   r(   r(   r)   Úget_open_positions«   ó   $ÿz"PositionManager.get_open_positionsc                 C   rH   )u&   Retourne toutes les positions fermÃ©esc                 S   rI   )rD   rJ   rK   r(   r(   r)   rN   ³   rO   z8PositionManager.get_closed_positions.<locals>.<listcomp>NrP   rR   r(   r(   r)   Úget_closed_positions°   rT   z$PositionManager.get_closed_positionsc                 C   s6   | j � | j |¡W  d  ƒ S 1 sw   Y  dS )u*   RÃ©cupÃ¨re une position par son trade hashN)r/   r.   Úget)r4   r
   r(   r(   r)   Úget_positionµ   s   
$ÿzPositionManager.get_positionc                 C   s8   | j � t| j ¡ ƒW  d  ƒ S 1 sw   Y  dS )zRetourne toutes les positionsN)r/   Úlistr.   rQ   rR   r(   r(   r)   Úget_all_positionsº   s   $ÿz!PositionManager.get_all_positionsc           	      C   sØ   | j �_ |  ¡ }|  ¡ }tdd„ |D ƒƒ}dd„ |D ƒ}dd„ |D ƒ}tdd„ |D ƒƒ}|r4|t|ƒ nd}|rBt|ƒt|ƒ d nd}t|ƒt|ƒt| jƒ|t|ƒt|ƒ|||d	œ	W  d
  ƒ S 1 sew   Y  d
S )z'Retourne les statistiques des positionsc                 s   s   � | ]}|j V  qd S ©N)r   rK   r(   r(   r)   Ú	<genexpr>Å   s   € z,PositionManager.get_stats.<locals>.<genexpr>c                 S   s    g | ]}|j r|j d kr|‘qS ©r   ©r   rK   r(   r(   r)   rN   Ç   ó     z-PositionManager.get_stats.<locals>.<listcomp>c                 S   s    g | ]}|j r|j d kr|‘qS r\   r]   rK   r(   r(   r)   rN   È   r^   c                 s   s   � | ]	}|j r|j V  qd S rZ   r]   rK   r(   r(   r)   r[   Ê   s   € r   rC   )	Úopen_positionsÚclosed_positionsÚtotal_positionsÚtotal_open_marginÚwinning_tradesÚlosing_tradesÚwin_rateÚ	total_pnlÚavg_pnlN)r/   rS   rU   Úsumr3   r.   )	r4   Úopen_posÚ
closed_posrb   rc   rd   rf   rg   re   r(   r(   r)   Ú	get_stats¿   s(   ÷$òzPositionManager.get_statsc              
   C   sà   zT| j �F | jt ¡  ¡ dd„ | j ¡ D ƒdœ}| jd }t|dƒ�}t	j
||dd� W d  ƒ n1 s5w   Y  t || j¡ W d  ƒ W dS 1 sMw   Y  W dS  tyo } zt d	|› �¡ W Y d}~dS d}~ww )
z-Sauvegarde les positions dans le fichier JSONc                 S   s   i | ]	\}}|t |ƒ“qS r(   )r   )rL   ÚkÚvr(   r(   r)   Ú
<dictcomp>â   rO   z(PositionManager.save.<locals>.<dictcomp>)ÚwalletÚlast_updatedr.   z.tmpÚwé   )ÚindentNu!   â�Œ Erreur sauvegarde positions: )r/   r,   r   r>   r?   r.   Úitemsr-   ÚopenÚjsonÚdumpÚosÚreplaceÚ	Exceptionr1   Úerror)r4   ÚdataÚ	temp_fileÚfÚer(   r(   r)   r@   Û   s    
ý
ÿ&ô€ÿzPositionManager.savec              
   C   sæ   zTt j | j¡st d| j› �¡ W dS t| jdƒ�}t |¡}W d  ƒ n1 s*w   Y  i | _	| 
di ¡ ¡ D ]\}}tdi |¤Ž| j	|< q:t d| j› �¡ W dS  tyr } zt d|› �¡ i | _	W Y d}~dS d}~ww )z+Charge les positions depuis le fichier JSONu#   ðŸ“‚ Nouveau fichier de positions: NÚrr.   u    ðŸ“‚ Positions chargÃ©es depuis u!   â�Œ Erreur chargement positions: r(   )rx   ÚpathÚexistsr-   r1   r2   ru   rv   r0   r.   rV   rt   r	   rz   r{   )r4   r~   r|   r
   Úpos_dictr   r(   r(   r)   r0   ï   s    ÿ€þzPositionManager.load)r+   )r   r   r   )Nr   )r   r    r!   r"   r#   r5   r%   r&   r'   r	   rB   r   rG   r   rS   rU   rW   rY   r   rk   r@   r0   r(   r(   r(   r)   r*   +   sn    ôÿþýüûúùø	÷
öõô
ô@ûÿþýüû
û3r*   r+   r,   r-   r6   c                 C   s&   t du r| du rtdƒ‚t| |ƒa t S )zå
    Retourne l'instance singleton du PositionManager

    Args:
        wallet_address: Adresse du wallet (requis au premier appel)
        storage_file: Fichier de stockage

    Returns:
        Instance du PositionManager
    Nz6wallet_address requis pour initialiser PositionManager)Ú_position_manager_instanceÚ
ValueErrorr*   )r,   r-   r(   r(   r)   Úget_position_manager  s
   
r†   Ú__main__)ÚlevelÚ*0x7476737C49d55bea691e54c2c96fD39a6bAf3049ztest_positions.jsonz0xabc123...z0xdef456...ÚBTCUSD_DEGENÚ*0xD89aE81e55b1Bd46591CB5555209fdF8fFb43b76Tg      9@éÈ   g    €1÷@g      à?g     óö@g     p÷@)r
   r   r   r   r   r   r   r   r   r   r   u   
ðŸ“Š Stats:z   z: u   
ðŸ’¼ Positions ouvertes:u      â€¢ r7   zx r8   r9   z @ $)Nr+   )'r"   rv   rx   Útypingr   r   r   Údataclassesr   r   r   ÚloggingÚ	threadingr   Ú	getLoggerr   r1   r	   r*   r„   r#   r†   ÚbasicConfigÚINFOÚmanagerrB   ÚposÚprintrk   Ústatsrt   ÚkeyÚvaluerS   rM   r   r   r   r   r(   r(   r(   r)   Ú<module>   sP   
 [
õ2ä