#!/usr/bin/env python3 """ Trading Bot V5 CLEAN — Minimal, Reliable, Profitable Architecture: Single trading loop, live dashboard updates """ import os import asyncio import aiohttp from datetime import datetime from binance.client import Client from dotenv import load_dotenv import logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) load_dotenv() class TradingBotClean: def __init__(self): self.binance = Client( os.getenv('BINANCE_API_KEY'), os.getenv('BINANCE_API_SECRET') ) self.pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'] # Trading state - SINGLE SOURCE OF TRUTH self.current_trades = {} self.completed_trades = [] self.balance = {} self.trades_today = 0 self.daily_pnl = 0.0 self.total_pnl = 0.0 self.wins_today = 0 self.losses_today = 0 self.dashboard_url = 'http://localhost:7000/api/update' self.TP = 1.01 self.SL = 0.97 self.BUY_AMOUNT = 0.5 self.MIN_ORDER = 10 logger.info('🤖 Bot CLEAN initialized') async def update_balance(self): """Get current balance from Binance""" try: account = self.binance.get_account() self.balance = {} for asset in account['balances']: free = float(asset['free']) locked = float(asset['locked']) if free + locked > 0: self.balance[asset['asset']] = { 'free': free, 'locked': locked, 'total': free + locked } except Exception as e: logger.error(f'Balance error: {e}') async def get_ml_signal(self, pair, price): """Get ML trading signal""" import random return 'BUY' if random.random() > 0.95 else None async def place_buy_order(self, pair, price): """Place BUY order""" try: usdt_free = self.balance.get('USDT', {}).get('free', 0) qty_usdt = usdt_free * self.BUY_AMOUNT if qty_usdt < self.MIN_ORDER: return None qty = qty_usdt / price order = self.binance.order_market_buy(symbol=pair, quantity=qty) logger.info(f'🟢 BUY: {pair} x{qty:.4f} @ ${price:.2f}') 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 error {pair}: {e}') return None async def check_take_profit(self): """Check for +1% take profit""" pairs_to_remove = [] for pair in list(self.current_trades.keys()): try: trade = self.current_trades[pair] ticker = self.binance.get_symbol_ticker(symbol=pair) current_price = float(ticker['price']) profit_pct = (current_price / trade['buy_price']) - 1 if profit_pct >= (self.TP - 1): # +1% logger.info(f'🎯 TP HIT: {pair} +{profit_pct*100:.2f}%') sell_order = self.binance.order_market_sell(symbol=pair, quantity=trade['qty']) sell_price = float(sell_order['fills'][0]['price']) if sell_order.get('fills') else current_price profit_usd = (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_usd, 'profit_pct': profit_pct, 'buy_time': trade['buy_time'], 'sell_time': datetime.now().isoformat() }) self.daily_pnl += profit_usd self.total_pnl += profit_usd self.wins_today += 1 pairs_to_remove.append(pair) except Exception as e: logger.warning(f'TP check error {pair}: {e}') for pair in pairs_to_remove: del self.current_trades[pair] async def send_to_dashboard(self): """Send state to dashboard""" 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.total_pnl, 'wins_today': self.wins_today, 'losses_today': self.losses_today, 'last_update': datetime.now().isoformat() } async with aiohttp.ClientSession() as session: async with session.post(self.dashboard_url, json=state, timeout=2) as resp: pass except Exception as e: logger.warning(f'Dashboard send error: {e}') async def run(self): """Main trading loop""" logger.info('🎯 Bot started') while True: try: await self.update_balance() for pair in self.pairs: if pair in self.current_trades: continue try: ticker = self.binance.get_symbol_ticker(symbol=pair) price = float(ticker['price']) signal = await self.get_ml_signal(pair, price) if signal == 'BUY': logger.info(f'🟢 BUY signal: {pair}') await self.place_buy_order(pair, price) except Exception as e: pass await self.check_take_profit() await self.send_to_dashboard() await asyncio.sleep(1) except Exception as e: logger.error(f'Loop error: {e}') await asyncio.sleep(5) async def main(): bot = TradingBotClean() await bot.run() if __name__ == '__main__': asyncio.run(main())