[Puppeteer] <初めてのPuppeteer> ドテン君を作ろう♪(2回目)
雛形の定義
Puppeteerの導入が終わったら、ドテン君の心臓部である
指定時間足を指定個数取得する部分
を作ってみましょう。
Puppeteerの導入については1回目をご覧になり進めてください。
でも、安心してください
とっても簡単
です(笑)
Puppeteer上で動作するPuppetの雛形を定義します。
まずは、Puppeteerの「Puppets」フォルダの下に以下のように
doten
フォルダを作り、そのdotenフォルダの下に
doten.py
doten.json
ファイルを作ります。
作成し終わった後は次のようになっているはずです。
それでは、bitmexのtestnetのAPIKey、Secretを入手して、早速ローソク足を取得してみましょう。
プログラムファイル(doten.py, doten.json)
doten.pyとdoten.jsonを以下のように記述してください。
doten.py
# -*- coding: utf-8 -*-
# ==========================================
# ドテン君 サンプル
# ==========================================
import time
from datetime import datetime as dt, timezone as tz, timedelta as delta
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):
# --------------------------
# ここに処理を記述します
# --------------------------
self._logger.info('candle : {}'.format(candle))
doten.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" : "1h",
"//" : "データ取得開始時刻(UNIXTIME:1ミリ秒)、使用しない場合 もしくは自動の場合は null(None) を指定",
"SINCE" : null,
"//" : "取得件数(未指定:100、MAX:500)",
"LIMIT" : null,
"//" : "True(New->Old)、False(Old->New) 未指定時はFlase",
"REVERSE" : false,
"//" : "True(最新の未確定足を含む)、False(含まない) 未指定はTrue",
"PARTIAL" : true
},
"//" : "板情報の収集定義。",
"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,
"//" : "===============================================",
"//" : " ユーザで自由に定義",
"//" : "==============================================="
}
上記の設定のうち、doten.jsonの
"//" : "===============================================",
"//" : " システムで利用",
"//" : "===============================================",
"//" : "取引所のapiKey, secretを設定します",
"APIKEY" : "YOUR_APIKEY",
"SECRET" : "YOUR_SECRET",
APIKEY,SECRETには、bitmexのtestnetで取得したAPIKEY,SECRETを定義してください。
実行
フォルダをpuppeteerの直下に移動して
python3 puppeteer.py puppets/doten/doten.py puppets/doten/doten.json
を実行しましょう。
すると、60秒周期で、1時間足が100個(個数が未指定なので、デフォルトの100個が取得されます)表示されるでしょう。
2019-07-14 01:53:04, INFO , class BitMEX initialized
2019-07-14 01:53:04, INFO , [傀儡師] 起動しました。Puppet=puppets/doten/doten.py, Config=puppets/doten/doten.json, 対象通貨ペア=BTC/USD, RUN周期=60(秒)
2019-07-14 01:53:07, INFO , candle : [[1562677200000, 12377.5, 12500, 12300, 12408.5, 6212136], [1562680800000, 12408.5, 12541.5, 12385, 12500.5, 9299117], [1562684400000, 12500.5, 12520, 12408.5, 12495, 1274727], [1562688000000, 12495, 12545, 12478, 12508, 3312428], [1562691600000, 12508, 12545, 12507.5, 12533.5, 1732720], [1562695200000, 12533.5, 12700, 12529.5, 12626, 5306834], [1562698800000, 12626, 12681, 12450, 12540.5, 4506398], [1562702400000, 12540.5, 12628, 12500, 12550, 1794284], [1562706000000, 12550, 12698, 12550, 12627, 2802806], [1562709600000, 12627, 12699.5, 12531.5, 12660, 2537158], [1562713200000, 12660, 12699.5, 12560, 12683.5, 1199284], [1562716800000, 12683.5, 12899.5, 12666.5, 12886, 8006520], [1562720400000, 12886, 12900, 12669, 12816, 1925502], [1562724000000, 12816, 13188.5, 12407.5, 13052.5, 8190548], [1562727600000, 13052.5, 13108, 12050, 12424.5, 13970781], [1562731200000, 12424.5, 12950, 12424.5, 12806, 3931930], [1562734800000, 12806, 12963.5, 12770, 12859.5, 1284295], [1562738400000, 12859.5, 12963.5, 12825, 12900.5, 2612710], [1562742000000, 12900.5, 12930, 12786, 12800, 1909868], [1562745600000, 12800, 12930, 12500, 12750, 6053707], [1562749200000, 12750, 12850, 12710, 12755.5, 1955232], [1562752800000, 12755.5, 12958, 12727, 12854, 2896582], [1562756400000, 12854, 12958, 12846.5, 12895, 1640000], [1562760000000, 12895, 12995, 12830, 12920.5, 4827528], [1562763600000, 12920.5, 13000, 12910, 12986, 3456531], [1562767200000, 12986, 12998, 12350.5, 12397, 6698850], [1562770800000, 12397, 12455, 12150, 12350.5, 5160644], [1562774400000, 12350.5, 12449, 12200, 12260, 3186603], [1562778000000, 12260, 12460, 12150, 12432, 2041963], [1562781600000, 12432, 12504.5, 12368.5, 12433.5, 1489719], [1562785200000, 12433.5, 12502, 12150, 12468, 4497132], [1562788800000, 12468, 12468.5, 12100, 12187, 17679250], [1562792400000, 12187, 12189, 11750.5, 12054.5, 7297638], [1562796000000, 12054.5, 12155.5, 12002.5, 12096, 1328546], [1562799600000, 12096, 12500, 12017.5, 12243, 5572498], [1562803200000, 12243, 12257.5, 11919.5, 11950, 810127], [1562806800000, 11950, 12303.5, 11950.5, 12067.5, 738707], [1562810400000, 12067.5, 12149.5, 12050, 12133.5, 686273], [1562814000000, 12133.5, 12141, 11843, 11894.5, 2975777], [1562817600000, 11894.5, 12200, 11531, 11598.5, 15329743], [1562821200000, 11598.5, 11800, 11575, 11677.5, 1973562], [1562824800000, 11677.5, 11699, 11656, 11692.5, 345240], [1562828400000, 11692.5, 11810, 11692.5, 11803.5, 2048952], [1562832000000, 11803.5, 11804.5, 11665.5, 11696.5, 1133375], [1562835600000, 11696.5, 11798, 11612, 11670.5, 1453208], [1562839200000, 11670.5, 11900.5, 11555, 11713, 3110552], [1562842800000, 11713, 11826.5, 11700, 11826, 862307], [1562846400000, 11826, 11900, 11815, 11852, 1648100], [1562850000000, 11852, 11852.5, 11798, 11800.5, 421212], [1562853600000, 11800.5, 11900.5, 11760, 11839.5, 3593823], [1562857200000, 11839.5, 12000, 11800, 11801, 2659605], [1562860800000, 11801, 11859, 11700, 11750, 7785767], [1562864400000, 11750, 11854, 11700, 11712, 1414122], [1562868000000, 11712, 11966.5, 11700, 11873, 3608131], [1562871600000, 11873, 12000, 11701, 11775, 3923511], [1562875200000, 11775, 11791.5, 11330, 11414, 32904994], [1562878800000, 11414, 11845.5, 11331, 11547, 3549635], [1562882400000, 11547, 11555, 11365, 11419, 3687221], [1562886000000, 11419, 11535, 11400, 11499, 1399638], [1562889600000, 11499, 11700, 11400, 11674, 1628088], [1562893200000, 11674, 11700, 11557.5, 11635.5, 812924], [1562896800000, 11635.5, 11643.5, 11502, 11531.5, 952850], [1562900400000, 11531.5, 11532, 11400, 11462, 822365], [1562904000000, 11462, 11507.5, 11446.5, 11500, 397146], [1562907600000, 11500, 11548, 11400, 11475, 844979], [1562911200000, 11475, 11550, 11445, 11518, 859208], [1562914800000, 11518, 11699.5, 11515.5, 11684, 1005212], [1562918400000, 11684, 11685, 11600, 11607.5, 940304], [1562922000000, 11607.5, 11768.5, 11550.5, 11726, 3107301], [1562925600000, 11726, 11800, 11720, 11737.5, 2157000], [1562929200000, 11737.5, 11755, 11695, 11732, 515183], [1562932800000, 11732, 11800, 11613, 11630, 1201246], [1562936400000, 11630, 11730.5, 11589.5, 11600, 3242771], [1562940000000, 11600, 11779, 11480, 11750, 4071784], [1562943600000, 11750, 11750, 11516.5, 11550, 5272510], [1562947200000, 11550, 11732, 11490, 11590, 2671607], [1562950800000, 11590, 11700, 11575, 11662, 1691568], [1562954400000, 11662, 11777, 11585, 11594.5, 2725840], [1562958000000, 11594.5, 11700, 11575, 11592.5, 1221651], [1562961600000, 11592.5, 12000, 11590, 11891, 11579856], [1562965200000, 11891, 12075, 11600, 11782, 8413145], [1562968800000, 11782, 11918.5, 11650, 11885, 1125073], [1562972400000, 11885, 11898.5, 11814.5, 11869, 1702160], [1562976000000, 11869, 11900, 11721.5, 11763.5, 4142519], [1562979600000, 11763.5, 11801.5, 11500.5, 11717.5, 3800950], [1562983200000, 11717.5, 11802, 11700, 11771, 595846], [1562986800000, 11771, 11802, 11561, 11620, 5014039], [1562990400000, 11620, 11704, 11540, 11700, 983469], [1562994000000, 11700, 11794, 11674, 11738, 754744], [1562997600000, 11738, 11783, 11626, 11654.5, 734782], [1563001200000, 11654.5, 11667, 11503, 11536.5, 1103562], [1563004800000, 11536.5, 11581.5, 11506, 11559, 530953], [1563008400000, 11559, 11602.5, 11500.5, 11557, 793142], [1563012000000, 11557, 11600, 11500.5, 11534.5, 8673298], [1563015600000, 11534.5, 11550, 11500.5, 11510.5, 3471953], [1563019200000, 11510.5, 11545, 11500.5, 11510.5, 1961132], [1563022800000, 11510.5, 11580, 11500.5, 11564, 1083181], [1563026400000, 11564, 11578.5, 11511, 11554, 1093469], [1563030000000, 11554, 11600, 11515, 11563.5, 1815158], [1563033600000, 11563.5, 11608, 11530, 11590.5, 1254123]]
・・・以下略・・・
candleに取得された内容は
timestamp : 日時(UNIXTIME) ミリ秒
open : 始値
high : 高値
low : 低値
close : 終値
volume : ボリューム
です。
一時間足ではなく、他の足を指定するにはdoten.jsonの
"//" : "ローソク足の収集定義。",
"CANDLE" : {
"//" : "ローソク足の足幅を設定する。設定値= 1m, 5m, 1h, 1d",
"TIMEFRAME" : "1h",
"//" : "データ取得開始時刻(UNIXTIME:1ミリ秒)、使用しない場合 もしくは自動の場合は null(None) を指定",
"SINCE" : null,
"//" : "取得件数(未指定:100、MAX:500)",
"LIMIT" : null,
"//" : "True(New->Old)、False(Old->New) 未指定時はFlase",
"REVERSE" : false,
"//" : "True(最新の未確定足を含む)、False(含まない) 未指定はTrue",
"PARTIAL" : true
},
"TIMEFRAME"を別の足の指定に変更します。
今は、doten君の足を1h(1時間)に指定しています。
また、直近の最新足を取得するために「PARTIAL」をTrueに指定しているので、実行を繰り返すたびに最新足は適宜更新された足の値が戻されるはずです。
pandas登場
さて、このままでも十分に機能をはたしますが、データ処理を楽にするためにpythonでお馴染みのpandasのデータフレームに値を設定しましょう。
pandasを使うことで、データ欠損のチェックや指定行の抜き出しや演算が楽に行えます。
以下の関数を追加することにします。
# ==========================================================
# ローソク足 DataFrame 取得
# ==========================================================
def __get_candleDF(self, candle):
# -----------------------------------------------
# Pandasのデータフレームに
# -----------------------------------------------
df = pd.DataFrame(candle,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
# -----------------------------------------------
# 日時データをDataFrameのインデックスにする
# -----------------------------------------------
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True, infer_datetime_format=True) # UNIX時間(ミリ秒)を変換, UTC=TrueでタイムゾーンがUTCに設定される, infer_datetime_format=Trueは高速化に寄与するとのこと。
df = df.set_index('timestamp')
return df
pandasのDataFrameを使って、candle生データを渡し、カラム情報を付加しています。
それから、timestampをUTC時間でミリ秒指定をしてdatetime型に変換してインデックスとして登録します。
上記の関数を組み込んだ doten.pyは以下になります。
# -*- coding: utf-8 -*-
# ==========================================
# ドテン君 サンプル
# ==========================================
import time
from datetime import datetime as dt, timezone as tz, timedelta as delta
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):
# --------------------------
# ここに処理を記述します
# --------------------------
# ------------------------------------------------------
# ローソク足
# ------------------------------------------------------
df = self.__get_candleDF(candle)
self._logger.info('df: {}'.format(df))
# ==========================================================
# ローソク足 DataFrame 取得
# ==========================================================
def __get_candleDF(self, candle):
# -----------------------------------------------
# Pandasのデータフレームに
# -----------------------------------------------
df = pd.DataFrame(candle,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
# -----------------------------------------------
# 日時データをDataFrameのインデックスにする
# -----------------------------------------------
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True, infer_datetime_format=True) # UNIX時間(ミリ秒)を変換, UTC=TrueでタイムゾーンがUTCに設定される, infer_datetime_format=Trueは高速化に寄与するとのこと。
df = df.set_index('timestamp')
return df
またプログラムを実行してみましょう。
python3 puppeteer.py puppets/doten/doten.py puppets/doten/doten.json
すると、次のような出力がされると思います。
2019-07-14 02:15:37, INFO , class BitMEX initialized
2019-07-14 02:15:38, INFO , [傀儡師] 起動しました。Puppet=puppets/doten/doten.py, Config=puppets/doten/doten.json, 対象通貨ペア=BTC/USD, RUN周期=60(秒)
2019-07-14 02:15:42, INFO , df: open high low close volume
timestamp
2019-07-09 14:00:00+00:00 12408.5 12541.5 12385.0 12500.5 9299117
2019-07-09 15:00:00+00:00 12500.5 12520.0 12408.5 12495.0 1274727
2019-07-09 16:00:00+00:00 12495.0 12545.0 12478.0 12508.0 3312428
2019-07-09 17:00:00+00:00 12508.0 12545.0 12507.5 12533.5 1732720
2019-07-09 18:00:00+00:00 12533.5 12700.0 12529.5 12626.0 5306834
2019-07-09 19:00:00+00:00 12626.0 12681.0 12450.0 12540.5 4506398
2019-07-09 20:00:00+00:00 12540.5 12628.0 12500.0 12550.0 1794284
2019-07-09 21:00:00+00:00 12550.0 12698.0 12550.0 12627.0 2802806
2019-07-09 22:00:00+00:00 12627.0 12699.5 12531.5 12660.0 2537158
2019-07-09 23:00:00+00:00 12660.0 12699.5 12560.0 12683.5 1199284
2019-07-10 00:00:00+00:00 12683.5 12899.5 12666.5 12886.0 8006520
2019-07-10 01:00:00+00:00 12886.0 12900.0 12669.0 12816.0 1925502
2019-07-10 02:00:00+00:00 12816.0 13188.5 12407.5 13052.5 8190548
2019-07-10 03:00:00+00:00 13052.5 13108.0 12050.0 12424.5 13970781
2019-07-10 04:00:00+00:00 12424.5 12950.0 12424.5 12806.0 3931930
2019-07-10 05:00:00+00:00 12806.0 12963.5 12770.0 12859.5 1284295
2019-07-10 06:00:00+00:00 12859.5 12963.5 12825.0 12900.5 2612710
2019-07-10 07:00:00+00:00 12900.5 12930.0 12786.0 12800.0 1909868
2019-07-10 08:00:00+00:00 12800.0 12930.0 12500.0 12750.0 6053707
2019-07-10 09:00:00+00:00 12750.0 12850.0 12710.0 12755.5 1955232
2019-07-10 10:00:00+00:00 12755.5 12958.0 12727.0 12854.0 2896582
2019-07-10 11:00:00+00:00 12854.0 12958.0 12846.5 12895.0 1640000
2019-07-10 12:00:00+00:00 12895.0 12995.0 12830.0 12920.5 4827528
2019-07-10 13:00:00+00:00 12920.5 13000.0 12910.0 12986.0 3456531
2019-07-10 14:00:00+00:00 12986.0 12998.0 12350.5 12397.0 6698850
2019-07-10 15:00:00+00:00 12397.0 12455.0 12150.0 12350.5 5160644
2019-07-10 16:00:00+00:00 12350.5 12449.0 12200.0 12260.0 3186603
2019-07-10 17:00:00+00:00 12260.0 12460.0 12150.0 12432.0 2041963
2019-07-10 18:00:00+00:00 12432.0 12504.5 12368.5 12433.5 1489719
2019-07-10 19:00:00+00:00 12433.5 12502.0 12150.0 12468.0 4497132
... ... ... ... ... ...
2019-07-12 12:00:00+00:00 11732.0 11800.0 11613.0 11630.0 1201246
2019-07-12 13:00:00+00:00 11630.0 11730.5 11589.5 11600.0 3242771
2019-07-12 14:00:00+00:00 11600.0 11779.0 11480.0 11750.0 4071784
2019-07-12 15:00:00+00:00 11750.0 11750.0 11516.5 11550.0 5272510
2019-07-12 16:00:00+00:00 11550.0 11732.0 11490.0 11590.0 2671607
2019-07-12 17:00:00+00:00 11590.0 11700.0 11575.0 11662.0 1691568
2019-07-12 18:00:00+00:00 11662.0 11777.0 11585.0 11594.5 2725840
2019-07-12 19:00:00+00:00 11594.5 11700.0 11575.0 11592.5 1221651
2019-07-12 20:00:00+00:00 11592.5 12000.0 11590.0 11891.0 11579856
2019-07-12 21:00:00+00:00 11891.0 12075.0 11600.0 11782.0 8413145
2019-07-12 22:00:00+00:00 11782.0 11918.5 11650.0 11885.0 1125073
2019-07-12 23:00:00+00:00 11885.0 11898.5 11814.5 11869.0 1702160
2019-07-13 00:00:00+00:00 11869.0 11900.0 11721.5 11763.5 4142519
2019-07-13 01:00:00+00:00 11763.5 11801.5 11500.5 11717.5 3800950
2019-07-13 02:00:00+00:00 11717.5 11802.0 11700.0 11771.0 595846
2019-07-13 03:00:00+00:00 11771.0 11802.0 11561.0 11620.0 5014039
2019-07-13 04:00:00+00:00 11620.0 11704.0 11540.0 11700.0 983469
2019-07-13 05:00:00+00:00 11700.0 11794.0 11674.0 11738.0 754744
2019-07-13 06:00:00+00:00 11738.0 11783.0 11626.0 11654.5 734782
2019-07-13 07:00:00+00:00 11654.5 11667.0 11503.0 11536.5 1103562
2019-07-13 08:00:00+00:00 11536.5 11581.5 11506.0 11559.0 530953
2019-07-13 09:00:00+00:00 11559.0 11602.5 11500.5 11557.0 793142
2019-07-13 10:00:00+00:00 11557.0 11600.0 11500.5 11534.5 8673298
2019-07-13 11:00:00+00:00 11534.5 11550.0 11500.5 11510.5 3471953
2019-07-13 12:00:00+00:00 11510.5 11545.0 11500.5 11510.5 1961132
2019-07-13 13:00:00+00:00 11510.5 11580.0 11500.5 11564.0 1083181
2019-07-13 14:00:00+00:00 11564.0 11578.5 11511.0 11554.0 1093469
2019-07-13 15:00:00+00:00 11554.0 11600.0 11515.0 11563.5 1815158
2019-07-13 16:00:00+00:00 11563.5 11608.0 11530.0 11607.0 1373885
2019-07-13 17:00:00+00:00 11607.0 11608.5 11530.0 11608.5 875087
[100 rows x 5 columns]
今度は綺麗に整列した値が出力されましたね。
次回予告
さて、次回からはdotenの計算を追加していってみましょう。
楽しいbotライフを!
ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。