Юпитер Блокнот

вступление

Индекс S&P 500 измеряет эффективность 500 крупнейших публично торгуемых компаний в Соединенных Штатах на основе рыночной капитализации, которая представляет собой общую стоимость акций компании, находящихся в обращении. Если значение увеличивается, то индекс будет расти; если значение уменьшится, то Индекс понизится.

Цель этого проекта — предсказать направление индекса S&P 500, чтобы мы могли совершать прибыльные сделки с минимальным риском. Чтобы точно классифицировать сделки как вверх или вниз, мы построим модель классификации случайного леса и рассчитаем первую оценку точности на основе самых последних 100 торговых дней, а затем рассчитаем следующие оценки точности на основе таких функций, как функции тестирования на исторических данных, технические индикаторы и вероятность. уровни. Наконец, мы сравним 3-ю оценку точности с процентом положительных торговых дней.

Отказ от ответственности — это только для академических целей.

Импортировать

Для начала давайте импортируем необходимые библиотеки. Затем извлеките исторические цены индекса S&P 500 из Yahoo Finance. Наконец, сохраните данные в файл CSV.

import datetime
import pandas as pd
from matplotlib import pyplot as plt
import yfinance as yf

sp500 = yf.Ticker("^GSPC")
sp500 = sp500.history(period = "max")
sp500.to_csv("/Users/tgut03/Jupyter/Data/sp500 Index.csv")

Во-первых, функция ticker возвращает исторические цены для тикера ^GPSC. Затем функция history определяет период времени исторических цен. Наконец, функция to_csv преобразует исторические цены в файл CSV, расположенный по заданному пути к файлу.

Ключевые идеи

  • Данные начинаются до 1940 г.
  • Цена закрытия резко выросла примерно в 2010 году.

Трансформировать

Чтобы предварительно обработать наши данные, давайте установим столбец Tomorrow равным цене закрытия следующего торгового дня. Затем установите столбец «Цель» равным 1, если завтрашняя цена больше цены закрытия (направление вверх), и 0 в противном случае (направление вниз). Наконец, установим sp500 DataFrame равным историческим ценам после 1 января 1990 года, потому что динамика рынка до этого периода может значительно отличаться от настоящей, поэтому, если мы исключим эти данные, мы уменьшим потенциальные смещения, внесенные в нашу модель, и повысим надежность нашей модели. предсказания.

# Tomorrow = Close - 1
sp500["Tomorrow"] = sp500["Close"].shift(-1)

# If Up Then 1 Else If Down Then 0
sp500["Target"] = (sp500["Tomorrow"] > sp500["Close"]).astype(int)

# Get Date After Jan 1990
date = datetime.date(1990, 1, 1)
sp500 = sp500[sp500.index >= date].copy()

Во-первых, функция shift возвращает значение столбца Close на 1 строку назад. Затем функция astype преобразует логическое значение true/false в 1 и 0. Затем функция date преобразует 1990–01–01 в год, месяц, день. Наконец, функция copy создает копию исходного DataFrame, где значения индекса относятся к периоду после 1 января 1990 года.

Ключевые идеи

  • Целевое значение на 1990–01–02 равно 0, поскольку завтрашняя цена $358,76 меньше цены закрытия $359,69.
  • Целевое значение на 1990-01-05 равно 1, потому что завтрашняя цена 353,79 доллара больше, чем цена закрытия 352,20 доллара.
  • Цель на 2023–06–26 равна NaN, потому что нет будущей цены закрытия, на которую можно ориентироваться.

Модель

Чтобы смоделировать наши данные, давайте импортируем необходимые библиотеки. Случайные леса случайным образом выбирают подмножества признаков на каждом уровне каждого дерева решений и применяют методы ансамбля, чтобы получить большинство голосов или средневзвешенное значение прогнозов из нескольких деревьев решений. Затем разделите набор данных так, чтобы набор данных поезда равнялся всем данным, кроме самых последних 100 торговых дней, а тестовый набор данных равнялся самым последним 100 торговым дням — 1 строка равнялась 1 торговому дню. Затем выберите соответствующие функции для нашей модели, которые представляют входные данные. Затем определите нашу модель случайного леса, чтобы мы могли классифицировать направление индекса sp500 как вверх или вниз. Затем научите нашу модель изучать закономерности между нашими входными данными и желаемыми выходными данными — наш желаемый выходной сигнал растет, потому что мы хотим торговать, когда индекс S&P 500 растет. Затем примените обученную модель для создания прогнозов на тестовом наборе данных. Наконец, рассчитайте показатель точности, который представляет собой долю истинных положительных прогнозов к общему количеству положительных прогнозов — прогнозы являются положительными, когда цель равна.

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import precision_score

# Split Dataset
train = sp500[:-100]
test = sp500[-100:]

# Select Features
prices = ["Open", "Close", "High", "Low", "Volume"]

# Model
model = RandomForestClassifier(n_estimators = 100,
min_samples_split = 100,
random_state = 1)

# Train Model
model.fit(train[prices], train["Target"])

# Predictions
preds = model.predict(test[prices])

# 1st Precision
score = precision_score(test["Target"], preds)
print(score)

Во-первых, гиперпараметр n_estimators определяет количество деревьев решений. Затем гиперпараметр min_samples_split определяет количество выборок, необходимых для разделения узлов деревьев решений. Затем гиперпараметр random_state определяет начальное значение, чтобы мы могли воспроизвести результаты случайного процесса. Затем функция fit учит нашу модель обновлять свои параметры, чтобы свести к минимуму функцию потерь или ошибку между нашими прогнозами и истинной реальностью — гиперпараметры определяются до обучения, а параметры изучаются во время обучения. Затем функция predict применяет нашу обученную модель для создания прогнозов на тестовом наборе данных. Наконец, функция precision_score измеряет способность моделей идентифицировать истинные положительные результаты.

Оценка точности = 0.61

Ключевые идеи

  • Модель Random Forest правильно предсказала, что индекс S&P 500 вырастет на 61% за последние 100 торговых дней.

Автоматизировать

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

def predict(train, test, prices, model) :
    model.fit(train[prices], train["Target"]) # Train Model
    preds = model.predict(test[prices]) # Predictions
    predsTruth = pd.concat([preds, test["Target"]], axis = 1)
    return predsTruth

Во-первых, функция fit учит нашу модель обновлять свои параметры, чтобы минимизировать функцию потерь или ошибку между нашими прогнозами и истинной реальностью. Затем функция predict применяет нашу обученную модель для создания прогнозов на тестовом наборе данных. Наконец, функция concat объединяет прогнозы и истину в 1 DataFrame, чтобы мы могли легко анализировать производительность.

Бэктест

Чтобы оценить эффективность нашей модели на 10-летних исторических ценах индекса S&P 500, а не на самых последних 100 торговых днях, давайте определим функцию ретроспективного тестирования. Затем итеративно перебираем диапазон индексов, чтобы разделить данные на окна, чтобы мы могли протестировать нашу модель на последовательных подмножествах исторических цен. Наконец, рассчитайте вторую оценку точности, которая представляет собой долю истинных положительных прогнозов к общему количеству положительных прогнозов.

# Backtest Function
def backtest(data, prices, model, start = 2500, step = 250) : # 1yr = 250
    totPreds = [] # Total Predictions
    
    for i in range(start, data.shape[0], step) :
        train = data.iloc[0:i].copy() # Window
        test = data.iloc[i:(i+step)].copy() # Sliding Window
        preds2 = predict(train, test, prices, model) # Predict Function
        totPreds.append(preds2) # Append Predictions
    return pd.concat(totPreds)

# 2nd Precision
score = precision_score(preds2["Target"], preds2["Predictions"])
print(score)

Во-первых, первая функция iloc определяет окна на основе их целочисленных позиций. Затем вторая функция iloc реализует скользящее окно для извлечения последовательных подмножеств данных. Затем функция predict использует автоматизированный процесс машинного обучения для создания прогнозов на основе последовательных подмножеств исторических цен. Затем функция append добавляет прогнозы в список. Наконец, функция concat объединяет предсказания списков в 1 DataFrame.

Оценка точности = 0.53

Ключевые идеи

  • Модель Random Forest правильно предсказала, что индекс S&P 500 вырастет на 53% за 10 лет торговых дней.

Технические характеристики

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

# Technical Indicators
horizons = [2, 5, 60, 250, 1000]
teks = []

for horizon in horizons : 
    rollAvgs = sp500.rolling(horizon).mean()
    
    ratio = f"{horizon} Day Close Ratio"
    sp500[ratio] = sp500["Close"] / rollAvgs["Close"]
    
    trend = f"{horizon} Day Trend"
    sp500[trend] = sp500.shift(1).rolling(horizon).sum()["Target"]
    
    teks += [ratio, trend]

Во-первых, функция rolling вычисляет скользящее среднее значение горизонта, которое представляет количество дней. Затем переменная ratio равняется отношению между ценой закрытия и скользящей средней цены закрытия. Затем переменная trend равняется скользящей сумме целевых значений за предыдущие дни. Наконец, переменная teks равняется значениям технических индикаторов.

Ключевые идеи

  • 60-дневный тренд 2023–06–28 равен 31, поэтому примерно 50% торговых дней были положительными.
  • Коэффициенты закрытия, значительно превышающие 1, подразумевают отклонение цены закрытия от скользящей средней.

Вероятность

Чтобы измерить вероятность предсказанных результатов, давайте определим функцию вероятности предсказания. Затем установите уровень вероятности для прогнозов — более высокие уровни вероятности требуют большей достоверности от модели, что увеличивает полноту, но снижает точность. Наконец, сравните 3-ю оценку точности с истинной, чтобы оценить производительность.

# Predict Probability Function
def predictProba(train, test, prices, model) :
    model.fit(train[prices], train["Target"]) # Train Model
    preds = model.predict_proba(test[prices])[:,1] # Probability
    preds[preds >= 0.6] = 1 # Up Probability Level
    preds[preds < 0.6] = 0 # Down Probability Level
    predsTruth = pd.concat([preds, test["Target"]], axis = 1)
    return predsTruth

# 3rd Precision
score = precision_score(preds2["Target"], preds2["Predictions"])
print(score)

# Ground Truth
truth = (preds2["Target"].value_counts() / preds2["Predictions"].shape[0])
positiveTruth = truth[1]
print(f"1 = {positiveTruth.round(2)}")

Во-первых, функция fit учит нашу модель обновлять свои параметры, чтобы минимизировать функцию потерь или ошибку между нашими прогнозами и истинной реальностью. Затем функция predict_proba предсказывает вероятность 1 с — если вероятность роста больше 0,6, то модель классифицирует цену индекса S&P 500 как рост. Затем функция concat объединяет прогнозы и истину в 1 DataFrame, чтобы мы могли легко анализировать производительность. Затем функция precision_score измеряет способность моделей идентифицировать истинные положительные результаты. Наконец, переменная positiveTruth равна пропорции 1 к общему количеству 1 и 0.

Оценка точности = 0.55

Основная правда 1s = 0.54

Ключевые идеи

  • Модель случайного леса правильно предсказала, что индекс S&P 500 будет расти 55% дней, в то время как индекс S&P 500 повышался 54% дней.

Заключение

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

Вы идентифицируете себя как латиноамериканца и работаете в области искусственного интеллекта или знаете кого-то из латиноамериканца и работает в области искусственного интеллекта?

  • Зарегистрируйтесь в нашем каталоге и станьте участником форума наших участников: https://forum.latinxinai.org/
  • Станьте автором публикации LatinX in AI, написав нам по адресу [email protected].
  • Узнайте больше на нашем сайте: http://www.latinxinai.org/

Не забудьте нажать 👏 ниже, чтобы помочь поддержать наше сообщество — это очень много значит!