From 336542728e32eb176703fd379256232797e1fcc6 Mon Sep 17 00:00:00 2001 From: Marc Blatter Date: Sat, 4 Jul 2026 19:20:01 +0200 Subject: [PATCH] Bot auto-update: src/main_ml.py --- src/main_ml.py | 114 ++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/src/main_ml.py b/src/main_ml.py index 86db97e..657417f 100644 --- a/src/main_ml.py +++ b/src/main_ml.py @@ -2,11 +2,11 @@ import os, asyncio, aiohttp, logging, random from datetime import datetime from binance.client import Client +from decimal import Decimal logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) -# Load env with open("/home/marc/bot-deploy/.env") as f: env = {} for line in f: @@ -22,10 +22,9 @@ class Bot: self.trades_today = 0 self.daily_pnl = 0.0 self.dashboard = "http://localhost:7000/api/update" - logger.info("🤖 Bot initialized - CLEAN") + logger.info("🤖 Bot initialized") def get_balance(self): - """GET BALANCE FROM BINANCE (SYNC)""" try: acc = self.binance.get_account() self.balance = {} @@ -33,45 +32,66 @@ class Bot: free, locked = float(a["free"]), float(a["locked"]) if free + locked > 0: self.balance[a["asset"]] = {"free": free, "locked": locked, "total": free+locked} - usdt_free = self.balance.get("USDT", {}).get("free", 0) - logger.info(f"💰 Balance updated: USDT ") + logger.info(f"💰 Balance updated: USDT") except Exception as e: logger.error(f"Balance error: {e}") def place_buy(self, pair): - """PLACE BUY ORDER""" try: usdt_free = self.balance.get("USDT", {}).get("free", 0) - qty_usdt = usdt_free * 0.5 - - if qty_usdt < 1: + if usdt_free < 5: return None + # Use 25% per trade + qty_usdt = usdt_free * 0.25 + ticker = self.binance.get_symbol_ticker(symbol=pair) price = float(ticker["price"]) - qty = round(qty_usdt / price, 4) - if qty <= 0: + # Get symbol info for filters + info = self.binance.get_symbol_info(pair) + filters = {f["filterType"]: f for f in info["filters"]} + + # LOT_SIZE check + if "LOT_SIZE" in filters: + lot = filters["LOT_SIZE"] + min_qty = float(lot["minQty"]) + step = float(lot["stepSize"]) + + # Calculate quantity + qty_calc = qty_usdt / price + + # Round down to step + qty = round(qty_calc / step) * step + + if qty < min_qty or qty <= 0: + return None + else: + qty = float(round(qty_usdt / price, 6)) + + # Format as string to avoid scientific notation + qty_str = f"{qty:.8f}".rstrip("0").rstrip(".") + + try: + order = self.binance.order_market_buy(symbol=pair, quantity=qty_str) + logger.info(f"🟢 BUY: {pair} x{qty_str}") + + self.current_trades[pair] = { + "qty": float(qty_str), + "buy_price": price, + "buy_time": datetime.now().isoformat(), + "order_id": order["orderId"] + } + self.trades_today += 1 + return order + except Exception as e: + logger.error(f"Buy {pair} error: {e}") return None - - order = self.binance.order_market_buy(symbol=pair, quantity=qty) - - logger.info(f"🟢 BUY: {pair} x{qty:.4f} @ ") - - self.current_trades[pair] = { - "qty": qty, - "buy_price": price, - "buy_time": datetime.now().isoformat(), - "order_id": order["orderId"] - } - self.trades_today += 1 - return order except Exception as e: - logger.error(f"Buy {pair} error: {e}") + logger.error(f"place_buy error: {e}") return None def check_tp(self): - """CHECK +1% TAKE PROFIT""" remove = [] for pair in list(self.current_trades.keys()): try: @@ -108,7 +128,6 @@ class Bot: del self.current_trades[p] async def send_dashboard(self): - """SEND STATE TO DASHBOARD""" try: state = { "current_trades": self.current_trades, @@ -128,40 +147,27 @@ class Bot: pass async def run(self): - """MAIN LOOP""" logger.info("🎯 Bot started") - tick = 0 while True: try: - tick += 1 - - # Get balance every 5 ticks (every 5 seconds) - if tick % 5 == 0: - self.get_balance() - - # Check signals - pairs = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT"] - for pair in pairs: - if pair not in self.current_trades: - if random.random() > 0.95: - logger.info(f"🟢 Signal: {pair}") - self.place_buy(pair) - - # Check exits + self.get_balance() self.check_tp() - # Send to dashboard - await self.send_dashboard() + pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'] - await asyncio.sleep(1) - except Exception as e: - logger.error(f"Loop error: {e}") + for pair in pairs: + if pair not in self.current_trades and random.random() < 0.05: + logger.info(f"🟢 Signal: {pair}") + self.place_buy(pair) + + await self.send_dashboard() await asyncio.sleep(5) - -async def main(): - bot = Bot() - await bot.run() + + except Exception as e: + logger.error(f"Run error: {e}") + await asyncio.sleep(10) if __name__ == "__main__": - asyncio.run(main()) + bot = Bot() + asyncio.run(bot.run())