hatunina’s blog

メモと日記です

kaggleの「Bitcoin Historical Data」のカーネルを読むその1

カーネルを上から順番に読んだものをまとめていきます。
その1としましたが、続くかはわかりません。

概要

Bitcoin Historical Data | Kaggle
コンペとして開かれているわけでなく、学生さんがデータセットを公開していて、みんなテキトーに遊んでねって感じっぽいです。

公開されているデータは下記の通り。

bitflyerJPY_1-min_data_2017-07-04_to_2018-03-27.csv
bitstampUSD_1-min_data_2012-01-01_to_2018-03-27.csv
coinbaseUSD_1-min_data_2014-12-01_to_2018-03-27.csv
coincheckJPY_1-min_data_2014-10-31_to_2018-03-27.csv


それぞれ、タイムスタンプとHLOC、ボリュームが含まれています。

読んだやつ

これです。

Bitcoin Trading Strategy Simulation | Kaggle
bitstampUSDを使って「Turtle Trading」という手法を試しています。

前半はデータの穴埋めが中心です。
2012年と古めのデータなので取引がない日もあるのかな?
ボリュームは0にして、価格は前日の各データで穴埋めしたりしてます。

下記コードはリンク元から拝借

# First thing is to fix the data for bars/candles where there are no trades. 
# Volume/trades are a single event so fill na's with zeroes for relevant fields...
data['Volume_(BTC)'].fillna(value=0, inplace=True)
data['Volume_(Currency)'].fillna(value=0, inplace=True)
data['Weighted_Price'].fillna(value=0, inplace=True)

# next we need to fix the OHLC (open high low close) data which is a continuous timeseries so
# lets fill forwards those values...
data['Open'].fillna(method='ffill', inplace=True)
data['High'].fillna(method='ffill', inplace=True)
data['Low'].fillna(method='ffill', inplace=True)
data['Close'].fillna(method='ffill', inplace=True)


fillnamethod='ffillとすることで、一つ前のデータで埋めることができます。

で、手法自体は「Turtle Trading」とやらを使っています。
あんまりトレーディング手法は詳しくないのですが、いわゆるチャネルブレイクアウトなのかな?
詳しくはこちら

www.investopedia.com
trend is your friendとのことで、めっちゃ雑に言うとトレンドに従って売買するぜ!って手法っぽいです。
(ごめんなさい、あんまり調べてないです)

まあ、そんな感じで高値と安値が更新されたタイミングでポジションをとるらしいのですが、そこでrollingという関数を使っています。

signal_lookback = 60 * 24 * 60 # days * hours * minutes

# here's our signal columns
data['Buy'] = np.zeros(len(data))
data['Sell'] = np.zeros(len(data))

# this is our 'working out', you could collapse these into the .loc call later on and save memory 
# but I've left them in for debug purposes, makes it easier to see what is going on
data['RollingMax'] = data['Close'].shift(1).rolling(signal_lookback, min_periods=signal_lookback).max()
data['RollingMin'] = data['Close'].shift(1).rolling(signal_lookback, min_periods=signal_lookback).min()
data.loc[data['RollingMax'] < data['Close'], 'Buy'] = 1
data.loc[data['RollingMin'] > data['Close'], 'Sell'] = -1


rolling移動平均を計算することができるとのこと。
ここで第1引数に渡しているsignal_lookback60 * 24 * 60なので60日分の1分足を指します。
第2引数は計算開始時点です。
なので、60日分の1分足の高値を計算しそれを更新したら買う、安値を更新したら売る、といったアルゴリズムです。

カーネルの最後ではテスト結果が描画されており、とりあえずはうまくいっていそう。。。

まあ、rollingなんてあるんだ〜勉強になりました〜って感じです。