SVARモデルでBitcoinの時系列分析
Bitcoinを他の通貨の動きで予測したい
PythonでSVARモデルでの分析をしている記事をあまり見ないのと、Bitcoinと他の通貨の動きの相関に興味を持ったのでやってみました。
もちろんですが、Statsmodelsを使います。(ただし、StatsmodelsではSVARモデルのクラスはメソッドも少なく使いづらいです。真面目に分析するならRを使ったほうが無難だと思います…)
SVARモデルとはStructural vector autoregressionモデルの略で、日本語だと構造ベクトル自己回帰モデルになります。複数の関係し合った時系列データを分析するときに使います。普通は"VARモデル"という、頭に"S"がついてないモデルを使うんですが、VARモデルだと同時点間の関係を分析できないので、SVARを使います。今回は日次データを使うので、同日中の動きの関連性もみたいのでSVARモデルを使ってみました。グレンジャー因果性とかその辺は今回はパス。
データとしてはQuandlからダウンロードした為替の日次データ1年分を使います。ビットコイン円、米ドル円、ユーロ円。ついでに金価格も入れてみます。
今回のコードはJupyterからそのままMarkdownで書き出しているのでレイアウト崩れているかもしれません。ご容赦ください。
# 準備
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
import statsmodels.api as sm
import quandl # データサイトQuandlからダウンロードするためのAPIラッパー。 pip install quandlでインストールできます。
import datetime
# 分析期間
start = datetime.datetime(2015, 8, 1)
end = datetime.datetime(2016, 7, 31)
# それぞれの通貨レートの終値とその変化率をpandas.DataFrameにする
btcjpy = quandl.get("BCHARTS/COINCHECKJPY", start_date=start, end_date=end).assign(
BTCJPY_roc = lambda df: df["Close"].pct_change()
)[["Close", "BTCJPY_roc"]].rename(columns={
"Close" : "BTCJPY"
})
usdjpy = quandl.get("BOE/XUDLJYD", start_date=start, end_date=end).assign(
USDJPY_roc = lambda df: df["Value"].pct_change()
).rename(columns={
"Value" : "USDJPY"
})
eurjpy = quandl.get("BOE/XUDLBK63", start_date=start, end_date=end).assign(
EURJPY_roc = lambda df: df["Value"].pct_change()
).rename(columns={
"Value" : "EURJPY"
})
gold = quandl.get("WGC/GOLD_DAILY_JPY", start_date=start, end_date=end).assign(
gold_roc = lambda df: df["Value"].pct_change()
).rename(columns={
"Value" : "Gold"
})
# 変化率の列だけを連結して一つにまとめる
df = pd.concat([btcjpy["BTCJPY_roc"], usdjpy["USDJPY_roc"], eurjpy["EURJPY_roc"], gold["gold_roc"]],
axis=1).rename(columns={
"BTCJPY_roc":"BTC/JPY",
"USDJPY_roc": "USD/JPY",
"EURJPY_roc":"EUR/JPY",
"gold_roc":"Gold"
}).dropna() # NaNは落としておく
# 記述統計量見てみる
df.describe()
BTC/JPY
USD/JPY
EUR/JPY
Gold
count
251.000000
251.000000
251.000000
251.000000
mean
0.002296
-0.000729
-0.000653
0.000060
std
0.032348
0.007603
0.007698
0.009094
min
-0.195545
-0.034245
-0.054097
-0.029910
25%
-0.008390
-0.004295
-0.004483
-0.005644
50%
0.002404
-0.000280
-0.000384
-0.000142
75%
0.012727
0.003507
0.002984
0.005614
max
0.125846
0.020587
0.024218
0.024528
# プロットしてみる。ビットコインの変化率の激しさがよく分かる
df.plot().legend(bbox_to_anchor=(1.2, 0.5))
<matplotlib.legend.Legend at 0x115f9dfd0>
ここまではデータ整理です。ここから下がSVARモデルの話になります。
詳しいことは省きますが、ラグ\(p\)のSVARモデルは
\[
Ay_t = A_1 y_{t-1} + \ldots + A_p y_{t-p} + B\varepsilon_t
\]
と表されます。\(A, A_1, \dots, A_p, B \)は\(n \times n\)行列、\(y_t, y_{t-1}, \dots, y_{t-p}, \varepsilon_t\)は\(n\)次元ベクトルです。
Statsmodelsではこの式中の\(n \times n\)で表される係数を求めます。
ただし、\(A\)と\(B\)については行列中のどの要素を求めたいのか指定してあげないといけません。今回は時系列データが4つなので\(n=4\)です。
%%capture
# ↑Jupyterで出力させないときのおまじない
A_mat = np.array([[1,"E","E","E"], [0,1,0,0],[0,0,1,0],[0,0,0,1]]) # 上式のAの中で求めたい要素を"E"とする
svar_model = sm.tsa.SVAR(df, svar_type="A", A=A_mat) # Aのみを推計したいときはsvar_type="A". AもBも求めたいときはsvar_type="AB".
svar_result =svar_model.fit(maxlags=2) # ラグは2にしておきます
svar_result.A # 求められたA
array([[ 1. , -0.59146287, 0.6685895 , -0.62556778],
[ 0. , 1. , 0. , 0. ],
[ 0. , 0. , 1. , 0. ],
[ 0. , 0. , 0. , 1. ]])
svar_result.summary() # 回帰結果
Summary of Regression Results
==================================
Model: SVAR
Method: OLS
Date: Mon, 08, Aug, 2016
Time: 00:40:07
--------------------------------------------------------------------
No. of Equations: 4.00000 BIC: -35.7620
Nobs: 249.000 HQIC: -36.0659
Log likelihood: 3138.42 FPE: 1.76987e-16
AIC: -36.2706 Det(Omega_mle): 1.53554e-16
--------------------------------------------------------------------
Results for equation BTC/JPY
=============================================================================
coefficient std. error t-stat prob
-----------------------------------------------------------------------------
const 0.002005 0.002085 0.961 0.337
L1.BTC/JPY 0.148403 0.065807 2.255 0.025
L1.USD/JPY -0.310475 0.362978 -0.855 0.393
L1.EUR/JPY 0.301240 0.364265 0.827 0.409
L1.Gold -0.346476 0.241212 -1.436 0.152
L2.BTC/JPY -0.040609 0.065891 -0.616 0.538
L2.USD/JPY -0.074339 0.364439 -0.204 0.839
L2.EUR/JPY -0.059074 0.364986 -0.162 0.872
L2.Gold -0.247649 0.241379 -1.026 0.306
=============================================================================
Results for equation USD/JPY
=============================================================================
coefficient std. error t-stat prob
-----------------------------------------------------------------------------
const -0.000886 0.000492 -1.802 0.073
L1.BTC/JPY -0.003380 0.015512 -0.218 0.828
L1.USD/JPY -0.018224 0.085562 -0.213 0.832
L1.EUR/JPY -0.016705 0.085865 -0.195 0.846
L1.Gold 0.063087 0.056859 1.110 0.268
L2.BTC/JPY 0.022905 0.015532 1.475 0.142
L2.USD/JPY 0.022443 0.085906 0.261 0.794
L2.EUR/JPY -0.095209 0.086035 -1.107 0.270
L2.Gold -0.031452 0.056898 -0.553 0.581
=============================================================================
Results for equation EUR/JPY
=============================================================================
coefficient std. error t-stat prob
-----------------------------------------------------------------------------
const -0.000691 0.000497 -1.391 0.165
L1.BTC/JPY -0.009591 0.015674 -0.612 0.541
L1.USD/JPY 0.050503 0.086455 0.584 0.560
L1.EUR/JPY -0.015944 0.086761 -0.184 0.854
L1.Gold 0.043325 0.057452 0.754 0.452
L2.BTC/JPY -0.001656 0.015694 -0.106 0.916
L2.USD/JPY 0.032432 0.086803 0.374 0.709
L2.EUR/JPY -0.172938 0.086933 -1.989 0.048
L2.Gold -0.034411 0.057492 -0.599 0.550
=============================================================================
Results for equation Gold
=============================================================================
coefficient std. error t-stat prob
-----------------------------------------------------------------------------
const 0.000229 0.000582 0.393 0.695
L1.BTC/JPY -0.019201 0.018362 -1.046 0.297
L1.USD/JPY 0.051701 0.101280 0.510 0.610
L1.EUR/JPY 0.027936 0.101639 0.275 0.784
L1.Gold -0.046397 0.067304 -0.689 0.491
L2.BTC/JPY -0.025403 0.018385 -1.382 0.168
L2.USD/JPY 0.210005 0.101688 2.065 0.040
L2.EUR/JPY -0.222826 0.101840 -2.188 0.030
L2.Gold -0.079226 0.067351 -1.176 0.241
=============================================================================
Correlation matrix of residuals
BTC/JPY USD/JPY EUR/JPY Gold
BTC/JPY 1.000000 0.103922 -0.024485 0.134834
USD/JPY 0.103922 1.000000 0.647955 0.172215
EUR/JPY -0.024485 0.647955 1.000000 0.273616
Gold 0.134834 0.172215 0.273616 1.000000
svar_result.irf(10).plot() # 10期までのインパルス応答関数を出力
考察
うーん、結果を見る限りあまり統計的には有意な関係はなさそうですね…笑
インパルス応答関数の形だけを見る限り、ビットコインはドル円とは正の関係があり、ユーロ円とは負の関係がありそうで面白いです。
ここからどのような結論を出すのかがきっとデータ分析する人の腕の見せ所なのではないかと思います。
以上、PythonでのSVARモデルの使い方でした。