【日経225先物】売買システム開発に向けた統計的分析②

 

前回の記事では、日経225先物の2007年から直近のデータについて分析しました。
寄り付きと引けの価格差に着目し、日中、日中~夜間、夜間、夜間~日中の4パターンを検証しました。
結果は、夜間取引の寄付と引けで正のリターンが得られる可能性が見られました。また、2013年を境にリターンが反転している様子も見られました。
(使用データ、分析手順等については前回の記事をご参照ください。)

今回の記事では分析対象期間を2013年以降として、より明確な特徴が得られるか分析をしてみます。
分析手順については、前回とほぼ同様です。

今回も「Python3ではじめるシステムトレード ──環境構築と売買戦略」を参考にしております。

分析

まずは、2013年以降について以下の4パターンごとに1日ごとの価格差の累積和をグラフにします。

  • 日中取引の寄りから引けまでの価格の動き(daytime)
  • 日中立ち合いの引けから夜間立ち合いの寄りまでの価格の動き(d_to_n)
  • 夜間立ち合いの寄りから引けまでの価格の動き(night)
  • 夜間立ち合いの引けから日中立ち合いの寄りまでの価格の動き(n_to_d)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 日経225先物データを読み込む
N225_daytime = pd.read_excel('./data/N225f_2020.xlsx', sheet_name='日中日足', index_col='日付')
N225_night = pd.read_excel('./data/N225f_2020.xlsx', sheet_name='ナイト場足', index_col='日付')
# 結合し、2013年以降にする
df = pd.merge(N225_daytime, N225_night, on='日付', suffixes=['_D', '_N'])['2013/1/1':] # D:daytime, N:night
# 各パターンの価格差を求める
daytime = df['終値_D'] - df['始値_D'] 
d_to_n = df['始値_N'] - df['終値_D'] 
night = df['終値_N'] - df['始値_N']
n_to_d = df['始値_D'] - df['終値_N'].shift(1)
# 価格差の累積和をグラフにする
plt.figure(figsize=(8, 6))
daytime.cumsum().plot(label='daytime')
d_to_n.cumsum().plot(label='d_to_n')
night.cumsum().plot(label='night')
n_to_d.cumsum().plot(label='n_to_d')
plt.legend(loc='upper left')

グラフを見ると、赤線(日中~夜間)はリターンを積み上げており、橙色はその逆の動きをしている様子が見られます。
夜間の引け~日中の寄りでプラスとなったリターンは、日中の寄り付け~引けを通してマイナスになり、結果として日中のリターンでは織り込まれてゼロとなっているのかもしれないです。
これは、前回も触れたが、情報の伝達が関係しているのかもしれないです。

次にヒストグラムと記述統計を算出し、特徴を見てみる。

# ヒストグラムを書く
plt.figure(figsize=(12, 4))
ax1 = plt.subplot(1, 2, 1)
daytime.hist(label='daytime', histtype='step', linewidth=3, ax=ax1)
d_to_n.hist(label='d_to_n', color='lightgreen', rwidth=0.7, ax=ax1)
plt.legend()
ax2 = plt.subplot(1, 2, 2)
night.hist(label='night', histtype='step', linewidth=3, ax=ax2)
n_to_d.hist(label='n_to_d', color='lightgreen', rwidth=0.7, ax=ax2)
plt.legend()
# 記述統計を算出
stats_desc = pd.concat([daytime.describe(), d_to_n.describe(), night.describe(), n_to_d.describe()],axis=1)
stats_desc.columns = ['daytime', 'd_to_n', 'night', 'n_to_d'] 
pd.options.display.precision = 4 # dfの桁数を調整
stats_desc

上記のグラフでも触れたましたが、
夜間、日中~夜間では平均はプラス、夜間~日中ではマイナスとなりました。日中はゼロに近い値となっています。

ヒストグラムを見ると、日中ではマイナスにすそ野が伸びているのが目立ちます(歪度はマイナスになりそう)。
他のパターンのヒストグラムは、概ね左右対称となりました。

n_to_dに関しては若干プラスの要素が多いようです。
ボラティリティ(標準偏差)は、日中~夜間、夜間~日中では始値と終値に乖離が生じることがあることから高い値となっています。

次に、ADF検定(ランダムウォークの検証)、t検定(平均値の状態)、JB検定(残差の正規性)を行います。

結果は以下の通り。(左が有意水準10%、右が有意水準5%)

alpha = 0.1
patterns = {'daytime': daytime,
            'd_to_n' : d_to_n,
            'night'  : night,
            'n_to_d' : n_to_d}
results = []
for key in patterns.keys():
    target = patterns[key].dropna()
    # ADF検定
    adf_nc = sm.tsa.adfuller(target, regression='nc')[1] #p値:ドリフト項無し
    adf_c  = sm.tsa.adfuller(target, regression='c')[1] #p値:ドリフト項付き
    adf_ct = sm.tsa.adfuller(target, regression='ct')[1] #p値:ドリフト項+時間項付き
    # t検定
    t_value = target.mean() * np.sqrt(target.count()) / target.std()
    t0 = t.ppf(1-alpha, target.count()-1)
    if t_value > t0:
        t_result = 'μ>0'
    elif t_value < -t0:
        t_result = 'μ<0'
    else:
        t_result = 'μ=0'
    # JB検定
    JB = sms.jarque_bera(target) # JB, p値, 歪度, 尖度
    
    # 結果を保存
    results.append([adf_nc, adf_c, adf_ct, t_result, JB[1], JB[2], JB[3]])
# dfにまとめる
df_result = pd.DataFrame(results, index=patterns.keys())
df_result.columns = ['ADF nc', 'ADF c', 'ADF ct', 't', 'JB', '歪度', '尖度']
df_result.T
有意水準:10%
有意水準:5%

ADF検定、JB検定は前回と同様となりました。
つまり、非定常過程ではなく、残差は正規性を持たない可能性が高いです。

一方でt検定は前回と異ります。
前回は、有意水準10%においてどのパターンの平均\(\mu\)はゼロでしたが、今回は有意にプラスとなりました。しかし、5%水準では有意性は見られなかったです。

ここまでの結果から、取引戦略には、night(夜間寄り付け~夜間引け)かn_to_d(夜間引け~翌日寄り付け)の2つが候補に挙がります。

ここで歪度についてみると、n_to_dはnightより分布がマイナスに寄っていることがわかります。つまり、リターンがマイナスをとりやすい。

前回の記事では、全期間における分析で唯一、nightにだけプラスの優位性が見られました。

以上を踏まえて、取引戦略には、nightを採用したほうが安定的にリターンを得られる可能性があります。平均はn_to_dの方が高いがその分ボラティリティも高い(リスクが高い)です。

まとめ

前回と今回で2つの記事にわたり日経225先物の寄付~引けの特徴を見てきました。結果として、night(夜間取引の寄付~引け)で安定してリターンが得られる可能性が見られました。

今後はnightをベースとした取引戦略を考えてみると安定的なリターンを稼ぐモデルを構築できる可能性がありそうです。

コメント

タイトルとURLをコピーしました