вступление
Индекс 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/
Не забудьте нажать 👏 ниже, чтобы помочь поддержать наше сообщество — это очень много значит!