Подход, использующий библиотеку Pycaret, бета-вариантность и Yahoo Finance для создания метрик для составления будущего портфеля акций.
Я хотел бы предсказать и проверить будущие возможные значения того, какие акции менее рискованны, чем другие; основываясь на этом; Я мог определить некоторые показатели экономической теории и статистики; в этом посте я поделюсь некоторыми фрагментами, которые могут предоставить информацию для экспериментов с прогнозами акций, а точнее с моделью временных рядов под названием авто-регрессивная интегрированная скользящая средняя (ARIMA).
До открытия Австралии люди в Старом Свете были убеждены, что все лебеди белые, и это непоколебимое убеждение, поскольку оно казалось полностью подтвержденным эмпирическими данными.” , Насим Николас Талеб
Во-первых, я понял, что у акций есть черные лебеди, такие как коронавирус, война на Украине, Илон Маск и другие ситуации, которые могут нарушить нормальность и каким-то образом изменить поведение акций. Исходя из этого, я начал искать какие-то системы управления рисками для акций и нашел интересный метод под названием CAPM — Модель ценообразования капитальных активов.
Модель CAPM предлагает теорию, называемую бета-дисперсией. Эту функцию можно использовать для расчета систематического риска акций путем сравнения дисперсии между акциями и другими индексами, такими как, например, индикаторы S&P500. Эта метрика может выступать в качестве фактора, который можно использовать для выбора менее нестабильной акции на основе некоторого индекса; подробнее вы можете прочитать в этой статье.
Нет больше слов, давайте погрузимся в данные!!
Чтобы организовать, я разделил этот пост на 6 больших шагов: образец, исследование, изменение, моделирование, заключение.
Все эти шаги и код доступны в этом git repo.
Образец
Во-первых, чтобы приступить к этому, нам нужно собрать акции из SP 500. С помощью простого веб-скрейпинга мы собираемся собрать значения символов акций SP500 со страницы Википедии.
#Identify after how much time they started at the SP500 after their foundation #Show how sectors are at the SP500 #show quantity based on security #show GICS Sub-Industry #function to take stocks and values import pandas as pd def returnstocks(): table=pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies') stocksdf = table[0] stocksdf.to_csv('S&P500-Info.csv') stocksdf.to_csv("S&P500-Symbols.csv", columns=['Symbol']) stocksdf['Symbol'] = stocksdf['Symbol'].replace('.B','', regex=True) return stocksdf def eachstock(): myList = ['^GSPC'] for stick in returnstocks()['Symbol'].unique(): myList.insert(0, stick) return myList tickers = ['^GSPC','ZTS','ZION','H','RA','YUM'..]
Функция eachstock() возвращает список акций, инициализированных SP500.
Исследовать
В ходе некоторого исследовательского анализа нам удалось определить основные секторы, используемые SP500, эти сектора можно использовать для диверсификации портфеля акций, так как более широкий спред с меньшим риском, тривиальный, но важный, чтобы избежать черных лебедей из определенного сектора.
Для этого шага мы используем компонент из Википедии, и собираемся ввести нового агента yahoo Finance. У Yahoo Finance есть горячие данные с https://finance.yahoo.com, и мы можем использовать эти данные, чтобы улучшить нашу способность принимать решения, касающиеся создания портфеля акций.
#@title Yahoo Finance request and beta/Alpha calculation #@markdown For this step, we are using the component from Wikipedia, and we are going to introduce a new agent, the yahoo finance. Yahoo Finance, has hot data from https://finance.yahoo.com, and we can use these data to improve our power to decision making, regarding to create a stocks portfolio. yfin.pdr_override() #override method from pandas_datareader by importing data as pdr tickers = eachstock() #tickers = ['ZTS', 'ZION', '^GSPC'] #function for receive list of stocks, source where to search and initial date/lastdate def stockdoublebench_returns(ticker, initialdate, lastdate): #future change ticker for returnstocks()['Symbol'].unique() stockdouble = yfin.download(ticker, initialdate, lastdate) #data = yf.download("SPY AAPL", period="max",) return stockdouble['Adj Close'] #stockdoublebench_returns #run just this command to check the volatility of each one. def stockdoublebench_percent(ticker, initialdate, lastdate): #future change ticker for returnstocks()['Symbol'].unique() stockdoublepercent = yfin.download(ticker, initialdate, lastdate) #return stockdouble['Adj Close']] #add this line to use the graph to compare the volatility return stockdoublepercent['Adj Close'].pct_change()[1:] #alpha, beta and stock abstocks = pd.DataFrame(columns=['Alpha', 'Beta', 'stocks']) #created dataframe def alphabetastock(df, index): #Function for generate alpha and beta from stocks for col in df: #for column in dataframe do x = sm.add_constant(df[index].values) #create a matrix using 1 and the value model = sm.regression.linear_model.OLS(df[col].values,x).fit() #linear regression to get values https://www.statsmodels.org/dev/generated/statsmodels.regression.linear_model.OLS.html abstocks.loc[len(abstocks.index)] = [model.params[0], model.params[1], col] #add each value to the dataframe return abstocks #model.params[0], model.params[1], col #need to add a new line at the df for show the predicted values from each stock, and its important add the value #from the accuracy from test as well.
Фрейм данных abstocksna вернул значения. Альфа, бета и акции, для получения дополнительной информации о бета и альфа, пожалуйста, прочтите эту статью.
Настроив нашу конфигурацию, мы можем проверить больше полезной информации.
Изменить
Нам нужно подготовить наши данные для использования, так как акции имеют высокую волатильность, чем нам нужно нормализовать наши данные, мы собираемся использовать библиотеку MinMaxScaler() из sklearn с функциями fit_transform и inverse_transform, теперь мы можем для доставки этого требования. Поскольку ARIMA дает лучшие результаты со скаляром minmax, чем с методом z-оценки, мы выберем minmax() напрямую, чтобы соответствовать и масштабировать наши данные.
stockdfs = pd.DataFrame() def datenormalization(stockdf): global stockdfs stockdf = stockdf.groupby('Date').sum() stockdf = stockdf.asfreq(freq ='D'); stockdfs = stockdf.ffill() #associate frequency by day to get hollidays stockdfs.sort_index(ascending=True, inplace=True) return pd.DataFrame(stockdfs) obj = '' #global variable def scaler_fit(series): global obj scaler = MinMaxScaler() obj = scaler.fit(series) return obj def min_max_fit(series): #normalization scaler_fit(series) scaler = MinMaxScaler() series[list(series.columns)] = scaler.fit_transform(series) return series def min_max_inverse(series, obj): #denormalization series[list(series.columns)] = obj.inverse_transform(series) return series
Модель
Модели ARIMA используют разность для преобразования нестационарных временных рядов в стационарные, а затем прогнозируют будущие значения на основе исторических данных. Эти модели используют автоматические корреляции и скользящие средние по остаточным ошибкам в данных для прогнозирования будущих значений. https://www.capitalone.com/tech/machine-learning/understanding-arima-models/
Настройка модели
Во время некоторых тестов мы определили ARIMA, один из лучших алгоритмов для прогнозирования запасов за короткий период времени, прогнозы на дни. Чтобы продолжить эти тесты, мы использовали пикарет для визуализации и определения методов наилучшего соответствия.
Во-первых, мы просто создаем нашу настройку, передавая значения fh (горизонта прогноза), а кратность используется для перекрестной проверки. Аргумент session_id используется для доставки случайного числа для этой настройки.
fh: Горизонт прогноза — это период времени в будущем, на который должны быть подготовлены прогнозы.
Pycaret возвращает некоторые хорошие значения в отношении целевого обученного и протестированного фрейма данных, одна вещь, которую следует знать, касается экзогенной переменной, как вы передаете переменную в pycarat, если у вас возникнут проблемы, проверьте эту ссылку ниже.
После процесса настройки нам нужно выбрать модель, так как у меня уже есть выбор модели ARIMA. Если вы хотите, чтобы Pycaret выбрал/протестировал лучший алгоритм для вас, вы можете использовать функцию compare-models(), вы можете проверить глубже через pycaret документация.
Создать модель
Поскольку у меня уже выбран вариант, мы продолжим работу с моделью ARIMA, где она классифицируется как алгоритм прогнозирования временных рядов.
Определите и прочитайте показатели
Сходство показателей стенда (MAE и MRSE)
1 — Стенд метрик выражает среднюю ошибку на основе прогнозируемой модели относительно исходного кода (поезд/тест).
2 — они находятся в диапазоне от 0 до бесконечности и возвращают ошибку величины.
3 — ближе к нулю (0), лучше значение.
Подробнее: MAE и MRSE
Проверка результатов — созданная модель
Создать модель
Доработка модели
На данный момент полученные результаты оправдывают ожидания, мы будем дорабатывать модель.
Построить прогнозные значения — на 5 вперед.
Поскольку мы создали нашу модель, мы прогнозируем 5 дней для будущих значений.
Разрабатываем все вместе
После этого мы создали две функции: одна для вычисления поезда, нормализации и денормализации, а вторая функция используется для создания массива и объединения каждой информации в один фрейм данных, благодаря чему мы можем продолжить дальнейший анализ.
Весь алгоритм работает в соответствии с приведенным ниже рабочим процессом:
minmax() → setup() → финализировать модель() → предсказать модель() → inverseminmax() → mergeresults() → Dataframe[] → проверка → Delviery
#@title Engineering All to Predict Stocks #@markdown Engineering to predict all 500 stocks from pycaret.time_series import * pred_unseen_deno = pd.DataFrame() dffdstocks = pd.DataFrame() transpredicted = pd.DataFrame() dfstocks = pd.DataFrame() dfstocks.iloc[0:0] def train_and_normalize(stock, initialdate, finaldate, predictdays, predictdaysx, crossvalidation): global pred_unseen_deno global transpredicted stock_returns = datenormalization(stockdoublebench_returns(stock, initialdate, finaldate)) print(stock_returns) exp2 = setup(min_max_fit(stock_returns[['Adj Close']]), fh = predictdays, fold = crossvalidation, session_id = 123) arima2 = exp2.create_model('arima') #pred_holdout = predict_model(arima2) pred_unseen_deno = min_max_inverse(predict_model(exp2.finalize_model(arima2), fh = predictdaysx), obj) #if you need to see the pred_holdout value #pred_unseen_deno = min_max_inverse(predict_model(finalize_model(arima2), fh = predictdaysx), obj) transpredicted = pred_unseen_deno.T transpredicted['stocks'] = stock return transpredicted def iterate_predicted_stocks(initialdate, finaldate, predictdays,predictdaysx, crossvalidation): global dffdstocks global dfstocks for value in (abstocksna['stocks']): try: train_and_normalize(value, initialdate, finaldate, predictdays, predictdaysx,crossvalidation) dffdstocks = dffdstocks.append(transpredicted, ignore_index = True) dfstocks = pd.merge(dffdstocks, abstocks, on='stocks') except: continue return dfstocks #We are going to use this function to start up our algoritm to predict future values. #initial date, last date, predictdays(for test), predictdate for future to be used after last date, and how #many values fold we are going to use for cross validation. abstocks = alphabetastock(stockdoublebench_percent(tickers, '2015-01-01', '2022-12-25'),'^GSPC') abstocksna = abstocks.dropna() iterate_predicted_stocks('2015-01-01', '2022-12-25', 30, 10 ,5)
Функция Alphastastock() сначала вызывается для вычисления всех значений из альфы и беты, после чего значения сохраняются в фрейме данных abstocksna, после чего функция iterate_predicted_stocks() начинает выполнять итерацию и доставляет каждое значение в нашу функцию train_and_normalize(). , видя это, мы предлагаем начальную дату, конечную дату, тестовый набор (30), прогнозируемое значение для будущего (10), а 5 — это количество, используемое для перекрестной проверки.
Заключение
В результате мы можем получить прогнозируемые значения для выбранных дней, в этом случае мы будем работать с 5 днями, и у нас есть бета-вариация и альфа-версия, которые помогут нам разработать наш фондовый кошелек. Можно увеличить этот фрейм данных с помощью: высоких значений, минимального значения, среднего и сектора каждого, чтобы использовать больше статистических выводов для определения и применения алгоритмов роя частиц, или можно использовать решение по нескольким критериям для определения лучшего будущего портфеля акций. .
Дальнейшие шаги
- Увеличьте окончательный фрейм данных новыми значениями, чтобы лучше принимать решения.
- Многокритериальный алгоритм для определения портфеля акций.
- Оптимизируйте будущий портфель.