Вот мой код скачивания датасета:
```py

# data_loader.py

import requests
import pandas as pd
import time
from datetime import datetime
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed


def get_data(symbol, start_time, end_time, interval):
    url = "https://api.binance.com/api/v3/klines"
    limit = 1000
    all_data = []
    while start_time < end_time:
        params = {
            'symbol': symbol,
            'interval': interval,
            'startTime': start_time,
            'endTime': end_time,
            'limit': limit
        }
        response = requests.get(url, params=params)
        data = response.json()
        if not data:
            break
        all_data.extend(data)
        start_time = data[-1][6] + 1  # Обновляем время начала
        time.sleep(0.001)  # Небольшая задержка, чтобы не перегружать API
    return all_data


def add_indicators(df):
    # Сортируем данные по времени
    df = df.sort_values('Open Time')

    # Простая скользящая средняя (SMA)
    df['SMA_10'] = df['Close'].rolling(window=10).mean()
    df['SMA_30'] = df['Close'].rolling(window=30).mean()

    # Экспоненциальная скользящая средняя (EMA)
    df['EMA_10'] = df['Close'].ewm(span=10, adjust=False).mean()
    df['EMA_30'] = df['Close'].ewm(span=30, adjust=False).mean()

    # Индекс относительной силы (RSI)
    delta = df['Close'].diff()
    up = delta.clip(lower=0)
    down = -delta.clip(upper=0)
    ema_up = up.ewm(com=13, adjust=False).mean()
    ema_down = down.ewm(com=13, adjust=False).mean()
    rs = ema_up / ema_down
    df['RSI'] = 100 - (100 / (1 + rs))

    return df


def collect_data(start_date_str, end_date_str, symbols):
    # Устанавливаем интервал в 5 минут
    interval = '5m'

    # Преобразуем строки дат в объекты datetime
    start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
    end_date = datetime.strptime(end_date_str, '%Y-%m-%d')

    # Начальное и конечное время в формате миллисекунд
    start_time = int(start_date.timestamp() * 1000)
    end_time = int(end_date.timestamp() * 1000)

    all_symbol_data = []

    print("Сбор данных для валют:", symbols)

    # Используем ThreadPoolExecutor для параллельного сбора данных
    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = {}
        for symbol in symbols:
            future = executor.submit(get_data, symbol, start_time, end_time, interval)
            futures[future] = symbol

        # Отслеживаем прогресс с помощью tqdm
        with tqdm(total=len(symbols), desc="Collecting data") as pbar:
            for future in as_completed(futures):
                symbol = futures[future]
                data = future.result()
                if not data:
                    print(f"Нет данных для валюты: {symbol}")
                else:
                    # Преобразуем данные в DataFrame
                    columns = ['Open Time', 'Open', 'High', 'Low', 'Close', 'Volume',
                               'Close Time', 'Quote Asset Volume', 'Number of Trades',
                               'Taker Buy Base Asset Volume', 'Taker Buy Quote Asset Volume', 'Ignore']
                    df = pd.DataFrame(data, columns=columns)
                    df['Symbol'] = symbol

                    # Конвертируем типы данных
                    df['Open Time'] = pd.to_datetime(df['Open Time'], unit='ms')
                    df['Close Time'] = pd.to_datetime(df['Close Time'], unit='ms')
                    numeric_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
                    df[numeric_columns] = df[numeric_columns].astype(float)

                    # Добавляем индикаторы
                    df = add_indicators(df)

                    # Удаляем строки с NaN (после вычисления индикаторов)
                    df.dropna(inplace=True)
                    df.reset_index(drop=True, inplace=True)

                    # Добавляем данные в общий список
                    all_symbol_data.append(df)

                pbar.update(1)
                time.sleep(0.001)  # Небольшая задержка

    # Объединяем все данные в один DataFrame
    full_df = pd.concat(all_symbol_data, ignore_index=True)

    # Сортируем по валюте и времени
    full_df.sort_values(['Symbol', 'Open Time'], inplace=True)

    # Сохраняем данные с индикаторами в CSV
    full_df.to_csv('data/raw_data.csv', index=False)
    print("Данные успешно сохранены в data/raw_data.csv")


def preprocess_data():
    df = pd.read_csv('data/raw_data.csv')

    # Выбираем нужные столбцы для модели
    features = ['Open', 'High', 'Low', 'Close', 'Volume', 'SMA_10', 'SMA_30', 'EMA_10', 'EMA_30', 'RSI']

    # Разбиваем данные на обучающую и тестовую выборки, учитывая валюты
    grouped = df.groupby('Symbol')

    train_dfs = []
    test_dfs = []

    for symbol, group in grouped:
        group = group.reset_index(drop=True)
        train_size = int(len(group) * 0.8)
        train_df = group.iloc[:train_size]
        test_df = group.iloc[train_size:]

        train_dfs.append(train_df)
        test_dfs.append(test_df)

    train_df = pd.concat(train_dfs, ignore_index=True)
    test_df = pd.concat(test_dfs, ignore_index=True)

    # Нормализация данных
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    scaled_train_features = scaler.fit_transform(train_df[features])
    scaled_test_features = scaler.transform(test_df[features])

    # Сохраняем скейлер
    import joblib
    joblib.dump(scaler, 'models/scaler.gz')

    # Создаём DataFrames с нормализованными данными
    scaled_train_df = pd.DataFrame(scaled_train_features, columns=features)
    scaled_train_df['Symbol'] = train_df['Symbol'].values
    scaled_test_df = pd.DataFrame(scaled_test_features, columns=features)
    scaled_test_df['Symbol'] = test_df['Symbol'].values

    # Сохраняем данные
    scaled_train_df.to_csv('data/train_data.csv', index=False)
    scaled_test_df.to_csv('data/test_data.csv', index=False)
    print("Данные успешно разбиты на train_data.csv и test_data.csv")


if __name__ == "__main__":
    start_date_str = '2021-09-16'  # Задайте дату начала в формате YYYY-MM-DD
    end_date_str = '2023-09-17'  # Задайте дату окончания в формате YYYY-MM-DD
    symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT']  # Укажите требуемые валютные пары
    print(f"Сбор данных с {start_date_str} по {end_date_str} для валют: {symbols}")
    collect_data(start_date_str, end_date_str, symbols)
    print("Предобработка данных")
    preprocess_data()

```
Можешь его не менять, а сделать так, чтобы прогрессбар показывал более подробно процесс выполнения каждой валюты.
Важно, чтобы прогрессбары создались только один раз и не спамились в новых строках