From deaeba6287cab9f77e559394bcc9f101ec7e36d7 Mon Sep 17 00:00:00 2001 From: Marc Blatter Date: Mon, 6 Jul 2026 22:00:01 +0200 Subject: [PATCH] Bot auto-update: src/__pycache__/main_ml.cpython-310.pyc,src/__pycache__/web_dashboard.cpython-310.pyc,src/dashboard_pnl.html,src/main_ml.py,src/web_dashboard.py --- src/__pycache__/main_ml.cpython-310.pyc | Bin 14985 -> 16255 bytes src/__pycache__/web_dashboard.cpython-310.pyc | Bin 20313 -> 13483 bytes src/dashboard_pnl.html | 1 + src/main_ml.py | 41 +++++++++++++++ src/web_dashboard.py | 49 ++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 src/dashboard_pnl.html diff --git a/src/__pycache__/main_ml.cpython-310.pyc b/src/__pycache__/main_ml.cpython-310.pyc index 7387957cf2e93b248060fcca02e146b8392f0ab7..83b811ac5540b7bb2b09fea4f27cc6df51e0b81c 100644 GIT binary patch delta 4426 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 delta 3233 zcmZuzeQaCR75DY$i|wW*NnPSNiQRk@$8|p1e6(5Xb|n;ALP<$S#bfaH^8D<)=J`G6 zzUQz zcD+W*&*z?dzVA8rzW+Y?Y^m8?w=U>{zfxfO*k^}-)Epy+E~LVQoM$`8?k4xFD+~Y0 zSmkZ|&U)W^DBF6y>?`3HsU&f{ma6C0Ty!VIc`aCw zHA5=sgT-Y>kR;8}Y)R^b9czkRX&S6-48B4_+hI*d5ysfXP-bcekWQeWT9%wwMNf(9 zGy^PApsH0g4NG;1%FS0{62+S(OEt2Rt?Fu?%7vNAX!t=-W)Qao%ceP7E2wloEa@1+ zI6%@((G#6Qz-Vjc=mad4%E#+};66NpJNpp0=G{Og1+M9Mi?T+!Er;ajG|D`H@F2oH z2n}Yp0q-<>z2z#ohdt9el;HkR&mmT$>_fnQoBgr%H$y0pf1>UEd#{{4y~iOVYXnMR zmW-@sum$ww}u79ouUAyU{b0_d1=*J15F0Awtlw}W?!}U9*qXikKI`3d zF~y6D$%awC@h7uS0W#zNjaRNb4cWs7n&92U^6pc1nwppCv&G9&_OJRU7&z)Vpdg<0i@&AHE5O;Cl}OZiylV- zJQ*5CX0xK3mMRrZOS3i8sAhEA0jJ+ZB|bM#03`;L5~ZqPbC+T`k9S*9r3$hz-f(@} zu%{9cva#|;Vv20RY`IbiOY-G8_FSA|K~IL_JeX{JZ@iZ-GEdLGF$}z}hFfttgfNVd zK-i0r2DmZdbe5g$>FBxXMf4O6y*?I{|31Lh%B7wwWKR*-#}IS?$FG~p0@PiGMbg80 z^cmdn*`_V)l$Uw|#pe(-_NTtIpRdobP=A7KW$FG+ejaz49qhl0A49d^?WlnDcLG%9 zT}kn#a(w)(DNinmGPMjJ!DZDLQVj>wT%8O&7%?y>>$0J!VoHf53|b37FKLsvO#KnS@@z*m4MI)}A!{ zXb%qX#blH`&)!KE$crp8un$V}$UqlKu@eI?lY5zvI&$QPDCkGvlYbvl4eyeV=P3HC z4n^TOv>Ao@a{QJp+a>G&UM%)uDn^c1ew+H7klpOvbhHC)JKlK{`t=p`fX#BFsn}oB z?FnArd1S62oJOc!KM(+m4)*r)&c9u4nrO+8lx0O%%WQ6NY2_QJ&$F073ZFTO?^oSL zQFDevT=j@8NqIqdkgwyi_B3&dk9`O>V(@Rp0R)#ogzZABkPxCmKxh(L1a@@jTO+8Q zB%)`|wCjxUqx9le$YlZsu<-8h`AG|*XW8dNFZAVsAqGl@hR6K%7XdQsZLpVyqw9Z# z`d-)(ykSDmv7Zhv#qg;SgNkY7w5$p}a*NV|k&bo0M2feRNY`c%|0I6 zmblfZvq70xl?7?Z)MZ=K;idnAwT<_X_t=i{Pspq6`uNdlK20y7qX7hdsq`aN^X0AH z9oPeW_{5NHX60r0w2;Ole4>+l!2Ue(3A~);9s9R0g5r^+uX;IcMk_rx z9q_}ees5Kic^bD)vG$!KeGSR9m5OjvsS;d1kc*KA|7J17%$?mkKLn*@(g{dX)>I_P zahn!>4R~TeH}iRrrMzFg$1Hfau#rS)ZF`=6lMQAHkvGsKPZxW`@tQ@|phwt+%)tF; zk>P=NC*=)3MPdC+`%gk1$QThi4GoT|&3WRrUaTDRa32p*U}uW*MD K3E$!U+5Z6J8vA?z diff --git a/src/__pycache__/web_dashboard.cpython-310.pyc b/src/__pycache__/web_dashboard.cpython-310.pyc index 988e2ef0b03450193e68079d57c5b00b066d8b63..16f0335a8a9f694c8b093df68dfa62d2cef3222d 100644 GIT binary patch literal 13483 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 literal 20313 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 P&L
Läd…
diff --git a/src/main_ml.py b/src/main_ml.py index 3a24db3..d43e79f 100644 --- a/src/main_ml.py +++ b/src/main_ml.py @@ -56,6 +56,11 @@ class TradingBot: self.trades_today = 0 self.last_trade_reset = None # -5% max + # Profit tracking + self.entry_price_history = {} # symbol -> entry price + self.closed_trades = [] # list of {symbol, entry, exit, profit_pct, profit_usdt} + self.session_start_balance = None + self.active_trades = {} self.daily_pnl = 0 self.paused = False @@ -539,3 +544,39 @@ if __name__ == '__main__': return True return False + + + def record_entry(self, pair, price, quantity): + """Record entry price for profit calculation""" + self.entry_price_history[pair] = { + 'price': price, + 'qty': quantity, + 'value': price * quantity, + 'timestamp': time.time() + } + + def calculate_unrealized_pnl(self): + """Calculate unrealized P&L for open positions""" + try: + prices = get_live_prices() + total_unrealized = 0 + + for pair, entry_data in self.entry_price_history.items(): + asset = pair.replace('USDT', '') + current_price = prices.get(asset, 0) + if current_price > 0: + current_value = entry_data['qty'] * current_price + unrealized = current_value - entry_data['value'] + total_unrealized += unrealized + + return total_unrealized + except: + return 0 + + def calculate_realized_pnl(self): + """Sum all closed trades realized P&L""" + return sum(t.get('profit_usdt', 0) for t in self.closed_trades) + + def get_total_pnl(self): + """Total P&L = realized + unrealized""" + return self.calculate_realized_pnl() + self.calculate_unrealized_pnl() diff --git a/src/web_dashboard.py b/src/web_dashboard.py index 753b2d9..e2920ee 100644 --- a/src/web_dashboard.py +++ b/src/web_dashboard.py @@ -578,6 +578,55 @@ setInterval(function() {{ return Response(content=html, media_type='text/html') + +@app.get('/api/pnl') +async def get_pnl(): + """Get live Profit & Loss (P&L) calculation""" + try: + account = binance.get_account() + + # Get current account value + prices = get_live_prices() + current_value = 0 + + for asset_data in account['balances']: + asset = asset_data['asset'] + total = float(asset_data['free']) + float(asset_data['locked']) + + if total > 0.00001 and asset != 'LDDOGE' and asset != 'LDBTTC': + price = prices.get(asset, 1.0) + current_value += total * price + + # Benchmark: Initial capital was $137.79 (before trading) + # This should be stored, but for now use a reference + initial_capital = 137.79 + + pnl_usdt = current_value - initial_capital + pnl_pct = (pnl_usdt / initial_capital * 100) if initial_capital > 0 else 0 + + # Get open trades for unrealized portion + state_file = '/home/marc/bot-deploy/trades.json' + open_trades = {} + if os.path.exists(state_file): + try: + data = json.load(state_file) + open_trades = data.get('current', {}) + except: + pass + + return { + 'current_value': round(current_value, 2), + 'initial_capital': initial_capital, + 'total_pnl_usdt': round(pnl_usdt, 2), + 'total_pnl_percent': round(pnl_pct, 2), + 'status': '🟢 PROFIT' if pnl_usdt > 0 else ('🔴 LOSS' if pnl_usdt < 0 else '⚪ BREAK'), + 'open_positions': len(open_trades), + 'timestamp': datetime.now().isoformat() + } + except Exception as e: + return {'error': str(e)} + + if __name__ == '__main__': import uvicorn uvicorn.run(app, host='0.0.0.0', port=7000)