Анализируйте данные о запасах с помощью RandomForestClassifier.

Привет, ребята,

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

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

Этот проект пройдет следующие этапы:

  1. Обзор проекта
  2. Подготовка данных
  3. ЭДА
  4. Моделирование
  5. Оценка
  6. Улучшение модели

Хорошо, начнем.

Обзор проекта

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

Техника моделирования: RandomForestClassifier
(может применяться для регрессии или классификации, более высокий уровень точности по сравнению с алгоритмом дерева решений, он ищет лучший признак среди случайного подмножества признаков.)

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

Мы также можем улучшить наш режим, используя различные методы. Подробности расскажу в процессе.

Спасибо, что следите за мной, надеюсь, вы чему-нибудь из этого научитесь.

Подготовка данных

Мы будем собирать данные об акциях Amazon через библиотеку yfinance на Python.
(используется для получения финансовых данных из Yahoo Finance).

import yfinance as yf

amzn = yf.Ticker("AMZN")

amzn = amzn.history(period="max") 
#retrieve the maximum available historical data

Хорошо, теперь у нас есть все исторические данные Amazon. Мы проведем некоторую фильтрацию данных в нашем наборе данных, чтобы убедиться, что мы можем запустить модель с менее предвзятыми данными:

  • Добавить столбец завтра
  • Добавить целевой столбец
  • Используйте данные только за 01.01.2000.
amzn["Tomorrow"] = amzn["Close"].shift(-1)
#calculates this column by shifting the "Close" prices one day up.
#This effectively aligns the "Close" prices of the current day with
#the "Open" prices of the next day.

amzn["Target"] = (amzn["Tomorrow"]> amzn["Close"]).astype(int)
#If price increased, the value in "Target" column will be 1; otherwise, 0.


sp500 = amzn.loc["2000-01-01":].copy()
# filtering the amzn DataFrame to include data starting from Jan 1, 1900 
# up to the most recent date. 

Наш набор данных:
(вы можете видеть, что добавлен столбец «завтра» и «целевой столбец»).
(цена завтрашнего дня = цена закрытия вчерашнего дня)

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

Посмотрим цену закрытия за весь период:

amzn.plot.line(y="Close", use_index = True)

# find out how many null value in our dataset
amzn.isna().sum()

Вы можете использовать профилирование Pandas, чтобы глубже понять набор данных. Я написал блог об этой функции: Посмотрите!

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

Случайный лес — это метод ансамблевого обучения, который объединяет несколько деревьев решений для создания более надежной модели.

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import precision_score
import pandas as pd

model = RandomForestClassifier(n_estimators=100, min_samples_split=100, 
random_state=1) #Seed -> help us to reproduce the model

#training data will be all rows except last 100 rows
train = amzn.iloc[:-100]

#Testing data will be last 100 rows 
test = amzn.iloc[-100:]

#feature columns that will be used as predictors for the model
predictors = ["Close", "Volume", "Open", "High", "Low"]

#Train the model 
model.fit(train[predictors], train["Target"])

Цель функции прогнозирования — обучить модель на обучающих данных, сделать прогнозы на основе тестовых данных и вернуть кадр данных, который объединяет фактические целевые значения и прогнозируемые значения.

def predict(train, test, predictors, model):
# Train the model on the training data
  model.fit(train[predictors], train["Target"])

 # Make predictions on the testing data
  preds = model.predict(test[predictors])

 # Create a pandas Series to hold the predicted values
 # with appropriate index and name
  preds = pd.Series(preds, index = test.index, name = "Predictions")

# Combine the actual target values and predicted values into a DataFrame
  combined = pd.concat([test["Target"], preds], axis = 1)
  return combined
  • › вы можете передать свои train и test DataFrames, список predictors и обученный model. Функция вернет DataFrame
    -> сравнит фактические целевые значения с прогнозами модели.

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

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

(мы возьмем данные за 10 последних лет, чтобы спрогнозировать 11-й год, затем данные за 11 лет, чтобы спрогнозировать 12-й год, затем данные за 12 лет, чтобы спрогнозировать 13-й год, и продолжим)

def backtest(data, model, predictors, start = 2500, step = 250):
  all_predictions = []

  for i in range(start, data.shape[0], step):
    train = data.iloc[0:i].copy()
    test = data.iloc[i:(i+step)].copy()

    predictions = predict(train, test, predictors, model)

    all_predictions.append(predictions)
#combines the prediction results from all iterations.
  
  return pd.concat(all_predictions)

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

Запустите функцию:

predictions = backtest(amzn, model, predictors)

Оценка

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

precision_score(predictions["Target"], predictions["Predictions"])

Результат:

Это не очень высокая точность, поэтому потребуется ее усовершенствование.

Улучшение модели

Создайте различные скользящие средние, это будут дополнительные предикторы к нашей модели.

horizons = [2,5,60,250,1000]
new_predictors = []

В целом, код создает новые функции на основе расчетов скользящего окна для разных горизонтов. Эти функции включают в себя соотношение цены закрытия к скользящим средним и скользящую сумму столбца «Цель», представляющую тенденции.

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

for horizon in horizons: 
  rolling_averages = amzn.rolling(horizon).mean()

  ratio_column = f"Close_Ratio_{horizon}"
  amzn[ratio_column] = amzn["Close"] / rolling_averages["Close"]

  trend_column = f"Trend_{horizon}"
  amzn[trend_column] = amzn.shift(1).rolling(horizon).sum()["Target"]

  new_predictors += [ratio_column, trend_column]

Теперь мы определяем функцию прогнозирования, которая применяет порог к прогнозируемым вероятностям, чтобы классифицировать их как 0 или 1 в зависимости от того, больше или равно 0,6.

def predict(train, test, predictors, model):
  model.fit(train[predictors], train["Target"])

  preds = model.predict_proba(test[predictors])[:,1]
  preds[preds >= .6] = 1 
  preds[preds < .6] = 0 
  preds = pd.Series(preds, index = test.index, name = "Predictions")

  combined = pd.concat([test["Target"], preds], axis = 1)
  return combined

Нам нужно удалить все значения для запуска функции.

amzn = amzn.dropna()

Переоценка

Теперь мы переоцениваем новую модель, чтобы увидеть, имеет ли она лучшую точность.

predictions = backtest(amzn, model, new_predictors)
precision_score(predictions["Target"], predictions["Predictions"])

Результат: 0,62

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

Примечание автора:

Спасибо, что вы здесь, надеюсь, это вам чем-то поможет.

Если у вас есть какие-либо вопросы, вы можете связаться со мной по электронной почте: [email protected]