イベントとボラティリティ (2017/08/04)

イベントとボラティリティとがどのような関係にあるかを調べてみる。

ただ、因果関係が逆にはなるものの、ボラティリティの拡大をイベントの発生と考えることにする。イベントの情報を集め、それを入力するのは面倒なので、ここは手を抜く。

イベントとしては経済指標を想定している。特定の時間に発表されることが多く、再現性が見込まれるからである。

そこで、0時0分から23時55分まで、5分ごとのボラティリティを調べた。調べた期間は2014年1月1日から2016年12月31日まで、通貨ペアはEURJPY、EURUSD、USDJPYである。

ボラティリイティはTrue Rangeで測り、正規化した。

ボラティリティが拡大する時間

それでは実際に検証してみる。

①この記事で使うライブラリをインポートする。

import forex_system as fs
import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime

②データの位置から時間を求める関数を定義する。

def find_time(position, timeframe):
    position = position * timeframe
    minute = position % 60
    hour = int(np.floor((position % 1440) / 60))
    return hour, minute

③検証して結果をグラフに表示する。

fs.remove_folder('temp')

timeframe = 5
n = 288
x = np.arange(n)
y = np.empty(n)
event = np.zeros([n, 3])
plt.figure(figsize=(6, 12))

start = datetime.strptime('2014.01.01 00:00', '%Y.%m.%d %H:%M')
end = datetime.strptime('2016.12.31 23:59', '%Y.%m.%d %H:%M')
close = fs.i_close('USDJPY', timeframe, 0)[start:end]
index = close.index
hour = fs.time_hour(index)
minute = fs.time_minute(index)

cnt = 0
for symbol in ['EURJPY', 'EURUSD', 'USDJPY']:
    plt.subplot(3, 1, cnt+1)
    atr = fs.i_atr(symbol, timeframe, 1, 0)[start:end]
    mean = atr.mean()
    std = atr.std()
    for i in range(n):
        temp = atr[(hour*60+minute)==i*timeframe].mean()
        y[i] = (temp-mean) / std
    if cnt == 0:
        event = y
    else:
        event = np.c_[event, y]
    plt.plot(x, y)
    plt.title('Event and Volatility (' + symbol + ')')
    plt.xlabel('Hour')
    plt.ylabel('Normalized True Range')
    plt.xlim(0, 288)
    plt.ylim(-1, 2)
    plt.xticks([0, 48, 96, 144, 192, 240, 288], [0, 4, 8, 12, 16, 20, 24])
    plt.axvline(x=48, color='black', linestyle=':')
    plt.axvline(x=96, color='black', linestyle=':')
    plt.axvline(x=144, color='black', linestyle=':')
    plt.axvline(x=192, color='black', linestyle=':')
    plt.axvline(x=240, color='black', linestyle=':')
    plt.axhline(y=0.0, color='black', linestyle=':')
    plt.tight_layout()
    cnt += 1
plt.savefig('event_and_volatility.png', dpi=150)
plt.show()

所々でボラティリティが拡大している時間のあることが分かる。グラフでは分かりにくいが14時30分が最も高くなる。これは米雇用統計の発表時間である。

ボラティリティ拡大の時間リスト

グラフでは分かりにくいので、ボラティリティが0.5以上となる時間をピックアップしてみる。

④各通貨ペアごとにボラティリティが拡大する時間リストを作る。

cnt = 0
for symbol in ['EURJPY', 'EURUSD', 'USDJPY']:
    print(symbol)
    position = np.where(event[:, cnt]>=0.5)[0]
    size = len(position)
    for i in range(size):
        time = find_time(position[i], timeframe)
        print(time)
    cnt += 1

fs.remove_folder('temp')

EURJPY
(9, 0)
(10, 0)
(11, 0)
(14, 30)
(14, 35)
(14, 40)
(14, 45)
(14, 50)
(14, 55)
(15, 0)
(15, 5)
(15, 10)
(15, 15)
(15, 20)
(15, 25)
(15, 30)
(15, 35)
(15, 40)
(15, 45)
(15, 50)
(15, 55)
(16, 0)
(16, 5)
(16, 10)
(16, 15)
(16, 20)
(16, 25)
(16, 30)
(16, 35)
(16, 40)
(16, 45)
(16, 50)
(16, 55)
(17, 0)
(17, 5)
(17, 10)
(17, 15)
(17, 55)
EURUSD
(9, 0)
(10, 0)
(11, 0)
(14, 30)
(14, 35)
(14, 40)
(14, 45)
(14, 50)
(14, 55)
(15, 0)
(15, 5)
(15, 10)
(15, 15)
(15, 20)
(15, 25)
(15, 30)
(15, 35)
(15, 40)
(15, 45)
(15, 50)
(15, 55)
(16, 0)
(16, 5)
(16, 10)
(16, 15)
(16, 20)
(16, 25)
(16, 30)
(16, 35)
(16, 40)
(16, 45)
(16, 50)
(16, 55)
(17, 0)
(17, 5)
(17, 10)
(17, 15)
(17, 55)
USDJPY
(2, 0)
(14, 30)
(15, 30)
(15, 35)
(16, 0)
(16, 55)
(17, 0)

いずれの通貨ペアでも14時30分が含まれていることが分かる。

(メモ)

経済指標の発表時間は様々である。時間が決まっていないもの、時間が決まっているもの、曜日と時間が決まっているもの、月の第何週と曜日と時間が決まってるもの、その他いろいろである。

となると、何曜日か、さらには第何週かで細分すべきかもしれない。例えば、米雇用統計のある第1金曜日以外ではボラティリティは14時30分に必ずしも拡大しないだろう。

ただ、トレードに資するかどうかという実用的な観点で見るならば、細分することでパフォーマンスが向上するということはなさそうである。もちろん、トレード戦略の性質にもよる。

特に第何週まで細分化すると、第5金曜日という3ヶ月に1回くらいしか出現しないデータが出てきて、データが少ない分、不安定化してボラティリティが大きく見えるという場合もある。

ただ、細分化しないとイベントが発生しない時間が含まれて、イベントが発生した時間のボラティリティが実際より小さく見えるという問題もある。

思うに、実用的な観点で見ると、細分化はせず、その代わりにイベントが発生したと判断する閾値を低目にするのがよさそうである。例えばボラティリティが0.5以上でイベント発生と判断する、というようにである。とはいえ、トレード戦略の性質にもよるので、一律に適用するのは問題があるだろう。