Введение

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

Блокноты Jupyter доступны в Google Colab и Github. Для этого анализа мы используем несколько технологий научных вычислений на основе Python, перечисленных ниже.

#Import Libraries
import math
import time
import requests
import numpy as np
import pandas as pd
from scipy import stats
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
from sklearn.linear_model import LinearRegression

Регрессия: ветвь контролируемого обучения

В контексте машинного обучения регрессия - это ветвь алгоритмов контролируемого обучения. Для контролируемого обучения требуются маркированные данные обучения, а также согласованные наборы наблюдаемых входных данных (X или особенности) и связанных выходных данных (Y или цель). Его можно разделить на две категории: регрессия и классификация. Если целевая переменная, которую нужно спрогнозировать, является непрерывной, то задача является одной из задач регрессии. Если целевая переменная является категориальной или порядковой (например, определение рейтинга фирмы), то это проблема классификации.

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

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

Мы можем написать уравнение для строки как:
Y = mX + b.
Y: зависимая переменная, также известная как переменная ответа или переменная результата
X: независимая переменная, также известная как независимая переменная или переменная-предиктор

Y - зависимая переменная, а X - независимая переменная. Мы наблюдаем значения X и Y, а затем используем их для оценки наклона m и точки пересечения b. При регрессии доходности IBM против доходности SPY (ETF, который предназначен для отслеживания индекса фондового рынка S&P 500), наклон m линии регрессии будет рыночной бета-версией для IBM, а точка пересечения b будет альфой.

Когда линейная регрессия рассматривается как параметрическая модель, это означает, что вся ее информация представлена ​​в ее параметрах. В случае этой линии вся информация модели может быть захвачена этими двумя параметрами, наклоном и пересечением. Все, что вам нужно для определения линии, - это m и b. Говоря языком машинного обучения, этот акт оценки параметров на основе некоторых наблюдаемых данных является процессом обучения модели.

Самый простой метод линейной регрессии - это метод наименьших квадратов (МНК). В регрессе мы пытаемся что-то минимизировать. В OLS мы рисуем линию прогноза, чтобы минимизировать сумму квадратов разницы между линией и данными. Таким образом, чем дальше точка находится от нашей линии прогноза, тем меньше модель расхождения в квадрате.

Важно количественно оценить, насколько хорошо вы подходите к регрессии. Одним из таких показателей является среднеквадратичная ошибка, которая представляет собой средний размер каждого квадрата на графике выше. Наиболее часто используемая мера согласия - это R в квадрате, который по сути является стандартизированной версией квадрата отклонения, который всегда будет числом от 0 до 1.

Еще одним ярким примером регресса в финансах является трехфакторная модель Фама-Френча. Вместо одной переменной X у нас есть три X или три независимые переменные. В случае с Fama-French они выражают доходность акций как зависимость от доходности рынка, превосходства акций с малой капитализацией над акциями с большой капитализацией и превосходства акций с высокой стоимостью над акциями с низкой стоимостью. . Используя наблюдаемую доходность факторов, которую определяют Фама и Френч, они оценивают эти три бета-чувствительности, чтобы объяснить доходность акций на рынке.

Примеры линейной регрессии

Одиночная переменная:

  • Регрессия рыночной модели: y = α + β X

Множественная переменная:

  • Фама-французский: y = α + βMKT * RMKT + βSMB * RSMB + βHML * RHML
  • Многофакторная модель: y = α + β1 * X1 + β2 * X2 + β3 * X3

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

Линейная регрессия отображает непрерывную переменную X в непрерывную переменную Y. Но когда Y, наша переменная ответа, является дискретной, что означает, что она может быть только 0, 1 или конечным числом категориальных значений, тогда мы можем выполнить логистическую регрессию.

Вместо того, чтобы моделировать переменную ответа напрямую, логистическая регрессия моделирует вероятность того, что Y принадлежит к определенной категории. Это означает, что вы пытаетесь максимизировать вероятность. В результате в алгоритмах классификации часто используется логистическая регрессия. Например, будет ли компания объявить дефолт по своему долгу?

Терминология

Терминология, используемая в алгоритмах машинного обучения, отличается от терминологии, используемой в регрессии. В управляемом машинном обучении зависимая переменная (Y) является целевой, а независимые переменные (X) называются функциями. Помеченные данные (набор обучающих данных) используются для обучения контролируемого алгоритма машинного обучения для вывода правила прогнозирования на основе шаблонов. Соответствие модели машинного обучения оценивается с использованием помеченных тестовых данных, в которых прогнозируемые цели (Y Predict) сравниваются с фактическими целями (Y Actual).

Ниже представлена ​​визуализация процесса обучения контролируемой модели обучения и перевод терминологии регрессии и машинного обучения.

Пример 1: Регрессия доходности IBM против SPY

В качестве нашего первого примера мы собираемся регрессировать ежедневную доходность IBM по сравнению с доходностью SPY. Мы можем использовать конечную точку Исторические дневные цены за 1 год из API цен на акции AlphaWave, чтобы получить годовые исторические цены. С помощью этих цен мы можем построить диаграмму рассеяния с доходностью IBM по оси Y и доходностью SPY по оси X, чтобы получить представление о том, как выглядят эти данные.

#fetch daily return data for IBM and SPY ETF
stock_tickers = ['IBM','SPY']

Чтобы вызвать этот API с помощью Python, вы можете выбрать один из поддерживаемых фрагментов кода Python, представленных в консоли API. Ниже приведен пример вызова API с помощью запросов Python. Вам нужно будет вставить свои собственные x-RapidAPI-host и x-RapidAPI-key в блок кода ниже.

#fetch 1 year daily return data
url = "https://stock-prices2.p.rapidapi.com/api/v1/resources/stock-prices/1y"
headers = {
    'x-rapidapi-host': "YOUR_X-RAPIDAPI-HOST_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS",
    'x-rapidapi-key': "YOUR_X-RAPIDAPI-KEY_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS"
    }
stock_frames = []
for ticker in stock_tickers:
    querystring = {"ticker":ticker}
    stock_daily_return_response = requests.request("GET", url, headers=headers, params=querystring)
# Create Stock Prices DataFrame
    stock_daily_return_df = pd.DataFrame.from_dict(stock_daily_return_response.json())
    stock_daily_return_df = stock_daily_return_df.transpose()
    stock_daily_return_df = stock_daily_return_df.rename(columns={'Close':ticker + ' Close'})
    stock_daily_return_df = stock_daily_return_df[{ticker + ' Close'}]
    stock_frames.append(stock_daily_return_df)
combined_stock_return_df = pd.concat(stock_frames, axis=1, join="inner")
pct_change_combined_stock_df = combined_stock_return_df.pct_change()
pct_change_combined_stock_df = pct_change_combined_stock_df.dropna()
pct_change_combined_stock_df

Постройте график ежедневной доходности IBM против ежедневной доходности SPY:

fig = px.scatter(
    pct_change_combined_stock_df, x=stock_tickers[1] + ' Close', y=stock_tickers[0] + ' Close',
    trendline='ols', trendline_color_override='red'
)
fig.update_layout(template='plotly_dark', xaxis_title=stock_tickers[1] + " Daily Return", yaxis_title=stock_tickers[0] + " Daily Return",yaxis_tickformat = '.2%',xaxis_tickformat = '.2%')
fig.show()

Теперь мы можем использовать библиотеку SciPy для OLS. Используя функцию stats.lineregress в SciPy, мы можем получить параметры наклона, точки пересечения, значения r, значения p и стандартной ошибки.

Линейная регрессия SciPy: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html

slope, intercept, r_value, p_value, std_err = stats.linregress(x=pct_change_combined_stock_df[stock_tickers[1]+' Close'],
                                                               y=pct_change_combined_stock_df[stock_tickers[0]+' Close'])

Коэффициенты регрессии OLS:

slope, intercept, r_value, p_value, std_err

R в квадрате:

r_value*r_value

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

#initialize figure
fig = go.Figure()
fig.add_trace(go.Scatter(x=pct_change_combined_stock_df[stock_tickers[1]+' Close'], \
                         y=pct_change_combined_stock_df[stock_tickers[0]+' Close'],
                    mode='markers', name='Daily return',))
#construct regression line from its coordinates from the scipy regression coefficients
line_x = [pct_change_combined_stock_df[stock_tickers[1]+' Close'].min(),  \
          pct_change_combined_stock_df[stock_tickers[1]+' Close'].max()]
line_y = [line_x[0]*slope+intercept,  line_x[1]*slope+intercept]
#add regression line to this plot
fig.add_trace(go.Scatter(x=line_x,y=line_y,name='OLS regression line', mode='lines'))
#show the figure
fig.update_layout(template='plotly_dark', xaxis_title=stock_tickers[1] + " Daily Return", yaxis_title=stock_tickers[0] + " Daily Return", yaxis_tickformat = '.2%',xaxis_tickformat = '.2%')
fig.show()

Однако Plotly упростил автоматическое построение наших данных и линии регрессии OLS одновременно с использованием приведенного ниже кода, поскольку построение линии регрессии часто используется.

Пример: Графическая регрессия машинного обучения в Python

fig = px.scatter(
    pct_change_combined_stock_df, x=stock_tickers[1] + ' Close', y=stock_tickers[0] + ' Close',
    trendline='ols', trendline_color_override='red'
)
fig.update_layout(template='plotly_dark', xaxis_title=stock_tickers[1] + " Daily Return", yaxis_title=stock_tickers[0] + " Daily Return",yaxis_tickformat = '.2%',xaxis_tickformat = '.2%')
fig.show()

Приведенный ниже пример регрессии IBM и SPY представляет собой регрессию с использованием математики и Numpy только вместо SciPy.

Ссылка на веб-сайт:

Https://towardsdatascience.com/linear-regression-from-scratch-cd0dee067f72



pct_change_combined_stock_df.tail()

X = pct_change_combined_stock_df[stock_tickers[1]+' Close'].values
y = pct_change_combined_stock_df[stock_tickers[0]+' Close'].values
#Calculate mean of dependent variable (IBM) returns and independendent variable (SPY) returns
x_mean = np.mean(X)
y_mean = np.mean(y)
#total N
n = len(X)
#calculate the coefficients by calculating the squared distance
numerator = 0
denominator = 0
for i in range(n):
    numerator += (X[i] - x_mean) * (y[i] - y_mean)
    denominator += (X[i] - x_mean) ** 2
    
slope = numerator / denominator
slope

intercept = y_mean - (slope * x_mean)
intercept

Рассчитайте R в квадрате:

sumofsquares = 0 
sumofresiduals = 0
#sum total squares over some of total residuals
for i in range(n):
    predicted_y = intercept + slope * X[i]
    sumofsquares += (y[i] - y_mean) ** 2
    sumofresiduals += (y[i] - predicted_y) ** 2
    
r2_score = 1 - (sumofresiduals/sumofsquares)
r2_score

Пример 2: возврат биткойнов против SPY

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

Сначала мы воспользуемся конечной точкой Исторические дневные цены за 2 года из API цен на акции AlphaWave, чтобы получить данные за двухлетние ежедневные исторические цены на биткойны и SPY. Затем мы конвертируем данные о ценах в дневную доходность.

#fetch daily return data for Bitcoin and SPY ETF
bitcoin_tickers = ['BTC-USD','SPY']

Чтобы вызвать этот API с помощью Python, вы можете выбрать один из поддерживаемых фрагментов кода Python, представленных в консоли API. Ниже приведен пример вызова API с помощью запросов Python. Вам нужно будет вставить свои собственные x-RapidAPI-host и x-RapidAPI-key в блок кода ниже.

#fetch 2 year daily return data
url = "https://stock-prices2.p.rapidapi.com/api/v1/resources/stock-prices/2y"
headers = {
    'x-rapidapi-host': "YOUR_X-RAPIDAPI-HOST_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS",
    'x-rapidapi-key': "YOUR_X-RAPIDAPI-KEY_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS"
    }
bitcoin_frames = []
for ticker in bitcoin_tickers:
    querystring = {"ticker":ticker}
    bitcoin_daily_return_response = requests.request("GET", url, headers=headers, params=querystring)
# Create Stock Prices DataFrame
    bitcoin_daily_return_df = pd.DataFrame.from_dict(bitcoin_daily_return_response.json())
    bitcoin_daily_return_df = bitcoin_daily_return_df.transpose()
    bitcoin_daily_return_df = bitcoin_daily_return_df.rename(columns={'Close':ticker + ' Close'})
    bitcoin_daily_return_df = bitcoin_daily_return_df[{ticker + ' Close'}]
    bitcoin_frames.append(bitcoin_daily_return_df)
combined_bitcoin_price_df = pd.concat(bitcoin_frames, axis=1, join="inner")
pct_change_combined_bitcoin_df = combined_bitcoin_price_df.pct_change()
pct_change_combined_bitcoin_df = pct_change_combined_bitcoin_df.dropna()
pct_change_combined_bitcoin_df.index =  pd.to_datetime(pct_change_combined_bitcoin_df.index)
pct_change_combined_bitcoin_df

Поскольку в настоящее время у нас есть ежедневные доходы за два года для биткойнов и SPY, мы будем использовать приведенный ниже код, чтобы преобразовать эти данные в желаемые еженедельные доходы. Затем мы создаем диаграмму рассеяния с доходностью биткойнов по оси Y и доходностью SPY по оси X, чтобы получить представление о том, как выглядят эти данные.

#convert daily return data into weekly return data
combined_bitcoin_price_df = combined_bitcoin_price_df.dropna()
weekly_pct_change_combined_bitcoin_df = combined_bitcoin_price_df.pct_change(periods=5)
weekly_pct_change_combined_bitcoin_df = weekly_pct_change_combined_bitcoin_df.iloc[::5, :].dropna()
weekly_pct_change_combined_bitcoin_df

fig = px.scatter(
    weekly_pct_change_combined_bitcoin_df, x=bitcoin_tickers[1] + ' Close', y=bitcoin_tickers[0] + ' Close', opacity=0.65, 
    trendline='ols', trendline_color_override='red', title='2 year weekly BTC vs SPY' 
)
fig.update_layout(template='plotly_dark', xaxis_title=bitcoin_tickers[1] + " Weekly Return", yaxis_title=bitcoin_tickers[0] + " Weekly Return", yaxis_tickformat = '.1%',xaxis_tickformat = '.1%')
fig.show()

Регрессия Биткойна не подходит, что можно увидеть с R-квадрат примерно 0,10.

Мы можем попытаться улучшить модель, соответствующую данным Биткойна, но при этом рискуем переобучиться. Чтобы проверить, может ли быть достигнута лучшая подгонка модели, мы можем работать с Scikit-learn и использовать PolynomialFeatures.

Линейная регрессия Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html

Полиномиальные особенности Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html

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

Мы используем полиномиальную линейную регрессию со степенью 9, чтобы увидеть, сможем ли мы получить лучшее соответствие с данными Биткойна.

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LinearRegression
#Fetch weekly return data of BTC and SPY  (This is our training data set)
df_X = weekly_pct_change_combined_bitcoin_df[{bitcoin_tickers[1] + ' Close'}]
df_y = weekly_pct_change_combined_bitcoin_df[{bitcoin_tickers[0] + ' Close'}]
#Fit training data to a polynomial regression model using sklearn.preprocessing and sklearn.pipeline
degree=9
polyreg=make_pipeline(PolynomialFeatures(degree),LinearRegression())
polyreg.fit(df_X,df_y)
#Using the predicted model, get the projected values over the space of X
X_seq = np.linspace(df_X.min(),df_X.max(),300).reshape(-1,1)
pred_y = polyreg.predict(X_seq)
l_pred_y = list(pred_y.reshape(-1,len(pred_y))[0])
l_X_seq = list(X_seq.reshape(-1,len(X_seq))[0])
df_scat = pd.DataFrame(data={'x':l_X_seq,'y':l_pred_y})
#Plot the original observations (BTC weekly returns) alongside the predicted values from the (massively overfitted) model
fig = go.Figure()
fig.add_trace(go.Scatter(x=df_scat['x'], y=df_scat['y'],   #fitted model
                    mode='lines',
                    name='Predicted BTC return'))
fig.add_trace(go.Scatter(x=df_X.values[:,0],y=df_y.values[:,0], #observed values
                         mode='markers',
                         name='Observed BTC weekly return'))
fig.update_layout(template='plotly_dark', xaxis_title=bitcoin_tickers[1] + " Weekly Return", yaxis_title=bitcoin_tickers[0] + " Weekly Return", yaxis_tickformat = '%',xaxis_tickformat = '%')
fig.show()

polyreg.score(X=df_X.values[:,0].reshape(-1,1), y=df_y.values[:,0])

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

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

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

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

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

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

Пример 3: Форвардная годовая дивидендная доходность в сравнении с коэффициентом выплат

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

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

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

#stocks for dividend analysis
dividend_stock_tickers = ['MMM','KO','CL','DOV','EMR','GPC','JNJ','PG','SWK','HRL','BDX',
'ITW','LEG','PPG','TGT','GWW','ABBV','ABT','FRT','KMB','PEP',
'VFC','NUE','SPGI','ADM','ADP','ED','LOW','WBA','CLX','MCD',
'PNR','WMT','MDT','SHW','SYY','BEN','CINF','AFL','APD','XOM',
'AMCR','T','BF-B','CTAS','ECL','MKC','TROW','CAH','CVX','ATO',
'GD','WST','AOS','LIN','ROP','CAT','CB','PBCT','ALB','ESS',
'EXPD','O','IBM','NEE']

Чтобы вызвать этот API с помощью Python, вы можете выбрать один из поддерживаемых фрагментов кода Python, представленных в консоли API. Ниже приведен пример вызова API с помощью запросов Python. Вам нужно будет вставить свои собственные x-RapidAPI-host и x-RapidAPI-key в блок кода ниже.

url = "https://stock-analysis.p.rapidapi.com/api/v1/resources/key-stats"
headers = {
    'x-rapidapi-host': "YOUR_X-RAPIDAPI-HOST_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS",
    'x-rapidapi-key': "YOUR_X-RAPIDAPI-KEY_WILL_COPY_DIRECTLY_FROM_RAPIDAPI_PYTHON_CODE_SNIPPETS"
    }
dividend_stock_frames = []
for ticker in dividend_stock_tickers:
    querystring = {"ticker":ticker}
    dividend_stock_key_stats_response = requests.request("GET", url, headers=headers, params=querystring)
    time.sleep(2)
try:
        # Create Key Statistics DataFrame
        dividend_stock_key_stats_df = pd.DataFrame.from_dict(dividend_stock_key_stats_response.json())
        dividend_stock_key_stats_df = dividend_stock_key_stats_df.transpose()
        dividend_stock_key_stats_df = dividend_stock_key_stats_df.rename(columns={'Value':ticker})
        dividend_stock_frames.append(dividend_stock_key_stats_df)
    except:
        continue
dividend_stock_df = pd.concat(dividend_stock_frames, axis=1, join="inner")
dividend_stock_df

#convert the dataframe to include features we are interested in and prepare for analysis
dividend_stock_analysis_df = dividend_stock_df.transpose()
dividend_stock_analysis_df = dividend_stock_analysis_df.reset_index()
dividend_stock_analysis_df = dividend_stock_analysis_df.rename(columns={'index':'Symbol'})
dividend_stock_analysis_df = dividend_stock_analysis_df[['Symbol',
'Forward annual dividend yield ','Payout ratio ','Total debt/equity (mrq)','Operating margin (ttm)']]
dividend_stock_analysis_df = dividend_stock_analysis_df.replace(r'[%]+$', '', regex=True)
dividend_stock_analysis_df['Forward annual dividend yield '] = dividend_stock_analysis_df['Forward annual dividend yield '].astype(float)/100
dividend_stock_analysis_df['Operating margin (ttm)'] = dividend_stock_analysis_df['Operating margin (ttm)'].astype(float)/100
dividend_stock_analysis_df['Payout ratio '] = dividend_stock_analysis_df['Payout ratio '].astype(float)
dividend_stock_analysis_df

Вместо того, чтобы смотреть на все данные в целом, регрессия lowess - это скользящая регрессия, которая рассматривает локализованные подмножества данных и выполняет взвешенную регрессию по этим подмножествам. Затем он объединяет эти подмножества. Хотя это сложнее представить математически, в определенных ситуациях это может быть оправдано.

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

#lowess regression
fig = px.scatter(
    dividend_stock_analysis_df, x='Payout ratio ', y='Forward annual dividend yield ',
    trendline='lowess', trendline_color_override='red'
)
fig.update_layout(template='plotly_dark', xaxis_title="Payout Ratio", yaxis_title="Forward Annual Dividend Yield",yaxis_tickformat = '.2%',xaxis_tickformat = '.2f')
fig.show()

#ordinary least squares regression
fig = px.scatter(
    dividend_stock_analysis_df, x='Payout ratio ', y='Forward annual dividend yield ',
    trendline='ols', trendline_color_override='red'
)
fig.update_layout(template='plotly_dark', xaxis_title="Payout Ratio ", yaxis_title="Forward Annual Dividend Yield",yaxis_tickformat = '.2%',xaxis_tickformat = '.2f')
fig.show()

Подгоните модель OLS и распечатайте коэффициенты Slope и Intercept:

#Fit the OLS model using sklearn.linear_model.LinearRegression
X = dividend_stock_analysis_df['Payout ratio '].values.reshape(-1, 1)
y = dividend_stock_analysis_df['Forward annual dividend yield '].values
model = LinearRegression()
model.fit(X,y)
#Model Coefficients
print('Slope: {:.4f}'.format(model.coef_[0]))
print('Intercept: {:.4f}'.format(model.intercept_))

Используйте модель для прогнозирования годовой форвардной дивидендной доходности акции с гипотетическим коэффициентом выплаты 150:

model.predict([[150]])

Остатки - это разница между наблюдаемыми данными и данными, предсказанными нашей моделью. Обратите внимание на любые закономерности в остатках. Чтобы добиться хорошей регрессии, остатки должны быть распределены случайным образом, как случайный шум. Если есть предсказуемое смещение в остатках (например, если все точки слева последовательно ниже прогнозируемых уровней, таким образом, все имеют отрицательные остатки), это будет преобразовано в смещенную модель, как показано в этом примере.

#Compute residuals as observed Forward Annual Dividend Yields minus
#the Forward Annual Dividend Yields predicted by the model
residuals = y - model.predict(X)
#Construct regression line from the model
x_vals_line = [dividend_stock_analysis_df['Payout ratio '].min(),dividend_stock_analysis_df['Payout ratio '].max()]
y_vals_line = model.predict(np.array(x_vals_line).astype(float).reshape(-1,1)).tolist()
#Plot
fig = go.Figure()
fig.add_trace(go.Scatter(x=dividend_stock_analysis_df['Payout ratio '].tolist(),y=dividend_stock_analysis_df['Forward annual dividend yield '].tolist(),mode='markers',name='Forward annual dividend yield'))
fig.add_trace(go.Scatter(x=x_vals_line, y=y_vals_line, name='Regression line', mode='lines'))
fig.add_trace(go.Bar(x=dividend_stock_analysis_df['Payout ratio '].tolist(),y=residuals.tolist(),width=3, name='Residuals'))
fig.update_layout(template='plotly_dark', xaxis_title="Payout Ratio", yaxis_title="Forward Annual Dividend Yield", yaxis_tickformat = '',xaxis_tickformat = '')
fig.show()

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

Сначала мы разделяем данные на два раздела: данные обучения и данные тестирования.

i_max_of_train_data = math.ceil(len(dividend_stock_analysis_df.dropna())/2)
df_train_data = dividend_stock_analysis_df.dropna().iloc[0:i_max_of_train_data]
df_train_data.count()

df_test_data = dividend_stock_analysis_df.dropna().iloc[i_max_of_train_data:]
df_test_data.dropna().count()

Теперь мы подгоняем модель многомерной регрессии к набору обучающих данных.

df_train_data.head()

#Multivariate Regression on Z_Spread against duration, Amount Outstanding, and Debt to Common Equity Ratio
y = df_train_data['Forward annual dividend yield ']
x = df_train_data[['Payout ratio ','Total debt/equity (mrq)','Operating margin (ttm)']]
#Define multiple linear regression model (using sklearn library)
linear_regression = LinearRegression()
#Fit the multivariate linear regression model
linear_regression.fit(x,y)

Расчетные коэффициенты нашей модели:

linear_regression.coef_

R в квадрате соответствия данных обучения:

linear_regression.score(x,y)

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

linear_regression.predict([[150,500,0.25]])

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

df_sub_test = df_test_data[['Payout ratio ','Total debt/equity (mrq)',\
                            'Operating margin (ttm)','Forward annual dividend yield ']].astype(float).copy()
#put test data into correct configuration to feed into model
l_features=['Payout ratio ','Total debt/equity (mrq)','Operating margin (ttm)']
num_features =3
l_lists = list()
for i in range(len(df_sub_test)):
    l_i = list()
    for i_feat in range(num_features):
        l_i.append(df_sub_test.iloc[i].loc[l_features[i_feat]])
    l_lists.append(l_i)
#predict values on test data set
predicted_vals = linear_regression.predict(l_lists)
df_sub_test = df_sub_test.assign(predicted_div_yield=predicted_vals)
df_sub_test.tail()

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

fig = go.Figure()
#dividend_plot
df = df_sub_test.sort_values('Payout ratio ')
fig.add_trace(go.Scatter(x=df['Payout ratio '],y=df['Forward annual dividend yield '],mode='markers',name='Observed Div Yield'))
fig.add_trace(go.Scatter(x=df['Payout ratio '],y=df['predicted_div_yield'],mode='markers',name='Predicted Div Yield'))
fig.update_layout(template='plotly_dark', xaxis_title="Payout Ratio", yaxis_title="Forward Annual Dividend Yield", yaxis_tickformat = '',xaxis_tickformat = '')
fig.show()

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

#Reshape data to produce a faceted plot
df_melted = df_sub_test.melt(id_vars=['Forward annual dividend yield ','predicted_div_yield'])
# Show faceted figure, with a plot for each of our features
fig = px.scatter(data_frame=df_melted,x='value',y=['Forward annual dividend yield ','predicted_div_yield'], facet_col='variable', template='plotly_dark')
fig.update_xaxes(matches=None)
fig.show()

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

Вывод

Модель регрессии берет сопоставленные данные (X, Y) и использует их для оценки параметров, которые характеризуют взаимосвязь между Y и X. Затем оцененные параметры можно использовать для прогнозирования Y на новом, другом наборе X. Разница между прогнозируемым и фактическим Y используется для оценки того, насколько хорошо регрессионная модель прогнозирует вне выборки (т. Е. С использованием новых данных).

Мы рассмотрели линейную регрессию доходности IBM по сравнению с доходностью SPY, показав, как это сделать с помощью библиотек SciPy, Scikit-learn и NumPy. Затем мы проанализировали взаимосвязь между биткойнами и SPY и обсудили некоторые подводные камни и причины, по которым регрессия может работать не во всех случаях. В нашем третьем примере мы построили многовариантную регрессию для прогнозирования годовой форвардной дивидендной доходности акции с использованием ее коэффициента выплаты, отношения долга к обыкновенному капиталу и операционной маржи.

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

Дополнительные ресурсы

Библиотеки Python

Линейная регрессия SciPy: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html

Линейная регрессия Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html

Пакеты машинного обучения Scikit-learn: https://scikit-learn.org/stable/supervised_learning.html

Регрессия гребня в Scikit-learn (Регуляризация): https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html

Регрессия LASSO в Scikit-learn (Регуляризация): https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html

Регрессия ML в Plotly: https://plotly.com/python/ml-regression/

Данная презентация предназначена только для информационных целей и не является предложением о продаже, призывом к покупке или рекомендацией по какой-либо ценной бумаге; он также не является предложением предоставить инвестиционные консультации или другие услуги со стороны AlphaWave Data, Inc. («AlphaWave Data»). Ничто из содержащегося здесь не является инвестиционным советом или предлагает какое-либо мнение относительно пригодности какой-либо ценной бумаги, и любые высказанные здесь мнения не следует воспринимать как совет покупать, продавать или держать какую-либо ценную бумагу или как одобрение какой-либо ценной бумаги или компании. При подготовке информации, содержащейся в данном документе, AlphaWave Data, Inc. не принимала во внимание инвестиционные потребности, цели и финансовые обстоятельства какого-либо конкретного инвестора. Любые высказанные мнения и проиллюстрированные здесь данные были подготовлены на основе информации, которая считается надежной, доступной AlphaWave Data, Inc. на момент публикации. AlphaWave Data не дает никаких гарантий относительно их точности или полноты. Вся информация может быть изменена и может быстро стать ненадежной по разным причинам, включая изменения рыночных условий или экономических обстоятельств.