[Python3] [CCXT] UKI さんの元祖ドテン君を実装してみた
元祖ドテン君とは、AKAGAMI さんのドテン君の名前の元になった bot で、こちらの記事で公開されてるやつのことです。
ここで紹介されている本来のロジックは「ブレイクした次の足でエントリー」ですが、あえて逆指値でレンジブレイク直後にエントリーするようにしました。バックテストした感じそっちのほうがパフォーマンス良かったので。
5/14追記:
バックテストのスクリプトが間違ってました。元祖のほうがパフォーマンス良かったです。修正版はこちら。
あまり自信はありませんが、それ以外は同じに作っているつもりです。
import json
import time
from datetime import datetime
import ccxt
import numpy as np
import requests
API_KEY = ''
API_SECRET = ''
POSITION_SIZE_USD = 50
# 元祖ドテン君
RESOLUTION_M = 120
WINDOW_SIZE = 5
K = 1.6
BTCUSD = 'BTC/USD'
XBTUSD = 'XBTUSD'
BUY = 'Buy'
SELL = 'Sell'
mex = ccxt.bitmex()
mex.apiKey = API_KEY
mex.secret = API_SECRET
class BitMEXChart:
def __init__(self, resolution_m):
"""
:param resolution_m: 1, 3, 5, 15, 30, 60, 60*2, 60*4, 60*6, 60*12, 60*24, 60*24*3, 60*24*7
"""
self._chart = self._fetch_chart(resolution_m=resolution_m)
def _fetch_chart(self, resolution_m):
chart = requests.get(
'https://api.cryptowat.ch/markets/bitmex/btcusd-perpetual-futures/ohlc?periods={:d}'.format(resolution_m * 60)).json()
return chart['result']['{}'.format(resolution_m * 60)]
def timestamps(self):
return [int(c[0]) for c in self._chart]
def open_values(self):
return [float(c[1]) for c in self._chart]
def high_values(self):
return [float(c[2]) for c in self._chart]
def low_values(self):
return [float(c[3]) for c in self._chart]
def close_values(self):
return [float(c[4]) for c in self._chart]
def volumes(self):
return [float(c[5]) for c in self._chart]
def stop(side, price):
positions_size = fetch_positions_size()
if side == BUY and positions_size > 0 or side == SELL and positions_size < 0:
# 同じ方向には注文しない
return
# 約定後 POSITION_SIZE_USD のポジションを持つ
order_size = POSITION_SIZE_USD + abs(positions_size)
orders = mex.fetch_orders(BTCUSD, params={
'filter': {
'open': True,
'ordType': 'Stop',
'side': side,
}
})
if len(orders) == 0:
# 新規注文
mex.create_order(BTCUSD, type='Stop', side=side, amount=order_size, params={
'stopPx': price,
'execInst': 'LastPrice',
})
else:
# price と amount をアップデートするだけ
order = orders[0]
if order['info'].get('stopPx') == price and order['amount'] == order_size:
return
mex.edit_order(order['id'], order['symbol'], order['type'], order['side'], order_size, params={
'stopPx': price,
'execInst': 'LastPrice',
})
def fetch_positions_size():
positions = mex.private_get_position({
'columns': json.dumps(['currentQty']),
'filter': json.dumps({'symbol': XBTUSD})
})
return sum([p['currentQty'] for p in positions])
def cancel_orders(side):
return mex.private_delete_order_all({
'filter': json.dumps({'side': side})
})
def main():
chart = BitMEXChart(resolution_m=RESOLUTION_M)
range_mean = np.mean([h - L for h, L in zip(chart.high_values(), chart.low_values())][-WINDOW_SIZE-1:-1])
open_value = chart.open_values()[-1]
up_bound = (open_value + range_mean * K) // 0.5 * 0.5
down_bound = (open_value - range_mean * K) // 0.5 * 0.5
positions_size = fetch_positions_size()
if positions_size == 0:
stop(BUY, up_bound)
stop(SELL, down_bound)
if positions_size > 0:
# 買いポジション持ち
stop(SELL, down_bound)
cancel_orders(BUY)
if positions_size < 0:
# 売りポジション持ち
stop(BUY, up_bound)
cancel_orders(SELL)
if __name__ == '__main__':
print('--- {} ---'.format(datetime.now()))
try:
while True:
main()
time.sleep(10)
except Exception as e:
time.sleep(10)
raise
動かすには API キーの設定と依存ライブラリのインストールが必要です。
pip install ccxt
pip install requests
pip install numpy
もしよくわからないところがあれば分かる範囲でお答えしますので、Twitter (@ycrypthon) かコメントでお知らせください。もしよろしければ♡やシェアをしてくださると喜びます\( 'ω')/
4/30 追記:
動かない場合は Python のバージョンを上げてみてください。Python 3.5.2 で動作確認できています。
よろしければこちらの note もどうぞ\( 'ω')/
ご覧いただきありがとうございます!