%matplotlib inline
import numpy as np
import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plt
import requests
まずは実験に使うデータを取ってきます(´・ω・`)
url_executions = 'https://api.bitflyer.jp/v1/getexecutions'
before = None
data = []
for i in range(5):
url = url_executions + '?count=500' + ('&before={}'.format(before) if before else '')
data.extend(requests.get(url).json())
before = data[-1]['id']
tick = DataFrame(data).set_index('exec_date').sort_values('id')['price']
tick.index = pd.to_datetime(tick.index).tz_localize('UTC').tz_convert('Asia/Tokyo')
print('shape', tick.shape)
tick.plot(figsize=(15,3))
tickのSeriesからm1, m5, m15のDataFrameを作ります(´・ω・`)
def resample(tick, freq='T', **kwargs):
df = tick.resample(freq, **kwargs).ohlc()
df.columns = df.columns.map(str.capitalize)
df.index.name = 'Date'
return df
m1 = resample(tick, freq='T').dropna()
m5 = resample(tick, freq='5T').dropna()
m15 = resample(tick, freq='15T').dropna()
print('m1 len', m1.shape[0])
print('m5 len', m5.shape[0])
print('m15 len', m15.shape[0])
※ MT4でいうところのiBarShift()的な目的
idx = m15.index.searchsorted(m5.index, side='right')-1
print(idx)
これだとこんな感じ
df = pd.concat([m5, m15.iloc[idx].set_index(m5.index)], axis=1)
df.columns = 'o h l c m15_o m15_h m15_l m15_c'.split()
df.head(10)
バックテストなどを行うときは、長いほうの足は確定済みの値を参照したい、という状況もあると思います。
(実際そうしないと上位足の H L C はその時点から見ると未来の情報を含んでしまったデータになっているので)
なので、こんな感じ?
fixbarmode = True
idx = m15.index.searchsorted(m5.index, side='right')-(1+int(fixbarmode))
m5idxm15 = m15.iloc[idx].set_index(m5.index)
m5idxm15.iloc[idx<0] = np.nan
df = pd.concat([m5, m5idxm15], axis=1)
df.columns = 'o h l c m15_o m15_h m15_l m15_c'.split()
df.head(10)
初めの部分は、一つ前の確定済みのM15を取得することができないのでそのぶぶんはnanで埋めました
これは、
m15.index.searchsorted(m5.index, side='right')-(1+int(fixbarmode))
で負数になる部分があるので
このままiloc[idx]とすると、負数の部分は末尾からの価格データとなってしまうので
見やすいように idx<0 の箇所をnanにしました。
上記の例だと確認のためにpd.concatしたデータフレームを表示してみましたが、実際に使うときなんかだと、
算出したインデックスでその位置の値を参照する感じで使うことになりますかね(´・ω・`)
上位足の4本値の参照に限らず、上位足のインジケータの値や、経済指標のような
価格データと間隔の違うデータの対応する値を取得するときになんかも使えそうな関数ですな
M1の位置の確定済みのM5、M15の終値に対応できてるかチェック(´・ω・`)
def ibarshift(upper_tf_data, idx, fixbarmode=True):
idxmask = upper_tf_data.index.searchsorted(idx, side='right')-(1+int(fixbarmode))
data = upper_tf_data.iloc[idxmask].copy()
data.iloc[idxmask<0] = np.nan
return data
mtfdf = m1[['Close']].copy()
mtfdf['m5Close_Shift1'] = ibarshift(m5, m1.index, True)['Close'].values
mtfdf['m15Close_Shift1'] = ibarshift(m15, m1.index, True)['Close'].values
mtfdf.plot(figsize=(15,5))
for i in m15.index: plt.axvline(i, lw=0.5, c='k')
for i in m5.index: plt.axvline(i, lw=0.5, c='k', ls=':')
shiftさせなかったら以下のように上位足がM1の時刻より先の価格データを持つことになるのでやばい(´・ω・`)
※ インデックスが足の開始時刻というタイプのデータの場合です
mtfdf = m1[['Close']].copy()
mtfdf['m5Close_Shift0'] = ibarshift(m5, m1.index, False)['Close'].values
mtfdf['m15Close_Shift0'] = ibarshift(m15, m1.index, False)['Close'].values
mtfdf.plot(figsize=(15,5))
for i in m15.index: plt.axvline(i, lw=0.5, c='k')
for i in m5.index: plt.axvline(i, lw=0.5, c='k', ls=':')