[Puppeteer] <初めてのPuppeteer> pandasを使ってマルチタイムフレームのローソク足を作ってみる
ご無沙汰しております。
BTCが俄然元気になってきましたね。
先日まで動かしていたbot「ヘカトンケイル」は見事に焼かれました(泣)
めちゃくちゃ低原資でしたので、一気に弾切れして、放置を決め込んでいたら、あっさりゼロカットを喰らいました。
しかし、実戦投入型実証実験機としての役割は十分に果たしてくれて、貴重なデータも取れたので良しとしましょう。
次期実戦投入型bot「バーサーカー」にインジケータを2つほど組み込み、試運転をしています。
Puppeteerを作っておいて良かったと思っています。
機能追加がめちゃくちゃ楽ですから。
さて、今日のお題は「マルチタイムフレーム」です。
botでインジケータや各種指標を計算させるときに欠かせない「ローソク足」
bitmexが公開しているAPIで取得可能なローソク足のタイムフレームは、
1分、5分、1時間、1日
の4種類に限られます。
しかし、bitmexのサイトで確認できるローソク足のタイムフレームの種類は以下に示すようにかなり多いです。
BTCの取引のスイング、デイ、スキャの方々の要望に応えるためか、タイムフレームの数は豊富に用意されています。
botで上記のタイムフレームのデータを用意しようと思ったら、1分、5分、1時間、1日の4種類のローソク足からその他のタイムフレームを「自前で演算」して作成するしかありません。
そんな時に便利な関数がpandasには用意されています。
前回の記事でローソク足データを取得する方法については述べましたので、今回はその取得したローソク足データをベースにして、他の分足に変換してみましょう。
その時に使うpandasのメソッドは
・resample
・agg
の2つです。
resampleに渡す引数は結構数があるので、次のページで調べました。
それでは、前回のプログラムに関数を一つ追加して、1分足を3分足に変換してみましょう。
前回同様、puppetsフォルダの下のsampleプログラムに手を加えます。
今回はccxt版のデータのみ変換してみます。websocket版についてはほとんど変更無いのでご自身で試してみてください。
- puppets/
- sample/
- sample.py
- sample.json
sample.py
# -*- coding: utf-8 -*-
# ==========================================
# サンプル Puppet
# ==========================================
import datetime
import pandas as pd
from puppeteer import Puppeteer
# ==========================================
# Puppet(傀儡) クラス
# param:
# puppeteer: Puppeteerオブジェクト
# ==========================================
class Puppet(Puppeteer):
# ==========================================================
# 初期化
# param:
# puppeteer: Puppeteerオブジェクト
# ==========================================================
def __init__(self, Puppeteer):
self._exchange = Puppeteer._exchange # 取引所オブジェクト(ccxt.bitmex)
self._logger = Puppeteer._logger # logger
self._config = Puppeteer._config # 定義ファイル
# ==========================================================
# 売買実行
# param:
# ticker: Tick情報
# orderbook: 板情報
# position: ポジション情報
# balance: 資産情報
# candle: ローソク足
# ==========================================================
def run(self, ticker, orderbook, position, balance, candle):
# -----------------------------------------------
# Pandasのデータフレームに
# -----------------------------------------------
df = pd.DataFrame(candle,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
# -----------------------------------------------
# 日時データをDataFrameのインデックスにする
# -----------------------------------------------
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df = df.set_index('timestamp')
print(df)
print(self.change_candleDF(df, '3m'))
#print(df.tail(3)['volume'].sum())
# ==========================================================
# ローソク足の足幅変換
# params:
# ohlcv: DataFrame (pandas)
# resolution: 刻み幅(1m, 3m, 5m, 15m, 30m, 1h, 2h, 3h, 4h, 6h, 12h, 1d, 3d, 1w, 2w, 1M)
# ==========================================================
def change_candleDF(self, ohlcv, resolution='1m'):
# 参考にしたサイト https://docs.pyq.jp/python/pydata/pandas/resample.html
"""
-------+------+------
引数 単位 区切り
-------+------+------
AS 年 年初
A 年 年末
MS 月 月初
M 月 月末
W 週 日曜
D 日 0時
H 時 0分
T,min 分 0秒
S 秒
L,ms ミリ秒
U,us マイクロ秒
N,ns ナノ秒
"""
"""
-------+------+------
関数 説明
-------+------+------
min 最小
max 最大
sum 合計
mean 平均
first 最初の値
last 最後の値
interpolate 補間
"""
period = {
'1m' : '1T',
'3m' : '3T',
'5m' : '5T',
'15m' : '15T',
'30m' : '30T',
'1h' : '1H',
'2h' : '2H',
'3h' : '3H',
'4h' : '4H',
'6h' : '6H',
'12h' : '12H',
'1d' : '1D',
'3d' : '3D',
'1w' : '1W',
'2w' : '2W',
'1M' : '1M'
}
if resolution not in period.keys():
return None
# 他の分刻みに直す
df = ohlcv[['open', 'high', 'low', 'close', 'volume']].resample(period[resolution], label='left', closed='left').agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
})
# ohlcを再度ohlcに集計するにはaggメソッド
return df
sample.json
{
"//" : "===============================================",
"//" : " システムで利用",
"//" : "===============================================",
"//" : "取引所のapiKey, secretを設定します",
"APIKEY" : "YOUR_APIKEY",
"SECRET" : "YOUR_SECRET",
"//" : "bitmex取引所で対応する通貨ペア等を記述",
"SYMBOL" : "BTC/USD",
"INFO_SYMBOL" : "XBTUSD",
"COIN_BASE" : "BTC",
"COIN_QUOTE" : "USD",
"//" : "bitmex取引所の価格の最小幅(0.5ドル)",
"PRICE_UNIT" : 0.5,
"//" : "TestNetを使うか?(使う: true, 使わない: false)",
"USE_TESTNET" : true,
"//" : "ticker, orderbook, position, balance, candle のどれを利用するかを指定する。Falseを指定した場合はそのデータは取得しない",
"USE" : {
"TICKER" : true,
"ORDERBOOK" : true,
"POSITION" : true,
"BALANCE" : true,
"CANDLE" : true
},
"//" : "ローソク足の収集定義。",
"CANDLE" : {
"//" : "ローソク足の足幅を設定する。設定値= 1m, 5m, 1h, 1d",
"TIMEFRAME" : "1m",
"//" : "データ取得開始時刻(UNIXTIME:1ミリ秒)、使用しない場合 もしくは自動の場合は null(None) を指定",
"SINCE" : null,
"//" : "取得件数(未指定:100、MAX:500)",
"LIMIT" : null,
"//" : "True(New->Old)、False(Old->New) 未指定時はFlase",
"REVERSE" : false,
"//" : "True(最新の未確定足を含む)、False(含まない) 未指定はTrue",
"PARTIAL" : false
},
"//" : "板情報の収集定義。",
"ORDERBOOK" : {
"//" : "取得件数(未指定:25、MAX:取引所による?)",
"LIMIT" : null
},
"//" : "websocketを使用するかどうかを指定",
"USE_WEBSOCKET" : false,
"//" : "ログレベルを指定。('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG')",
"LOG_LEVEL" : "INFO",
"//" : "インターバル(botの実行周期)を秒で設定",
"INTERVAL" :60,
"//" : "discord通知用URL",
"DISCORD_WEBHOOK_URL" : "",
"//" : "資産状況通知をするか",
"USE_SEND_BALANCE" : false,
"//" : "===============================================",
"//" : " ユーザで自由に定義",
"//" : "===============================================",
"//" : "",
"XXXX" : null
}
上記のファイルを配置して、次のコマンドを実行しましょう。
(apikey, secretはご自身のものを設定してください)
python3 puppeteer.py puppets/sample/sample.py puppets/sample/sample.json
実行すると以下のように2つのohlcv(ローソク足)情報がコンソール上にプリントされます。
1分足情報
open high low close volume
timestamp
2019-06-23 09:40:00 10772.0 10772.0 10771.5 10771.5 686
2019-06-23 09:41:00 10771.5 10816.0 10771.5 10784.5 42509
2019-06-23 09:42:00 10784.5 10785.0 10784.5 10784.5 2610
2019-06-23 09:43:00 10784.5 10786.0 10784.5 10786.0 4372
2019-06-23 09:44:00 10786.0 10785.5 10785.5 10785.5 200
2019-06-23 09:45:00 10785.5 10800.0 10785.5 10785.5 8989
2019-06-23 09:46:00 10785.5 10787.0 10770.0 10770.0 22631
2019-06-23 09:47:00 10770.0 10780.0 10727.0 10757.0 41686
2019-06-23 09:48:00 10757.0 10759.0 10703.5 10703.5 32461
2019-06-23 09:49:00 10703.5 10785.0 10680.0 10738.0 80350
2019-06-23 09:50:00 10738.0 10734.5 10686.0 10719.0 12115
2019-06-23 09:51:00 10719.0 10718.5 10690.0 10691.0 11796
2019-06-23 09:52:00 10691.0 10715.5 10691.0 10700.5 22728
2019-06-23 09:53:00 10700.5 10700.0 10691.5 10700.0 20962
2019-06-23 09:54:00 10700.0 10700.0 10691.0 10697.5 10134
2019-06-23 09:55:00 10697.5 10727.0 10697.5 10718.5 55277
・・・(以下略)・・・
3分足情報
open high low close volume
timestamp
2019-06-23 09:39:00 10772.0 10816.0 10771.5 10784.5 43195
2019-06-23 09:42:00 10784.5 10786.0 10784.5 10785.5 7182
2019-06-23 09:45:00 10785.5 10800.0 10727.0 10757.0 73306
2019-06-23 09:48:00 10757.0 10785.0 10680.0 10719.0 124926
2019-06-23 09:51:00 10719.0 10718.5 10690.0 10700.0 55486
2019-06-23 09:54:00 10700.0 10727.0 10691.0 10718.5 67624
2019-06-23 09:57:00 10718.5 10718.0 10698.0 10698.0 18109
2019-06-23 10:00:00 10698.0 10700.0 10691.0 10700.0 43952
2019-06-23 10:03:00 10700.0 10700.0 10691.5 10696.5 12419
2019-06-23 10:06:00 10696.5 10697.0 10690.0 10690.0 20724
2019-06-23 10:09:00 10690.0 10700.0 10653.5 10653.5 132172
2019-06-23 10:12:00 10653.5 10677.0 10653.5 10669.0 37998
2019-06-23 10:15:00 10669.0 10682.0 10654.0 10676.0 41637
2019-06-23 10:18:00 10676.0 10700.0 10653.5 10670.0 114294
・・・(以下略)・・・
プログラム中でohlcv(ローソク足)データを変換しているコマンド部分は
df = ohlcv[['open', 'high', 'low', 'close', 'volume']].resample(period[resolution], label='left', closed='left').agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
})
です。
resampleメソッドで単純にデータを変換すると、open、high、low等のデータがそれぞれ open, high, lowなどに分割されてしまい、うまく行きません。
そのために「agg」を使って値をまとめてあげます。
このように、一度ローソク足データをpandasのデータフレームに格納してしまえば、他の時間足に変換することは容易です。
もっとも、1分足を1時間足に変換する場合は60個の1分足データが1個にまとめられてしまいますので、元データの数が相当多くないと変換後のデータが少しだけになってしまいます。
どれくらいの数のデータが欲しいかによって、変換元データを何分足にするかを決めないとなりません。
みなさんもマルチタイムフレームを使って複数のインジケータで分析してみてはいかがでしょうか。
Puppeteerは無料でご利用になれます。
楽しいbotライフを!
ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。