#!/usr/bin/env python3 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__) with open("/home/marc/bot-deploy/.env") as f: env = {} for line in f: k, _, v = line.partition("=") env[k.strip()] = v.strip() class Bot: def __init__(self): self.binance = Client(env.get("BINANCE_API_KEY_LIVE"), env.get("BINANCE_API_SECRET_LIVE")) self.current_trades = {} self.completed_trades = [] self.balance = {} self.trades_today = 0 self.daily_pnl = 0.0 self.dashboard = "http://localhost:7000/api/update" logger.info("🤖 Bot initialized") def get_balance(self): try: acc = self.binance.get_account() self.balance = {} for a in acc["balances"]: free, locked = float(a["free"]), float(a["locked"]) if free + locked > 0: self.balance[a["asset"]] = {"free": free, "locked": locked, "total": free+locked} logger.info(f"💰 Balance updated: USDT") except Exception as e: logger.error(f"Balance error: {e}") def place_buy(self, pair): try: usdt_free = self.balance.get("USDT", {}).get("free", 0) 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"]) # 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 except Exception as e: logger.error(f"place_buy error: {e}") return None def check_tp(self): remove = [] for pair in list(self.current_trades.keys()): try: trade = self.current_trades[pair] ticker = self.binance.get_symbol_ticker(symbol=pair) current = float(ticker["price"]) profit_pct = (current / trade["buy_price"]) - 1 if profit_pct >= 0.01: logger.info(f"🎯 TP HIT: {pair} +{profit_pct*100:.2f}%") sell = self.binance.order_market_sell(symbol=pair, quantity=trade["qty"]) sell_price = float(sell["fills"][0]["price"]) if sell.get("fills") else current profit = (sell_price - trade["buy_price"]) * trade["qty"] self.completed_trades.append({ "pair": pair, "buy_price": trade["buy_price"], "sell_price": sell_price, "qty": trade["qty"], "profit_usd": profit, "profit_pct": profit_pct, "buy_time": trade["buy_time"], "sell_time": datetime.now().isoformat() }) self.daily_pnl += profit remove.append(pair) except Exception as e: pass for p in remove: del self.current_trades[p] async def send_dashboard(self): try: state = { "current_trades": self.current_trades, "completed_trades": self.completed_trades[-20:], "balance": self.balance, "trades_today": self.trades_today, "daily_pnl": self.daily_pnl, "total_pnl": self.daily_pnl, "wins_today": len([t for t in self.completed_trades if t.get("profit_usd", 0) > 0]), "losses_today": len([t for t in self.completed_trades if t.get("profit_usd", 0) < 0]), "last_update": datetime.now().isoformat() } async with aiohttp.ClientSession() as s: async with s.post(self.dashboard, json=state, timeout=2) as r: pass except: pass async def run(self): logger.info("🎯 Bot started") while True: try: self.get_balance() self.check_tp() pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'] 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) except Exception as e: logger.error(f"Run error: {e}") await asyncio.sleep(10) if __name__ == "__main__": bot = Bot() asyncio.run(bot.run())