у меня есть два кода import ccxt.async_support as ccxt
import asyncio
import platform
import random

# Ensure the correct event loop is used for Windows
if platform.system() == 'Windows':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())


async def fetch_funding_rate(exchange, symbol):
    try:
        funding_rate = await exchange.fetch_funding_rate(symbol)

        # Introducing a random delay between requests to avoid rate limiting
        await asyncio.sleep(random.uniform(1, 1.5))

        return {
            'symbol': symbol,
            'rate': funding_rate['fundingRate']
        }
    except Exception as e:
        print(f"Error fetching funding rate for {symbol} from {exchange.name}: {str(e)}")
        return None


async def fetch_funding_rates_for_exchange(exchange_name, exchange, semaphore):
    async with semaphore:
        try:
            await exchange.load_markets()
            market_names = [market for market in exchange.markets if exchange.markets[market]['type'] == 'swap']
            tasks = [fetch_funding_rate(exchange, market) for market in market_names]

            results = await asyncio.gather(*tasks)
            funding_rates = [result for result in results if result]

            # Close the exchange to properly release resources
            await exchange.close()
            return exchange_name, funding_rates

        except Exception as e:
            print(f"Error initializing markets for {exchange_name}: {str(e)}")
            await exchange.close()
            return exchange_name, []


async def get_funding_rates():
    exchanges = {
        'Binance': ccxt.binance(),
        'OKX': ccxt.okx(),
        'MEXC': ccxt.mexc(),
        'Bybit': ccxt.bybit(),
        'Kraken': ccxt.kraken(),
        'Huobi': ccxt.huobi(),
        'Gate': ccxt.gateio()
    }

    semaphore = asyncio.Semaphore(7)  # Limit the number of simultaneous requests per exchange

    tasks = [
        fetch_funding_rates_for_exchange(exchange_name, exchange, semaphore)
        for exchange_name, exchange in exchanges.items()
    ]

    results = await asyncio.gather(*tasks)
    return {exchange_name: funding_rates for exchange_name, funding_rates in results if funding_rates}


async def main():
    funding_rates = await get_funding_rates()
    ret = []
    for exchange_name, rates in funding_rates.items():
        # print(f"{exchange_name} Funding Rates:")
        for rate in rates:
            ret.append(f"Symbol: {rate['symbol']}, Rate: {rate['rate']}, EX: {exchange_name}")
    # print(ret)
    return ret

if __name__ == '__main__':
    asyncio.run(main())
  и второй import tkinter as tk
from tkinter import ttk
import asyncio
import threading
import main
import ccxt
import logging

logging.basicConfig(level=logging.DEBUG)


# Преобразование данных в словарь для удобного доступа
def parse_data(data):
    parsed_data = {}
    for line in data:
        try:
            parts = line.split(', ')
            if len(parts) != 3:
                logging.warning(f"Skipping line due to incorrect format: {line}")
                continue

            symbol_part, rate_part, exchange_part = parts

            # Debugging parts after split
            logging.debug(f"symbol_part: {symbol_part}, rate_part: {rate_part}, exchange_part: {exchange_part}")

            symbol = symbol_part.split(': ')[1]
            rate = float(rate_part.split(': ')[1])
            exchange = exchange_part.split(': ')[1]
            base_currency = symbol.split(' / ')[-1].split(':')[0]  # Получаем базовую валюту

            # Debugging symbol and base_currency
            logging.debug(f"symbol: {symbol}, base_currency: {base_currency}")

            pair = symbol.replace(':USDT', '')  # Удаляем ':USDT' из символов
            if 'USDT' in base_currency:  # Условие для фьючерсов с базовой валютой USDT
                if pair not in parsed_data:
                    parsed_data[pair] = []
                parsed_data[pair].append((rate, exchange))

        except (IndexError, ValueError) as e:
            logging.error(f"Error processing line: {line}, error: {e}")
            continue

    return parsed_data


def filter_data(parsed_data):
    filtered = []
    for pair, rates in parsed_data.items():
        if len(rates) > 1:
            for i in range(len(rates)):
                for j in range(i + 1, len(rates)):
                    rate_i, exchange_i = rates[i]
                    rate_j, exchange_j = rates[j]
                    if abs(rate_i - rate_j) >= 0.002:
                        filtered.append(f'{pair}: {rate_i}(EX: {exchange_i}), {rate_j}(EX: {exchange_j})')
    return filtered

async def fetch_data():
    data = await main.main()
    logging.debug(f"Fetched data: {data}")
    parsed_data = parse_data(data)
    logging.debug(f"Parsed data: {parsed_data}")
    return filter_data(parsed_data)

def display_data(filtered_data):
    listbox.delete(0, tk.END)
    for item in filtered_data:
        listbox.insert(tk.END, item)

def show_prices():
    if listbox.curselection():
        selected_item = listbox.get(listbox.curselection()[0])
        pair = selected_item.split(":")[0]
        exchanges = [part.split("EX: ")[1].strip(')') for part in selected_item.split(", ") if "EX: " in part]
        create_price_window(pair, exchanges)
    else:
        logging.info("No item selected")

def create_price_window(pair, exchanges):
    new_window = tk.Toplevel(root)
    new_window.title(f'Prices for {pair}')

    label = ttk.Label(new_window, text=f'Prices for {pair}')
    label.grid(row=0, column=0, pady=10)

    prices_frame = ttk.Frame(new_window)
    prices_frame.grid(row=1, column=0, pady=10)

    price_labels = {exchange: ttk.Label(prices_frame, text="") for exchange in exchanges}
    for idx, (exchange, label) in enumerate(price_labels.items()):
        ttk.Label(prices_frame, text=exchange).grid(row=idx, column=0, padx=10, pady=5)
        label.grid(row=idx, column=1, padx=10, pady=5)

    async def update_prices():
        while True:
            prices = await fetch_current_prices(pair, exchanges)
            if prices:
                for exchange, price in prices.items():
                    if isinstance(price, dict):
                        price_text = f"Long: {price['long']} / Short: {price['short']}"
                    else:
                        price_text = price
                    price_labels[exchange].config(text=price_text)
            await asyncio.sleep(2)

    asyncio.run_coroutine_threadsafe(update_prices(), loop)

    buy_button = ttk.Button(new_window, text='Buy', command = lambda: buy_on_exchanges(pair, exchanges))
    buy_button.grid(row=2, column=0, pady=10)

async def fetch_current_prices(pair, exchanges):
    prices = {}
    for ex in exchanges:
        try:
            logging.debug(f"Fetching current prices for {pair} on {ex}")
            exchange_class = getattr(ccxt, ex.lower())
            exchange = exchange_class({
                'enableRateLimit': True,
                'options': {
                    'defaultType': 'future',  # Установим параметр для работы с фьючерсами
                },
            })
            market = f'{pair}:USDT' if ' / ' not in pair else f'{pair.replace("/","")}T'  # Для фьючерсов
            ticker = await loop.run_in_executor(None, exchange.fetch_ticker, market)
            prices[ex] = {
                'long': ticker['ask'],
                'short': ticker['bid']
            }
        except Exception as e:
            logging.error(f"Error fetching prices for {pair} on {ex}: {str(e)}")
            prices[ex] = f"Error: {str(e)}"
    return prices
def buy_on_exchanges(pair, exchanges):
    logging.info(f"Buying {pair} on selected exchanges {exchanges} (Placeholder)")

async def load_data():
    filtered_data = await fetch_data()
    display_data(filtered_data)

def start_loading():
    asyncio.run_coroutine_threadsafe(load_data(), loop)

def run_event_loop():
    global loop
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_forever()

root = tk.Tk()
root.title('FilteredData')

frame = ttk.Frame(root, padding='10')
frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

scrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL)
scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))

listbox = tk.Listbox(frame, yscrollcommand=scrollbar.set, width=100, height=20)
listbox.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
scrollbar.config(command=listbox.yview)

listbox.bind('<<ListboxSelect>>', lambda event: show_prices())

button = ttk.Button(root, text='Load Data', command = start_loading)
button.grid(row=1, column=0, pady=10)

thread = threading.Thread(target=run_event_loop, daemon=True)
thread.start()

root.mainloop() улучши их пояснения на русском