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
This commit is contained in:
parent
c1fb49c827
commit
deaeba6287
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><meta charset=UTF-8><title>Bot P&L</title><style>body{background:#1e1e1e;color:#d0d0d0;font-family:monospace;padding:20px}.pnl-value{font-size:48px;font-weight:700;margin:15px 0}.profit{color:#00ff88}.loss{color:#ff4444}.details{display:grid;grid-template-columns:1fr 1fr;gap:15px}</style></head><body><div id=c><div style=text-align:center>Läd…</div></div><script>setInterval(async()=>{const d=await(await fetch('http://172.16.1.168:7000/api/pnl')).json();const p=d.total_pnl_usdt,c=p>0?'profit':p<0?'loss':'';document.getElementById('c').innerHTML=`<h1>Bot P&L</h1><div class='pnl-value ${c}'>${p>=0?'+':''}$${p.toFixed(2)}</div><div>${d.total_pnl_percent>=0?'+':''}${d.total_pnl_percent.toFixed(2)}%</div>`},5000)</script></body></html>
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue