Makerで売るならaskの値を取得すべきでした
引き続きPythonを使ってbitcoinのアービトラージの自動売買プログラムの構築に向けて勉強中です。
先日こちらの記事で手数料込みのアービトラージの計算プログラムを作ったのですが、1点間違いが見つかりました。。
こちらのプログラムではbitbankで売るので取得する情報は「bid」、GMOで買うので取得する情報は「ask」としていました。ただし、bitbankはテイカーではなくメイカーとして注文する戦略だったので、「bid」ではなく「ask」として価格取得するのが正解でした。
「bid」は既に取引所に買い注文が出ている価格なので、その価格で売り注文を出すとテイカーとして約定してしまいます。以上を踏まえ、修正版のソースコードを下記に記載します。
import ccxt
import time
import datetime
import csv
from pprint import pprint
import requests
import json
import winsound
max = 500 #cryptowatchで取得できる足の数
before = 5 #さかのぼる足の数
periods = 1800 #3600秒=1時間足
range_th = 15000 #値動きの最大幅
range_flag = 0 #値動きの最大幅が許容内の時のフラグ
arbi_th = 2000 #裁定取引開始差額
arbi_flag = 0 #裁定取引開始差額の時のフラグ
sage_flag = 0 #下げ局面でないことを確認する時のフラグ
delay = 10 #指定秒数待って繰り返し
ask_exchange = 'GMO' #購入元取引所
bid_exchange = 'bitbank' #売却先取引所
ask_taker_fee = 0.0005 #GMOのTaker手数料
bid_maker_fee = -0.0002 #bitbankのMaker手数料
transfer_fee = 0 #送金手数料 GMOの場合無料
ask_amount = 1 #購入数量
bid_amount = ask_amount - transfer_fee #売却数量(送金手数料差し引き後)
def get_price(min,i):
data = response.json()
last_data = data["result"][str(min)][i]
return { "close_time" : last_data[0],
"open_price" : last_data[1],
"high_price" : last_data[2],
"low_price" : last_data[3],
"close_price":last_data[4] }
def check_candle( data ):
if data["close_price"]-data["open_price"] > 0 : return True
else : return False
def check_ascend( data,last_data ):
if data["open_price"] > last_data["open_price"] and data["close_price"] > last_data["close_price"]:
return True
else:
return False
while 1:
dt = datetime.datetime.now()
print(dt)
#bitbank売り価格取得
exchange = eval('ccxt.' + 'bitbank' + '()')
orderbook = exchange.fetch_order_book ('BTC/JPY')
bid_price = orderbook['asks'][0][0] #※指値でMaker取引をするためbidではなくask(売り注文)の値を取得
#GMOコイン買い価格取得
response = requests.get('https://api.coin.z.com/public/v1/ticker?symbol=BTC')
json_data = response.json()
ask_price = float(json_data["data"][0]["ask"])
#アービトラージ計算結果を出力
print ('買い数量=', ask_amount, 'BTC')
print ('送金手数料=',transfer_fee, 'BTC')
print ('売り数量=', bid_amount, 'BTC')
arbi = bid_price*bid_amount - ask_price*ask_amount
print (ask_exchange,'で', ask_price, 'x',ask_amount,'円で買って(Taker)')
print (bid_exchange,'で', bid_price, 'x',bid_amount,'円で売れば(Maker)')
print (arbi, '円の利益!')
final_ask_taker_fee = ask_price * ask_amount * ask_taker_fee
final_bid_maker_fee = bid_price * bid_amount * bid_maker_fee
print ('taker手数料は',final_ask_taker_fee, '円')
print ('maker手数料は',final_bid_maker_fee, '円')
print ('手数料込みだと',arbi - final_ask_taker_fee - final_bid_maker_fee, '円の利益!')
if arbi > arbi_th:
arbi_flag = 1
print('①',arbi_th,'円以上の差額なのでフラグ立てます')
else:
arbi_flag = 0
print('①',arbi_th,'円以下の差額なのでフラグ立てません')
#過去のボラティリティを確認
response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc",params = { "periods" : periods })
json_data = response.json()
i = max - before
max_range = 0
while i in range(max):
data = get_price(periods, i)
price_range = data["high_price"] - data["low_price"]
print((max-i)*periods/3600,'時間前の値幅',price_range)
if max_range < price_range:
max_range = price_range
i = i+1
print('直近',before*periods/3600,'時間の値幅は',max_range,'円です')
if max_range < range_th:
range_flag = 1
print('②',range_th,'円以内の値幅なのでフラグ立てます')
else:
range_flag = 0
print('②',range_th,'円以上の値幅なのでフラグ立てません')
#売り局面でないことを確認
data1 = check_candle(get_price(periods, max-3))
data2 = check_candle(get_price(periods, max-2))
data3 = check_candle(get_price(periods, max-1))
data4 = check_ascend(get_price(periods, max-2),get_price(periods, max-3))
data5 = check_ascend(get_price(periods, max-1),get_price(periods, max-2))
if data1 or data2 or data3 or data4 or data5:
sage_flag = 1
print('③','下げ局面ではないのでフラグ立てます')
else:
sage_flag = 0
print('③','下げ局面なのでフラグ立てません')
if arbi_flag * range_flag * sage_flag == 1:
print('発注条件成立しました\n')
winsound.Beep(800, 300)
time.sleep(0.3)
winsound.Beep(800, 300)
time.sleep(0.3)
winsound.Beep(800, 300)
else:
print('発注条件成立せず\n')
time.sleep(delay)
変更箇所はこちらです。

ディスカッション
コメント一覧
まだ、コメントがありません