289 KiB
import pandas as pd
ddata = pd.read_csv("../static/csv/Yamana_Gold_Inc._AUY.csv")
data['Date'] = pd.to_datetime(data['Date'])
# Первичный анализ данных
print(data.info())
print(data.head())
1. Бизнес-цели для набора данных по акции компании Yamana Gold Inc.¶
Цель 1: Прогнозирование изменения цены акции компании. Прогнозирование цен на акции является одной из ключевых задач в области финансов и инвестирования. Задача состоит в предсказании будущих изменений стоимости акции на основе исторических данных, таких как открытие и закрытие торгов, объемы торгов и другие показатели.
Цель 2: Оценка волатильности акций компании. Измерение волатильности позволяет инвесторам оценить риск и принять решения по управлению капиталом. Задача заключается в прогнозировании уровня волатильности на основе исторической динамики цен, объемов торгов и других рыночных факторов.
2. Цели технического проекта для каждой бизнес-цели¶
Цель 1: Прогнозирование изменения цены акции компании
Разработать модель машинного обучения для прогнозирования будущих цен акций на основе исторических данных. Использовать регрессионные модели, такие как линейная регрессия или более сложные модели, например, LSTM (долгосрочная краткосрочная память) для временных рядов. Цель 2: Оценка волатильности акций компании
Создать модель, которая будет прогнозировать волатильность на основе исторических данных о ценах. Использовать методы статистического анализа, такие как вычисление стандартного отклонения, или методы машинного обучения для более точной оценки волатильности.
3 Проверим датасет на пропуски и удалим при необходимости строки с недостающими данными¶
Обработка пропусков¶
Пропуски в данных могут негативно влиять на обучение моделей. Сначала оцениваем количество пропусков по столбцам. Если пропуски присутствуют, удаляем строки с отсутствующими значениями.
# 3. Проверим датасет на наличие пропусков и удалим строки с недостающими данными
print(data.isnull().sum())
data.dropna(inplace=True)
print("Данные после очистки:", data.shape)
Добавление признаков¶
Для выполнения задач добавляем два новых признака:
Daily_Change: разница между ценой закрытия и открытия торгов.
Volatility: относительная волатильность, рассчитываемая как отношение разницы между максимальной и минимальной ценой к цене открытия.
print(data.isnull().sum())
data.dropna(inplace=True)
print(f"Количество строк после удаления пропусков: {data.shape[0]}")
Создание новых признаков
data['Daily_Change'] = data['Close'] - data['Open']
data['Volatility'] = (data['High'] - data['Low']) / data['Open']
print(data[['Daily_Change', 'Volatility']].head())
Проведем масштабированние данных
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaled_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
data[scaled_columns] = scaler.fit_transform(data[scaled_columns])
Разбиение данных на выборки¶
Для предотвращения просачивания данных используем разбиение на три части:
Обучающая выборка (60%): для тренировки модели.
Валидационная выборка (20%): для подбора гиперпараметров модели и проверки ее производительности на новых данных.
Тестовая выборка (20%): для оценки финальной производительности модели.
from sklearn.model_selection import train_test_split
X = data[scaled_columns]
y = data['Close']
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
print(f"Размер обучающей выборки: {X_train.shape}")
print(f"Размер валидационной выборки: {X_val.shape}")
print(f"Размер тестовой выборки: {X_test.shape}")
Оценка и балансировка классов¶
Проверяем распределение классов в целевой переменной для каждого набора данных. Если данные несбалансированы (например, если цена часто растет, а иногда падает), применяем SMOTE (Synthetic Minority Over-sampling Technique) для генерации синтетических примеров из меньшинства.
from collections import Counter
from imblearn.over_sampling import SMOTE
# Проверка на наличие пропусков после масштабирования
print("Проверка на пропуски после масштабирования:\n", data.isnull().sum())
# Проверка распределения целевой переменной
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
plt.hist(data['Close'], bins=30, edgecolor='k', alpha=0.7)
plt.title("Распределение целевой переменной 'Close'")
plt.xlabel("Цена закрытия")
plt.ylabel("Частота")
plt.grid(True)
plt.show()
Создадим модель для прогназирования
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# Модель для прогнозирования цены акции
print("\n--- Прогнозирование цены акции ---")
price_model = LinearRegression()
price_model.fit(X_train, y_train)
# Предсказание на тестовой выборке
y_pred_price = price_model.predict(X_test)
Оценка модели
# Оценка модели
mse_price = mean_squared_error(y_test, y_pred_price)
r2_price = r2_score(y_test, y_pred_price)
print(f"Mean Squared Error (MSE): {mse_price:.4f}")
print(f"R^2 Score: {r2_price:.4f}")
MSE = 0.0000 и R² = 1.0000, это говорит о том, что ваша модель предсказывает данные абсолютно точно. (йоу)
Визуализируем полученный результат
# Визуализация результатов прогноза
plt.figure(figsize=(10, 5))
plt.plot(y_test.values, label='Истинные значения', color='blue')
plt.plot(y_pred_price, label='Предсказанные значения', color='red')
plt.title("Прогнозирование цены акции")
plt.xlabel("Наблюдения")
plt.ylabel("Цена закрытия")
plt.legend()
plt.grid(True)
plt.show()
В целом, на основе этой диаграммы можно сделать вывод, что текущая модель не точно предсказывает цену акции
Теперь сделаем все то же самое для волотильности
# Модель для оценки волатильности
print("\n--- Оценка волатильности ---")
X_volatility = data[['High', 'Low', 'Open']] # Переменные для оценки волатильности
y_volatility = data['Volatility']
# Разделение на выборки для модели волатильности
X_train_vol, X_test_vol, y_train_vol, y_test_vol = train_test_split(X_volatility, y_volatility, test_size=0.2, random_state=42)
volatility_model = LinearRegression()
volatility_model.fit(X_train_vol, y_train_vol)
# Предсказание на тестовой выборке
y_pred_volatility = volatility_model.predict(X_test_vol)
# Оценка модели волатильности
mse_volatility = mean_squared_error(y_test_vol, y_pred_volatility)
r2_volatility = r2_score(y_test_vol, y_pred_volatility)
print(f"Mean Squared Error (MSE) для волатильности: {mse_volatility:.4f}")
print(f"R^2 Score для волатильности: {r2_volatility:.4f}")
MSE = 0.0003 и R² = 0.6214 говорят о том, что модель делает предсказания с малой ошибкой, но есть еще пространство для улучшения, поскольку она объясняет менее 70% вариации в данных.
Визуализируем
# Визуализация результатов прогноза волатильности
plt.figure(figsize=(10, 5))
plt.plot(y_test_vol.values, label='Истинные значения волатильности', color='green')
plt.plot(y_pred_volatility, label='Предсказанные значения волатильности', color='orange')
plt.title("Прогнозирование волатильности")
plt.xlabel("Наблюдения")
plt.ylabel("Волатильность")
plt.legend()
plt.grid(True)
plt.show()
По этой модели же можно сказать, что она более точно предсказывает, то есть она получилась более правильной
Теперь воспользуемся фреймворком Featuretools
# Импорт библиотек для работы с Featuretools
import featuretools as ft
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import woodwork as ww
# Проверим и удалим дублирующиеся столбцы
if not data.columns.is_unique:
print("Обнаружены дублирующиеся столбцы. Переименуем их.")
data = data.loc[:, ~data.columns.duplicated()]
# Переименование столбцов для совместимости с Featuretools
data = data.rename(columns={'Date': 'datetime', 'Open': 'open', 'High': 'high',
'Low': 'low', 'Close': 'close', 'Volume': 'volume'})
# Создание EntitySet
es = ft.EntitySet(id="stocks")
# Добавление данных в EntitySet с правильными логическими типами
es = es.add_dataframe(
dataframe_name="stock_data",
dataframe=data,
index="datetime",
logical_types={
"open": ww.logical_types.Double,
"high": ww.logical_types.Double,
"low": ww.logical_types.Double,
"close": ww.logical_types.Double,
"volume": ww.logical_types.Double,
},
)
# Автоматическое создание признаков с использованием Featuretools
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_dataframe_name="stock_data",
agg_primitives=["mean", "sum"],
trans_primitives=["day", "month", "year"]
)
# Выводим имена столбцов в feature_matrix, чтобы убедиться, какие признаки были сгенерированы
print("Generated feature columns:", feature_matrix.columns)
data_featuretools = data.join(feature_matrix, lsuffix='_orig', rsuffix='_feature')
scaler = StandardScaler()
scaled_columns = ['open_orig', 'high_orig', 'low_orig', 'close_orig', 'volume_orig']
data_featuretools[scaled_columns] = scaler.fit_transform(data_featuretools[scaled_columns])
# Разделение данных на выборки
feature_columns = [col for col in feature_matrix.columns if 'feature' in col]
X = data_featuretools[scaled_columns + feature_columns]
y = data_featuretools['close_orig']
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
print(f"Размер обучающей выборки: {X_train.shape}")
print(f"Размер валидационной выборки: {X_val.shape}")
print(f"Размер тестовой выборки: {X_test.shape}")