import tkinter as tk
from tkinter import messagebox
import ccxt
import logging
from datetime import datetime, timedelta
import pandas as pd
import time
import hmac
import hashlib
import requests

# Логирование
logging.basicConfig(filename=‘trading_bot.log’, level=logging.INFO)

# Конфигурация API (замените YOUR_API_KEY и YOUR_SECRET_KEY своими настоящими ключами)
api_key = ‘YOUR_API_KEY’
secret = ‘YOUR_SECRET_KEY’

# Функция для генерации сигнатуры
def generate_signature(api_key, secret, req_time, params=‘’):
    message = api_key + str(req_time) + params
    signature = hmac.new(secret.encode(‘utf-8’), message.encode(‘utf-8’), hashlib.sha256).hexdigest()
    return signature

# Инициализация биржи MEXC через библиотеку ccxt для получения маркетинговой информации
exchange = ccxt.mexc({
    ‘apiKey’: api_key,
    ‘secret’: secret,
})

# Функция для синхронизации времени (основа для дальнейших временных расчетов)
def synchronize_time():
    try:
        exchange.load_time_difference()
        logging.info(“Синхронизация времени с биржей.”)
    except Exception as e:
        logging.error(“Ошибка синхронизации времени: %s”, e)

# Глобальные переменные
open_positions = []
session_profit = 0.0
session_start_time = None
trading_active = False
paused = False
trade_history = []

# Функция для обновления UI
def update_ui():
    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"Время сессии: {str(elapsed_time).split(‘.’)[0]}”)
    
    connection_status.config(bg=“green” if connected else “red”)
    update_open_positions_display()
    root.after(1000, update_ui)

# Функция для получения текущей цены
def get_current_price(symbol):
    try:
        if not validate_symbol(symbol):
            return None

        ticker = exchange.fetch_ticker(symbol)
        return ticker[‘last’]
    except Exception as e:
        logging.error(“Ошибка при получении текущей цены: %s”, e)
        messagebox.showerror(“Ошибка”, f"Не удалось получить текущую цену для {symbol}.“)
        return None

# Функция для покупки на заданную сумму в валюте
def buy(symbol, cost):
    try:
        if cost <= 0:
            messagebox.showerror(“Ошибка”, “Сумма должна быть положительной.”)
            return None
        
        current_price = get_current_price(symbol)
        if current_price is None or current_price <= 0:
            messagebox.showerror(“Ошибка”, “Не удалось получить корректную текущую цену.”)
            return None

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

        amount_units = cost / current_price
        amount_units = round(amount_units, market[‘precision’][‘amount’])

        logging.info(f"Текущая цена: {current_price}”)
        logging.info(f"Вычисленное количество единиц: {amount_units}“)
        logging.info(f"Минимальный объем для {symbol}: {min_volume}”)

        if amount_units < min_volume:
            messagebox.showerror(“Ошибка”, f"Минимальный объем для торговли: {min_volume}“)
            return None

        if amount_units <= 0:
            messagebox.showerror(“Ошибка”, “Количество единиц должно быть положительным.”)
            return None

        order = place_order(symbol, amount_units, current_price, ‘BID’)
        if order:
            open_positions.append({‘symbol’: symbol, ‘amount’: amount_units, ‘buy_price’: current_price, ‘order_id’: order[‘id’]})
    except Exception as e:
        logging.error(“Ошибка покупки: %s”, e)
        messagebox.showerror(“Ошибка”, f"Не удалось купить: {e}”)
        return None

# Функция для размещения ордера
def place_order(symbol, quantity, price, trade_type=‘BID’):
    endpoint = “/open/api/v2/order/place”
    url = f"https://www.mexc.com{endpoint}“

    req_time = int(time.time() * 1000)
    params = {
        “symbol”: symbol,
        “quantity”: quantity,
        “price”: price,
        “trade_type”: trade_type,
        “order_type”: “LIMIT_ORDER”
    }

    sign = generate_signature(api_key, secret, req_time, f"symbol={symbol}&quantity={quantity}&price={price}&trade_type={trade_type}&order_type=LIMIT_ORDER”)

    headers = {
        “ApiKey”: api_key,
        “Request-Time”: str(req_time),
        “Signature”: sign,
        “Content-Type”: “application/json”
    }
    
    response = requests.post(url, headers=headers, json=params)

    if response.status_code == 200:
        data = response.json()
        if data[‘code’] == 200:
            logging.info(“Order placed: %s”, data)
            return data[‘data’]
        else:
            logging.error(“Failed to place order: %s”, data)
    else:
        logging.error(“HTTP Error: %d”, response.status_code)

# Загрузка состояния торговли из логов
def load_trade_state():
    global session_profit, 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)})
                session_profit += float(profit)
    except FileNotFoundError:
        logging.info(“Лог состояния торговли не найден.”)

# Сохранение состояния торговли
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")

# Экспорт истории торгов в Excel
def export_to_excel():
    df = pd.DataFrame(trade_history)
    df.to_excel(“trade_history.xlsx”, index=False)

# Функция для обновления и отображения открытых позиций
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[‘buy_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[‘buy_price’]) * position[‘amount’]
        return profit
    return 0.0

# Функция для начала/продолжения торговли
def execute_trade():
    global session_start_time, trading_active, paused
    if paused:
        paused = False
        button_trade.config(text=“Торговля активна”)
        return

    try:
        if not trading_active:
            session_start_time = datetime.now()
            button_trade.config(text=“Торговля активна”)
            trading_active = True

        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:
            return

        if not hasattr(execute_trade, “baseline_price”):
            execute_trade.baseline_price = current_price

        # Покупка при просадке
        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

        # Продажа при росте
        if current_price >= execute_trade.baseline_price * (1 + rise_threshold):
            for pos in open_positions:
                sell(pos[‘symbol’], pos[‘amount’])
                open_positions.remove(pos)

        label_positions.config(text=f"Открытых сделок: {len(open_positions)}“)
        label_profit.config(text=f"Прибыль сессии: {session_profit:.2f}”)

    except ValueError:
        messagebox.showerror(“Ошибка”, “Некорректный ввод. Убедитесь, что все значения заданы корректно.”)

# Функция для продажи
def sell(symbol, amount):
    try:
        current_price = get_current_price(symbol)
        if current_price is None or current_price <= 0:
            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

        order = exchange.create_market_sell_order(symbol, amount)
        logging.info(“Продажа: %s”, order)
        if open_positions:
            last_buy_order = open_positions.pop()
            profit = (order[‘price’] - last_buy_order[‘price’]) * amount
            save_trade_state(‘sell’, order, profit)
            log_trade(‘sell’, order, profit)
        return order[‘price’]
    except Exception as e:
        logging.error(“Ошибка продажи: %s”, e)
        messagebox.showerror(“Ошибка”, f"Не удалось продать: {e}”)
        return None

# Создание интерфейса
root = tk.Tk()
root.title(“MEXC Trading Bot”)

# Инициализация состояния
load_trade_state()

# Элементы интерфейса
label_search = tk.Label(root, text=‘Поиск символа:’)
label_search.pack()
entry_search = tk.Entry(root)
entry_search.pack()

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

selected_symbol = tk.StringVar(root)
symbol_menu = tk.OptionMenu(root, selected_symbol, ‘’)
symbol_menu.pack()

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

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

label_min_volume = tk.Label(root, text=“Мин. объем:”)
label_min_volume.pack()

label_amount = tk.Label(root, text=‘Сумма (в фиатной или криптовалюте):’)
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=lambda: execute_trade())
button_trade.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()

# Обновление UI
update_ui()
root.mainloop() Traceback (most recent call last):
  File "C:\Users\NOD\trading_bot.py", line 313, in <module>
    button_pause = tk.Button(root, text="Пауза", command=pause_trade)
                                                         ^^^^^^^^^^^
NameError: name 'pause_trade' is not defined