import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
import MetaTrader5 as mt5

# Parameters
SYMBOL = "EURUSD"
TERMINAL_PATH = r"C:/Program Files/RoboForex MT5 Terminal/terminal64.exe"
START_DATE = datetime(2014, 1, 1)
END_DATE = datetime(2025, 1, 1)
WINDOW_BARS = 10


def get_data():
    """Get data from MT5"""
    if not mt5.initialize(path=TERMINAL_PATH):
        print("MT5 initialization error")
        return None

    rates = mt5.copy_rates_range(SYMBOL, mt5.TIMEFRAME_H1, START_DATE, END_DATE)
    mt5.shutdown()

    if rates is None or len(rates) == 0:
        print("No data")
        return None

    df = pd.DataFrame(rates)
    df["time"] = pd.to_datetime(df["time"], unit="s")
    return df


def calculate_returns(df, window):
    """Calculate returns on a sliding window"""
    returns = []

    for i in range(len(df) - window):
        price_start = df["close"].iloc[i + window]
        price_end = df["close"].iloc[i]

        if price_start > 0:
            ret = (price_end - price_start) / price_start
            returns.append(ret)

    return np.array(returns)


def plot_histogram(returns):
    """Build distribution histogram"""
    fig = plt.figure(figsize=(7, 5), dpi=100)
    ax = fig.add_subplot(111)

    ax.hist(returns * 100, bins=100, edgecolor="black", alpha=0.7, color="steelblue")
    ax.set_xlabel("Return (%)", fontsize=12, fontweight="bold")
    ax.set_ylabel("Frequency", fontsize=12, fontweight="bold")
    ax.set_title(
        f"{SYMBOL} Return Distribution (Window: {WINDOW_BARS} bars)",
        fontsize=13,
        fontweight="bold",
    )
    ax.axvline(x=0, color="red", linestyle="--", linewidth=2, label="Zero return")
    ax.grid(True, alpha=0.3)
    ax.legend(fontsize=10)

    # Statistics on the chart
    textstr = f"Mean: {np.mean(returns)*100:.4f}%\nStd: {np.std(returns)*100:.4f}%\nN: {len(returns)}"
    props = dict(boxstyle="round", facecolor="wheat", alpha=0.8)
    ax.text(
        0.02,
        0.98,
        textstr,
        transform=ax.transAxes,
        fontsize=10,
        verticalalignment="top",
        bbox=props,
    )

    plt.tight_layout()
    plt.savefig("histogram_700px.png", dpi=100, bbox_inches="tight")
    print("Saved: histogram_700px.png")
    plt.close()


def plot_cumulative(returns):
    """Build cumulative distribution"""
    fig = plt.figure(figsize=(7, 5), dpi=100)
    ax = fig.add_subplot(111)

    sorted_returns = np.sort(returns) * 100
    cumulative = np.arange(1, len(sorted_returns) + 1) / len(sorted_returns)

    ax.plot(
        sorted_returns,
        cumulative,
        linewidth=2.5,
        color="darkblue",
        label="Cumulative probability",
    )
    ax.set_xlabel("Return (%)", fontsize=12, fontweight="bold")
    ax.set_ylabel("Cumulative Probability", fontsize=12, fontweight="bold")
    ax.set_title(
        f"{SYMBOL} Cumulative Distribution (Window: {WINDOW_BARS} bars)",
        fontsize=13,
        fontweight="bold",
    )
    ax.axvline(x=0, color="red", linestyle="--", linewidth=2, label="Zero return")
    ax.grid(True, alpha=0.3)
    ax.legend(fontsize=10)

    # Percentiles on a chart
    percentiles = [10, 50, 90]
    for p in percentiles:
        val = np.percentile(returns * 100, p)
        prob = p / 100
        ax.plot(val, prob, "ro", markersize=8)
        ax.text(
            val,
            prob + 0.05,
            f"P{p}\n{val:.3f}%",
            ha="center",
            fontsize=9,
            bbox=dict(boxstyle="round", facecolor="yellow", alpha=0.7),
        )

    plt.tight_layout()
    plt.savefig("cumulative_700px.png", dpi=100, bbox_inches="tight")
    print("Saved: cumulative_700px.png")
    plt.close()


def print_statistics(returns):
    """Display distribution statistics"""
    print("\n" + "=" * 60)
    print("RETURN DISTRIBUTION STATISTICS")
    print("=" * 60)
    print(f"Symbol: {SYMBOL}")
    print(f"Period: {START_DATE.date()} - {END_DATE.date()}")
    print(f"Window: {WINDOW_BARS} bars")
    print(f"Observations: {len(returns)}")
    print("-" * 60)
    print(f"Mean: {np.mean(returns)*100:.4f}%")
    print(f"Median: {np.median(returns)*100:.4f}%")
    print(f"Std Dev: {np.std(returns)*100:.4f}%")
    print(f"Min: {np.min(returns)*100:.4f}%")
    print(f"Max: {np.max(returns)*100:.4f}%")
    print(f"Skewness: {pd.Series(returns).skew():.4f}")
    print(f"Kurtosis: {pd.Series(returns).kurtosis():.4f}")
    print("-" * 60)
    print("PERCENTILES:")
    for p in [10, 20, 30, 40, 50, 60, 70, 80, 90]:
        val = np.percentile(returns * 100, p)
        print(f"  P{p}: {val:.4f}%")
    print("=" * 60 + "\n")


if __name__ == "__main__":
    print("Loading data from MT5...")
    df = get_data()

    if df is None:
        print("Failed to retrieve data")
        exit(1)

    print(f"Loaded {len(df)} bars")

    print(f"Calculating returns with window {WINDOW_BARS} bars...")
    returns = calculate_returns(df, WINDOW_BARS)

    print_statistics(returns)

    print("Building charts...")
    plot_histogram(returns)
    plot_cumulative(returns)

    print("\nDone!")
