【Python】scipy.statsを使って株や為替の統計データを取得・分析する

pandas-datareaderを使って株価・為替データを取得、それを使って統計データの分析をする。

今回は、S&P 500 ETF、Google(Alphabet)、USDJPY、EURUSDのデータを使うことにする。

ライブラリのインポートとデータ取得

利用するライブラリのインポート、pandas-datareaderを使ってyahoo financeからターゲット・データを取得。

import pandas_datareader.data as web
import scipy.stats as scs
import cufflinks
import numpy as np

datas = ['SPY','GOOGL','JPY=X','EURUSD=X']
df = web.DataReader(datas,'yahoo',start='2015-01-01').Close
dfr = df/df.shift(1).dropna()-1

scipy.stats.describe()を使って統計データを表示

まずは、scipy.stats.describe()を利用した場合の出力例を示す。

CMDで実行した場合の結果です。

>>> scs.describe(dfr['SPY'])
DescribeResult(nobs=1149, minmax=(-0.10942373540494488, 0.09060326182884682), mean=0.00043909840426899823, variance=0.0001458162528770003, skewness=-0.9454697330108027, kurtosis=17.632082978141707)

少し見づらいですが、結果は、データ数、最小値と最大値のタプル、平均、分散、歪度、尖度の入ったタプルを返します。

forループで、各リターンの統計データを表示する。

for i in dfr.columns:
    statisticalData = scs.describe(dfr[i])
    print('\n',i)
    print('最小   ', statisticalData[1][0])
    print('最大   ', statisticalData[1][1])
    print('平均   ', statisticalData[2])
    print('標準偏差 ', np.sqrt(statisticalData[3]))
    print('歪度   ', statisticalData[4])
    print('尖度   ', statisticalData[5])

リターン分布の分析

skewtestとkutosistestを使うことで、指定データの歪度と尖度が正規分布の形状と異なるか否かをテストすることができる。
また、それらを組み合わせて評価するnormaltestもあわせて使ってみる。

テストは、指定データと正規分布の歪度や尖度が同じあるという帰無仮説によって行われる。

結果は、テストのZ-valueとp値とが入ったタプルで返される。

こちらもループ処理で各リターンに対してテストを行う。

for i in dfr.columns:
    print('\n',i)
    print('歪度テスト ', scs.skewtest(dfr[i])[1].round(5))
    print('尖度テスト ', scs.kurtosistest(dfr[i])[1].round(5))
    print('総合テスト ', scs.normaltest(dfr[i])[1].round(5))

上記結果でp値が0.05以上の場合には、リターンが概ね正規分布と同じ歪度、尖度であることを意味する。normaltest()に関しても見方は同じ。

サンプルとして実行結果を載せておく。

SPY
歪度テスト 0.0
尖度テスト 0.0
総合テスト 0.0

GOOGL
歪度テスト 0.00032
尖度テスト 0.0
総合テスト 0.0

JPY=X
歪度テスト 0.93865
尖度テスト 0.0
総合テスト 0.0

EURUSD=X
歪度テスト 0.47151
尖度テスト 0.0
総合テスト 0.0

今回利用したデータのリターンはいずれも正規分布しているとはいえない。

scipy.norm.cdf()でショートフォールリスクを計算する

scipy.norm.ppf(信頼区間)で指定した信頼区間のz値を返す。
scipy.norm.cdf(z値)でそのz値を信頼区間に変換。

これらを使って、年間リターンのショートフォールリスクを計算してみたいと思う。

ショートフォールリスクとは、目標リターンに達しないリスクのことです。

下記関数は、retsにリターンデータ、thresholdにターゲット・リターンを渡せば、ショートフォールリスク(ショートフォール確率)を返す。

dfy = df.resample('m',label='right').last().pct_change(12).dropna()

def SFrisk(rets, threshold):
    mean = rets.mean()
    std = rets.std()
    return scs.norm.cdf((threshold-mean)/std)

print(SFrisk(dfy['SPY'], 0.1))
# => 0.48084343981519884

参考にSPYの年間リターンが10%を下回る確率を計算してみると、48%程との結果になった。

z-table(標準正規分布表)を使って手計算する場合には、
目標収益 – 期待リターン / 標準偏差 = z値
1 – z値の信頼水準 = ショートフォールリスク

のように計算するが、scs.norm.cdf()は、渡したz値の下側の区間になる確率を返してくる。
(つまりは、上記計算の1-信頼水準を行った後の最終結果を返してくれる)

自分のポートフォリオの銘柄がわかれば、これでショートフォールリスクの計算が可能になります。

フリーリスクレートやインフレ率、元本割れリスクなどを計算してみると面白いかもしれない。