import requests
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.ar_model import AutoReg
from scipy.stats import norm
import pywt  # Для вейвлет-анализа
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.model_selection import train_test_split

# Функция для получения данных
def fetch_data(symbol='XXBTZUSD', interval=1):
    url = f'https://api.kraken.com/0/public/OHLC?pair={symbol}&interval={interval}'
    response = requests.get(url)
    data = response.json()
    prices = [float(item[4]) for item in data['result'][symbol]]  # Закрывающие цены
    timestamps = [item[0] for item in data['result'][symbol]]  # Временные метки
    return np.array(prices), timestamps

# Функция для форматирования времени
def format_timestamps(timestamps):
    return [pd.to_datetime(ts, unit='s').strftime('%d.%m.%Y %H:%M:%S') for ts in timestamps]

# Функция для расчета скользящего среднего (MA) и EMA
def calculate_moving_average(prices, window=20):
    return pd.Series(prices).rolling(window=window).mean()

def calculate_ema(prices, span=20):
    return pd.Series(prices).ewm(span=span, adjust=False).mean()

# Функция для проверки стационарности
def check_stationarity(series):
    result = adfuller(series)
    return result[1] < 0.05  # p-value < 0.05 означает стационарность

# Функция для прогнозирования цен с использованием AutoReg
def forecast_prices(prices, steps=10):
    model = AutoReg(prices, lags=1)
    model_fit = model.fit()
    forecast = model_fit.predict(start=len(prices), end=len(prices) + steps - 1)
    return forecast

# Функция для квантильной регрессии с использованием случайного леса и градиентного бустинга
def quantile_regression(prices, quantile=0.5):
    X = np.arange(len(prices)).reshape(-1, 1)  # Индексы как признаки
    y = prices
    
    # Разделение на обучающую и тестовую выборки
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    
    # Модель Random Forest
    rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
    rf_model.fit(X_train, y_train)
    rf_predictions = rf_model.predict(X_test)
    
    # Модель Gradient Boosting
    gb_model = GradientBoostingRegressor(n_estimators=100, random_state=42)
    gb_model.fit(X_train, y_train)
    gb_predictions = gb_model.predict(X_test)
    
    # Квантильная регрессия
    quantile_predictions_rf = np.percentile(rf_predictions, quantile * 100)
    quantile_predictions_gb = np.percentile(gb_predictions, quantile * 100)
    
    return quantile_predictions_rf, quantile_predictions_gb

# Основная функция
def main(symbol='XXBTZUSD', interval=1):
    prices, timestamps = fetch_data(symbol, interval)
    formatted_timestamps = format_timestamps(timestamps)
    
    # Расчет MA
    ma = calculate_moving_average(prices)
    
    # Проверка стационарности
    is_stationary = check_stationarity(prices)
    if is_stationary:
        print("Ряд стационарен, можно торговать в ренже.")
    else:
        print("Ряд не стационарен, требуется дальнейший анализ.")
    
    # Прогнозирование цен
    forecast = forecast_prices(prices, steps=200)  # Прогнозируем 200 позиций
    
    # Квантильная регрессия
    quantile_prediction_rf, quantile_prediction_gb = quantile_regression(prices, quantile=0.5)
    print(f'Квантильная регрессия (Random Forest): {quantile_prediction_rf:.2f}')
    print(f'Квантильная регрессия (Gradient Boosting): {quantile_prediction_gb:.2f}')
    
    # Визуализация
    plt.figure(figsize=(14, 8))
    
    # Основные цены
    plt.plot(prices, label='Цены', color='black')
    
    # Скользящее среднее
    plt.plot(ma, label='Скользящее Среднее (MA)', color='orange')
    
    # Прогнозируемые цены
    forecast_index = np.arange(len(prices), len(prices) + len(forecast))
    plt.plot(forecast_index, forecast, label='Прогнозируемая цена (AutoReg)', color='blue', linestyle='--')
    
    # Квантильные регрессии
    plt.axhline(y=quantile_prediction_rf, color='red', linestyle='--', label='Квантильная регрессия (Random Forest)')
    plt.axhline(y=quantile_prediction_gb, color='green', linestyle='--', label='Квантильная регрессия (Gradient Boosting)')
    
    # Настройка графика
    plt.title('Анализ цен и прогнозирование')
    plt.xlabel('Время')
    plt.ylabel('Цена')
    plt.legend()
    plt.grid()
    plt.show()

    # Создание таблицы с данными
    data = {
        'Timestamp': formatted_timestamps,
        'Price': prices
    }
    
    # Прогнозируемые цены по 10 минут
    forecast_timestamps = [pd.to_datetime(ts, unit='s') + pd.Timedelta(minutes=10 * i) for i in range(1, 201)]
    forecast_data = {
        'Forecast Timestamp': forecast_timestamps,
        'Forecast Price': forecast
    }
    
    # Создание DataFrame для отображения
    prices_df = pd.DataFrame(data)
    forecast_df = pd.DataFrame(forecast_data)

    # Отображение таблицы с данными
    print("Таблица с ценами:")
    print(prices_df.tail(10))  # Показываем последние 10 цен

    print("\nТаблица с прогнозируемыми ценами:")
    print(forecast_df.head(10))  # Показываем первые 10 прогнозируемых цен

# Пример использования
if __name__ == "__main__":
    main('XXBTZUSD', interval=1)  # Используем валютную пару XXBTZUSD и интервал 1 нужно доработать систему как у goldmansachs