Ну, после 6 лет работы в финансовой сфере я ушел с работы, чтобы в течение 3 месяцев изучать науку о данных в General Assembly. Безумный выбор, но я ни разу не пожалел, что изучил науку о данных. Итак, вот мой сумасшедший завершающий проект!

Вспышка коронавируса

Глобальная вспышка коронавируса вызвала социальные и экономические потрясения, в результате чего финансовые рынки пошатнулись.

Поскольку миллионы людей не работают, закрываются школы, закрываются тысячи ресторанов и других предприятий. В результате мировые финансовые рынки испытывают крайнюю волатильность, поскольку инвесторы борются с множеством последствий, которые может иметь вирус.

Из-за этого глобального явления ежедневные заголовки новостей, сообщающие о коронавирусе, стремятся лишь вызвать СТРАХ на рынке.

Это привело к резкому скачку индекса волатильности (индекса страха) до пикового значения более 80 в результате вспышки с момента мирового финансового кризиса.

Что такое индекс волатильности?

Индекс волатильности CBOE (VIX) — это ключевой показатель рыночных ожиданий краткосрочной волатильности, выраженный ценами опционов на фондовый индекс S&P 500.

С момента своего появления в 1993 году многие считают VIX главным в мире барометром настроений инвесторов и волатильности рынка, известным какиндекс страха.

Более высокий рыночный риск, страх и стресс на рынке обычно указывают на повышение цены Индекса волатильности.

Поскольку в этом сезоне появилось так много новостей о коронавирусе, давайте посмотрим, сможем ли мы использовать заголовки новостей для прогнозирования движения индекса волатильности (VIX) с помощью моделей машинного обучения.

Сначала мы начнем с импорта выбранного нами набора данных, показанного ниже.

Заголовки новостей (переменные X)

Для заголовков новостей мы будем импортировать исторические заголовки новостей из Reddit WorldNews Channel с веб-сайта kaggle. (Диапазон: с 08.06.2008 по 01.07.2016). Все новости ранжируются сверху вниз в зависимости от того, насколько они актуальны.

  • 1-й столбец: «Дата» > диапазон дат
  • 2-й столбец: «Ярлык»-› Движение цены DJIA (нам не требуется этот столбец для этого проекта)
  • Остальные столбцы: заголовки новостей от «Top1» до «Top25»

Индекс волатильности (переменная Y)

Затем мы получим цены VIX с веб-сайта Чикагской биржи опционов.

  • 1-й столбец: диапазон дат цен VIX с 2004 г. по настоящее время.
  • 2-я колонка: Дневная цена открытия для VIX
  • 3-я колонка: Самая высокая цена за день для VIX
  • 4-я колонка: Самая низкая цена за день для VIX
  • 5-я колонка: Цена закрытия дня для VIX.

Предварительная обработка данных

После того, как мы получили вышеуказанные наборы данных, мы приступаем к предварительной обработке обоих наборов данных, объединяем их вместе и группируем по датам.

  • Дата: диапазон дат для заголовков новостей
  • all25: объедините все 25 заголовков новостей и сгруппируйте их по дням.
  • вверх или вниз:

1.0 › Цена закрытия для индекса волатильности выше цены открытия

0.0 › Цена закрытия для индекса волатильности ниже цены открытия

Моделирование данных

Пришло время для веселья! Мы выбрали приведенные ниже модели для обработки естественного языка (NLP) в заголовках новостей.

Машинное обучение

Глубокое обучение

Прежде чем приступить к моделированию, мы сначала выполняем следующий процесс над нашим текстом в заголовках новостей:

  1. Группировка в стебли
  2. Исключение стоп-слов
  3. Удаление знаков препинания
  4. Удаление цифр
  5. Удаление пробелов
def cleaner(text):
    stemmer = PorterStemmer()                                          # groups words having the same stems
    stop = stopwords.words('english')                                  # excludes stop words
    text = text.translate(str.maketrans('', '', string.punctuation))   # removes punctuation
    text = text.translate(str.maketrans('', '', string.digits))        # removes digits
    text = text.lower().strip()                                        # removes spaces
    final_text = []
    for w in text.split():
        if w not in stop:
            final_text.append(stemmer.stem(w.strip()))
    return ' '.join(final_text)

После того, как мы предварительно обработали наш текст для заголовка новости, мы выполняем наше тестовое разделение поезда — случайным образом перемешиваем и разделяем обработанные данные на 67% обучающего и 33% тестового набора.

X = combined_news 
y = combined_news['upordown']
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.33,stratify = y, random_state=42)

Наконец, мы создали переменные X и Y и приступаем к моделированию.

Коды для выбранных моделей я намеренно опустил (слишком длинные), если хотите сослаться на процесс моделирования, можете сослаться на мой гитхаб :)

Оценка модели

По сути, мы выполнили наше моделирование, и ниже представлены сводные результаты наших моделей.

Помните: наша цель — создать модель классификатора, чтобы иметь возможность прогнозировать ежедневное движение цены индекса волатильности с высокой точностью.

#settings the parameters of the dataframe
#Model type
Model               = ['Countvectandlogreg',
                       'TDIFandlogreg',
                       'NaivesbayesandTDIF',
                       'randomforestandTDIF',
                       'LSTM3layers',
                      ]
#Training Dataset Accuracy Scores
Training_Accuracy   = [trainingacc1,
                       trainingacc2,
                       trainingacc3,
                       trainingacc4,
                       trainingacc5]
#Prediction Dataset Accuracy Scores
Prediction_Accuracy = [acc1,
                       acc2,
                       acc3,
                       acc4,
                       acc5]
#ROC_AUC_scores
Roc_Auc_score       = [rocauc1,
                       rocauc2,
                       rocauc3,
                       rocauc4,
                       rocauc5]

Сводка результатов приведенной выше модели показывает производительность различных моделей и различные показатели, используемые для оценки моделей, точность набора данных для обучения и тестирования, а также кривые ROC и AUC. Классификаторы сортируются в порядке убывания оценки чувствительности в наборе данных проверки.

Из сводки выше видно, что randomforestTDIF и LSTM работают хорошо.

randomforestTDIF

randomforestTDIF набрал 96 %, однако в нашем проверочном наборе данных его точность составила всего 60 %. Это признак переобучения, когда модель очень хорошо работает на тренировочном наборе, но не на нашем проверочном.

Это ожидается, поскольку деревья решений, такие как модель случайного леса, представляют собой непараметрический алгоритм машинного обучения, который является очень гибким и подвержен переобучению обучающих данных. Эту проблему можно попытаться решить, обрезав дерево после того, как оно научилось, чтобы удалить некоторые детали, которые оно усвоило.

LSTM

Мы выберем LSTM3layers в качестве нашего лучшего классификатора, учитывая, что он имеет самый высокий показатель AUC, а также показатель точности для набора данных проверки (79%) и точность (76%) для нашего набора обучающих данных. Похоже, что наш набор данных для проверки работает лучше, чем наш набор данных для обучения. Совсем неплохо!

Мы также строим кривую AUC-RUC для нашей модели LSTM (оценка AUC 0,87).

# Plot ROC_AUC Curve
#Create figure.
plt.figure(figsize = (10,7))
# Create threshold values.
thresholds = np.linspace(0, 1, 200)
# Define function to calculate sensitivity. (True positive rate.)
def TPR(df, true_col, pred_prob_col, threshold):
    true_positive = df[(df[true_col] == 1) & (df[pred_prob_col] >= threshold)].shape[0]
    false_negative = df[(df[true_col] == 1) & (df[pred_prob_col] < threshold)].shape[0]
    return true_positive / (true_positive + false_negative)
    
# Define function to calculate 1 - specificity. (False positive rate.)
def FPR(df, true_col, pred_prob_col, threshold):
    true_negative = df[(df[true_col] == 0) & (df[pred_prob_col] <= threshold)].shape[0]
    false_positive = df[(df[true_col] == 0) & (df[pred_prob_col] > threshold)].shape[0]
    return 1 - (true_negative / (true_negative + false_positive))
    
# Calculate sensitivity & 1-specificity for each threshold between 0 and 1.
tpr_values = [TPR(pred_df, 'true_values', 'pred_probs', prob) for prob in thresholds]
fpr_values = [FPR(pred_df, 'true_values', 'pred_probs', prob) for prob in thresholds]
# Plot ROC curve.
plt.plot(fpr_values, # False Positive Rate on X-axis
         tpr_values, # True Positive Rate on Y-axis
         label='ROC Curve')
# Plot baseline. (Perfect overlap between the two populations.)
plt.plot(np.linspace(0, 1, 200),
         np.linspace(0, 1, 200),
         label='baseline',
         linestyle='--')
# Label axes.
plt.title('Receiver Operating Characteristic Curve', fontsize=22)
plt.ylabel('Sensitivity', fontsize=18)
plt.xlabel('1 - Specificity', fontsize=18)
# Create legend.
plt.legend(fontsize=16);

Одна из возможных причин, по которой LSTM работали лучше, чем остальные модели, заключалась в том, что они очень эффективны в задачах прогнозирования последовательности, поскольку они могут хранить прошлую информацию.

Это важно в нашем случае, потому что некоторые ключевые слова в предыдущих заголовках новостей имеют решающее значение для прогнозирования тех же заголовков новостей, чтобы предсказать, будет ли индекс волатильности падать или расти.

Наконец-то мы создали нашу модель, предсказывающую движение индекса волатильности! Но что, если мы сможем создать сценарий, чтобы использовать нашу обученную модель для прогнозирования ежедневного движения индекса волатильности?

Если вы хотите просмотреть коды для этого проекта, вы можете обратиться к моему портфолио на github или моему видео на YouTube.

Github: https://github.com/derrickhoe1988/Capstone-project

Ютуб: https://www.youtube.com/watch?v=JU2erC9lUME

Следите за моим вторым продолжением этой статьи!

Примечание простым языком

А вы знали, что у нас четыре публикации и канал на YouTube? Вы можете найти все это на нашей домашней странице plainenglish.io — проявите свою любовь, подписавшись на наши публикации и подписавшись на наш канал YouTube!