{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#Анализ цен с применением метода кластеризации"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from scipy.cluster.hierarchy import dendrogram, linkage, fcluster\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.metrics import silhouette_score\n",
    "\n",
    "df = pd.read_csv(\".//static//csv//Starbucks Dataset.csv\")\n",
    "print(df.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Date</th>\n",
       "      <th>Open</th>\n",
       "      <th>High</th>\n",
       "      <th>Low</th>\n",
       "      <th>Close</th>\n",
       "      <th>Adj Close</th>\n",
       "      <th>Volume</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1992-06-26</td>\n",
       "      <td>0.328125</td>\n",
       "      <td>0.347656</td>\n",
       "      <td>0.320313</td>\n",
       "      <td>0.335938</td>\n",
       "      <td>0.260703</td>\n",
       "      <td>224358400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1992-06-29</td>\n",
       "      <td>0.339844</td>\n",
       "      <td>0.367188</td>\n",
       "      <td>0.332031</td>\n",
       "      <td>0.359375</td>\n",
       "      <td>0.278891</td>\n",
       "      <td>58732800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1992-06-30</td>\n",
       "      <td>0.367188</td>\n",
       "      <td>0.371094</td>\n",
       "      <td>0.343750</td>\n",
       "      <td>0.347656</td>\n",
       "      <td>0.269797</td>\n",
       "      <td>34777600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1992-07-01</td>\n",
       "      <td>0.351563</td>\n",
       "      <td>0.359375</td>\n",
       "      <td>0.339844</td>\n",
       "      <td>0.355469</td>\n",
       "      <td>0.275860</td>\n",
       "      <td>18316800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1992-07-02</td>\n",
       "      <td>0.359375</td>\n",
       "      <td>0.359375</td>\n",
       "      <td>0.347656</td>\n",
       "      <td>0.355469</td>\n",
       "      <td>0.275860</td>\n",
       "      <td>13996800</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         Date      Open      High       Low     Close  Adj Close     Volume\n",
       "0  1992-06-26  0.328125  0.347656  0.320313  0.335938   0.260703  224358400\n",
       "1  1992-06-29  0.339844  0.367188  0.332031  0.359375   0.278891   58732800\n",
       "2  1992-06-30  0.367188  0.371094  0.343750  0.347656   0.269797   34777600\n",
       "3  1992-07-01  0.351563  0.359375  0.339844  0.355469   0.275860   18316800\n",
       "4  1992-07-02  0.359375  0.359375  0.347656  0.355469   0.275860   13996800"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Open</th>\n",
       "      <th>High</th>\n",
       "      <th>Low</th>\n",
       "      <th>Close</th>\n",
       "      <th>Adj Close</th>\n",
       "      <th>Volume</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>8036.000000</td>\n",
       "      <td>8036.000000</td>\n",
       "      <td>8036.000000</td>\n",
       "      <td>8036.000000</td>\n",
       "      <td>8036.000000</td>\n",
       "      <td>8.036000e+03</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>30.054280</td>\n",
       "      <td>30.351487</td>\n",
       "      <td>29.751322</td>\n",
       "      <td>30.058857</td>\n",
       "      <td>26.674025</td>\n",
       "      <td>1.470459e+07</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>33.615577</td>\n",
       "      <td>33.906613</td>\n",
       "      <td>33.314569</td>\n",
       "      <td>33.615911</td>\n",
       "      <td>31.728090</td>\n",
       "      <td>1.340021e+07</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0.328125</td>\n",
       "      <td>0.347656</td>\n",
       "      <td>0.320313</td>\n",
       "      <td>0.335938</td>\n",
       "      <td>0.260703</td>\n",
       "      <td>1.504000e+06</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4.392031</td>\n",
       "      <td>4.531250</td>\n",
       "      <td>4.304922</td>\n",
       "      <td>4.399610</td>\n",
       "      <td>3.414300</td>\n",
       "      <td>7.817750e+06</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>13.325000</td>\n",
       "      <td>13.493750</td>\n",
       "      <td>13.150000</td>\n",
       "      <td>13.330000</td>\n",
       "      <td>10.352452</td>\n",
       "      <td>1.169815e+07</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>55.250000</td>\n",
       "      <td>55.722501</td>\n",
       "      <td>54.852499</td>\n",
       "      <td>55.267499</td>\n",
       "      <td>47.464829</td>\n",
       "      <td>1.778795e+07</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>126.080002</td>\n",
       "      <td>126.320000</td>\n",
       "      <td>124.809998</td>\n",
       "      <td>126.059998</td>\n",
       "      <td>118.010414</td>\n",
       "      <td>5.855088e+08</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              Open         High          Low        Close    Adj Close  \\\n",
       "count  8036.000000  8036.000000  8036.000000  8036.000000  8036.000000   \n",
       "mean     30.054280    30.351487    29.751322    30.058857    26.674025   \n",
       "std      33.615577    33.906613    33.314569    33.615911    31.728090   \n",
       "min       0.328125     0.347656     0.320313     0.335938     0.260703   \n",
       "25%       4.392031     4.531250     4.304922     4.399610     3.414300   \n",
       "50%      13.325000    13.493750    13.150000    13.330000    10.352452   \n",
       "75%      55.250000    55.722501    54.852499    55.267499    47.464829   \n",
       "max     126.080002   126.320000   124.809998   126.059998   118.010414   \n",
       "\n",
       "             Volume  \n",
       "count  8.036000e+03  \n",
       "mean   1.470459e+07  \n",
       "std    1.340021e+07  \n",
       "min    1.504000e+06  \n",
       "25%    7.817750e+06  \n",
       "50%    1.169815e+07  \n",
       "75%    1.778795e+07  \n",
       "max    5.855088e+08  "
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Date         0\n",
      "Open         0\n",
      "High         0\n",
      "Low          0\n",
      "Close        0\n",
      "Adj Close    0\n",
      "Volume       0\n",
      "dtype: int64\n",
      "Date         False\n",
      "Open         False\n",
      "High         False\n",
      "Low          False\n",
      "Close        False\n",
      "Adj Close    False\n",
      "Volume       False\n",
      "dtype: bool\n"
     ]
    }
   ],
   "source": [
    "# Процент пропущенных значений признаков\n",
    "for i in df.columns:\n",
    "    null_rate = df[i].isnull().sum() / len(df) * 100\n",
    "    if null_rate > 0:\n",
    "        print(f'{i} Процент пустых значений: %{null_rate:.2f}')\n",
    "\n",
    "print(df.isnull().sum())\n",
    "\n",
    "print(df.isnull().any())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Date          object\n",
       "Open         float64\n",
       "High         float64\n",
       "Low          float64\n",
       "Close        float64\n",
       "Adj Close    float64\n",
       "Volume         int64\n",
       "dtype: object"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Проверка типов столбцов\n",
    "df.dtypes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**Цель:** Кластеризация цен на акции для определения схожих характеристик.  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Очистка данных"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "       Open      High       Low     Close     Volume\n",
      "0  0.328125  0.347656  0.320313  0.335938  224358400\n",
      "1  0.339844  0.367188  0.332031  0.359375   58732800\n",
      "2  0.367188  0.371094  0.343750  0.347656   34777600\n",
      "3  0.351563  0.359375  0.339844  0.355469   18316800\n",
      "4  0.359375  0.359375  0.347656  0.355469   13996800\n"
     ]
    }
   ],
   "source": [
    "# Удалим несущественные столбцы\n",
    "columns_to_drop = [\"Date\", \"Adj Close\"]\n",
    "df_cleaned = df.drop(columns=columns_to_drop)\n",
    "\n",
    "print(df_cleaned.head())  # Вывод очищенного DataFrame"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Визуализация парных взаимосвязей"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 236528 characters]",
      "text/plain": [
       "<Figure size 1500x1000 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Настройка стиля графиков\n",
    "sns.set(style=\"whitegrid\")\n",
    "\n",
    "# Создание фигуры\n",
    "plt.figure(figsize=(15, 10))\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 1)\n",
    "sns.scatterplot(x=df_cleaned[\"Open\"], y=df_cleaned[\"Volume\"], alpha=0.6, color=\"purple\")\n",
    "plt.title(\"Open vs Volume\")\n",
    "plt.xlabel('Open')\n",
    "plt.ylabel(\"Volume\")\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 2)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"High\"],\n",
    "    y=df_cleaned[\"Volume\"],\n",
    "    alpha=0.6,\n",
    "    color=\"green\",\n",
    ")\n",
    "plt.title(\"High vs Volume\")\n",
    "plt.xlabel(\"High\")\n",
    "plt.ylabel(\"Volume\")\n",
    "\n",
    "plt.subplot(2, 2, 3)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"High\"], y=df_cleaned[\"Close\"], alpha=0.6, color=\"red\"\n",
    ")\n",
    "plt.title(\"High vs Close\")\n",
    "plt.xlabel(\"High\")\n",
    "plt.ylabel(\"Close\")\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 4)\n",
    "sns.scatterplot(x=df_cleaned[\"High\"], y=df_cleaned[\"Low\"], alpha=0.6, color=\"red\")\n",
    "plt.title(\"High vs Low\")\n",
    "plt.xlabel(\"High\")\n",
    "plt.ylabel(\"Low\")\n",
    "\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Стандартизация данных для кластеризации"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 43480 characters]",
      "text/plain": [
       "<Figure size 800x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Нормализация данных\n",
    "scaler = StandardScaler()\n",
    "data_scaled = scaler.fit_transform(df_cleaned)\n",
    "\n",
    "# Преобразование в DataFrame для удобства\n",
    "df_scaled = pd.DataFrame(data_scaled, columns=df_cleaned.columns)\n",
    "\n",
    "# Понижение размерности до 2 компонент\n",
    "pca = PCA(n_components=2)\n",
    "kc_pca = pca.fit_transform(df_scaled)\n",
    "\n",
    "# Визуализация\n",
    "plt.figure(figsize=(8, 6))\n",
    "plt.scatter(kc_pca[:, 0], kc_pca[:, 1], alpha=0.6)\n",
    "plt.title(\"PCA Visualization\")\n",
    "plt.xlabel(\"Principal Component 1\")\n",
    "plt.ylabel(\"Principal Component 2\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Агломеративная (иерархическая) кластеризация"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 37156 characters]",
      "text/plain": [
       "<Figure size 1000x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 2 2 ... 4 4 4]\n"
     ]
    }
   ],
   "source": [
    "# Построение дендрограммы\n",
    "linkage_matrix = linkage(data_scaled, method='ward')\n",
    "plt.figure(figsize=(10, 7))\n",
    "dendrogram(linkage_matrix)\n",
    "plt.title('Дендрограмма агломеративной кластеризации')\n",
    "plt.xlabel('Индекс образца')\n",
    "plt.ylabel('Расстояние')\n",
    "plt.show()\n",
    "\n",
    "# Получение результатов кластеризации с заданным порогом\n",
    "result = fcluster(linkage_matrix, t=60, criterion='distance')\n",
    "print(result)  # Вывод результатов кластеризации"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 51204 characters]",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Выбираем подмножество данных для кластеризации\n",
    "features = df[[\"Open\", \"High\", \"Low\", \"Close\", \"Volume\"]]\n",
    "\n",
    "scaled_features = scaler.fit_transform(features)\n",
    "\n",
    "# Построение дендрограммы\n",
    "linkage_matrix = linkage(scaled_features, method='ward')  # Метод \"Ward\"\n",
    "\n",
    "plt.figure(figsize=(12, 8))\n",
    "dendrogram(linkage_matrix, labels=df.index, leaf_rotation=90, leaf_font_size=10)\n",
    "plt.title('Иерархическая кластеризация (дендрограмма)')\n",
    "plt.xlabel('Индекс')\n",
    "plt.ylabel('Евклидово расстояние')\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Визуализация распределения кластеров**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 292840 characters]",
      "text/plain": [
       "<Figure size 1400x1200 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Визуализация кластеров\n",
    "plt.figure(figsize=(14, 12))\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 1)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"High\"],\n",
    "    y=df_cleaned[\"Low\"],\n",
    "    hue=result,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.title(\"High vs Low\")\n",
    "plt.xlabel(\"High\")\n",
    "plt.ylabel(\"Low\")\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 2)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"Open\"],\n",
    "    y=df_cleaned[\"Close\"],\n",
    "    hue=result,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.title(\"Open vs Close\")\n",
    "plt.xlabel(\"Open\")\n",
    "plt.ylabel(\"Close\")\n",
    "\n",
    "plt.subplot(2, 2, 3)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"Open\"],\n",
    "    y=df_cleaned[\"Volume\"],\n",
    "    hue=result,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.title(\"Open vs Volume\")\n",
    "plt.xlabel(\"Open\")\n",
    "plt.ylabel(\"Volume\")\n",
    "\n",
    "\n",
    "plt.subplot(2, 2, 4)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"Low\"],\n",
    "    y=df_cleaned[\"Close\"],\n",
    "    hue=result,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.title(\"Low vs Close\")\n",
    "plt.xlabel(\"Low\")\n",
    "plt.ylabel(\"Close\")\n",
    "\n",
    "# Настройка графиков\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## KMeans (неиерархическая кластеризация) для сравнения"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\3_КУРС_ПИ\\МИИ\\aisenv\\Lib\\site-packages\\joblib\\externals\\loky\\backend\\context.py:136: UserWarning: Could not find the number of physical cores for the following reason:\n",
      "[WinError 2] Не удается найти указанный файл\n",
      "Returning the number of logical cores instead. You can silence this warning by setting LOKY_MAX_CPU_COUNT to the number of cores you want to use.\n",
      "  warnings.warn(\n",
      "  File \"d:\\3_КУРС_ПИ\\МИИ\\aisenv\\Lib\\site-packages\\joblib\\externals\\loky\\backend\\context.py\", line 257, in _count_physical_cores\n",
      "    cpu_info = subprocess.run(\n",
      "               ^^^^^^^^^^^^^^^\n",
      "  File \"C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\subprocess.py\", line 548, in run\n",
      "    with Popen(*popenargs, **kwargs) as process:\n",
      "         ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\subprocess.py\", line 1026, in __init__\n",
      "    self._execute_child(args, executable, preexec_fn, close_fds,\n",
      "  File \"C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\subprocess.py\", line 1538, in _execute_child\n",
      "    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,\n",
      "                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Центры кластеров:\n",
      " [[8.52117049e+00 8.62736886e+00 8.41326822e+00 8.52272871e+00\n",
      "  1.45213248e+07]\n",
      " [9.49545632e+01 9.58306473e+01 9.40483657e+01 9.49479692e+01\n",
      "  7.38231053e+06]\n",
      " [6.77988164e+00 6.94807875e+00 6.62080017e+00 6.79650203e+00\n",
      "  4.47902932e+07]\n",
      " [5.19517442e+01 5.24112855e+01 5.14880750e+01 5.19697707e+01\n",
      "  9.69487539e+06]]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 291724 characters]",
      "text/plain": [
       "<Figure size 1600x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "features_used = [\n",
    "    'Open','High','Low','Close','Volume'\n",
    "]\n",
    "data_to_scale = df_cleaned[features_used]\n",
    "scaler = StandardScaler()\n",
    "data_scaled = scaler.fit_transform(data_to_scale)\n",
    "\n",
    "random_state = 42\n",
    "kmeans = KMeans(n_clusters=4, random_state=random_state)\n",
    "labels = kmeans.fit_predict(data_scaled)\n",
    "centers = kmeans.cluster_centers_\n",
    "\n",
    "# Отображение центроидов\n",
    "centers_original = scaler.inverse_transform(centers)  # Обратная стандартизация\n",
    "print(\"Центры кластеров:\\n\", centers_original)\n",
    "\n",
    "# Визуализация результатов кластеризации KMeans\n",
    "plt.figure(figsize=(16, 12))\n",
    "plt.subplot(2, 2, 1)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"High\"],\n",
    "    y=df_cleaned[\"Volume\"],\n",
    "    hue=labels,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.scatter(centers[:, 0], centers[:, 1], s=300, c='cyan', label='Centroids')\n",
    "plt.title(\"KMeans Clustering: High vs Volume\")\n",
    "plt.legend()\n",
    "\n",
    "plt.subplot(2, 2, 2)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"Low\"],\n",
    "    y=df_cleaned[\"Volume\"],\n",
    "    hue=labels,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.scatter(centers[:, 2], centers[:, 3], s=300, c='cyan', label='Centroids')\n",
    "plt.title(\"KMeans Clustering: Low vs Volume\")\n",
    "plt.legend()\n",
    "\n",
    "plt.subplot(2, 2, 3)\n",
    "sns.scatterplot(\n",
    "    x=df_cleaned[\"Open\"],\n",
    "    y=df_cleaned[\"Close\"],\n",
    "    hue=labels,\n",
    "    palette=\"Set1\",\n",
    "    alpha=0.6,\n",
    ")\n",
    "plt.scatter(centers[:, 1], centers[:, 3], s=300, c='cyan', label='Centroids')\n",
    "plt.title(\"KMeans Clustering: Open vs Close\")\n",
    "plt.legend()\n",
    "\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### PCA для визуализации сокращенной размерности"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 125980 characters]",
      "text/plain": [
       "<Figure size 1600x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pca = PCA(n_components=2)\n",
    "reduced_data = pca.fit_transform(data_scaled)\n",
    "\n",
    "# Визуализация сокращенных данных\n",
    "plt.figure(figsize=(16, 6))\n",
    "plt.subplot(1, 2, 1)\n",
    "sns.scatterplot(x=reduced_data[:, 0], y=reduced_data[:, 1], hue=result, palette='Set1', alpha=0.6)\n",
    "plt.title('PCA reduced data: Agglomerative Clustering')\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "sns.scatterplot(x=reduced_data[:, 0], y=reduced_data[:, 1], hue=labels, palette='Set1', alpha=0.6)\n",
    "plt.title('PCA reduced data: KMeans Clustering')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Анализ инерции для метода локтя (метод оценки суммы квадратов расстояний)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 44848 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "inertias = []\n",
    "clusters_range = range(1, 11)\n",
    "for i in clusters_range:\n",
    "    kmeans = KMeans(n_clusters=i, random_state=random_state)\n",
    "    kmeans.fit(data_scaled)\n",
    "    inertias.append(kmeans.inertia_)\n",
    "\n",
    "\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(clusters_range, inertias, marker='o')\n",
    "plt.title('Метод локтя для оптимального k')\n",
    "plt.xlabel('Количество кластеров')\n",
    "plt.ylabel('Инерция')\n",
    "plt.grid(True)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Расчет коэффициентов силуэта"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58968 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "silhouette_scores = []\n",
    "for i in clusters_range[1:]:  \n",
    "    kmeans = KMeans(n_clusters=i, random_state=random_state)\n",
    "    labels = kmeans.fit_predict(data_scaled)\n",
    "    score = silhouette_score(data_scaled, labels)\n",
    "    silhouette_scores.append(score)\n",
    "\n",
    "# Построение диаграммы значений силуэта\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(clusters_range[1:], silhouette_scores, marker='o')\n",
    "plt.title('Коэффициенты силуэта для разных k')\n",
    "plt.xlabel('Количество кластеров')\n",
    "plt.ylabel('Коэффициент силуэта')\n",
    "plt.grid(True)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Средний коэффициент силуэта: 0.557\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 87940 characters]",
      "text/plain": [
       "<Figure size 1000x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.metrics import silhouette_score\n",
    "from sklearn.cluster import KMeans\n",
    "\n",
    "# ========================\n",
    "# Применение K-Means\n",
    "# ========================\n",
    "kmeans = KMeans(n_clusters=3, random_state=42)  \n",
    "df_clusters = kmeans.fit_predict(df_scaled)\n",
    "\n",
    "# ========================\n",
    "# Оценка качества кластеризации\n",
    "# ========================\n",
    "silhouette_avg = silhouette_score(df_scaled, df_clusters)\n",
    "print(f'Средний коэффициент силуэта: {silhouette_avg:.3f}')\n",
    "\n",
    "# ========================\n",
    "# Визуализация кластеров\n",
    "# ========================\n",
    "from sklearn.decomposition import PCA\n",
    "\n",
    "pca = PCA(n_components=2)\n",
    "df_pca = pca.fit_transform(df_scaled)\n",
    "\n",
    "plt.figure(figsize=(10, 7))\n",
    "sns.scatterplot(x=df_pca[:, 0], y=df_pca[:, 1], hue=df_clusters, palette='viridis', alpha=0.7)\n",
    "plt.title('Визуализация кластеров с помощью K-Means')\n",
    "plt.xlabel('Первая компонентa PCA')\n",
    "plt.ylabel('Вторая компонентa PCA')\n",
    "plt.legend(title='Кластер', loc='upper right')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Средний коэффициент силуэта, равный 0.557, указывает на умеренно хорошую кластеризацию.  \n",
    "\n",
    "Средний коэффициент силуэта (silhouette score) указывает на качество кластеризации, измеряя, насколько хорошо точки внутри одного кластера близки друг к другу по сравнению с точками из других кластеров. Значения коэффициента силуэта находятся в диапазоне от -1 до 1:\n",
    "\n",
    "1: Указывает на идеально плотные и четко разделенные кластеры.  \n",
    "0: Указывает на перекрытие кластеров или слабую структуру кластеризации.  \n",
    "Отрицательные значения: Указывают, что точки в кластере расположены ближе к другому кластеру, чем к своему."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Средний коэффициент силуэта (агломеративная кластеризация): 0.565\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 91600 characters]",
      "text/plain": [
       "<Figure size 1000x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.cluster import AgglomerativeClustering\n",
    "\n",
    "# ========================\n",
    "# Агломеративная кластеризация\n",
    "# ========================\n",
    "agg_cluster = AgglomerativeClustering(n_clusters=3)  \n",
    "labels_agg = agg_cluster.fit_predict(df_scaled)\n",
    "\n",
    "# ========================\n",
    "# Оценка качества кластеризации\n",
    "# ========================\n",
    "silhouette_avg_agg = silhouette_score(df_scaled, labels_agg)\n",
    "print(f'Средний коэффициент силуэта (агломеративная кластеризация): {silhouette_avg_agg:.3f}')\n",
    "\n",
    "# ========================\n",
    "# Визуализация кластеров\n",
    "# ========================\n",
    "pca = PCA(n_components=2)\n",
    "df_pca = pca.fit_transform(df_scaled)\n",
    "\n",
    "plt.figure(figsize=(10, 7))\n",
    "sns.scatterplot(x=df_pca[:, 0], y=df_pca[:, 1], hue=labels_agg, palette='viridis', alpha=0.7)\n",
    "plt.title('Визуализация кластеров с помощью агломеративной кластеризации')\n",
    "plt.xlabel('Первая компонентa PCA')\n",
    "plt.ylabel('Вторая компонентa PCA')\n",
    "plt.legend(title='Кластер', loc='upper right')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Значение коэффициента силуэта лежит в диапазоне от -1 до 1. Ближе к 1: Хорошо сформированные, плотные кластеры, четко отделенные друг от друга.  \n",
    "\n",
    "Ближе к 0: Кластеры пересекаются или слабо разделены, не имеют четких границ. Точки расположены одинаково близко как к своему кластеру, так и к соседним. \n",
    "Ближе к -1 (Отрицательные значения): Некоторые точки скорее относятся к другим кластерам, чем к текущему (ближе к центрам других кластеров). Очень плохая кластеризация.  \n",
    "Ближе к 1: Все точки внутри каждого кластера плотно сгруппированы и значительно удалены от точек других кластеров. Свидетельствует о четкой и хорошо разделенной структуре данных. Единица говорит об идеальной кластеризации.\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "aisenv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
