Bot auto-update: src/main_ml.py
This commit is contained in:
parent
09dc561027
commit
336542728e
|
|
@ -2,11 +2,11 @@
|
||||||
import os, asyncio, aiohttp, logging, random
|
import os, asyncio, aiohttp, logging, random
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from binance.client import Client
|
from binance.client import Client
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Load env
|
|
||||||
with open("/home/marc/bot-deploy/.env") as f:
|
with open("/home/marc/bot-deploy/.env") as f:
|
||||||
env = {}
|
env = {}
|
||||||
for line in f:
|
for line in f:
|
||||||
|
|
@ -22,10 +22,9 @@ class Bot:
|
||||||
self.trades_today = 0
|
self.trades_today = 0
|
||||||
self.daily_pnl = 0.0
|
self.daily_pnl = 0.0
|
||||||
self.dashboard = "http://localhost:7000/api/update"
|
self.dashboard = "http://localhost:7000/api/update"
|
||||||
logger.info("🤖 Bot initialized - CLEAN")
|
logger.info("🤖 Bot initialized")
|
||||||
|
|
||||||
def get_balance(self):
|
def get_balance(self):
|
||||||
"""GET BALANCE FROM BINANCE (SYNC)"""
|
|
||||||
try:
|
try:
|
||||||
acc = self.binance.get_account()
|
acc = self.binance.get_account()
|
||||||
self.balance = {}
|
self.balance = {}
|
||||||
|
|
@ -33,33 +32,52 @@ class Bot:
|
||||||
free, locked = float(a["free"]), float(a["locked"])
|
free, locked = float(a["free"]), float(a["locked"])
|
||||||
if free + locked > 0:
|
if free + locked > 0:
|
||||||
self.balance[a["asset"]] = {"free": free, "locked": locked, "total": free+locked}
|
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:
|
except Exception as e:
|
||||||
logger.error(f"Balance error: {e}")
|
logger.error(f"Balance error: {e}")
|
||||||
|
|
||||||
def place_buy(self, pair):
|
def place_buy(self, pair):
|
||||||
"""PLACE BUY ORDER"""
|
|
||||||
try:
|
try:
|
||||||
usdt_free = self.balance.get("USDT", {}).get("free", 0)
|
usdt_free = self.balance.get("USDT", {}).get("free", 0)
|
||||||
qty_usdt = usdt_free * 0.5
|
if usdt_free < 5:
|
||||||
|
|
||||||
if qty_usdt < 1:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Use 25% per trade
|
||||||
|
qty_usdt = usdt_free * 0.25
|
||||||
|
|
||||||
ticker = self.binance.get_symbol_ticker(symbol=pair)
|
ticker = self.binance.get_symbol_ticker(symbol=pair)
|
||||||
price = float(ticker["price"])
|
price = float(ticker["price"])
|
||||||
|
|
||||||
qty = round(qty_usdt / price, 4)
|
# Get symbol info for filters
|
||||||
if qty <= 0:
|
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
|
return None
|
||||||
|
else:
|
||||||
|
qty = float(round(qty_usdt / price, 6))
|
||||||
|
|
||||||
order = self.binance.order_market_buy(symbol=pair, quantity=qty)
|
# Format as string to avoid scientific notation
|
||||||
|
qty_str = f"{qty:.8f}".rstrip("0").rstrip(".")
|
||||||
|
|
||||||
logger.info(f"🟢 BUY: {pair} x{qty:.4f} @ ")
|
try:
|
||||||
|
order = self.binance.order_market_buy(symbol=pair, quantity=qty_str)
|
||||||
|
logger.info(f"🟢 BUY: {pair} x{qty_str}")
|
||||||
|
|
||||||
self.current_trades[pair] = {
|
self.current_trades[pair] = {
|
||||||
"qty": qty,
|
"qty": float(qty_str),
|
||||||
"buy_price": price,
|
"buy_price": price,
|
||||||
"buy_time": datetime.now().isoformat(),
|
"buy_time": datetime.now().isoformat(),
|
||||||
"order_id": order["orderId"]
|
"order_id": order["orderId"]
|
||||||
|
|
@ -69,9 +87,11 @@ class Bot:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Buy {pair} error: {e}")
|
logger.error(f"Buy {pair} error: {e}")
|
||||||
return None
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"place_buy error: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def check_tp(self):
|
def check_tp(self):
|
||||||
"""CHECK +1% TAKE PROFIT"""
|
|
||||||
remove = []
|
remove = []
|
||||||
for pair in list(self.current_trades.keys()):
|
for pair in list(self.current_trades.keys()):
|
||||||
try:
|
try:
|
||||||
|
|
@ -108,7 +128,6 @@ class Bot:
|
||||||
del self.current_trades[p]
|
del self.current_trades[p]
|
||||||
|
|
||||||
async def send_dashboard(self):
|
async def send_dashboard(self):
|
||||||
"""SEND STATE TO DASHBOARD"""
|
|
||||||
try:
|
try:
|
||||||
state = {
|
state = {
|
||||||
"current_trades": self.current_trades,
|
"current_trades": self.current_trades,
|
||||||
|
|
@ -128,40 +147,27 @@ class Bot:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
"""MAIN LOOP"""
|
|
||||||
logger.info("🎯 Bot started")
|
logger.info("🎯 Bot started")
|
||||||
|
|
||||||
tick = 0
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
tick += 1
|
|
||||||
|
|
||||||
# Get balance every 5 ticks (every 5 seconds)
|
|
||||||
if tick % 5 == 0:
|
|
||||||
self.get_balance()
|
self.get_balance()
|
||||||
|
self.check_tp()
|
||||||
|
|
||||||
|
pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT']
|
||||||
|
|
||||||
# Check signals
|
|
||||||
pairs = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT"]
|
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
if pair not in self.current_trades:
|
if pair not in self.current_trades and random.random() < 0.05:
|
||||||
if random.random() > 0.95:
|
|
||||||
logger.info(f"🟢 Signal: {pair}")
|
logger.info(f"🟢 Signal: {pair}")
|
||||||
self.place_buy(pair)
|
self.place_buy(pair)
|
||||||
|
|
||||||
# Check exits
|
|
||||||
self.check_tp()
|
|
||||||
|
|
||||||
# Send to dashboard
|
|
||||||
await self.send_dashboard()
|
await self.send_dashboard()
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Loop error: {e}")
|
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
async def main():
|
except Exception as e:
|
||||||
bot = Bot()
|
logger.error(f"Run error: {e}")
|
||||||
await bot.run()
|
await asyncio.sleep(10)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
bot = Bot()
|
||||||
|
asyncio.run(bot.run())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue