BrainDock/src/main_ml_v2.py

158 lines
6.1 KiB
Python

import asyncio, logging, joblib, time
from datetime import datetime
from src.config import get_config
from src.bot.binance_client import BinanceClientWrapper
from src.integrations.telegram_notifier import TelegramNotifier
from src.integrations.obsidian_logger import ObsidianLogger
from src.strategies.ml_strategy import MLStrategy
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class MLTradingBot:
def __init__(self, config, binance, telegram, obsidian, model, scaler):
self.config = config
self.binance = binance
self.telegram = telegram
self.obsidian = obsidian
self.model = model
self.scaler = scaler
self.strategy = MLStrategy(trading_pair=config.trading_pair)
self.last_report_time = time.time()
self.report_interval = 10800
self.trades_today = 0
self.wins_today = 0
self.losses_today = 0
self.daily_pnl = 0.0
self.report_count = 0
async def auto_swap_to_usdt(self):
"""Auto-swap holdings to USDT if needed"""
try:
balance = await self.binance.get_balance()
usdt_free = float(balance.get('USDT', {}).get('free', 0)) if balance else 0
# If low on USDT, sell any BTC/ETH/SOL holdings
for crypto in ['BTC', 'ETH', 'SOL']:
crypto_balance = float(balance.get(crypto, {}).get('free', 0)) if balance else 0
if usdt_free < 20 and crypto_balance > 0.0001:
pair = crypto + 'USDT'
logger.info(f'SWAP: Selling {crypto_balance:.6f} {crypto} for USDT')
try:
await self.binance.place_order(pair, 'SELL', 'MARKET', crypto_balance * 0.95)
await self.telegram.send_alert(f'SWAP: Sold {crypto_balance:.6f} {crypto}')
return True
except Exception as e:
logger.error(f'Swap failed: {e}')
except Exception as e:
logger.error(f'Auto-swap error: {e}')
return False
async def find_best_trade(self):
"""Scan multiple pairs for best signal"""
pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT']
for pair in pairs:
try:
price = await self.binance.get_ticker_price(pair)
signal = self.strategy.predict(price) if hasattr(self.strategy, 'predict') else 'HOLD'
if signal == 'BUY':
logger.info(f'BUY signal: {pair} at {price:.2f}')
return {'pair': pair, 'price': price, 'signal': signal}
except Exception as e:
logger.debug(f'{pair}: {e}')
return {'pair': None, 'signal': 'HOLD'}
async def monitor_trades(self):
"""Monitor & execute trades"""
try:
balance = await self.binance.get_balance()
usdt = float(balance.get('USDT', {}).get('free', 0)) if balance else 0
# Auto-swap if needed
if usdt < 15:
await self.auto_swap_to_usdt()
return
# Find best trade
trade = await self.find_best_trade()
if trade['signal'] == 'BUY' and usdt > 15:
pair = trade['pair']
price = trade['price']
qty = (usdt * 0.7) / price
logger.info(f'EXECUTE BUY: {qty:.6f} {pair} @ {price:.2f}')
try:
await self.binance.place_order(pair, 'BUY', 'MARKET', qty)
self.trades_today += 1
await self.telegram.send_alert(f'BUY {pair}\n{qty:.6f} @ {price:.2f}')
except Exception as e:
logger.error(f'Trade failed: {e}')
except Exception as e:
logger.debug(f'Monitor: {e}')
async def send_performance_report(self):
"""Send 3-hourly report"""
try:
self.report_count += 1
price = await self.binance.get_ticker_price(self.config.trading_pair)
balance = await self.binance.get_balance()
usdt = float(balance.get('USDT', {}).get('free', 0)) if balance else 0
report = f'''REPORT #{self.report_count}
BTC: {price:.2f}
Balance: {usdt:.2f} USDT
Trades: {self.trades_today}
Wins: {self.wins_today}'''
logger.info(report)
await self.telegram.send_alert(report)
except Exception as e:
logger.error(f'Report error: {e}')
async def run(self):
"""Main bot loop"""
logger.info('BOT STARTED - Multi-Crypto Auto-Trading')
await self.telegram.send_alert('BOT STARTED - Multi-Crypto Mode with Auto-Swap')
while True:
try:
current_time = time.time()
if (current_time - self.last_report_time) >= self.report_interval:
await self.send_performance_report()
self.last_report_time = current_time
await self.monitor_trades()
await asyncio.sleep(60)
except Exception as e:
logger.error(f'Bot error: {e}')
await asyncio.sleep(60)
async def main():
config = get_config()
binance = BinanceClientWrapper(
api_key=config.binance_api_key_live,
api_secret=config.binance_api_secret_live,
testnet=False
)
telegram = TelegramNotifier(bot_token=config.telegram_bot_token, chat_id=config.telegram_chat_id)
obsidian = ObsidianLogger(vault_path=config.obsidian_vault_path, trade_log_file=config.obsidian_trade_log_file)
model = joblib.load(config.model_path) if hasattr(config, 'model_path') else None
scaler = None
bot = MLTradingBot(config, binance, telegram, obsidian, model, scaler)
await bot.run()
if __name__ == '__main__':
asyncio.run(main())