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

Что такое случайный лес и почему? Согласно IBM, «Случайный лес — это часто используемый алгоритм машинного обучения, зарегистрированный под торговой маркой Лео Бреймана и Адель Катлер, который объединяет выходные данные нескольких деревьев решений для достижения единого результата. Его простота использования и гибкость способствовали его принятию, поскольку он справляется как с классификацией, так и с регрессией». Другими словами, это мощная модель, которая учитывает множество различных факторов для достижения результата. Для получения более подробной информации см. ссылку ниже.



В проекте будут использоваться биржевые данные Mastercard, полученные от Yahoo! Сайт финансов. Ссылка здесь. Данные содержат записи стоимости акций, которые включают даты и значения для открытия, максимума, минимума закрытия, скорректированного закрытия и объема. Данные собирались ежедневно с понедельника по пятницу, за исключением праздничных дней с 2006 по 2023 год.

Моя цель — оценить прогностическую способность модели Random Forest Regression на самих биржевых данных Mastercard. Для этого проекта я использовал Python, Jupyter Notebook и Visual Studio Code. Я начал с импорта библиотек Python для чтения данных и построения графиков.

#import basic components
import pandas as pd
import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
%matplotlib inline

#import data
masterData = pd.read_csv("MA.csv")
masterData

Я импортировал данные с помощью библиотеки pandas и присвоил данные переменной с именем «masterData». Блокнот показывает компактную таблицу, содержащую 4244 записи и 7 столбцов. Столбцы: открытие, максимум, минимум закрытия, скорректированное закрытие и объем. Записи — это значения для каждого столбца. Чтобы узнать, отсутствует ли в данных запись, я использовал код, показанный ниже.

#info on each column and entry
masterData.info()

Блокнот возвращает таблицу, содержащую общее количество записей и тип данных для каждого столбца. Всего в каждом столбце 4244 записи, что означает, что ничего не пропущено. Столбец даты в настоящее время установлен как объект в качестве типа данных, что не идеально при построении графиков. Блокнот не будет правильно отображать графики, если я не преобразую этот тип данных. Я преобразовал столбец в формат datetime, который является другим типом данных, используя код, показанный ниже.

#convert object to datetime for date column
masterData['Date'] = pd.to_datetime(masterData['Date'])
masterData.info()

Исследовательский анализ данных (EDA)

Из другой статьи, опубликованной IBM: «Исследовательский анализ данных (EDA) используется учеными для анализа и исследования наборов данных и обобщения их основных характеристик, часто с использованием методов визуализации данных. Это помогает определить, как лучше всего манипулировать источниками данных, чтобы получить нужные ответы, облегчая специалистам по данным обнаружение закономерностей, выявление аномалий, проверку гипотез или проверку предположений». EDA — это первый шаг, который нужно сделать, чтобы определить, как лучше всего использовать набор данных для достижения цели. Для получения более подробной информации см. ссылку ниже.



Для этого проекта значения скорректированного закрытия будут иметь большее значение, чем цена закрытия. Согласно статье из The Balance, цена закрытия просто говорит вам, по какой цене акции торговались в конце любого торгового дня. Скорректированная цена закрытия обновляет эту информацию, отражая такие события, как выплата дивидендов и дробление акций. Поскольку скорректированная цена закрытия учитывает информацию, не включенную в цену закрытия, она считается более точным представлением, чем цена закрытия.

Я сделал сравнительные графики для открытия и скорректированного закрытия, а также максимума и минимума.

Открытие против скорректированного закрытия

plt.plot(masterData['Date'], masterData["Open"], '-b', label = "Open")
plt.plot(masterData['Date'], masterData["Adj Close"], '-', color = "orange", label = "Adjusted Close")
plt.legend()
plt.show()

Скорректированные значения закрытия росли экспоненциально с 2017 по 2021 год. Данные указывали на множество факторов за пределами набора данных, которые способствовали экспоненциальному увеличению.

Высокий против низкого

plt.plot(masterData['Date'], masterData['High'], '-b', label = "High")
plt.plot(masterData['Date'], masterData['Low'], '-', color = "orange", label = "Low")
plt.xlabel("Date")
plt.ylabel("Values")
plt.legend()
plt.show()

Значения высокого и низкого уровня также показали сильное сходство.

Чтобы модель регрессии случайного леса использовала данные, я снова преобразовал тип данных для столбца даты в str и разделил дату на год, месяц и день, используя код, показанный ниже.

#convert datetime to str
masterData['dateStr'] = masterData['Date'].astype(str)
masterData.info()

#separate date into year, month, and day
masterData[['year', 'month', 'day']] = masterData['dateStr'].str.split("-", expand=True)
masterData

Я создал новый столбец с именем «dateStr», который содержит записи для дат, но с типом данных str. Таким образом, я могу видеть все даты в строке str и соответственно разбивать их. Я удалил столбцы date и dateStr из masterData, используя код, показанный ниже.

masterData = masterData.drop(columns=['Date', 'dateStr'])
masterData

Алгоритмы, используемые трейдерами

Из статьи Investopedia Использование технических индикаторов для разработки торговых стратегий: Индикаторы, такие как скользящие средние и полосы Боллинджера, представляют собой математические инструменты технического анализа, которые трейдеры и инвесторы используют для анализа прошлых и прогнозирования будущих ценовых тенденций и моделей. Там, где фундаменталисты могут отслеживать экономические данные, годовые отчеты или различные другие показатели корпоративной прибыльности, технические трейдеры полагаются на графики и индикаторы, помогающие интерпретировать ценовые движения. Целью использования индикаторов является выявление торговых возможностей. Для получения дополнительной информации о технических индикаторах см. ссылку ниже. В проекте будет использоваться 15-дневная скользящая средняя и балансовый объем.



Примечание об использовании технических индикаторов для долгосрочного инвестирования

The Motley Fool упомянул в статье Технический анализ для долгосрочного инвестора, что он не использует технический анализ для прогнозирования движения цены акций. Статья продолжилась: Технический анализ может быть полезным для некоторых трейдеров, но наиболее устойчивый путь к достижению успеха в долгосрочном инвестировании не включает чтение краткосрочных графиков. Сосредоточение внимания на фундаментальных показателях, таких как рост выручки и прибыли — показатели того, что компания работает в отрасли с темпами роста выше среднего, — или на признаках того, что компания обладает конкурентным преимуществом, — все это совместимо с долгосрочным созданием богатства. Обратите внимание, что долгосрочные цены на акции зависят от основных показателей компании, таких как прибыль и инвестиции в ее бизнес.

15-дневные скользящие средние и балансовый объем

Я создал новый столбец под названием «MA15» для хранения значений 15-дневной скользящей средней. Я также создал новый столбец под названием «OBV» для хранения значений балансового объема. Оба столбца включены в masterData, и код показан ниже.

#acquire 15 day moving average - https://www.learnpythonwithrune.org/simple-and-exponential-moving-average-with-python-and-pandas/
masterData['MA15'] = masterData['Close'].rolling(15).mean().fillna(0)

#acquire on-balance volume - https://medium.com/wwblog/implement-the-on-balance-volume-obv-indicator-in-python-10ac889efe72
masterData['OBV'] = masterData['Close'].diff() * masterData['Volume'].fillna(0).cumsum()

#replace nan values with 0
masterData.fillna(0, inplace=True)

#return masterData
masterData

Подготовка данных для модели случайной регрессии леса

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

# identify features and target
features = masterData.drop('Adj Close', axis=1)
target = masterData['Adj Close']

Модель регрессии случайного леса

Я разделил данные на обучающий набор для обучения модели и тестовый набор для оценки модели. Обучающий набор будет содержать 80% данных, а тестовый набор будет содержать 20% данных. Оттуда я создал модель регрессии случайного леса и накормил модель обучающим набором и тестовым набором. Код показан ниже.

#import necessary libraries for splitting data, calculating mean squared error, and using the Random Forest Model
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.ensemble import RandomForestRegressor

# identify training and test sets from the data
features_train, features_test, target_train, target_test = train_test_split(features, target, test_size=0.2, random_state=42)

# initialize the model with 6000 decision trees
randomForest = RandomForestRegressor(n_estimators=6000, random_state=42)

# fit the model
randomForest.fit(features_train, target_train)

Я использовал модель для генерации прогнозируемых значений и присвоил их target_pred. Затем я рассчитал потерю между целевым значением из фактического тестового набора и значениями, предсказанными моделью, известной как среднеквадратическая ошибка (RMSE). Я также рассчитал среднюю абсолютную ошибку в процентах, которая измеряет точность модели (цитата взята из Datagy). Код показан ниже.

# prediction time
target_pred = randomForest.predict(features_test)

#calculate rmse
rmse1 = float(format(np.sqrt(mean_squared_error(target_test, target_pred)), '.3f'))
print("RMSE: ", rmse1)
# calculate Mean Absolute Error
from sklearn.metrics import mean_absolute_percentage_error
error1 = mean_absolute_percentage_error(target_test, target_pred)
print("Mean absolute percentage error: ", round(error1, 2))

Блокнот возвращает значение 0,534 для RMSE и 0,0 для средней абсолютной ошибки в процентах. Наконец, я рассчитал r-квадрат, который показывает, насколько хорошо данные соответствуют регрессионной модели (цитата получена из CFI), используя код, показанный ниже.

# calculate adjusted R-squared
from sklearn.metrics import r2_score
r2 = r2_score(target_test.values.ravel(), target_pred)
print('R-squared: ', round(r2, 2))

Блокнот возвращает 1,0 для r-квадрата. Я создал график, который показывает «target_pred» и «target_test», используя код, показанный ниже.

#plot target_pred vs target_test
plt.plot(target_pred, target_test, "o", c = "green")
plt.xlabel("prediction")
plt.ylabel("actual")
plt.show()

RMSE высокий, но остальные хороши. На фактическом графике по сравнению с прогнозируемым график превращается в идеальную прямую линию, которая идет вверх, что означает, что я переоценил данные. Другими словами, я создал модель, которая хорошо тестируется на выборке, но имеет небольшую прогностическую ценность. Фактические значения между открытием, закрытием, максимумом, минимумом и закрытием очень похожи на скорректированное закрытие. Следовательно, модель не может делать прогнозируемые значения. Стоит отметить, что ни одна из функций не влияет на значения скорректированного закрытия. Результаты не будут иметь смысла, если кто-то не сможет определить, как функции могут внести свой вклад в значения для цели.

Выводы

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

В настоящее время Mastercard очень прибыльна, но есть много опасений относительно возможного экономического спада. Это означает, что инвестор использует возможный страх перед будущим, чтобы управлять сегодняшними ценами в целом. Страх не является частью модели Random Forest, равно как и чувства. И страх, и чувства не поддаются количественной оценке. Эмпирическое правило заключается в том, что если человек хочет правильно проанализировать цену акций для достижения цели, ему сначала понадобятся соответствующие данные. Этот проект является нежным напоминанием о том, что, хотя нужно сосредоточиться на поиске правильной модели для данных, получение набора данных, содержащего соответствующие факторы, имеет решающее значение для получения реальных результатов.

Чтобы увидеть все материалы в этом проекте, пожалуйста, перейдите по ссылке ниже. Это приведет вас к моему репозиторию GitHub для этого проекта.