From e3125650635db3a5ab48551d2e3cfdb2c04ac5fd Mon Sep 17 00:00:00 2001 From: Marc Blatter Date: Sat, 4 Jul 2026 13:45:01 +0200 Subject: [PATCH] Bot auto-update: src/__pycache__/main_ml.cpython-310.pyc,src/main_ml.py --- src/__pycache__/main_ml.cpython-310.pyc | Bin 28263 -> 28097 bytes src/main_ml.py | 44 +++++++----------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/src/__pycache__/main_ml.cpython-310.pyc b/src/__pycache__/main_ml.cpython-310.pyc index b0c00e0308dd395d69b5c136fda4dba2f93696cd..320cf5a867283317b0cd26867ffad83d7fe9644d 100644 GIT binary patch delta 5754 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 FzX99IBuxMS delta 5857 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 diff --git a/src/main_ml.py b/src/main_ml.py index 33f9a0e..4db7a0d 100644 --- a/src/main_ml.py +++ b/src/main_ml.py @@ -1,4 +1,3 @@ -from src.persistence import load_persistent_trades, save_persistent_trades, load_binance_positions_on_startup, init_persistence import asyncio, logging, joblib, time, json, aiohttp, os from datetime import datetime, timedelta from src.config import get_config @@ -107,24 +106,6 @@ class MLTradingBot: self.max_drawdown = 0.0 self.min_daily_pnl = 0.0 self.starting_capital = 100.0 - - # Initialize persistence and load trades - init_persistence() - self.current_trades, self.completed_trades, self.swaps = load_persistent_trades() - - if self.current_trades: - logger.info(f"Loaded {len(self.current_trades)} trades from persistent storage") - - # If portfolio value exists but no trades: recover from Binance - portfolio_val = self.binance.get_portfolio_value_usd() - if not self.current_trades and portfolio_val > 50: - logger.info(f"Portfolio exists ({portfolio_val:.2f}) but no trades - loading from Binance...") - binance_trades = load_binance_positions_on_startup() - if binance_trades: - self.current_trades.update(binance_trades) - save_persistent_trades(self.current_trades, self.completed_trades, self.swaps) - logger.info(f"Recovered {len(binance_trades)} positions from Binance API") - self.daily_loss_limit_reached = False # Symbol constraints cache @@ -132,7 +113,7 @@ class MLTradingBot: self.pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'] # Track open positions - self.current_trades = {} # CLEAN START - reset on bot restart + self.open_positions = {} # CLEAN START - reset on bot restart logger.info('🗑️ RESET: Cleared all stored positions (dashboard will show REAL Binance state only)') @@ -485,11 +466,11 @@ class MLTradingBot: logger.warning(f'Failed to get price for {pair}: {e}') continue - if pair not in self.current_trades: - logger.debug(f'⏭️ {pair} not in open_positions (keys: {list(self.current_trades.keys())})') + if pair not in self.open_positions: + logger.debug(f'⏭️ {pair} not in open_positions (keys: {list(self.open_positions.keys())})') continue - pos = self.current_trades[pair] + pos = self.open_positions[pair] buy_price = pos['buy_price'] buy_qty = pos['qty'] buy_time = datetime.fromisoformat(pos['buy_time']) @@ -570,7 +551,7 @@ class MLTradingBot: f'{icon} CLOSED {exit_reason}\n' f'{pair}: {current_qty:.8f} @ ${current_price:.2f}\n' f'Profit: ${profit_usd:+.2f} ({profit_pct:+.2f}%)\n' - f'Hold: {(datetime.now() - datetime.fromisoformat(self.current_trades[pair]["buy_time"])).total_seconds() / 60:.0f} min' + f'Hold: {(datetime.now() - datetime.fromisoformat(self.open_positions[pair]["buy_time"])).total_seconds() / 60:.0f} min' ) else: logger.info(f'Loss trade skipped from Telegram (visible on dashboard): {profit_pct:.2f}%') @@ -583,11 +564,11 @@ class MLTradingBot: self.error_count = 0 # Send to dashboard BEFORE deleting position (ONLY for REAL executed trades!) - hold_time_s = (datetime.now() - datetime.fromisoformat(self.current_trades[pair]["buy_time"])).total_seconds() + hold_time_s = (datetime.now() - datetime.fromisoformat(self.open_positions[pair]["buy_time"])).total_seconds() hold_time_min = hold_time_s / 60 await self.dashboard.record_sell(pair, current_qty, current_price, profit_usd, profit_pct, hold_time_min) - del self.current_trades[pair] + del self.open_positions[pair] logger.info(f'✅ EXIT EXECUTED & RECORDED TO DASHBOARD!') else: logger.warning(f'❌ EXIT order FAILED or returned no result for {pair} - NOT recording') @@ -756,7 +737,7 @@ class MLTradingBot: # ONLY RECORD if order was SUCCESSFUL if result and result.get('status') in ['FILLED', 'NEW', 'PARTIALLY_FILLED']: logger.info(f'🔍 DEBUG: Storing BUY position {pair}: qty={qty}, price={price}') - self.current_trades[pair] = { + self.open_positions[pair] = { 'qty': qty, 'buy_price': price, 'buy_time': datetime.now().isoformat(), @@ -764,8 +745,7 @@ class MLTradingBot: 'trailing_stop': None, 'order_id': result.get('orderId', 'unknown') } - save_persistent_trades(self.current_trades, self.completed_trades, self.swaps) - logger.info(f'🔍 DEBUG: After storage, open_positions keys = {list(self.current_trades.keys())}') + logger.info(f'🔍 DEBUG: After storage, open_positions keys = {list(self.open_positions.keys())}') self.trades_today += 1 self.error_count = 0 @@ -832,7 +812,7 @@ class MLTradingBot: Max Drawdown: ${self.max_drawdown:.2f} (CHF {self.max_drawdown * 0.84:.2f}) 🤖 BOT STATUS: {'🟢 RUNNING' if time.time() >= self.error_cooldown_until else '🟡 ERROR_COOLDOWN'} - Open Positions: {len(self.current_trades)} + Open Positions: {len(self.open_positions)} Error Count: {self.error_count}/{self.error_threshold}''' logger.info(report) @@ -984,13 +964,13 @@ class MLTradingBot: except: pass - logger.info(f'✅ Sending to dashboard: USDT={usdt_live:.2f}, portfolio={portfolio_value_usd:.2f}, trades_today={self.trades_today}, open_trades={len(self.current_trades)}') + logger.info(f'✅ Sending to dashboard: USDT={usdt_live:.2f}, portfolio={portfolio_value_usd:.2f}, trades_today={self.trades_today}, open_trades={len(self.open_positions)}') # SYNC open_positions with dashboard async with aiohttp.ClientSession() as session: async with session.post('http://localhost:7000/api/update', json={ 'balance': {'USDT': usdt_live}, - 'current_trades': self.current_trades, # Send ALL open positions! + 'current_trades': self.open_positions, # Send ALL open positions! 'daily_pnl': self.daily_pnl, 'total_pnl': self.total_pnl, 'trades_today': self.trades_today,