3Dサーフェスで見える世界

3次元空間で違う景色を見る?  

前回までの分析の基本は、1単位時間当たりの価格の動きの特性の把握であった。ここでは1単位時間だけではなく、複数の累積時間当たりの価格の動きの特性を調べてみました。

ヒストグラムの利用  

ヒストグラムは頻度図ともいわれ、例えばx軸に変化率、収益率を取り、y軸にその頻度を取った図である。変化率の分布は、一般に中央が1つ飛び出た単峰の釣り鐘型の形状をしている。

価格の変化率は1日間隔の変化率Pt/Pt-1-1を中心に分析してきたが、本章では変化率Pt/Pt-j-1のjの値をいろいろと変化させてその特徴を見てみよう。 最初にj = 1の場合とj = 250の場合について調べてみました。

1日間隔の変化率  

日経平均株価の1日間隔の変化率Pt/Pt-1-1を1949年から直近までの16676個のデータを用いてヒストグラムを描いてみよう

In [2]:
%matplotlib inline
import pandas as pd
import pandas_datareader.data as web
import numpy as np
import matplotlib.pyplot as plt
n225 = web.DataReader("NIKKEI225", 'fred',"1949/5/16").dropna()
rn225=n225.pct_change().dropna()
plt.figure(figsize=(10,6))
ax=plt.subplot(1,1,1)
rn225.hist(bins=100,color='lightgray',ax=ax)
plt.xlabel('$P_{t}/P_{t-1}-1$')
plt.ylabel('frequency')
Out[2]:
<matplotlib.text.Text at 0x7fac44c47908>

プログラムコードの解説

rn225.hist(bins=100,color='skyblue',ax=ax)

bins=100はx軸の箱の数を100個に指定している

alphaは色の透明度の指定をしている。小さい数値は透明度が高い。

plt.xlabel('$P_{t}/P_{t-1}-1$')

x軸のラベルの設定

plt.ylabel('frequency')

y軸のラベルの設定

さらにこの変化率の分布に日経平均株価の変化率の平均と分散を用いて描いた正規分布を重ね合わせてみよう

In [3]:
from scipy.stats import norm
fig=plt.figure(figsize=(10,6))
ax=plt.subplot(1,1,1)
x=np.linspace(float(rn225.min()),float(rn225.max()),100)
pdf=norm.pdf(x,rn225.mean(),rn225.std())
rn225.hist(bins=100,color='lightgray',normed=True,ax=ax)
plt.plot(x,pdf)
plt.xlabel('$P_{t}/P_{t-1}-1$')
plt.ylabel('probability density function')
Out[3]:
<matplotlib.text.Text at 0x7fac2924b470>
In [4]:
print("mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(rn225.mean(),rn225.std(),rn225.skew(),rn225.kurt()))
mean 0.00036 std 0.01233 skew -0.13705 kurt 9.56483

図から分かるように実際の変化率は正規分布に比べて中心付近の尖りが強く、中間部分が薄く、すそ野の部分が厚い分布です。

分布の形状を表現する尺度として歪度と尖度を見てみよう。

歪度(わいど)は分布のひずみを表す尺度で、歪度がゼロであれば左右対称の分布である。

正の歪度とは分布の山が左側によっていて右側にゆっくりと裾野が伸びていくような感じである。

逆に負の歪度とは分布の山が右側によっていて、左側のすそ野がゆっくりと伸びていく感じである。

金融関連の価格の時系列は正の歪度をもつことが多い。尖度は分布のすそ野の厚さ、または中心の山のとがり具合を表している。

正規分布の尖度は3である。ここでFisherの定義では3であるが、Peasonの定義では0であることに注意。

本資料の場合はFisherの定義を用いている。尖度は大きければすそ野が広くなる。

歪度は‐0.12、尖度は9.5である。分布に歪はほどんどなく、すそ野が厚い分布です。

プログラムコードの解説

from scipy.stats import norm

scipy.statsからnormをインポート

linspace(max,min,n)

max,minで変数の上限と下限を与え、それをn等分した変数を返す関数である。

ここでは日経株価平均の変化率の最大値と最小値の間を

100個に区切ってそれをxに代入している。

norm.pdf(x,mean,std)

平均(mean)、標準偏差(std)で与えられた正規分布の変数xの確率分布を与える。

ここでは日経平均株価の変化率の平均と分散からxの値の確率分布を出力している。

hist(bins=100,alpha=0.2,normed=1)

normed=1とすることで頻度ではなく確率密度関数を表示している。最大値は100である。

plt.plot(x,pdf)

変数xをx軸に、その確率分布はy軸としてグラフを描いている。

250日間隔の変化率のヒストグラム

次に当日と前日の終値から計算した1日間隔の変化率から当日の終値と250日前の終値から計算した250日間隔の変化率$P_{t}/P_{t-250}-1$に変更してみよう。pct_change(250)とすることで250日間隔の変化率を算出できる。

このように同じ時系列から異なる期間の変化率を算出しその分布を求めて特徴をとらえることができる。

In [5]:
fig=plt.figure(figsize=(10,6))
ax=plt.subplot(1,1,1)
r250n225=n225.pct_change(250).dropna()
x=np.linspace(float(r250n225.min()),float(r250n225.max()),100)
pdf=norm.pdf(x,r250n225.mean(),r250n225.std())
r250n225.hist(bins=100,color='lightgray',normed=True,ax=ax)
plt.plot(x,pdf)
plt.xlabel('$P_{t}/P_{t-250}-1$')
plt.ylabel('probability density function')
Out[5]:
<matplotlib.text.Text at 0x7fac28d0ada0>

分布はほぼ正規分布に近いように見える。歪度と尖度で確かめてみました。

In [6]:
print("mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(r250n225.mean(),r250n225.std(),r250n225.skew(),r250n225.kurt()))
mean 0.10583 std 0.25636 skew 0.79390 kurt 1.79940

歪度(skew)が0.80、尖度(kurt)が1.79である。分布の歪はほぼゼロである。尖度が1日間隔の変化率と比べると正規分布に近づいてきました。

バブル崩壊前と後の変化率のヒストグラムを比較  

実際にバブル崩壊前と後で本当に経済の背後にある構造が変化しているのであれば、どこかに明確な変化が見て取れるはずである。それを探し当ててみよう。

次のグラフは1日間隔の変化率のバブル崩壊前と後の比較である。すそ野の広がりに違いが見られるが、大まかな釣り鐘型はキープされています。

In [9]:
plt.figure(figsize=(9,4))
ax=plt.subplot(1,2,1)
before=rn225.loc[:'1989/12/31']
before.hist(ax=ax,bins=100,color='blue',normed=True)
plt.title('before bubble crashed')
plt.xlabel('$P_{t}/P_{t-1}-1$')
plt.ylabel('probability density function')
ax2=plt.subplot(1,2,2)
after=rn225.ix['1989/12/31':]
after.hist(ax=ax2,bins=100,color='blue',normed=True)
plt.title('after bubble crashed')
plt.xlabel('$P_{t}/P_{t-1}-1$')
plt.ylabel('probability density function')
Out[9]:
<matplotlib.text.Text at 0x7fac2813e080>

次に基本的な記述統計を計算して確かめてみました。

In [10]:
print("before crashed: mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(before.mean(),before.std(),before.skew(),before.kurt()))
print("after crashed: mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(after.mean(),after.std(),after.skew(),after.kurt()))
before crashed: mean 0.00058 std 0.00987 skew -0.44466 kurt 15.46825
after crashed: mean 0.00002 std 0.01530 skew 0.03837 kurt 5.48206
平均 標準偏差 歪度 尖度
バブ ル崩壊前 0.058% 0.99% -0.44 15.47
バブル崩壊後 -0.001% 1.54% 0.04 5.35

平均値は当然バブル崩壊前がプラスでその後がマイナスである。標準偏差はバブル崩壊後は前の1.5倍ぐらいに膨らんでいる。

ボラティリティが上がっている。次に歪度であるがバブル崩壊前は負の歪度であり、尖度が非常に高い、尖度が極端に高くなっているのはブラックマンデーの影響があるかもしれない。

バブル崩壊後では割と正規分布に近いので驚く。歪度はほぼゼロですね。

次に250日間隔の変化率の性質を見てみよう。まず、歪度(skew)、尖度(kurt)を算出しました。

In [11]:
before250=r250n225.loc[:'1989/12/31']
print("before crashed: mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(before250.mean(),before250.std(),before250.skew(),before250.kurt()))
after250=r250n225.loc['1989/12/31':]
print("after crashed: mean %2.5f std %2.5f skew %2.5f kurt %2.5f"\
%(after250.mean(),after250.std(),after250.skew(),after250.kurt()))
before crashed: mean 0.17481 std 0.24833 skew 1.12898 kurt 2.74224
after crashed: mean 0.00462 std 0.23334 skew 0.47220 kurt -0.14199
平均 標準偏差 歪度 尖度
バブ ル崩壊前 17.48% 24.83% 1.13 2.74
バブル崩壊後 0.13% 23.52% 0.5 -0.13

次に250日間隔の変化率の性質を見てみよう。まず、歪度(skew)、尖度(kurt)を算出した。

どちらの期間の分布も正の歪度をもっているが、バブル崩壊前の歪度の方が大きい。

これは正のフィードバックが反映されている可能性がある。バブル崩壊後は歪度はゼロに近い。

また、尖度に関してはバブル崩壊前がプラス2.74であるのに対して、バブル崩壊後は若干のマイナスである。

バブル崩壊前は正規分布に近い。

次のグラフは250日間隔の変化率のバブル崩壊前と後のヒストグラムです。

In [12]:
plt.figure(figsize=(9,4))
ax3=plt.subplot(1,2,1)
before250.hist(ax=ax3,bins=100,color='blue',normed=True)
plt.title('before bubble crashed')
plt.xlabel('$P_{t}/P_{t-250}-1$')
plt.ylabel('probability density function')
ax4=plt.subplot(1,2,2)
after250.hist(ax=ax4,bins=100,color='blue',normed=True)
plt.title('after bubble crashed')
plt.xlabel('$P_{t}/P_{t-250}-1$')
plt.ylabel('probability density function')
Out[12]:
<matplotlib.text.Text at 0x7fac27cedef0>

左がバブル崩壊前、右がバブル崩壊後である。明らかな違いがある。バブル崩壊前では0.3近辺にこぶがあるように見えます。

それを除くと1つの分であるようにも見える。また、中心部分が非常に大きく伸びている。バブル崩壊後ではピークが複数あるようにも見える。

また、すそ野の広がりはバブル崩壊後のほうが狭いです。

歪度、尖度から受けるイメージとはまた違うところが面白いですね。  

2つのヒストグラムを重ね合わせてみるとさらに特徴を比べることができます。

In [13]:
plt.figure(figsize=(9,4.3))
ax5=plt.subplot(1,1,1)
before250.hist(ax=ax5,bins=100,normed=True,label='before',histtype="step")
after250.hist(ax=ax5,bins=100,normed=True,label='after',histtype="step",linestyle='--')
plt.xlabel('$P_{t}/P_{t-250}-1$')
plt.ylabel('probability density function')
plt.legend()
Out[13]:
<matplotlib.legend.Legend at 0x7fac279525c0>

最も大きな違いはデータの数であることから標本数を調整して直接分布の形状を比べられるようにしました。

Y軸は確率密度関数に成っている。250日間変化率の平均値がバブル崩壊後では大きく下がっていることがよくわかと思います。

また、すそ野はバブル崩壊前がプラス方向に大きく伸びているのに対して、バブル崩壊後はすそ野が伸びるというよりは幾つかの分布が重なっているイメージです。

これがバブル崩壊前の歪度が崩壊後に比べて正に大きい理由です。  

実際に内閣府発表の景気循環期は戦後15期あり、それぞれの景気循環期には景気拡張期と後退期に分かれていて、バブル崩壊前では拡張期と後退期で日経平均株価の価格の変化率はプラスであったが、

バブル崩壊後では拡張期にはプラスになり、後退期にはマイナスになっています。

1日間隔の変化率のヒストグラムからはボラティリティの違いが目に付くだけなのに対して、250日間隔の変化率からは歪度に見られるような特殊性が見て取れるので、統計的な分析だけでは不十分で、経済の状態を事細かに

調べる必要があることに気づかされました。

実際にはすべての景気循環期の拡張期と後退期についてのさまざまな分析をする必要があります。

3Dサーフェスの活用  

実際の価格の変化率は資産を保持している期間によって影響を受けます。

それは1日間隔の変化率と250日間隔の変化率の比較で理解できたと思ます。

しかし、これを実際の頭の中で連続した現象として理解しておくことは容易なことではないですね。

それを直感的に与えてくれるのが3Dサーフェスです。

In [14]:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
rmax=float(n225.pct_change(10).max())
rmin=float(n225.pct_change(10).min())
rmax=int(rmax*100)/100.0
rmin=int(rmin*100)/100.0
nbins=30
dx=(rmax-rmin)/nbins
rc=int(rmin/2+rmax/2)/100.0
bins = np.arange(rmin, rmax, dx)
xyz=[]
k=0
start=1
end=250
for i in range(start,end):
    tmp=n225.pct_change(i).dropna()
    nn225=np.array(tmp)
    n, bin, rectangles = ax.hist(nn225, bins,normed=True)
    xyz.append([])
    for j in range(len(bins)-1):
        xyz[k].append(n[j])
    k+=1
xyz=np.array(xyz)
fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
Y = np.arange(0, len(n), 1)
X = np.arange(0, k-2, 1)
X, Y = np.meshgrid(X, Y)
Z = xyz[X,Y]#np.sqrt(X**2 + Y**2)
surf = ax.plot_surface(X, Y, Z, rstride=2, cstride=10, cmap=cm.Accent,
                       linewidth=0.5, antialiased=True)
plt.yticks([0,int(nbins/2),int(nbins)],[rmin,rc,rmax])
ax.set_xlabel='days'
ax.set_ylabel='ror'

x軸は変化率の計算に用いる日数の間隔、y軸はそれぞれの日数間隔の変化率です。

z軸は正規化された頻度であるが、その正規化は変化率を計算する際の日数の間隔を固定した時の変化率の分布の正規化の結果であり、3Dサーフェスすべてに用いられている変化率の正規化ではないことに注意が必要です。

この3Dサーフェスが語ってくれるものは何であろうか? 

それは頻度です。

1日間隔の変化率と250日間隔の変化率を2Dヒストグラムで見て、どちらの分布もベル型であることは分かります。

従って、変化率が動かないところの頻度が一番高い。それが2Dヒストグラムから受ける印象です。

最初の1日目では価格は初期値からほどんど動かない。動いてもほんのわずかです。

2日目も同じです。

違いは初期値から比べれば価格の動きが1日分加算され、累積価格の動きの幅(変化率)が大きくなることです。

そして、その動きは数日間ではあまり気にならない。

ところがこの同じ状態が何度も何度も繰り返される内に、初期値からの価格の最大乖離幅はどんどん大きくなっていきます。

しかし、釣り鐘型の分布の形状は維持されている。それは250日経過した後でも同じです。

2Dヒストグラムで見ると、幅の広い釣鐘状です。

中心の頻度が高く両側のすそ野に行くほど頻度が低くなるので、価格は大きくは動かないと思いがちです。

しかし、この2Dヒストグラムの釣鐘状は1日目のヒストグラムに比べれば明らかな平面です。

それは何を意味するのだろうか? 

それはどの価格帯も同じ確率で起こりうる可能性があります。

その真実を3Dサーフェスは明らかにしてくれてます。  

3Dサーフェスから見て取れるように250日目のサーフェスはほぼ平らです。

どの価格にいる確率も1日目の価格変化の確率と比べればほぼ等しい。

このことを2Dヒストグラムから読み取ることは難しい。

2Dヒストグラムを比べる場合にはy軸の頻度のレベル、または確率密度関数の大きさに注意しなくてはならない。

3Dサーフェスではこれを気にする必要はないです。

便利な道具です。そして、この現象は、ランダムウォークの特徴でもあるし、AR(1)の回帰係数が1に近いときの特徴でもあります。

この特徴を決して忘れないでほしいですね。

プログラムコードの解説

from mpl_toolkits.mplot3d import Axes3D

3Dコレクションの追加

from matplotlib import cm

cm:カラーマップの提供

rmax=float(n225.pct_change(10).max())

変化率の最大値の設定

rmin=float(n225.pct_change(10).min())

変化率の最小値の設定

rmax=int(rmax*100)/100.0

ヒストグラムの瓶の数

rmin=int(rmin*100)/100.0

ヒストグラムの瓶の幅

nbins=30

dx=(rmax-rmin)/nbins

rc=int(rmin/2+rmax/2)/100.0

目盛りの中心鎖

bins = np.arange(rmin, rmax, dx)

ヒストグラムの瓶の設定

xyz=[]

頻度の格納容器

k=0

start=1

最小の日数間隔

end=250

最大の日数間隔

for i in range(start,end):

tmp=n225.pct_change(i).dropna()           変化率の設定

nn225=np.array(tmp)                          numpy配列への変更

n, bin, rectangles = ax.hist(nn225, bins,normed=True) nは瓶に対する頻度

xyz.append([])         新たな変化率の格納スペースの確保

for j in range(len(bins)-1):

   xyz[k].append(n[j])         頻度のコピー

k+=1

xyz=np.array(xyz)         頻度データベースをnumpy配列に変更

fig = plt.figure(figsize=(10,10))

ax = fig.gca(projection='3d')         現在の軸情報を取得

Y = np.arange(0, len(n), 1)         Y値の設定

X = np.arange(0, k-2, 1)         X値の設定

X, Y = np.meshgrid(X, Y)         X,Yのメッシュを作成

Z = xyz[X,Y]#np.sqrt(X2 + Y2)         頻度をxにコピー

surf = ax.plot_surface(X, Y, Z, rstride=2, cstride=10, cmap=cm.Accent,

linewidth=0.5, antialiased=True)         サーフェスのプロット

plt.yticks([0,int(nbins/2),int(nbins)],[rmin,rc,rmax])  Y軸の目盛りの設定

ax.set_xlabel='days'         x軸のタイトル

ax.set_ylabel='ror'         Y軸のタイトル

散布図の利用  

時系列の j 日間隔の変化率$P_{t}/P_{t-j}-1$を算出し、それをそのj日間前の変化率$P_{t-j}/P_{t-2j}-1$と比べてみました。  

ここでjは移動する日数である。これは変化率の自己相関を散布図で表現していることに近い。自己相関が無ければ散布図はきれいな円形になるはずです。

1日間隔の変化率  

日経平均株価の1日間隔の変化率の散布図を描いてみよう。x軸がt-1日の変化率、y軸がt日の変化率である。その右側の図は変化率の標本自己相関のコレログラムです。

In [16]:
import pandas as pd
import pandas_datareader.data as web
import numpy as np
import statsmodels.api as sm
fig = plt.figure(figsize=(10,4))
ax1=fig.add_subplot(1,2,1)
plt.scatter(rn225,rn225.shift(1),color='pink',alpha=0.05)
plt.xticks([-0.2,0,0.2])
plt.title('1 days')
plt.xlabel('$P_{t-1}/P_{t-2}-1$')
plt.ylabel('$P_{t}/P_{t-1}-1$')
plt.hlines([0],-0.1,0.1)
plt.vlines([0],-0.1,0.1)
ax2=fig.add_subplot(1,2,2)
fig=sm.graphics.tsa.plot_acf(rn225.squeeze(), lags=5,ax=ax2,color='gray')

左の図から見て取れるように、色の薄い部分と濃い部分に分かれる。それぞれのドットが2つの変化率の対を表している。

薄い部分はそのドットの頻度が低く、濃い部分は頻度が多い。

全体として完全な円形ではなく、若干のひずみが見られる。

中央部分の形状がひし形に近いが、これは変化率が大きな日の次の日には小さな変化率の日が生じやすい現象を示している。

同様に変化率の小さな日の次の日には大きな変化率の日が来ることを示している。

右側の標本自己相関のコレログラムからは自己相関は見られない。散布図はコレログラムでは見ることのできない世界を表現している

プログラムコードの解説

plt.scatter(rn225,rn225.shift(1),color='pink',alpha=0.05) 散布図の描画

plt.xticks([-0.2,0,0.2]) x軸の目盛りの設定

plt.title('1 days') タイトルの設定

plt.xlabel('$P_{t-1}/P_{t-2}-1$') x軸の名前の設定

plt.ylabel('$P_{t}/P_{t-1}-1$') y軸の名前の設定

plt.hlines([0],-0.1,0.1) 平行線の描画

plt.vlines([0],-0.1,0.1) 垂直線の描画

250日間隔の変化率の 散布図  

次に変化の期間を1日間隔から250日間隔にしてみよう。それは$P_{t}/P_{t-250}-1$です。また、比べる期間も250日間前の変化率$P_{t-250}/P_{t-500}-1$と比べることにしました。

これは変化率の算出に用いるデータに重複が無いようにするためである

In [17]:
fig=plt.figure(figsize=(10,4.2))
ax1=fig.add_subplot(1,2,1)
plt.scatter(r250n225,r250n225.shift(250),color='violet',alpha=0.05)
plt.title('250 days')
plt.xlabel('$P_{t-250}/P_{t-500}-1$')
plt.ylabel('$P_{t}/P_{t-250}-1$')
plt.hlines([0],-0.8,1.8)
plt.vlines([0],-0.8,2)
ax2=fig.add_subplot(1,2,2)
fig=sm.graphics.tsa.plot_acf(r250n225.squeeze(),lags=500,ax=ax2,color='gray')

左の図の結果は、大きな変化率の後には小さな変化率の期間が現れるという現象がさらに強調されている。

250日間で価格が動かなかったつぎの250日間では価格は‐50%から+150%程度まで動く可能性がある。

また、250日間で50%下落した後にはつぎの250日間で50%下落する可能性はないし、50%上昇する可能性もない。

同じ価格水準を維持するか若干下落する可能性が高い。

250日間で50%上昇するとつぎの250日間はどうなるだろうか? 

50%下落する可能性から100%上昇する可能性まで幅が広い。

つまり結論は厄介です! 

中心回帰の動きとモメンタムが生じる2つの動きが強調され、少なくとも関係が無いわけではないということだ。  

コレログラムの結果の解釈には注意が必要です。

コレログラムの場合には250日の変化率が1日毎に移動していくので250日までは重複したデータを用いて変化率を計算しています。

従ってちょうど250日近辺から自己相関がゼロである可能性が出てきています。

つまり、コレログラムによると、重複の無い250日間隔の変化率の間には自己相関はないです。

散布図はコレログラムでは見ることのできない相関を表している。shift(250)とすることで、250日分のデータの移動ができる

バブル崩壊前後の変化率の散布図比較  

バブル崩壊前と後で価格の動きのメカニズムに変化があるのであれば、散布図の分析でも違いが出るはず

In [18]:
plt.figure(figsize=(10,4))
plt.subplot(121)
plt.scatter(before,before.shift(1),color='pink',alpha=0.05)
plt.xticks([-0.2,0,0.2])
plt.yticks([-0.2,0,0.2])
plt.hlines([0],-0.1,0.1)
plt.vlines([0],-0.1,0.1)
plt.title('before')
plt.xlabel('$P_{t-1}/P_{t-2}-1$')
plt.ylabel('$P_{t}/P_{t-1}-1$')
plt.subplot(122)
plt.scatter(after,after.shift(1),color='seagreen',alpha=0.05)
plt.xticks([-0.2,0,0.2])
plt.yticks([-0.2,0,0.2])
plt.hlines([0],-0.1,0.1)
plt.vlines([0],-0.1,0.1)
plt.title('after')
plt.xlabel('$P_{t-1}/P_{t-2}-1$')
plt.ylabel('$P_{t}/P_{t-1}-1$')
Out[18]:
<matplotlib.text.Text at 0x7fac16e590f0>

左側がバブル崩壊前、右がバブル崩壊後である。バブル崩壊後の方が価格の変動性が大きくなっているので、その影響で円の大きさがバブル崩壊後の方が大きい。

また、分布の形状がバブル崩壊前の方がよりイビツに感じるのは正のフィードバックが掛かっているからではないか?  つぎに250日間隔の変化率を見てみよう

In [19]:
plt.figure(figsize=(10,6))
plt.subplot(121)
plt.scatter(before250,before250.shift(250),color='violet',alpha=0.05)
plt.xticks([-1,0,1])
plt.yticks([-1,0,2])
plt.hlines([0],-0.8,1.8)
plt.vlines([0],-0.8,2)
plt.title('bdfore')
plt.xlabel('$P_{t-250}/P_{t-500}-1$')
plt.ylabel('$P_{t}/P_{t-250}-1$')
plt.subplot(122)
plt.scatter(after250,after250.shift(250),color='seagreen',alpha=0.05)
plt.xticks([-1,0,1])
plt.yticks([-1,0,2])
plt.hlines([0],-0.8,1.8)
plt.vlines([0],-0.8,2)
plt.title('after')
plt.xlabel('$P_{t-250}/P_{t-500}-1$')
plt.ylabel('$P_{t}/P_{t-250}-1$')
Out[19]:
<matplotlib.text.Text at 0x7fac16ca16d8>

左がバブル崩壊前、右がバブル崩壊後である。250日間隔の分析ではバブル崩壊前と後では形状に大きな違いがある。

バブル前では基本的には上昇トレンドをいつでも継続できていた関係でプラス方向に分布が偏っている。

一方、バブル崩壊後では250日間隔の穏やかな価格の動きの後には下落トレンドか上昇トレンドが生じている可能性が高い。

つまり大きな振幅を価格の動きはもっている。

また、バブル崩壊後は割と小さい250日間隔の価格の変化に驚かされる。

1日間隔の変化率ではバブル崩壊後の方が価格の変化が大きかったのとは対照的です

変化率の最大値、最小値の期間構造  

例えば、250日間の投資では、1日、2日、3日、そして250日間隔というように日を追うごとに向き合っている変化率の特性は異なる。

3Dサーフェスで見たとおりである。従って長期投資の際にはこれらの一連の変化率の特性を把握しておく必要がある。

このように期間の異なる一連の変化率の特性をそれぞれの期間の変化率の最大値、平均値そして最小値により表現すると3Dサーフェスとはまた違ったイメ

ージが生まれます。それは境界がハッキリします。

平均値の動きに注目してほしい。また、4分位点を加えることもできます。

In [20]:
plt.figure(figsize=(8,4.8))
high=[0]*250
low=[0]*250
ave=[0]*250
for i in range(250):
    high[i]=float(n225.pct_change(i).max())
    ave[i]=float(n225.pct_change(i).mean())
    low[i]=float(n225.pct_change(i).min())
plt.plot(high,label="high", linestyle=':')
plt.plot(ave,label='ave')
plt.plot(low,label='low',linestyle='--')
plt.legend(loc='upper left')
plt.title('all data')
plt.xlabel('$t$')
plt.ylabel('$P_{t}/P_{1}-1$')
print(len(n225),len(after),len(before))
16975 6779 10195

全データ数は16870個である。このデータからは250日間の時系列を10195個作ることができる。

この時系列の1つ1つはそれぞれが異なる動きをしている。その動きの大まかな特徴をつかもうとするのが上述の図です。

すでに3Dサーフェスで見た通り、時間の経過と共に価格が動ける幅は広がっている。

大きく上昇することもできるし、大きく下落することもできる。その最大値(high)と最小値(low)を示しているのがこの図である。

従って250日間で価格が上昇する際に最大値のグラフのような動きをして、下落するときは最小値のような動きをするといっているわけではない。

これはあくまでも価格が過去に動いた幅を示している。  

理論的には価格がランダムウォークに従えば時間の経過に比例して価格の動ける幅は大きくなるはずです。

しかし、価格が下落する際にはそのような傾向が見られるが、上昇する際には広がる時期と停滞する時期に分かれているように見える。

この構造はバブル崩壊前の特性を強く反映していることが次のグラフからわかります。

プログラムコードの解説

high.plot(label="high") 凡例のlabelを用いてhighに設定

ave. plot (label='ave') 凡例のlabelを用いてaveに設定

low.plot(label='low') 凡例のlabelを用いてlowに設定

plt.legend(loc='upper left') 凡例の位置を左上に設定

In [23]:
plt.figure(figsize=(8,4.8))
high=[0]*250;low=[0]*250;ave=[0]*250
for i in range(250):
    high[i]=float(n225.loc[:'1989/12/31'].pct_change(i).max())
    ave[i]=float(n225.loc[:'1989/12/31'].pct_change(i).mean())
    low[i]=float(n225.loc[:'1989/12/31'].pct_change(i).min())
plt.plot(high,label="high",linestyle=':')
plt.plot(ave,label='ave')
plt.plot(low,label='low',linestyle='--')
plt.legend(loc='upper left')
plt.title('before bubble crash')
plt.xlabel('$t$')
plt.ylabel('$P_{t}/P_{1}-1$')
Out[23]:
<matplotlib.text.Text at 0x7fac168860b8>

最大値のグラフは、バブル崩壊前(before bubble crash)とすべての期間(all data)でほぼ同じである。なぜだろうか? 

それぞれの変化率の最大値がバブル崩壊前に生じているからである。ということは下落側に関してはバブル崩壊後の影響を色濃く受けているはずである。

また、250日間隔の変化率の平均値はプラスである

In [24]:
plt.figure(figsize=(8,4.2))
high=[0]*250;low=[0]*250;ave=[0]*250
for i in range(250):
    high[i]=float(n225.ix['1991/3/1':].pct_change(i).max())
    ave[i]=float(n225.ix['1991/3/1':].pct_change(i).mean())
    low[i]=float(n225.ix['1991/3/1':].pct_change(i).min())
plt.plot(high,label="high",linestyle=':')
plt.plot(ave,label='ave')
plt.plot(low,label='low',linestyle='--')
plt.legend(loc='center right')
plt.title('after bubble crash')
plt.xlabel('$t$')
plt.ylabel('$P_{t}/P_{1}-1$')
Out[24]:
<matplotlib.text.Text at 0x7fac16767320>

バブル崩壊後では最小値の下落は急激に起こり最大値の上昇はゆっくりと半年間かけて起こるが、それ以降は停滞してしまうことが分かる。

平均値はほぼ一貫してゼロである。また、最大値、最小値のグラフはギザギザしている。

一方、平均値のグラフはほぼ直線である。これは、最大値と最小値のグラフが経過日数毎の最も大きな変化率、または小さな変化率の1点を次々に結んだグラフであるのに対して、平均のグラフは多くのデータポイントの累積

の結果だからです。

全期間ではデータ数が16,777、バブル崩壊前では10,195、バブル崩壊後では、6,581です。  

今回は2Dヒストグラム、3Dサーフェス、散布図、チャートを用いて分析を行いました。

1日間隔の変化率からは見ることのできない現象が250日間隔の変化率から見ることができた。

また、変化の期間を連続して変えることで価格変化の期間構造のようなものが明らかになった。

時間トレンド、ランダムウォーク、AR(1)の特徴の違いは期間の長い方が直感的にはつかみ易い。

これは日々の価格の変化を単に見ているだけでは、その日々の変化が累積してできる結果を簡単には想像できないことを意味しています。

In [ ]: