파이썬으로 폭락 직후 상하이 종합주가지수 예측

소개.



신형 코로나바이러스의 영향으로 상하이 종합주가지수가 7% 할인된 대형 세일.

여기까지 무자비하게 내려가면 정부가 아마 돈을 넣어 오기 때문에, 이 후 단기적으로 다소 돌아갈 것 같은 생각이 드네요. (제외하면… 유감이었습니다)
바겐세일을 사랑하지 않는 내 아내(중국인)가 전력으로 구입을 추천하고 있기 때문에, 조금 quantitative에 분석해 봅시다.
알고 싶은 것은, 「대폭락한 다음날~다음 달의 반동으로 돈을 벌지 여부」.

정량 모델 프레임 워크



그렇다면 먼저 일상적인 리턴을 zscore화하고 -2σ를 초과하는 날만 꺼냅니다.
t\in\{t~|~{\rm zscore}(r_t)\leq -2\},~{\rm zscore}(r_t)=\frac{r_t - \mu}{\sigma}

그리고 그 날 다음날, 1주 후, 2주 후, 3주 후, 1개월 후의 리턴과의 관계를 구합니다.
E[r_{t+d}]=f(r_t), ~d\in\{1, 5, 10, 15, 20\}

모델 ① 자기 상관



우선 자기 상관을 살펴 보겠습니다. 상하이 종합은 중국답게 특이치 뿐이며, 통상의 pearson의 적율 상관(특이치에 영향을 받기 쉽다)은 특이한 생각이 들기 때문에, 여기는 spearman의 순위상관(rank화되기 때문에 이상치에 영향을 받는다) 어려움)으로 요청했습니다.
\rho=1-\frac{6\sum D^2}{N^3-N}

여기서 D는 대응하는 X와 Y의 순위 차이, N은 값 쌍의 수입니다 (자세한 내용은 Wiki라고 함).

순위상관계를 Excel에서 구하는 것은 나름대로 뼈가 부러지지만, pandas이면 이하의 코드로 일발입니다. 훌륭합니다!
rho_spearman = df.corr(method='spearman')

실제로 pandas에서 상관을 계산한 결과는 그림과 같이 전체적으로 부의 자기 상관이 확인됩니다(=평균이 0이라고 하면 반발하는 경향).


모델 ② 회귀 분석



다음으로 회귀분석을 사용하여 오늘의 폭락(따라서 -7.72%)부터 다음날부터 다음달까지의 리턴을 예측해 보겠습니다. 예를 들어, 이상치에 의한 회귀 계수의 영향을 완화하기 위해, 우선 리턴(사전 & 사후)을 ±2σ의 범위에서 winsorize합니다.
{\rm winsorize}(r_{t+d})={\rm min}({\rm max}(r_{t+d},~\mu-2\sigma),~\mu+2\sigma)

그 후, x를 폭락일 당일 리턴, y를 그 다음 d일 후 리턴으로 하는 선형 회귀를 실시해, 오늘의 리턴 x=-7.72%에 대한 예측치 y를 각 d에 대해 구했습니다.
{\rm winsorize}(r_{t+d})=\beta_d*{\rm winsorize}(r_{t})+\alpha_d+\epsilon_{t+d}

이상의 회귀 분석을 scikit-learn.linear_models의 LinearRegression에서 실시한 결과, 예측된 d일 후 리턴(일일의 일률)은 이쪽.

이 그림에서 알 수 있듯이 반발하더라도 대체로 1주~2주가 수명인 것 같습니다.
여기서의 주의점으로서, 1개월 후에도 자기 상관은 음이었음에도 불구하고 예측치가 마이너스인 것에 모순을 느끼는 분도 있을지도 모릅니다만, 원래 조건에 해당하는 기간( = 당일 리턴이 -2σ 이하의 폭락일) 1개월 후 리턴의 평균이 크게 마이너스였기 때문에 이러한 현상이 일어납니다. 상관은 평균을 0으로 생각하는 반면, 회귀 분석이면 절편항에 의해 평균도 고려됩니다.
리턴의 평균이 0이 아닌 경우는 종종 발생하므로 상관만으로 이해하려고 하는 것은 위험합니다.

또한 다음 그림은 x: 당일 리턴(폭락일만), y: 다음 n일 누적 리턴(n=1, 5, 10, 15, 20)의 산포도입니다.
seaborn의 sns.regplot()를 사용하면 산점도 위에 회귀 직선과 그 예측 범위도 포함하여 단번에 플롯 해 버린다! 편리!


파이썬 코드



※상하이 종합주가지수의 히스토리컬 데이터는 yahoo finance로부터 다운로드했습니다.
ㅡㅡㅜㅜㅜㅜㅜㅜㅜ 야호오. 코 m/쿠오테/000001. s / 히 s와 ry? p = 000001. s
이것을 사용해, 이런 느낌↓에 데이터를 성형해, pandas에 읽었습니다.

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

df = pd.read_clipboard()
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index('Date').astype('float')

df_clip = df.apply(lambda x: np.clip(x, x.mean() - x.std() * 2, x.mean() + x.std() * 2), axis='index')

span_list = df_clip.columns[1:-1]
pred = pd.Series(index=span_list)
X_pred = -0.0772
for span in span_list:
    X = df_clip['ret'].values.reshape(-1, 1)
    Y = df_clip[span].values.reshape(-1, 1)
    reg.fit(X, Y)
    pred[span] = reg.predict(np.array(X_pred).reshape(-1, 1)).flatten() * int(span[:-1])
    plt.clf()
    sns.regplot(x=df_clip['ret'], y=df_clip[span])
    plt.title('x: ret(t), y:average_ret(t+1:t+' + span[:-1] + ')')
    plt.savefig('span + '.png')

plt.clf()
fig, [ax1, ax2] = plt.subplots(ncols=1, nrows=2)
df_clip.corr(method='spearman').iloc[0, 1:-1].plot(kind='bar', ax=ax1)
ax1.set_title('conditional autocorrelation when ret < -2σ')
pred.plot(kind='bar', ax=ax2)
ax2.set_title('conditional predicted return when ret < -2σ')
plt.tight_layout()
plt.savefig('pred_ret.png')

좋은 웹페이지 즐겨찾기