ошибка такая 2024-09-15 10:11:44,929 ERROR - Ошибка инициализации биржи MEXC: 'status'
2024-09-15 10:11:45,043 INFO - Лог состояния торговли не найден.
2024-09-15 10:11:45,044 INFO - Местное время компьютера: 2024-09-15 10:11:45.044063
Traceback (most recent call last):
  File "C:\Users\NOD\trading_bot.py", line 354, in <module>
    symbol_menu = OptionMenu(root, selected_symbol, *symbols)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ в коде import tkinter as tk
from tkinter import messagebox, OptionMenu, StringVar
import ccxt
import logging
from datetime import datetime
import time
import threading
from queue import Queue, Empty
import pytz

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('trading_bot.log'),
        logging.StreamHandler()
    ]
)

# Конфигурация API
api_key = 'mx0vgl9KtaKYrVqgxi'
secret = '067d53047cf245f0b5e6b2f9e987c4c6'

# Глобальные переменные
connected = False
symbols = []
units = []  
open_positions = []
session_start_time = None
paused = False

# Инициализация биржи
try:
    exchange = ccxt.mexc({
        'apiKey': api_key,
        'secret': secret,
        'enableRateLimit': True,
    })
    markets = exchange.fetch_markets()
    symbols = [market['symbol'] for market in markets if market['status'] == 'ENABLED']
    logging.info('Биржа MEXC успешно инициализирована.')
    logging.info(f'Доступные символы: {symbols}')
    connected = True
except Exception as e:
    logging.error('Ошибка инициализации биржи MEXC: %s', e)
    connected = False

# Получение и отображение баланса
def get_and_display_balance():
    try:
        balance = exchange.fetch_balance()
        usdt_balance = balance.get('total', {}).get('USDT', 0)
        label_balance.config(text=f'Баланс USDT: {usdt_balance:.2f}')
    except Exception as e:
        logging.error('Ошибка получения баланса: %s', e)

# Получение текущей цены для символа
def get_current_price(symbol):
    try:
        ticker = exchange.fetch_ticker(symbol)
        return ticker['last']
    except Exception as e:
        logging.error('Ошибка получения текущей цены: %s', e)
        return None

# Проверка символа
def validate_symbol(symbol):
    if not symbol:
        messagebox.showerror('Ошибка', 'Символ не выбран.')
        return False
    if symbol not in symbols:
        messagebox.showerror('Ошибка', f'Символ {symbol} не поддерживается или отключен.')
        return False
    return True

# Функция покупки
def buy(symbol, cost):
    try:
        if cost <= 0:
            messagebox.showerror('Ошибка', 'Сумма покупки должна быть положительной.')
            return None

        if not validate_symbol(symbol):
            return None

        logging.info(f'Попытка купить на сумму: {cost} для символа: {symbol}')
        
        current_price = get_current_price(symbol)
        if current_price is None:
            messagebox.showerror('Ошибка', 'Не удалось получить текущую цену.')
            return None

        market = exchange.market(symbol)
        min_cost = market['limits']['cost']['min']
        
        if cost < min_cost:
            messagebox.showerror('Ошибка', f'Минимальная сумма для покупки: {min_cost:.8f}.')
            return None

        # Создание рыночного ордера с использованием параметра 'quoteOrderQty'
        order = exchange.create_order(
            symbol=symbol,
            type='market',
            side='buy',
            amount=None,
            params={'quoteOrderQty': cost}
        )

        if order:
            open_positions.append({'symbol': symbol, 'amount': cost, 'price': current_price, 'order_id': order['id']})
            return current_price
    except Exception as e:
        logging.error('Ошибка при покупке: %s', e)
        messagebox.showerror('Ошибка', f'Ошибка при покупке: {e}')
        return None

# Функция продажи
def sell(symbol, amount):
    try:
        if not validate_symbol(symbol):
            return None
        
        logging.info(f'Попытка продать {amount} для символа: {symbol}')

        current_price = get_current_price(symbol)
        if current_price is None:
            messagebox.showerror('Ошибка', 'Не удалось получить текущую цену.')
            return None

        market = exchange.market(symbol)
        min_volume = market['limits']['amount']['min']

        if amount < min_volume:
            messagebox.showerror('Ошибка', f"Минимальное количество для продажи: {min_volume}.")
            return None

        precision = market['precision']['amount']
        amount = round(amount, precision)

        # Создание рыночного ордера на продажу
        order = exchange.create_order(
            symbol=symbol,
            type='market',
            side='sell',
            amount=amount
        )
        logging.info('Продажа: %s', order)

        if open_positions:
            last_buy_order = open_positions.pop(0)  # Поправим, чтобы соответствовать FIFO
            profit = (current_price - last_buy_order['price']) * amount
            save_trade_state('sell', order, profit)
            logging.info('Торговая история: %s', {'type': 'sell', 'order': order, 'profit': profit})
            return current_price
    except Exception as e:
        logging.error('Ошибка продажи: %s', e)
        messagebox.showerror('Ошибка', f"Не удалось продать: {e}")
        return None

# Сохранение состояния торговли
def save_trade_state(action, order, profit=0):
    with open('trading_bot_state.log', 'a') as f:
        f.write(f"{action},{order['symbol']},{order['amount']},{order['price']},{profit}\n")

# Загрузка состояния торговли из логов
def load_trade_state():
    global open_positions
    try:
        with open('trading_bot_state.log', 'r') as f:
            lines = f.readlines()
            open_positions = []
            for line in lines:
                action, symbol, amount, price, profit = line.strip().split(',')
                if action == 'buy':
                    open_positions.append({'symbol': symbol, 'amount': float(amount), 'price': float(price)})
    except FileNotFoundError:
        logging.info('Лог состояния торговли не найден.')

def continue_previous_session():
    load_trade_state()
    messagebox.showinfo('Продолжение торговой сессии', 'Предыдущая торговая сессия загружена.')
    execute_trade()

# Обновление и отображение открытых позиций
def update_open_positions_display():
    open_orders_text.delete(1.0, tk.END)
    for position in open_positions:
        current_profit = calculate_current_profit(position)
        open_orders_text.insert(tk.END, f"{position['symbol']} {position['amount']} @ {position['price']} текущая прибыль: {current_profit:.2f}\n")

# Расчет текущей прибыли
def calculate_current_profit(position):
    current_price = get_current_price(position['symbol'])
    if current_price is not None:
        profit = (current_price - position['price']) * position['amount']
        return profit
    return 0.0

# Обновление меню символов
def update_symbol_menu(search_query):
    filtered_symbols = [symbol for symbol in symbols if search_query.lower() in symbol.lower()]
    menu = symbol_menu['menu']
    menu.delete(0, 'end')
    for symbol in filtered_symbols:
        menu.add_command(label=symbol, command=lambda s=symbol: on_symbol_select(s))
    if filtered_symbols:
        selected_symbol.set(filtered_symbols[0])
        update_units(filtered_symbols[0])

# Выбор символа
def on_symbol_select(symbol):
    selected_symbol.set(symbol)
    update_units(symbol)

# Обновление единиц
def update_units(symbol):
    global units
    if symbol in exchange.markets:
        market = exchange.markets[symbol]
        base_currency = market['base']
        quote_currency = market['quote']
        units = [base_currency, quote_currency]
    else:
        units = []
    update_unit_menu()

# Обновление меню единиц
def update_unit_menu():
    menu = unit_menu['menu']
    menu.delete(0, 'end')
    for unit in units:
        menu.add_command(label=unit, command=lambda u=unit: selected_unit.set(u))
    if units:
        selected_unit.set(units[0])

# Пауза торговли
def pause_trade():
    global paused
    paused = True
    button_trade.config(text='Торговля на паузе')
    logging.info('Торговля приостановлена пользователем.')

# Синхронизация времени
def synchronize_time():
    global connected
    try:
        server_time = exchange.fetch_time()
        local_time = int(time.time() * 1000)
        time_difference = server_time - local_time
        utc = pytz.utc
        logging.info('Синхронизация времени с биржей.')
        logging.info(f'Серверное время: {datetime.fromtimestamp(server_time / 1000, utc)}')
        logging.info(f'Локальное время: {datetime.fromtimestamp(local_time / 1000, utc)}')
        logging.info(f'Временная разница: {time_difference} мс')
    except Exception as e:
        logging.error('Ошибка синхронизации времени: %s', e)
        connected = False

# Торговая логика
def trade_logic_thread(q):
    try:
        symbol = selected_symbol.get()
        cost = float(entry_amount.get())
        dip_threshold = float(entry_dip.get()) / 100
        rise_threshold = float(entry_rise.get()) / 100

        current_price = get_current_price(symbol)
        if current_price is None:
            raise Exception('Недоступна текущая цена.')

        if not hasattr(execute_trade, "baseline_price") or not open_positions:
            new_buy_price = buy(symbol, cost)
            if new_buy_price:
                execute_trade.baseline_price = new_buy_price
                q.put('Куплено!')

        else:
            if current_price <= execute_trade.baseline_price * (1 - dip_threshold):
                new_buy_price = buy(symbol, cost)
                if new_buy_price:
                    execute_trade.baseline_price = new_buy_price
                    q.put('Куплено на просадке!')

            if current_price >= execute_trade.baseline_price * (1 + rise_threshold):
                for pos in open_positions[:]:
                    sell(pos['symbol'], pos['amount'])
                    open_positions.remove(pos)
                q.put('Продано при росте!')
    except Exception as e:
        q.put(f'Ошибка: {e}')

# Выполнение торговли
def execute_trade():
    global paused
    if paused:
        paused = False
        button_trade.config(text='Торговля активна')
        return

    session_start_time = datetime.now()
    button_trade.config(text='Торговля активна')

    q = Queue()
    trade_thread = threading.Thread(target=trade_logic_thread, args=(q,))
    trade_thread.start()

    check_queue(q)

def check_queue(q):
    try:
        message = q.get_nowait()
    except Empty:
        root.after(100, check_queue, q)
        return

    messagebox.showinfo('Статус', message)

def update_ui():
    if not connected:
        return

    symbol = selected_symbol.get()
    current_price = get_current_price(symbol)
    if current_price:
        label_current_price.config(text=f'Текущая цена: {current_price:.2f}')

    if session_start_time:
        elapsed_time = datetime.now() - session_start_time
        label_session_time.config(text=f'Время сессии: {elapsed_time}')

    connection_status.config(bg='green' if connected else 'red')
    update_open_positions_display()
    root.after(1000, update_ui)

# Интерфейс
root = tk.Tk()
root.title('MEXC Trading Bot')

load_trade_state()
logging.info(f'Местное время компьютера: {datetime.now()}')

label_search = tk.Label(root, text='Поиск символа:')
label_search.pack()

entry_search = tk.Entry(root)
entry_search.pack()
entry_search.bind('<KeyRelease>', lambda event: update_symbol_menu(entry_search.get()))

label_symbol = tk.Label(root, text='Символ:')
label_symbol.pack()

selected_symbol = StringVar(root)
symbol_menu = OptionMenu(root, selected_symbol, *symbols)
symbol_menu.pack()

label_unit = tk.Label(root, text='Торговая единица:')
label_unit.pack()
selected_unit = StringVar(root)
unit_menu = OptionMenu(root, selected_unit, '')
unit_menu.pack()

update_symbol_menu('')

label_balance = tk.Label(root, text="Баланс")
label_balance.pack()

label_amount = tk.Label(root, text='Сумма (в USDT):')
label_amount.pack()
entry_amount = tk.Entry(root)
entry_amount.pack()
entry_amount.insert(tk.END, '10')

label_dip = tk.Label(root, text='Покупка при просадке (%):')
label_dip.pack()
entry_dip = tk.Entry(root)
entry_dip.pack()
entry_dip.insert(tk.END, '0.5')

label_rise = tk.Label(root, text='Продажа при росте (%):')
label_rise.pack()
entry_rise = tk.Entry(root)
entry_rise.pack()
entry_rise.insert(tk.END, '1')

button_trade = tk.Button(root, text='Начать торговлю', command=execute_trade)
button_trade.pack()

button_continue = tk.Button(root, text='Продолжить прошлую сессию', command=continue_previous_session)
button_continue.pack()

button_pause = tk.Button(root, text='Пауза', command=pause_trade)
button_pause.pack()

label_current_price = tk.Label(root, text='Текущая цена:')
label_current_price.pack()

label_positions = tk.Label(root, text='Открытых сделок: 0')
label_positions.pack()

label_profit = tk.Label(root, text='Прибыль сессии: 0.00')
label_profit.pack()

label_session_time = tk.Label(root, text='Время сессии: 00:00:00')
label_session_time.pack()

label_trade_history = tk.Label(root, text='История ордеров:')
label_trade_history.pack()
text_history = tk.Text(root, height=10, width=50)
text_history.pack()

label_open_orders = tk.Label(root, text='Текущие ордера:')
label_open_orders.pack()
open_orders_text = tk.Text(root, height=10, width=50)
open_orders_text.pack()

connection_status = tk.Label(root, text='Статус подключения', width=20, bg='red')
connection_status.pack(anchor='se')

synchronize_time()
get_and_display_balance()
update_ui()

root.mainloop()