import ccxt
import tkinter as tk
from tkinter import messagebox
import logging
from datetime import datetime
import pandas as pd

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

# Инициализация биржи MEXC с расширенными опциями
exchange = ccxt.mexc({
‘apiKey’: ‘mx0vgl9KtaKYrVqgxi’,
‘secret’: ‘067d53047cf245f0b5e6b2f9e987c4c6’,
‘options’: {
‘createMarketBuyOrderRequiresPrice’: False,
‘recvWindow’: 10000, # Увеличение recvWindow до 10000 миллисекунд (10 секунд)
}
})

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

# Синхронизируем время перед выполнением торговых операций
synchronize_time()

# Настройка для работы с MEXC
exchange.options[‘createMarketBuyOrderRequiresPrice’] = False

# Проверка подключения к бирже
def check_connection():
try:
exchange.fetch_time()
return True
except Exception as e:
logging.error(“Ошибка подключения к бирже: %s”, e)
return False

connected = check_connection()

# Загрузка доступных рынков
try:
markets = exchange.load_markets()
symbols = list(markets.keys())
logging.info(f"Загружено {len(symbols)} символов")
except Exception as e:
logging.error(“Ошибка при загрузке рынков: %s”, e)
messagebox.showerror(“Ошибка”, “Не удалось загрузить рынки с биржи - проверьте подключение к сети или конфигурацию API.”)
symbols = []

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

# Функция для фильтрации символов
def filter_symbols():
search_text = entry_search.get().lower()
filtered_symbols = [symbol for symbol in symbols if search_text in symbol.lower()]
menu = symbol_menu[‘menu’]
menu.delete(0, ‘end’)
for symbol in filtered_symbols:
menu.add_command(label=symbol, command=lambda value=symbol: selected_symbol.set(value) or update_units())
if filtered_symbols:
selected_symbol.set(filtered_symbols[0])
update_units()

# Функция для обновления доступных единиц торговли
def update_units():
symbol = selected_symbol.get()
base, quote = symbol.split(‘/’)
unit_menu[‘menu’].delete(0, ‘end’)
unit_menu[‘menu’].add_command(label=base, command=lambda value=base: selected_unit.set(value))
unit_menu[‘menu’].add_command(label=quote, command=lambda value=quote: selected_unit.set(value))
selected_unit.set(base)
update_balance_display(base, quote)
update_min_trade_volume(symbol)

# Функция для обновления информации о балансе
def update_balance_display(base, quote):
try:
balance = exchange.fetch_balance()
base_balance = balance[‘total’].get(base, 0)
quote_balance = balance[‘total’].get(quote, 0)
label_balance.config(text=f"Баланс {base}: {base_balance:.4f}, {quote}: {quote_balance:.4f}“)
except Exception as e:
logging.error(“Ошибка получения баланса: %s”, e)
label_balance.config(text=“Ошибка получения баланса”)

# Функция для обновления минимального объема торговли
def update_min_trade_volume(symbol):
try:
market = exchange.market(symbol)
min_volume = market[‘limits’][‘amount’][‘min’]
label_min_volume.config(text=f"Мин. объем для {symbol}: {min_volume}”)
except Exception as e:
logging.error(“Ошибка получения минимального объема: %s”, e)
label_min_volume.config(text=“Ошибка получения минимального объема”)

# Функция для обновления 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:
ticker = exchange.fetch_ticker(symbol)
return ticker[‘last’]
except Exception as e:
logging.error(“Ошибка при получении текущей цены: %s”, e)
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

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

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

# Выполняем ордер на покупку
order = exchange.create_order(symbol, ‘market’, ‘buy’, amount_units)
logging.info(“Покупка: %s”, order)
save_trade_state(‘buy’, order)
open_positions.append(order)
log_trade(‘buy’, order)
return order[‘price’]
except Exception as e:
logging.error(“Ошибка покупки: %s”, e)
messagebox.showerror(“Ошибка”, f"Не удалось купить: {e}”)
return None

# Функция для продажи на заданную сумму в валюте
def sell(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

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

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

# Выполняем ордер на продажу
order = exchange.create_market_sell_order(symbol, amount_units)
logging.info(“Продажа: %s”, order)
if open_positions:
last_buy_order = open_positions.pop()
profit = (order[‘price’] - last_buy_order[‘price’]) * amount_units
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

# Функция для логирования сделки
def log_trade(action, order, profit=0):
trade_info = {
‘action’: action,
‘symbol’: order[‘symbol’],
‘amount’: order[‘amount’],
‘price’: order[‘price’],
‘timestamp’: datetime.now().strftime(“%Y-%m-%d %H:%M:%S”),
‘profit’: profit,
}
trade_history.append(trade_info)
update_trade_history_display()
export_to_excel()

# Функция для сохранения состояния торговли
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 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(“Лог состояния торговли не найден.”)

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

# Функция для обновления отображения истории торгов
def update_trade_history_display():
text_history.delete(1.0, tk.END)
for trade in trade_history:
text_history.insert(tk.END, f"{trade[‘timestamp’]} {trade[‘action’].upper()} {trade[‘amount’]} {trade[‘symbol’]} @ {trade[‘price’]} Profit: {trade[‘profit’]}\n")

# Функция для обновления открытых позиций
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: {current_profit:.2f}\n")

# Функция для расчета текущей прибыли
def calculate_current_profit(position):
current_price = get_current_price(position[‘symbol’])
profit = (current_price - position[‘price’]) * position[‘amount’]
return profit

# Функция для начала/продолжения торговли
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())
buy(symbol, cost)

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):
new_sell_price = sell(symbol, cost)
if new_sell_price:
execute_trade.baseline_price = new_sell_price

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

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

# Пауза торговли
def pause_trade():
global paused
if trading_active:
paused = True
button_trade.config(text=“Торговля на паузе”)

# Создание интерфейса
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()
entry_search.bind(‘<KeyRelease>’, lambda event: filter_symbols())

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

selected_symbol = tk.StringVar(root)
if symbols:
selected_symbol.set(symbols[0])
symbol_menu = tk.OptionMenu(root, selected_symbol, *symbols, command=lambda _: update_units())
symbol_menu.pack()
else:
messagebox.showerror(“Ошибка”, “Список символов пуст. Проверьте соединение с биржей.”)

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=execute_trade)
button_trade.pack()

button_continue = tk.Button(root, text=“Продолжить”, command=execute_trade)
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’)

update_ui()
root.mainloop() ERROR:root:Ошибка при получении текущей цены: mexc does not have market symbol
ERROR:root:Ошибка при получении текущей цены: mexc does not have market symbol yf heccrjv jndtnm