![noteのタイトル画像](https://assets.st-note.com/production/uploads/images/11187627/rectangle_large_type_2_8e628bdfbfd3c3e877dfa84b6cc473d2.png?width=1200)
[Puppeteer] OHLCVデータの足幅を別の足幅に変更する
以前、pythonのpandasモジュールを使ってSMA,EMAを計算させてみました。
pandasは結構色々なことができるので、今回は
bitmexのOHLCVデータの足幅を別の足幅に変更する小技
を紹介したいと思います。
例によってPuppeteerのPuppetとして実装しています。
Puppeteerの取得は、こちらをご覧になって行ってください。
(MITライセンスで無償でご利用いただけます)
Puppeteerをgitからcloneした後、puppetsフォルダの下に
- pupptes/
- ohlcv/
- ohlcv.py
- ohlcv.json
のように「ohlcv」フォルダと「ohlcv.py」「ohlcv.json」ファイルを作成します。
● ohlcv.py
# -*- coding: utf-8 -*-
# ==========================================
# サンプル・ストラテジ
# ==========================================
import numpy as np
import pandas as pd
from puppeteer import Puppeteer
# ==========================================
# Puppet(傀儡) クラス
# param:
# puppeteer: Puppeteerオブジェクト
# ==========================================
class Puppet(Puppeteer):
_exchange = None # 取引所オブジェクト(ccxt.bitmex)
_logger = None # logger
_config = None # 定義ファイル
_discord = None # discord
_name = 'ohlcv' # 自分の名称
# ==========================================================
# 初期化
# param:
# puppeteer: Puppeteerオブジェクト
# ==========================================================
def __init__(self, Puppeteer):
self._exchange = Puppeteer._exchange
self._logger = Puppeteer._logger
self._config = Puppeteer._config
self._discord = Puppeteer._discord
# ==========================================================
# 売買実行
# param:
# ticker: Tick情報
# orderbook: 板情報
# position: ポジション情報
# balance: 資産情報
# candle: ローソク足
# ==========================================================
def run(self, ticker, orderbook, position, balance, candle):
# --------------------------
# ここに処理を記述します
# --------------------------
df_ohlcv1m = self.get_candleDF(candle)
# for DEBUG
self._logger.debug(df_ohlcv1m)
df_ohlcv15m = self.change_candleDF(df_ohlcv1m, '15m')
# for DEBUG
self._logger.debug(df_ohlcv15m)
# ==========================================================
# ローソク足DataFrame
# params:
# candle: ローソク足の配列[timestamp(UNIXTIME(ミリ秒), open, high, low, close, volume)]
# return:
# df: ローソク足DataFrame (pandas)
# ==========================================================
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') # UNIX時間(ミリ秒)を変換
df = df.set_index('timestamp')
return df
# ==========================================================
# ローソク足の足幅変換
# 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 分 0秒
S 秒
"""
"""
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 = pd.concat([ohlcv[['open', 'high', 'low', 'close']].resample(period[resolution], label='left', closed='left').agg({'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last'}),
ohlcv['volume'].resample(period[resolution], label='left', closed='left').sum()],
axis=1
) # ohlcを再度ohlcに集計するにはaggメソッド
return df
● ohlcv.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" : false,
"ORDERBOOK" : false,
"POSITION" : false,
"BALANCE" : false,
"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
},
"//" : "インターバルを秒で設定",
"INTERVAL" :60,
"//" : "discord通知用URL",
"DISCORD_WEBHOOK_URL" : "",
"//" : "===============================================",
"//" : " ユーザで自由に定義",
"//" : "===============================================",
"//" : "売買するサイズ",
"LOT_SIZE" :50
}
上記の内容をコピペで記述してください。
ohlcv.jsonの apikey, secret にbitmex取引所のapikey,secretを設定します。
puppeteerフォルダに移動して、コンソールから
python3 puppeteer.py puppets/ohlcv/ohlcv.py puppets/ohlcv/ohlcv.json
と実行します。
以下のような結果が出力されると思います。
1つ目は1分足のohlcv、2つ目は15分足のohlcvです。
1分足
2019-04-21 02:21:03, DEBUG , open high low close volume
timestamp
2019-04-20 15:42:00 5308.0 5308.0 5307.5 5307.5 2321.0
2019-04-20 15:43:00 5307.5 5307.5 5307.5 5307.5 0.0
2019-04-20 15:44:00 5307.5 5307.5 5307.5 5307.5 1.0
2019-04-20 15:45:00 5307.5 5307.5 5307.5 5307.5 0.0
2019-04-20 15:46:00 5307.5 5307.5 5307.0 5307.5 1021.0
2019-04-20 15:47:00 5307.5 5307.5 5307.5 5307.5 0.0
2019-04-20 15:48:00 5307.5 5317.0 5295.5 5305.5 67271.0
2019-04-20 15:49:00 5305.5 5305.5 5305.5 5305.5 0.0
2019-04-20 15:50:00 5305.5 5317.5 5303.0 5309.0 111805.0
2019-04-20 15:51:00 5309.0 5319.0 5295.0 5309.5 124239.0
2019-04-20 15:52:00 5309.5 5319.5 5293.5 5306.5 120170.0
2019-04-20 15:53:00 5306.5 5307.0 5307.0 5307.0 26.0
2019-04-20 15:54:00 5307.0 5318.0 5293.5 5306.0 108303.0
2019-04-20 15:55:00 5306.0 5306.5 5306.0 5306.5 29.0
2019-04-20 15:56:00 5306.5 5306.5 5306.0 5306.5 1255.0
2019-04-20 15:57:00 5306.5 5306.5 5306.0 5306.5 4000.0
2019-04-20 15:58:00 5306.5 5306.5 5306.0 5306.0 22.0
2019-04-20 15:59:00 5306.0 5306.0 5306.0 5306.0 0.0
2019-04-20 16:00:00 5306.0 5306.0 5304.5 5304.5 5800.0
2019-04-20 16:01:00 5304.5 5306.5 5304.0 5304.0 1613.0
2019-04-20 16:02:00 5304.0 5304.5 5304.5 5304.5 1.0
2019-04-20 16:03:00 5304.5 5304.0 5304.0 5304.0 61.0
2019-04-20 16:04:00 5304.0 5304.5 5304.5 5304.5 33.0
2019-04-20 16:05:00 5304.5 5304.5 5304.0 5304.5 1015.0
2019-04-20 16:06:00 5304.5 5304.5 5304.0 5304.0 410.0
2019-04-20 16:07:00 5304.0 5304.5 5304.0 5304.0 20.0
2019-04-20 16:08:00 5304.0 5304.5 5304.0 5304.0 340.0
2019-04-20 16:09:00 5304.0 5304.5 5304.5 5304.5 21.0
2019-04-20 16:10:00 5304.5 5304.5 5304.0 5304.0 4850.0
2019-04-20 16:11:00 5304.0 5304.5 5304.5 5304.5 2.0
... ... ... ... ... ...
2019-04-20 16:52:00 5307.0 5307.5 5304.5 5304.5 12414.0
2019-04-20 16:53:00 5304.5 5307.5 5303.5 5304.0 8362.0
2019-04-20 16:54:00 5304.0 5304.5 5304.0 5304.5 937.0
2019-04-20 16:55:00 5304.5 5305.5 5304.5 5304.5 4314.0
2019-04-20 16:56:00 5304.5 5304.5 5304.0 5304.5 2639.0
2019-04-20 16:57:00 5304.5 5306.0 5304.0 5306.0 6700.0
2019-04-20 16:58:00 5306.0 5308.0 5306.0 5308.0 4205.0
2019-04-20 16:59:00 5308.0 5307.0 5306.5 5306.5 2.0
2019-04-20 17:00:00 5306.5 5307.0 5306.5 5307.0 15.0
2019-04-20 17:01:00 5307.0 5306.5 5306.5 5306.5 350.0
2019-04-20 17:02:00 5306.5 5308.5 5306.5 5308.5 3057.0
2019-04-20 17:03:00 5308.5 5308.0 5307.0 5308.0 860.0
2019-04-20 17:04:00 5308.0 5308.5 5308.5 5308.5 200.0
2019-04-20 17:05:00 5308.5 5308.5 5308.0 5308.0 592.0
2019-04-20 17:06:00 5308.0 5308.5 5308.0 5308.5 1010.0
2019-04-20 17:07:00 5308.5 5308.0 5308.0 5308.0 155.0
2019-04-20 17:08:00 5308.0 5308.0 5308.0 5308.0 0.0
2019-04-20 17:09:00 5308.0 5308.0 5308.0 5308.0 0.0
2019-04-20 17:10:00 5308.0 5308.0 5308.0 5308.0 0.0
2019-04-20 17:11:00 5308.0 5308.0 5308.0 5308.0 0.0
2019-04-20 17:12:00 5308.0 5308.0 5308.0 5308.0 0.0
2019-04-20 17:13:00 5308.0 5308.5 5308.0 5308.5 250.0
2019-04-20 17:14:00 5308.5 5308.0 5306.5 5306.5 1310.0
2019-04-20 17:15:00 5306.5 5307.0 5304.0 5304.0 6794.0
2019-04-20 17:16:00 5304.0 5306.5 5306.0 5306.0 4280.0
2019-04-20 17:17:00 5306.0 5306.0 5306.0 5306.0 0.0
2019-04-20 17:18:00 5306.0 5306.0 5306.0 5306.0 2866.0
2019-04-20 17:19:00 5306.0 5306.5 5306.0 5306.0 2.0
2019-04-20 17:20:00 5306.0 5306.5 5305.5 5306.5 509.0
2019-04-20 17:21:00 5306.5 5306.0 5305.5 5305.5 1055.0
[100 rows x 5 columns]
15分足
2019-04-21 02:21:03, DEBUG , open high low close volume
timestamp
2019-04-20 15:30:00 5308.0 5308.0 5307.5 5307.5 2322.0
2019-04-20 15:45:00 5307.5 5319.5 5293.5 5306.0 538141.0
2019-04-20 16:00:00 5306.0 5306.5 5304.0 5305.0 17695.0
2019-04-20 16:15:00 5305.0 5313.0 5294.0 5304.5 198628.0
2019-04-20 16:30:00 5304.5 5310.0 5304.0 5308.5 30591.0
2019-04-20 16:45:00 5308.5 5310.5 5303.5 5306.5 64034.0
2019-04-20 17:00:00 5306.5 5308.5 5306.5 5306.5 7799.0
2019-04-20 17:15:00 5306.5 5307.0 5304.0 5305.5 15506.0
足幅の変更にはpandasの「resample」メソッドを使っています。
このメソッドはなかなか優秀です。
tickerの価格データをohlcデータに変更するときに「ohlcメソッド」を使うケースはあると思いますが、すでにohlc形式データになっているDataFrameにohlcメソッドを適用すると、へんてこりんなことになるので、
df = pd.concat([ohlcv[['open', 'high', 'low', 'close']].resample(period[resolution], label='left', closed='left').agg({'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last'}),
ohlcv['volume'].resample(period[resolution], label='left', closed='left').sum()],
axis=1
) # ohlcを再度ohlcに集計するにはaggメソッド
のようにして、ohlcデータを加工します。
参考にしたサイトは
と
です。
今回volumeを別途算出し、わざわざconcatで連結していますが、そんなことをせずに
.agg({'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'})
とすれば良いことに後から気がつきました。
ですが、DataFrameの連結方法を勉強する意味(axisの考え方がいまいち良く理解できていないので)でも、このまま掲載しておきます。
楽しいbotライフを!
ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。