В этом посте мы продолжим изучение других способов использования методов фильтра Калмана, в основном в качестве альтернативы многомерному прогнозу. Другой вариант включает векторную авторегрессию (VAR). Этот пост не будет вдаваться в подробности о VAR, а скорее предоставит альтернативу моделированию многомерного вывода, когда известен процесс перехода. Важно знать, что при использовании фильтра Калмана известна как взаимосвязь между ненаблюдаемой переменной и наблюдаемым выходом (или есть разумное предположение), так и то, как ненаблюдаемая переменная переходит к следующему периоду таймера (предполагается). Кроме того, все модели, сделанные до сих пор, имеют линейное предположение, и процесс перехода, и процесс наблюдения являются линейными.
Введение
Для тех, кто не знаком с моделями векторной авторегрессии, вы можете найти подробную информацию на вики. В python пакет statsmodel имеет встроенные функции для VAR, подробное использование можно найти в документации.
Короче говоря, VAR используется, если мы считаем, что наблюдаемые переменные взаимодействуют друг с другом. В этой статье предлагается PC-VAR, который применялся для моделирования многих экономических рядов. Быстрый пример — процентные ставки. Процентные ставки сильно коррелированы, и существует множество рядов (от однодневных до 30-летних ставок), но их можно легко свести к трем измерениям с помощью анализа основных компонентов (PCA). Первые 3 компонента процентной ставки хорошо определены как уровень, наклон и кривизна, что объясняет более 95% дисперсии процентной ставки. Затем мы применили бы VAR к этим основным компонентам, одновременно находя коэффициенты.
Что касается PC-VAR, существует преобразование, позволяющее превратить исходные процентные ставки в основные компоненты, применить VAR к основным компонентам для прогнозирования, а затем преобразовать основные компоненты обратно в процентные ставки. Учтите, что на практике модели сложно предсказать уровень (на долю которого приходится более 50 % дисперсии процентной ставки).
Многомерный фильтр Калмана
В этом посте мы будем анализировать временной ряд SP500 вместе с двухлетней процентной ставкой.
Матрица перехода разработана таким образом, что
Вот код: Обратите внимание, что казначейская ставка взята из Министерства финансов США.
n_train = int(len(data) * 0.9) n_test = len(data) - n_train result_set = {} graph_text = "" filter_input = np.concatenate([sp_return.T, interest_rate], axis=1) kf = KalmanFilter(transition_matrices=[1], observation_matrices=[1], transition_covariance=np.array([[1]]), observation_covariance=1, n_dim_obs=1) kf_mean, filtered_std = kf.filter(filter_input[:n_train,0]) kf_pred = np.array([1]) * np.power(np.array([1]), np.arange(n_test-1)) * kf_mean[-1] result_set = {'kf-1 state': np.append(kf_mean[5:], kf_pred.reshape(-1,1))} graph_text = "kf-1 rmse: " + "{:.4f}".format(rmse(filter_input[n_train:,0],kf_pred)) n_season = 5 F = np.zeros((n_season + 1, n_season + 1)) F[0,0] = 1 F[1, 1:-1] = [-1.0] * (n_season - 1) F[2:,1:-1] = np.eye(n_season - 1) H = np.array([1, 1, 0, 0, 0, 0]) P_init = np.eye(n_season + 1) * 0 P_init[:2,:2] = np.eye(1) * Q kf = KalmanFilter(transition_matrices=F, observation_matrices=H, transition_covariance=P_init, observation_covariance=1, n_dim_obs=1) kf_1, filtered_std = kf.filter(filter_input[:n_train,0]) filtered_obs = kf_1.dot(H) filtered_pred = forecast_kf(n_test-1, kf_1[-1], F, H.reshape(1,-1)) graph_text += "\nkf_5 rmse: " + "{:.4f}".format(rmse(filter_input[n_train:,0],filtered_pred)) result_set['kf_5_2'] = np.append(filtered_obs[5:], filtered_pred.reshape(-1,1)) n_int=2 F = np.zeros((n_season + 1 + n_int, n_season + 1 + n_int)) F[0,0] = 1 F[0,-2:] = [-1, 1] F[1, 1:n_season] = [-1.0] * (n_season - 1) F[2:n_season+1,1:n_season] = np.eye(n_season - 1) F[-2,-2] = 1 F[-1,-2] = 1 H = np.array([[1, 1, 0, 0, 0, 0, 0, 0],[0,0,0,0,0,0,1,0]]) P_init = np.eye(n_season + 1 + n_int) * 0 P_init[:2,:2] = np.eye(2) * Q P_init[-2:,-2:] = np.eye(2) * Q R = np.eye(2) * R X_0 = np.zeros(n_season + 1 + n_int) kf = KalmanFilter(transition_matrices=F, observation_matrices=H, transition_covariance=P_init, observation_covariance=R, initial_state_mean=X_0, initial_state_covariance=P_init, n_dim_state=8 ) mean_, std_ = kf.filter(filter_input[:n_train,:]) filtered_pred = forecast_kf(n_test-1, mean_[-1], F, H) fitted_value = np.dot(mean_,H.T) result_set['SPY Kalman with Treasury'] = np.append(fitted_value.T[0,5:], filtered_pred[0,:]) graph_text += "\nSPY Kalman with Treasury rmse: " + "{:.4f}".format(rmse(filter_input[n_train:,0], filtered_pred[0,:])) ## VAR model = VAR(filter_input[:n_train,:]) results = model.fit(1) filtered_pred = results.forecast(filter_input[n_train-1:n_train,:], n_test-1) result_set['SPY VAR(1)'] = np.append(results.fittedvalues[4:,0], filtered_pred[:,0]) graph_text += "\nSPY VAR(1) rmse: " + "{:.4f}".format(rmse(filter_input[n_train:,0], filtered_pred[:,0])) results = model.fit(5) filtered_pred = results.forecast(filter_input[n_train - 5:n_train, :], n_test - 1) result_set['SPY VAR(5)'] = np.append(results.fittedvalues[:, 0], filtered_pred[:, 0]) graph_text += "\nSPY VAR(5) rmse: " + "{:.4f}".format(rmse(filter_input[n_train:, 0], filtered_pred[:, 0]))
Результат выглядит следующим образом. Обратите внимание, что на графике ниже он рассматривает только прогноз доходности SP500, игнорируя результат, чтобы прогноз процентной ставки соответствовал другим сообщениям. Сила модели в том, что она предсказывает оба ряда.
увеличение в течение зеленого периода тестирования
Существует небольшая разница между фильтром Калмана с циклическим термином из последнего поста (названным kf_5 здесь и kf_5_2 ранее, в основном второй горб менее выражен при включении казначейской ставки).
Заключение
Присмотревшись внимательнее, мы заметили, что хотя и наблюдается небольшое снижение RMSE с включением казначейства, точность направления несколько падает. Мы могли бы улучшить набор моделей, вдохновившись моделью PC-VAR, включив дополнительные ряды процентных ставок (сначала применив PCA для уменьшения размерности) и/или мы могли бы включить другую доходность капитала (DJ) или ряды, такие как индекс волатильности.
Что следует учитывать
До сих пор мы сделали несколько сильных предположений (линейность) и не использовали неизвестный параметр в модели перехода и наблюдения. Во многих случаях использования это не так. В будущих сообщениях мы рассмотрим, как работать с нелинейной моделью перехода и как оценивать параметры.
Пожалуйста, следите и подпишитесь, если вас интересуют будущие публикации на эту тему.