Этот проект по науке о данных направлен на построение модели AI / ML для прогнозирования динамики цен акций за 52 недели на основе финансовых данных, экстраполированных из списка компаний S&P 500. Данные исследуются, визуализируются и обрабатываются. Затем реализуется и уточняется регрессия опорных векторов (SVR). Наконец, результаты приводятся вместе с заключением.
Трудно точно предсказать динамику цены акции за 52 недели. Финансовые эксперты используют определенные критерии для прогнозирования результатов деятельности, но этот навык является неявным и трудным для освоения. Этот проект будет направлен на то, чтобы научить машину делать прогнозы с точностью 70% +. Набор данных собран с сайта Fidelity.com. Если у вас есть учетная запись в Fidelity, вы можете извлечь данные из их опции экрана, используя их опцию «скачать в Excel».
Постановка задачи
- Машины не знают, как точно предсказать динамику цены акции. Этот проект демонстрирует стратегию решения проблемы с помощью машины опорных векторов (SVM). После того, как модель будет обучена и протестирована, она сможет предоставить решение, которое может прогнозировать динамику цены акций за 52 недели с точностью 73%.
Метрики
- Мы использовали регрессионную форму SVM, известную как SVR (регрессия опорных векторов). Метрика, используемая для измерения эффективности модели SVR, - это оценка R2. Чем ближе оценка к 1, тем точнее модель. Оценка около 0,7 или выше считается приемлемой, чтобы считать модель надежной. Мы выбрали эту модель и метрику, потому что нам нужна высокая точность для прогнозирования фондового рынка, и мы не можем позволить себе 50/50% шанс для такой важной темы, которая связана с финансовыми разветвлениями.
В этом проекте используются библиотеки Python: numpy, pandas, math, matplotlib, collections и sklearn.
Исследование данных
Переменные / характеристики набора данных отображались с помощью функции info (). Исходный набор данных содержал 22 столбца (функции) и 500 строк данных. Переменные / функции были следующими:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 500 entries, 0 to 499 Data columns (total 22 columns): Symbol 500 non-null object Company_Name 500 non-null object Security_Price 500 non-null float64 Volume__90_Day_Avg_ 500 non-null float64 Market_Capitalization 500 non-null object Dividend_Yield 418 non-null float64 Company_Headquarters_Location 500 non-null object Sector 500 non-null object Industry 500 non-null object Price_Performance__52_Weeks_ 500 non-null float64 Total_Return__1_Yr_Annualized_ 500 non-null float64 Beta__1_Year_Annualized_ 499 non-null float64 Standard_Deviation__1_Yr_Annualized_ 500 non-null float64 S&P_Global_Market_Intelligence_Valuation 498 non-null float64 S&P_Global_Market_Intelligence_Quality 498 non-null float64 S&P_Global_Market_Intelligence_Growth_Stability 498 non-null float64 S&P_Global_Market_Intelligence_Financial_Health 497 non-null float64 P/E__Price/TTM_Earnings_ 500 non-null object PEG_Ratio 406 non-null float64 EPS_Growth__Proj_This_Yr_vs._Last_Yr_ 486 non-null float64 Institutional_Ownership 487 non-null float64 Institutional_Ownership__Last_vs._Prior_Qtr_ 498 non-null float64 dtypes: float64(15), object(7)
Мы очистили набор данных, удалив все значения NAN. На этапе исследования данных мы использовали функцию describe () для отображения описательной статистики набора данных. После этого мы искали корреляции между различными функциями, используя функцию corr (). Затем мы визуализировали данные, разбив акции по секторам, создав функцию graphS (), которая выглядит следующим образом:
# Использование функции графика для лучшего понимания данных путем разбивки запасов индекса S&P 500 по промышленным секторам
def graphS ():
ps = df.Sector.value_counts ()
(ps / df.shape [0]). plot (kind = «bar»);
plt.title («Sector»)
«» »Эта функция 'graphS ()' построит график акции в S% P 500 по секторам ”” ”
graphS ()
Предварительная обработка данных
Проанализировав 22 функции, мы определили, что многие из них не являются числовыми и их необходимо удалить. Мы использовали функцию drop (), чтобы удалить все нечисловые функции. Мы также использовали функцию fillna () для заполнения всех значений NAN. Мы заметили, что функция Dividend Yield имеет наибольшее количество значений NAN на основе исследования данных, поэтому мы отбросили все значения NAN для этой функции, которая одновременно отбросила все значения NAN в наборе данных. Мы разделили набор данных на два набора. Данные, которые содержат все независимые переменные и наблюдения, и Target, содержащие зависимую переменную (Ценовые характеристики) и ее варианты. Информация об очищенном фрейме данных отображается ниже:
<class 'pandas.core.frame.DataFrame'> Int64Index: 389 entries, 0 to 499 Data columns (total 13 columns): Security_Price 389 non-null float64 Volume__90_Day_Avg_ 389 non-null float64 Dividend_Yield 389 non-null float64 Beta__1_Year_Annualized_ 389 non-null float64 Standard_Deviation__1_Yr_Annualized_ 389 non-null float64 S&P_Global_Market_Intelligence_Valuation 389 non-null float64 S&P_Global_Market_Intelligence_Quality 389 non-null float64 S&P_Global_Market_Intelligence_Growth_Stability 389 non-null float64 S&P_Global_Market_Intelligence_Financial_Health 389 non-null float64 PEG_Ratio 389 non-null float64 EPS_Growth__Proj_This_Yr_vs._Last_Yr_ 389 non-null float64 Institutional_Ownership 389 non-null float64 Institutional_Ownership__Last_vs._Prior_Qtr_ 389 non-null float64 dtypes: float64(13)
После разработки функций мы использовали matplotlib для отображения распределения каждой функции, чтобы увидеть, нормально ли распределяются данные. Код, который использовался, был следующим (мы изменили номер столбца для каждой функции), и все распределения показаны ниже:
cols = final_df.columns [: 1]
densityplot = final_df [cols] .plot (kind = ’density’)
Мы определили, что многие из функций не имеют нормального распределения, поэтому мы определили, что существует необходимость в преобразовании данных перед применением модели. Мы также нормализовали данные, используя следующий код:
normalized_df = (final_df-final_df.min ()) / (final_df.max () - final_df.min ()).
Реализация
Прежде чем выбрать алгоритм / модель ML, мы просмотрели следующую шпаргалку, чтобы выбрать правильную модель для этой проблемы (получена с веб-сайта Scikit Learn):
Поскольку мы не пытаемся классифицировать или кластеризовать, все модели в левой части диаграммы исключаются. Мы стремимся определить количество (ценовые характеристики) акций на основе различных характеристик (переменных). Следовательно, наша проблема требует регрессионной модели. Поскольку у нас меньше 100 тыс. Выборок, также исключается SDG Regressor - поскольку наличие небольшого количества функций не важно, также исключаются алгоритмы Lasso и ElasticNet. Таким образом, остается SVR и RidgeRegression. В этом случае мы решили использовать SVR (регрессия вектора поддержки).
Используя функцию train, test, split в библиотеке scikit learn, данные были разделены на обучающий набор и набор для тестирования, был использован приведенный ниже код:
# Разделение данных на обучение и тестирование
X_train, X_test, y_train, y_test = train_test_split (data, target,
test_size = 0.3,
random_state = 0)
масштабирование = MinMaxScaler (feature_range = (- 1, 1)). Fit (X_train)
X_tr = scaling.transform (X_train)
X_t = scaling.transform (X_test)
Затем модель SVR была реализована с использованием следующего кода:
# Реализация модели
svr = SVR ()
search_space = [{'kernel': ['linear'],
'C': np.logspace (-3, 2 , 6),
'epsilon': [0, 0,01, 0,1, 0,5, 1, 2, 4]},
{'ядро': ['rbf'],
'градус ': [2,3],
' C ': np.logspace (-3, 3, 7),
' gamma ': np.logspace (-3, 2, 6),
'epsilon': [0, 0,01, 0,1, 0,5, 1, 2, 4]}]
gridsearch = GridSearchCV (svr,
param_grid = search_space,
refit = True, < br /> scoring = 'r2',
cv = 10, n_jobs = -1)
gridsearch.fit (X_tr, y_train)
cv = gridsearch.best_score_
test_score = gridsearch .score (X_tr, y_train)
print ('Оценка CV R2:% 0,3f'% cv)
print ('Оценка теста R2:% 0,3f'% test_score)
print (' Лучшие параметры:% s '% gridsearch.best_params_)
Затем мы создали модель прогнозирования машинного обучения, используя SVM со следующим кодом:
# Создание прогнозной модели
model = SVR ()
print (model)
X = data
y = target
# Подбор модели
model.fit (X, y)
# Создание модели прогноза
pred_y = model.predict (X)
# Показать прогноз
pred_y
Чтобы улучшить модель, мы вернулись к анализу данных немного дальше, пытаясь найти мультиколлинеарность между функциями, построив график каждой функции по сравнению с другим. Некоторые графики показаны ниже.
После построения графика всех функций, взаимно совпадающих друг с другом, мы решили удалить PEG_Ratio, так как оно было слишком искажено даже после преобразования в попытке улучшить модель. Затем мы повторно запустили модель, и было внесено небольшое улучшение.
Полученные результаты
Результат был следующим:
CV R2 score: 0.628 Test R2 score: 0.735 Best parameters: {'C': 1.0, 'degree': 2, 'epsilon': 0.1, 'gamma': 0.1, 'kernel': 'rbf'}
Результаты показали, что R2 составляет 0,735, что свидетельствует о высокой точности, которой мы довольны.
Заключение
Отражение
Мы начали с попытки найти способы решить проблему. Я многое узнал о выборе правильного алгоритма и узнал о многих существующих вариантах. Самые сложные части этого проекта были двоякими. 1. Обнаружив данные, мы сначала попытались построить конвейер ETL, используя API для удаления веб-страниц yahoo, но безуспешно. Я узнал, что извлечение данных и построение конвейеров ETL - самая сложная часть науки о данных, что заставляет меня еще больше узнать об инженерии данных. Я также узнал, что существует множество API-интерфейсов из многих источников, и некоторым из них требуется партнерство с провайдером, чтобы предоставить доступ к своим данным. Я обнаружил, что только у Google есть сотни и сотни API, которые пройдут полный семестровый курс только для того, чтобы изучить некоторые из них. Вторая часть заключалась в разработке функций, чтобы найти наиболее подходящие функции, которые сделают точный прогноз.
Улучшение
Этот проект можно улучшить / расширить с помощью конвейера ETL, который может автоматически извлекать данные с помощью кнопки обновления с финансового веб-сайта. Его также можно улучшить, создав приложение, которое позволяет пользователям вводить тикер акций и получать результат прогноза динамики цен на 52 недели той конкретной акции, которую они искали.