
    i              	          U d Z ddlZddlZddlZddlZddlmZmZ ddlmZ ddl	m
Z
mZmZmZ ddlmZ ddlZej$                  j'                  ej$                  j)                  e      d      ZdZd	Zd
Z G d d      Z G d dee      Z G d dee      Ze G d d             Ze G d d             Z G d d      Z  G d d      Z! G d d      Z"da#ee!   e$d<   da%ee"   e$d<   de!fdZ&de"fdZ'd ed!ed"edee   fd#Z(y)$u  
CryptoClaw Paper Trading System
================================
Two-mode paper trading simulator:
  1. FREE MODE  — User places manual trades, tracks P&L
  2. GUIDED MODE — Auto Hedge-Mart V4 runs live, teaches step by step

Designed for Telegram integration via OpenClaw command routing.

Storage: SQLite database for persistence across sessions.
Price feed: Live BTC price via public API (or replay from tick data).
    N)datetimetimezone)	dataclass)ListOptionalDictTuple)Enumzpaper_trading.dbg     @g{Gz?BTCUSDc                   R    e Zd ZU dZdZeed<   dZeed<   dZeed<   e	defd       Z
y	)
	PriceFeedz:Fetch live BTC price from public APIs (no API key needed).        _cache_price_cache_timeg      @
_cache_ttlreturnc                    t        j                          }| j                  dkD  r(|| j                  z
  | j                  k  r| j                  S ddg}|D ]  \  }}	 t        j
                  j                  |ddi      }t        j
                  j                  |d      5 }t        j                  |j                         j                               }|}|j                  d	      D ]  }	||	   }	 t        |      }
|
dkD  r|
| _        || _        |
cd
d
d
       c S 	 d
d
d
        | j                  dkD  r| j                  S y# 1 sw Y   'xY w# t        $ r Y w xY w)z3Get current BTCUSD mid price. Caches for 5 seconds.r   )z:https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDTprice)z/https://api.coinbase.com/v2/prices/BTC-USD/spotzdata.amountz
User-AgentzCryptoClaw/1.0)headers   )timeout.Ng     j@)timer   r   r   urllibrequestRequesturlopenjsonloadsreaddecodesplitfloat	Exception)clsnowapisurlpathreqrespdatavalkeyr   s              //var/www/html/crpytotradingbot/paper_trading.pyget_btc_pricezPriceFeed.get_btc_price,   sZ    iikaS3??%:cnn$L### TN

  	ICnn,,S<IY:Z,[^^++C+; 	%t::diik&8&8&:;DC#zz# '!#h'!#JEqy+0(*-$	% 	% !	%	  a###	% 	%  s2   AE
A.D>	E
E
>E	E

	EEN)__name__
__module____qualname____doc__r   r#   __annotations__r   r   classmethodr0        r/   r   r   %   s<    DL%KJe  r8   r   c                       e Zd ZdZdZy)TradeDirectionBUYSELLN)r1   r2   r3   r;   r<   r7   r8   r/   r:   r:   Q   s    
CDr8   r:   c                       e Zd ZdZdZy)SessionModefreeguidedN)r1   r2   r3   FREEGUIDEDr7   r8   r/   r>   r>   V   s    DFr8   r>   c                       e Zd ZU dZeed<   eed<   eed<   eed<   eed<   e	e   ed<   e	e   ed<   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d<   dZeed<   dZeed<   edefd       ZdedefdZy
)
PaperTradezA single paper trade.trade_iduser_id	directionlotsentry_pricetp_pricesl_price	open_timeN
close_timeclose_pricepnlr   
commissionOPENstatus commentr   c                      | j                   dk(  S )NrQ   )rR   selfs    r/   is_openzPaperTrade.is_openm   s    {{f$$r8   current_pricec                     | j                   t        j                  k(  r| j                  || j                  z
  z  }n| j                  | j                  |z
  z  }|| j
                  z
  S N)rG   r:   r;   rH   rI   rP   )rW   rY   raws      r/   unrealized_pnlzPaperTrade.unrealized_pnlq   sU    >>^///))}t/?/??@C))t//-?@CT__$$r8   )r1   r2   r3   r4   intr5   strr:   r#   r   rM   rN   rO   rP   rR   rT   propertyboolrX   r]   r7   r8   r/   rD   rD   [   s    ML
KuouoN $J$#'K%'C%JFCGS% % %%E %e %r8   rD   c                       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<   dZe	ed	<   dZ
e	ed
<   dZe	ed<   dZeed<   dZeed<   dZeed<   dZeed<   y)UserSessionzA user's paper trading session.rF   usernamemodebalanceinitial_balance
start_timer   trades_countwinslossesr   	total_pnlmax_balancemin_balanceT	is_activeN)r1   r2   r3   r4   r_   r5   r>   r#   ri   r^   rj   rk   rl   rm   rn   ro   ra   r7   r8   r/   rc   rc   y   si    )LM
NOL#D#MFCOIuKKItr8   rc   c                   x   e Zd ZdZefdefdZedej                  fd       Z
d Zdedee   fdZefded	ed
ededef
dZdefdZdefdZd#dedee   fdZ	 	 d$dededededee   dee   dedefdZdededee   fdZdedee   fdZd%dededee   fdZdedee   fdZdefd Z ded!edee   fd"Z!y)&PaperTradingDBz5SQLite storage for paper trading sessions and trades.db_pathc                     || _         t        j                  | j                   d      | _        t        j                  | j                  _        | j                  j                  d       | j                          y )NF)check_same_threadzPRAGMA journal_mode=WAL)rr   sqlite3connect_connectionRowrow_factoryexecute_init_dbrW   rr   s     r/   __init__zPaperTradingDB.__init__   sP    "??4<<5Q'.{{$  !:;r8   r   c                     | j                   S r[   )rw   rV   s    r/   connzPaperTradingDB.conn   s    r8   c                 :    | j                   j                  d       y )Na  
            CREATE TABLE IF NOT EXISTS sessions (
                user_id TEXT PRIMARY KEY,
                username TEXT NOT NULL,
                mode TEXT NOT NULL DEFAULT 'free',
                balance REAL NOT NULL,
                initial_balance REAL NOT NULL,
                start_time TEXT NOT NULL,
                trades_count INTEGER DEFAULT 0,
                wins INTEGER DEFAULT 0,
                losses INTEGER DEFAULT 0,
                total_pnl REAL DEFAULT 0.0,
                max_balance REAL NOT NULL,
                min_balance REAL NOT NULL,
                is_active INTEGER DEFAULT 1
            );

            CREATE TABLE IF NOT EXISTS trades (
                trade_id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id TEXT NOT NULL,
                direction TEXT NOT NULL,
                lots REAL NOT NULL,
                entry_price REAL NOT NULL,
                tp_price REAL,
                sl_price REAL,
                open_time TEXT NOT NULL,
                close_time TEXT,
                close_price REAL,
                pnl REAL,
                commission REAL DEFAULT 0.0,
                status TEXT DEFAULT 'OPEN',
                comment TEXT DEFAULT '',
                FOREIGN KEY (user_id) REFERENCES sessions(user_id)
            );

            CREATE INDEX IF NOT EXISTS idx_trades_user ON trades(user_id);
            CREATE INDEX IF NOT EXISTS idx_trades_status ON trades(status);
        )r   executescriptrV   s    r/   r{   zPaperTradingDB._init_db   s    		 %! %	r8   rF   c                     | j                   j                  d|f      j                         }|rQt        |d   |d   t	        |d         |d   |d   |d   |d   |d	   |d
   |d   |d   |d   t        |d               S y )Nz(SELECT * FROM sessions WHERE user_id = ?rF   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   )rF   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   )r   rz   fetchonerc   r>   ra   )rW   rF   rows      r/   get_sessionzPaperTradingDB.get_session   s    ii6


(* 	 IZ V-s9~ #$5 63|CT 0s6{8}K0@.C<Ns;/0  r8   rd   re   rf   c                    t        j                  t        j                        j	                         }t        ||||||||d	      }| j                  j                  d|j                  |j                  |j                  j                  |j                  |j                  |j                  dddd|j                  |j                  df       | j                  j                          |S )NT)	rF   rd   re   rf   rg   rh   rm   rn   ro   a  
            INSERT OR REPLACE INTO sessions
            (user_id, username, mode, balance, initial_balance, start_time,
             trades_count, wins, losses, total_pnl, max_balance, min_balance, is_active)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        r   r      )r   r&   r   utc	isoformatrc   r   rz   rF   rd   re   valuerf   rg   rh   commit)rW   rF   rd   re   rf   r&   sessions          r/   create_sessionzPaperTradingDB.create_session   s    ll8<<(224hTWW	
 			  OOW--w||/A/AOOW44g6H6Hq!S'//7??A
		 			r8   r   c                 H   | j                   j                  d|j                  |j                  |j                  |j
                  |j                  |j                  |j                  t        |j                        |j                  f	       | j                   j                          y )Nz
            UPDATE sessions SET
                balance=?, trades_count=?, wins=?, losses=?,
                total_pnl=?, max_balance=?, min_balance=?, is_active=?
            WHERE user_id=?
        )r   rz   rf   ri   rj   rk   rl   rm   rn   r^   ro   rF   r   )rW   r   s     r/   update_sessionzPaperTradingDB.update_session   sz    		  OOW117<<w22G4G4G!!"GOO
		 			r8   c                     | j                   j                  d|f       | j                   j                  d|f       | j                   j                          y )Nz$DELETE FROM trades WHERE user_id = ?z&DELETE FROM sessions WHERE user_id = ?)r   rz   r   )rW   rF   s     r/   reset_sessionzPaperTradingDB.reset_session   s@    		@7*M		BWJO		r8   limitc                     | j                   j                  d|f      j                         }|D cg c]  }t        |       c}S c c}w )Na	  
            SELECT username, balance, initial_balance, total_pnl, trades_count, wins, losses,
                   max_balance, min_balance, mode
            FROM sessions
            WHERE is_active = 1
            ORDER BY balance DESC
            LIMIT ?
        )r   rz   fetchalldict)rW   r   rowsrs       r/   get_leaderboardzPaperTradingDB.get_leaderboard   sH    yy   " X  xz 	 "&&AQ&&&s   ANrG   rH   rI   rJ   rK   rT   c                    t        j                  t        j                        j	                         }||z  t
        dz  z  }	| j                  j                  d||j                  ||||||	|f	      }
|
j                  }| j                  j                          | j                  |      }|r&|xj                  |	z  c_        | j                  |       t        |||||||||	d|      S )Nd   z
            INSERT INTO trades (user_id, direction, lots, entry_price, tp_price, sl_price,
                                open_time, commission, status, comment)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'OPEN', ?)
        rQ   )rE   rF   rG   rH   rI   rJ   rK   rL   rP   rR   rT   )r   r&   r   r   r   COMMISSION_PCTr   rz   r   	lastrowidr   r   rf   r   rD   )rW   rF   rG   rH   rI   rJ   rK   rT   r&   rP   cursorrE   r   s                r/   
open_tradezPaperTradingDB.open_trade  s     ll8<<(224K'>C+?@
"" $ yk8X:w(	) ##		 ""7+OOz)O(w);7	
 	
r8   rE   rN   c                    | j                   j                  d|f      j                         }|sy t        |d         }|d   }|d   }|d   }|t        j                  k(  r	|||z
  z  }n|||z
  z  }||z  t
        dz  z  }	||	z   }
||	z
  }t        j                  t        j                        j                         }| j                   j                  d||||
|f       | j                   j                          |d   }| j                  |      }|r|xj                  ||	z
  z  c_        |xj                  d	z  c_        |xj                  |z  c_        |d
kD  r|xj                   d	z  c_        n|d
k  r|xj"                  d	z  c_        t%        |j&                  |j                        |_        t)        |j*                  |j                        |_        | j-                  |       t/        ||||||d   |d   |d   ||||
d|d         S )Nz;SELECT * FROM trades WHERE trade_id = ? AND status = 'OPEN'rG   rH   rI   rP   r   z
            UPDATE trades SET close_time=?, close_price=?, pnl=?, commission=?, status='CLOSED'
            WHERE trade_id=?
        rF   r   r   rJ   rK   rL   CLOSEDrT   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rR   rT   )r   rz   r   r:   r;   r   r   r&   r   r   r   r   r   rf   ri   rl   rj   rk   maxrm   minrn   r   rD   )rW   rE   rN   r   rG   rH   rI   entry_commissionraw_pnlclose_commissiontotal_commissionnet_pnlr&   rF   r   s                  r/   close_tradezPaperTradingDB.close_trade(  s   iiIH;

(* 	 "3{#34	6{-(|, ***kK78GkK78G  +-#1EF+.>>,,ll8<<(224		  ;)98D	F 			 i.""7+OOw)999O  A% ({!1!#"%g&9&97??"KG"%g&9&97??"KG(w);Z_K0@'#i.
 	
r8   c                     | j                   j                  d|f      j                         }|D cg c]  }| j                  |       c}S c c}w )NzLSELECT * FROM trades WHERE user_id = ? AND status = 'OPEN' ORDER BY trade_idr   rz   r   _row_to_trade)rW   rF   r   r   s       r/   get_open_tradeszPaperTradingDB.get_open_trades^  sK    yy  ZJ
 (* 	 044!""1%444s   Ac                     | j                   j                  d||f      j                         }|D cg c]  }| j                  |       c}S c c}w )Nz[SELECT * FROM trades WHERE user_id = ? AND status = 'CLOSED' ORDER BY trade_id DESC LIMIT ?r   )rW   rF   r   r   r   s        r/   get_trade_historyz PaperTradingDB.get_trade_historye  sN    yy  ie
 (* 	 044!""1%444s   Ac                     | j                   j                  d|f      j                         }|r| j                  |      S y )Nz'SELECT * FROM trades WHERE trade_id = ?)r   rz   r   r   )rW   rE   r   s      r/   	get_tradezPaperTradingDB.get_tradel  s@    ii5{

(* 	 %%c**r8   c                     t        |d   |d   t        |d         |d   |d   |d   |d   |d   |d	   |d
   |d   |d   |d   |d         S )NrE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rR   rT   r   )rD   r:   )rW   r   s     r/   r   zPaperTradingDB._row_to_tradet  su    _c)n$S%56S[M*S__K0@<(c-6HE
s<'8x=#i.
 	
r8   rY   c                    g }| j                  |      }|D ]@  }d}|}|j                  ru|j                  t        j                  k(  r||j                  k\  rd|j                  }}n:|j                  t        j
                  k(  r||j                  k  rd|j                  }}|s|j                  ru|j                  t        j                  k(  r||j                  k  rd|j                  }}n:|j                  t        j
                  k(  r||j                  k\  rd|j                  }}|s| j                  |j                  |      }|s0|j                  |       C |S )z2Check and auto-close any trades that hit TP or SL.FT)
r   rJ   rG   r:   r;   r<   rK   r   rE   append)	rW   rF   rY   closedopen_tradestradehitclose_atresults	            r/   check_tp_slzPaperTradingDB.check_tp_sl  s   **73  	*EC$H~~??n&8&88]enn=\$(%..C__(;(;;QVQ_Q_@_$(%..C5>>??n&8&88]enn=\$(%..C__(;(;;QVQ_Q_@_$(%..C))%..(CMM&)'	*( r8   
   )NNrS   )   )"r1   r2   r3   r4   DB_PATHr_   r}   r`   ru   
Connectionr   r{   r   rc   r   DEFAULT_BALANCEr>   r#   r   r   r   r^   r   r   r   r:   rD   r   r   r   r   r   r   r   r7   r8   r/   rq   rq      s   ?&-    g((    &T3 8K+@ " )8c S   %<G,k S 
	'S 	'$t* 	' DHDF
# 
. 
 
 %
19%
%e_
>A
KU
84
C 4
e 4
@T 4
l5s 5tJ/? 55 5S 5$zBR 5# (:*> 	
J 	
3 u jAQ r8   rq   c                   .   e Zd ZdZefdefdZddedededefdZdded	ed
ededef
dZdded	ed
ededef
dZ		 ddede
d	ed
ededefdZddededefdZdedefdZdedefdZdedefdZddededefdZdefdZdededefdZdefdZdefdZy) PaperTradingEnginez{
    Main interface for the paper trading system.
    All methods return formatted strings ready for Telegram display.
    rr   c                 $    t        |      | _        y r[   )rq   dbr|   s     r/   r}   zPaperTradingEngine.__init__  s     )r8   rF   rd   re   r   c                    | j                   j                  |      }|rB|j                  r6d|j                  j                  j                          d|j                  ddS 	 t        |j                               }| j                   j                  |||      }|t        j                  k(  rd|j                  ddt         dS d	|j                  dd
S # t        $ r Y yw xY w)z"Start a new paper trading session.u1   ⚠️ You already have an active session!
Mode: z
Balance: $,.2fz$

Use `/paper reset` to start fresh.uG   ❌ Invalid mode. Use `free` or `guided`.

Example: `/paper start free`uH   🎮 **Paper Trading Started — FREE MODE**

💰 Starting Balance: **$u(   **
📊 Symbol: BTCUSD
💸 Commission: u  % per trade

**Commands:**
`/buy <lots>` — Open long (e.g. `/buy 0.01`)
`/sell <lots>` — Open short
`/buy <lots> tp=<price> sl=<price>` — With TP/SL
`/close <id>` — Close a trade
`/close all` — Close all trades
`/positions` — View open trades
`/balance` — Check balance & P&L
`/history` — Trade history
`/paper stats` — Full statistics
`/paper leaderboard` — Channel rankings

Good luck! 🦾uJ   🤖 **Paper Trading Started — GUIDED MODE**

💰 Starting Balance: **$u  **
📊 Strategy: Auto Hedge-Mart V4
⚙️ Config: 0.03 lot, $15 exit, adaptive grid

I'll run the algo and explain every trade as it happens.
Watch your balance grow while learning the system.

**Commands:**
`/positions` — View current algo trades
`/balance` — Check balance & P&L
`/paper explain` — Explain current state
`/paper stats` — Full statistics
`/paper stop` — Stop guided session

🔄 Algo is running... watching for entry signals.)r   r   ro   re   r   upperrf   r>   lower
ValueErrorr   rA   r   )rW   rF   rd   re   existingsession_moder   s          r/   startzPaperTradingEngine.start  s   77&&w/**!,,2245 6%--d3 456	_&tzz|4L ''(((LI;+++--4__T,B C$$2#3 4"#(--4__T,B CFG3  	_^	_s   !C 	CClots_strtp_strsl_strc                 H    | j                  |t        j                  |||      S r[   )_open_trader:   r;   rW   rF   r   r   r   s        r/   buyzPaperTradingEngine.buy  s!    ););XvvVVr8   c                 H    | j                  |t        j                  |||      S r[   )r   r:   r<   r   s        r/   sellzPaperTradingEngine.sell  s"    )<)<hPVWWr8   rG   c                    | j                   j                  |      }|r|j                  sy|j                  t        j
                  k(  ry	 t        |      }|dk  rt        	 |dkD  ryt        j                         }||z  }	|	dz  }
|
|j                  kD  rd|	d	d
|
d	d|j                  d	S d }d }|rJ	 t        |      }|t        j                  k(  r||k  rd|ddS |t        j                  k(  r||k\  rd|ddS |rJ	 t        |      }|t        j                  k(  r||k\  rd|ddS |t        j                  k(  r||k  rd|ddS | j                   j                  |      }t!        |      dk\  ry| j                   j#                  ||||||      }| j                   j                  |      }|t        j                  k(  rdnd}|rd|ddnd}|rd|ddnd}| d|j$                   d| d|d	d |j&                   d| | d!|j(                  d	d"|j                  d	S # t        t        f$ r Y yw xY w# t        $ r Y yw xY w# t        $ r Y yw xY w)#N9   ❌ No active session. Start one with `/paper start free`uc   🤖 You're in GUIDED mode — the algo trades for you!
Use `/paper start free` for manual trading.r   u*   ❌ Invalid lot size. Example: `/buy 0.01`g      $@u+   ❌ Max lot size is 10.0 for paper trading.g?u+   ❌ Insufficient balance.
Position value: $r   z
Required margin (10%): $z
Your balance: $u#   ❌ TP must be above entry price ($z,.1fz) for a BUY.u#   ❌ TP must be below entry price ($z) for a SELL.u   ❌ Invalid TP price.u#   ❌ SL must be below entry price ($u#   ❌ SL must be above entry price ($u   ❌ Invalid SL price.r   u)   ❌ Max 20 open trades. Close some first.   🟢   🔴u
   🎯 TP: $
rS   u
   🛑 SL: $ ** z BTC @ $u   **
📝 Trade #u   💸 Commission: $u   
💰 Balance: $)r   r   ro   re   r>   rB   r#   r   	TypeErrorr   r0   rf   r:   r;   r<   r   lenr   r   rE   rP   )rW   rF   rG   r   r   r   r   rH   r   position_valuerequired_marginrJ   rK   r   r   emojitp_linesl_lines                     r/   r   zPaperTradingEngine._open_trade  s   ''%%g.g//N<<;---y	@?Dqy   
 $;@ '') (4/W__,$$24#8 9++:4*@ A"")//$!79 / = 2 22x57H@tLYY 3 33E8I@tMZZ / = 2 22x57H@tLYY 3 33E8I@tMZZ
 gg--g6{r!> ""7ItUHhW''%%g.#~'9'99v4<JxoR0"4<JxoR0" gS)4&t E >>*"iy !1!1$ 7 8%ood3	5	
s I& 	@?	@>  /./  /./sB   
H  3)H5 H5 ?)I )I  H21H25	I I	IItargetc                    | j                   j                  |      }|r|j                  syt        j	                         }| j                   j                  ||      }|j                         dk(  r`| j                   j                  |      }|s|syt        |      }|D ]<  }| j                   j                  |j                  |      }	|	s,|j                  |	       > t        d |D              }
| j                   j                  |      }dt        |       dg}|D ]k  }|j                  xs ddk\  rdnd	}|j                  | d
|j                   d|j                  j                    d|j"                   d|j                  d	       m |j                  d|
dd       |j                  d|j$                  dd       dj'                  |      S 	 t)        |      }| j                   j/                  |      }|r|j0                  |k7  rd| dS |j2                  sd| dS | j                   j                  ||      }	|	sd| dS | j                   j                  |      }|	j                  xs ddk\  rdnd	}d| d|	j                  j                    d|	j4                  dd|dd|	j"                   d| d|	j                  dd|	j6                  dd |j$                  ddS # t*        t,        f$ r Y yw xY w)!N   ❌ No active session.allu   📭 No open trades to close.c              3   N   K   | ]  }|j                   |j                     y wr[   rO   .0ts     r/   	<genexpr>z+PaperTradingEngine.close.<locals>.<genexpr>G  s     Haaee6GAEEH   %%u   🔒 **Closed z trade(s)**
r      ✅   ❌ #r       → $+,.2fu   
💰 Net P&L: **$**   💰 Balance: **$r   r   .   ❌ Usage: `/close <trade_id>` or `/close all`u   ❌ Trade #z not found.z is already closed.u   ❌ Failed to close trade #r   u   🔒 **Trade #z CLOSED**

Direction: z	
Entry: $z
Exit: $z
Lots: z	 P&L: **$u   **
💸 Commission: $u   

💰 Balance: **$)r   r   ro   r   r0   r   r   r   listr   rE   r   sumr   rO   rG   r   rH   rf   joinr^   r   r   r   rF   rX   rI   rP   )rW   rF   r   r   r   auto_closedr   resultsr   r   rl   linesr   	pnl_emojirE   s                  r/   closezPaperTradingEngine.close2  s   ''%%g.g//+'') gg))'59<<>U"''11':K{6;'G$ +,,U^^UCNN6*+
 H7HHIgg))'2G%c'l^=ABE k&'eejqQ%6EE		{"QZZL!++:K:K9LAaffXU[\]\a\abg[hijk LL.y.?rBCLL,W__T,B"EF99U##	D6{H !!(+0 
+66}} 
*=>>$$Xu50
!<<''%%g.$jjoA!3E	 XJ ' **001 2))$/ 0D\ "[[Mk6::e"4 5!!'!2!24 8 9  '5R9		
! I& 	DC	Ds   K K0/K0c                 F   | j                   j                  |      }|r|j                  syt        j	                         | j                   j                  |      }| j                   j                  |      }dddg}|r|j                  dt        |       d       |D ]_  }|j                  xs ddk\  rdnd	}|j                  d
| d|j                   d|j                  j                   d|j                  d       a |j                  d       |s|j                  d       nd}|D ]  }|j                        }	||	z  }|j                  t        j                  k(  rdnd}
|	dk\  rdnd}|j                   rd|j                   dnd}|j"                  rd|j"                  dnd}|j                  |
 d|j                   d|j                  j                   d|j$                   d|j&                  dd| d|	d| |         |j                  d|dd       | j                   j                  |      }|j                  d|j(                  dd       |j(                  t+        fd |D              z   }|j                  d!|dd       d"j-                  |      S )#Nr   u   📊 **Open Positions** (BTC: $r   z)
u   ⚡ z" trade(s) auto-closed (TP/SL hit):r   r   r   z  r   r   r   r   rS   u   📭 No open positions.r   r   r      📈   📉z | TP: $,.0fz | SL: $z **#z**  @ $z $u   
📊 Unrealized P&L: **$r   r   c              3   @   K   | ]  }|j                          y wr[   r]   r   r   r   s     r/   r   z/PaperTradingEngine.positions.<locals>.<genexpr>  s     &T1q'7'7'>&T   u   💎 Equity: **$r   )r   r   ro   r   r0   r   r   r   r   rO   rE   rG   r   r]   r:   r;   rJ   rK   rH   rI   rf   r   r   )rW   rF   r   r   r   r   r   r   
total_upnlupnlr   tp_infosl_infoequityr   s                 @r/   	positionszPaperTradingEngine.positionsq  s   ''%%g.g//N'')gg))'59gg--g625,cBCLL4K 011STU  d&'eejqQ%6EE	r)Bqzzl!AKK<M<M;NfUVUZUZ[`Tabcd LLLL23J  
''.d"
"#++1C1C"C&*aiFV	:;**HQZZ$56":;**HQZZ$56"gT!**S1B1B0C1QVVHDQRQ^Q^_cPd	{"T%L	'D
 LL5j5GrJK''%%g.((>bAB3&T&T#TT't}B78yyr8   c                   
 | j                   j                  |      }|r|j                  syt        j	                         
| j                   j                  |
       | j                   j                  |      }t        
fd|D              }|j                  |z   }||j                  z
  }||j                  z  dz  }d}|j                  dkD  r)|j                  |j                  z
  |j                  z  dz  }|dk\  rdnd}	d
d	d
|j                  d	d|dd|d	d|	 d|dd|dd|ddt        |       d|j                   S )Nr   c              3   @   K   | ]  }|j                          y wr[   r  r  s     r/   r   z-PaperTradingEngine.balance.<locals>.<genexpr>       FQ))%0Fr  r   r   r   r  r  u1   💰 **Paper Trading Balance**

📊 BTC Price: $r   u   

💵 Balance: **$u   **
📊 Unrealized: $r   u   
💎 Equity: **$z**

z Total P&L: **$ (+.1fu   %)**
📉 Max Drawdown: .1fu   %
🔄 Open Trades: u   
📋 Total Closed: )r   r   ro   r   r0   r   r   r   rf   rg   rm   rn   r   ri   )rW   rF   r   r   r	  r  pnl_from_startpnl_pctmax_ddr   r   s             @r/   rf   zPaperTradingEngine.balance  sl   ''%%g.g//N'')GU+gg--g6F+FF
:-'"9"99!G$;$;;sB"**W-@-@@GDWDWW[^^F,1Fv	  %d| ,  '5 6!!+E 2 3%dm6k(>b O""( .!!$[!1 2 3"")"6"6!79
	
r8   c                 V   | j                   j                  |      }|r|j                  syt        j	                         | j                   j                  |      }| j                   j                  |d      }t        fd|D              }|j                  |z   }||j                  z
  }||j                  z  dz  }|j                  dkD  r|j                  |j                  z  dz  nd}	t        d |D              }
t        t        d |D                    }|dkD  r|
|z  n|
dkD  rt        d	      nd}t        d
 |D        d      }t        d |D        d      }d}|j                   dkD  r)|j                   |j"                  z
  |j                   z  dz  }|dkD  rt        |      |z  nd}d|j$                  j&                  j)                          d|dd|dd|dd|j                   d|j                   d|j*                   d|	dd|dd|dd|dd|dd|dd t-        |       d!|dS )"Nr   i  r   c              3   @   K   | ]  }|j                          y wr[   r  r  s     r/   r   z+PaperTradingEngine.stats.<locals>.<genexpr>  r  r  r   r   c              3   n   K   | ]-  }|j                   s|j                   d kD  s |j                    / ywr   Nr   r   s     r/   r   z+PaperTradingEngine.stats.<locals>.<genexpr>  s$     G1155QUUQYG   555c              3   n   K   | ]-  }|j                   s|j                   d k  s |j                    / ywr  r   r   s     r/   r   z+PaperTradingEngine.stats.<locals>.<genexpr>  s$     M15519quuMr  infc              3   N   K   | ]  }|j                   s|j                     y wr[   r   r   s     r/   r   z+PaperTradingEngine.stats.<locals>.<genexpr>  s     4aaeeAEE4r   )defaultc              3   N   K   | ]  }|j                   s|j                     y wr[   r   r   s     r/   r   z+PaperTradingEngine.stats.<locals>.<genexpr>  s     5qquuQUU5r   r   u(   📊 **Paper Trading Statistics**
Mode: u   

💎 Equity: **$r   u   **
📈 Return: **r  z%** ($r   u   )

🔢 Total Trades: u   
✅ Wins: u    | ❌ Losses: u   
🎯 Win Rate: **r  u   %**
⚖️ Profit Factor: **z.2fu   **

🏆 Best Trade: $u   
💀 Worst Trade: $u   
📉 Max Drawdown: **u   %**
📐 Risk-Adj Return: **u   **

🔄 Open Positions: u   
📊 Unrealized: $)r   r   ro   r   r0   r   r   r   rf   rg   ri   rj   absr#   r   r   rm   rn   re   r   r   rk   r   )rW   rF   r   r   historyr	  r  r  r  win_rate
gross_winsgross_lossespfbestworstr  rarr   s                    @r/   statszPaperTradingEngine.stats  sc   ''%%g.g//+'')gg--g6''++G4+@F+FF
:-'"9"99!G$;$;;sBBIBVBVYZBZGLL7#7#77#=`aGGG
3MgMMN,81,<j<'R\_`R`%,fg474a@5G5qA"**W-@-@@GDWDWW[^^F)/!s7|f$\\''--/0 1%dm ,%d^6.1G H"")"6"6!7 8 ognn5E F  (~ .'')#h /!!%e -""' /$$*3< 0''*3i 0$$'$4#5 6!!+E 24	
r8   r   c                 :   | j                   j                  |      }|r|j                  sy| j                   j                  ||      }|sydt	        |       dg}|D ]  }|j
                  xs ddk\  rdnd}|j                  t        j                  k(  rd	nd
}|j                  | d|j                   d|j                  j                   d|j                   d|j                  dd|j                  dd| d|j
                  dd        dj                  |      S )Nr   r  u)   📭 No closed trades yet. Start trading!u   📋 **Last z
 Trades**
r   r   r   r   r   r   r   r  r  r   z **$r   r   r   )r   r   ro   r   r   rO   rG   r:   r;   r   rE   r   rH   rI   rN   r   )	rW   rF   r   r   tradesr   r   r   r   s	            r/   r$  zPaperTradingEngine.history  s   ''%%g.g//+**7%*@>F}K89 	A"#%%*1!2Ikk^-?-??FVELL'AJJ<q):):(;1QVVH EmmD)d/C1+T!%%b2	 yyr8   c                 t   | j                   j                  d      }|sydg}g d}t        |      D ]t  \  }}|dk  r||   nd|dz    }|d	   |d
   z
  }||d
   z  dz  }|d   dkD  r|d   |d   z  dz  nd}	|j                  | d|d    d|d	   dd|dd|d    d|	dd       v dj	                  |      S )Nr   r  u=   📭 No active traders yet. Be the first! `/paper start free`u#   🏆 **Paper Trading Leaderboard**
)u   🥇u   🥈u   🥉   #r   rf   rg   r   ri   r   rj   r   rd   u   ** — $r  r  r  z%) | z
 trades | z.0fz% WRr   )r   r   	enumerater   r   )
rW   boardr   medalsientrymedalrO   r  wrs
             r/   leaderboardzPaperTradingEngine.leaderboard  s   ''b'1R78)!%( 	HAu!"QF1Ia!uIE	"U+<%==CU#455<GBGBWZ[B[%-%"77#=abBLL'U:./xi8H7N OD>u^'<&=Z3xtU	 yyr8   c                 :    | j                   j                  |       y)Nui   🗑️ Session reset. All trades cleared.

Start fresh with `/paper start free` or `/paper start guided`)r   r   )rW   rF   rd   s      r/   resetzPaperTradingEngine.reset  s    g&|r8   c                 8    t         j                         }d|ddS )Nu   ₿ **BTC/USD: $r   r   )r   r0   )rW   r   s     r/   r   zPaperTradingEngine.price  s!    '')!%R00r8   c                     dS )Nu  🦾 **CryptoClaw Paper Trading**

**Getting Started:**
`/paper start free` — Manual trading mode
`/paper start guided` — Algo teaches you

**Trading (Free Mode):**
`/buy <lots>` — Open long
`/sell <lots>` — Open short
`/buy <lots> tp=<price> sl=<price>` — With TP/SL
`/close <id>` — Close trade by ID
`/close all` — Close all positions

**Info:**
`/positions` — Open trades + live P&L
`/balance` — Balance & equity
`/history` — Recent closed trades
`/price` — Current BTC price

**Stats:**
`/paper stats` — Full statistics
`/paper leaderboard` — Channel rankings
`/paper reset` — Wipe & start over

💰 Start with $20,000 fake money
💸 Commission: 0.04% (same as Binance)
📊 Tracks: Win rate, P&L, drawdown, profit factorr7   rV   s    r/   helpzPaperTradingEngine.help  s    B	
r8   N)r?   )rS   rS   )rS   r   )r1   r2   r3   r4   r   r_   r}   r   r   r   r:   r   r   r  rf   r,  r^   r$  r9  r;  r   r>  r7   r8   r/   r   r     s   
 '. * *4S 4C 4s 4 4lW3 W# Ws W WVY WXC X3 X X# XWZ X DFM
3 M
> M
!M
+.M
=@M
JMM
^=
S =
# =
s =
~(  (  ( T
s 
s 
@,
S ,
S ,
\ s  3    ( S  &}S }C }C }1s 1
c 
r8   r   c            	       \    e Zd ZdZddefdZdedededee   fd	Zd
e	e   de
eef   fdZy)CommandParserz>Parse Telegram-style commands and route to PaperTradingEngine.Nenginec                 *    |xs
 t               | _        y r[   )r   rA  )rW   rA  s     r/   r}   zCommandParser.__init__:  s    4 2 4r8   rF   rd   textr   c                 *   |j                         }|j                  d      sy |j                         }|d   j                         }d|v r|j                  d      d   }|dk(  rt	        |      dk  r| j
                  j                         S |d   j                         }|dk(  r2t	        |      dkD  r|d   nd}| j
                  j                  |||      S |d	k(  r| j
                  j                  |      S |d
k(  r| j
                  j                         S |dk(  r| j
                  j                  ||      S |dk(  r| j
                  j                         S | j
                  j                         S |dk(  rIt	        |      dk  ry|d   }| j                  |dd        \  }	}
| j
                  j                  |||	|
      S |dk(  rIt	        |      dk  ry|d   }| j                  |dd        \  }	}
| j
                  j                  |||	|
      S |dk(  r4t	        |      dkD  r|d   nd}|sy| j
                  j                  ||      S |dk(  r| j
                  j                  |      S |dk(  r| j
                  j!                  |      S |dk(  rMt	        |      dkD  r!|d   j#                         rt%        |d         nd}| j
                  j'                  ||      S |dk(  r| j
                  j)                         S |dk(  r| j
                  j                         S y )N/r   @z/paper   r   r   r?   r,  r9  r;  r>  z/buyu+   ❌ Usage: `/buy <lots>` (e.g. `/buy 0.01`)z/sellu-   ❌ Usage: `/sell <lots>` (e.g. `/sell 0.01`)z/closerS   r   z
/positionsz/balancez/historyr   z/pricez/leaderboard)strip
startswithr"   r   r   rA  r>  r   r,  r9  r;  _parse_tp_slr   r   r   r  rf   isdigitr^   r$  r   )rW   rF   rd   rC  partscmdsubre   r   r   r   r   r   s                r/   parsezCommandParser.parse=  s   zz|s#

Ahnn #:))C.#C(?5zA~{{''))(.."Cg~#&u:>uQxv{{(((DAA{{((11%{{..00{{(((;;{{'')){{''))F]5zA~DQxH!..uQRy9NFF;;??7HffEEG^5zA~FQxH!..uQRy9NFF;;##GXvvFFH_!$UaU1XRFG;;$$Wf55L ;;((11J;;&&w//J%(Z!^a8H8H8JCaMPRE;;&&w66H_;;$$&&N";;**,,r8   argsc                     d}d}|D ]@  }|j                         }|j                  d      r|dd  }*|j                  d      s<|dd  }B ||fS )NrS   ztp=r0  zsl=)r   rI  )rW   rP  r   r   arg	arg_lowers         r/   rJ  zCommandParser._parse_tp_sl  sd     	!C		I##E*QR%%e,QR	! v~r8   r[   )r1   r2   r3   r4   r   r}   r_   r   rO  r   r	   rJ  r7   r8   r/   r@  r@  7  s\    H51 5BS BC Bs Bx} BH	c 	uS#X 	r8   r@  _engine_parserr   c                  .    t         
t               a t         S r[   )rT  r   r7   r8   r/   
get_enginerW    s    $&Nr8   c                  @    t         t        t                     a t         S r[   )rU  r@  rW  r7   r8   r/   
get_parserrY    s    
-Nr8   rF   rd   rC  c                 8    t               j                  | ||      S )z;Top-level entry point: parse text, return response or None.)rY  rO  )rF   rd   rC  s      r/   handle_commandr[    s    <gx66r8   ))r4   r   ru   osr   r   r   dataclassesr   typingr   r   r   r	   enumr
   urllib.requestr   r)   r   dirname__file__r   r   r   SYMBOLr   r_   r:   r>   rD   rc   rq   r   r@  rT  r5   rU  rW  rY  r[  r7   r8   r/   <module>rd     s<     	  ' ! . .  
 '',,rwwx02D
E	% %XS$ 
#t 
 % % %:   *H H^R
 R
rS St )-$	% ,#'-	  '& M 7C 73 7c 7hsm 7r8   