Pythonを使ったbitcoinアービトラージの(ほぼ)自動売買プログラムが完成しました!その③
[2020/5/5追記]ここで紹介しているプログラムは最終版ではありません。あくまで参考程度にご参照ください。最終版のプログラムは販売する形で提供させていただくことにいたしました。詳しくはこちら→https://tsurezure.info/arbitrage/index.php/2020/05/05/post-496/
こちらの記事でPythonを使ったbitcoinアービトラージの(ほぼ)自動売買プログラムの修正版を公開しましたが、まだそれでもたまにエラーで止まってしまう場合があったのでさらにロジックを見直しました。今回はそちらのソースコードを公開いたします。「try」と「except」を随所にちりばめています。また、CSVへのログ書き出しもあまり必要なくなってきたのとCSVへの書き込みに失敗して止まるケースもあったのでコメントアウトしました。ソースコードのアップばかりして解説を全然できておらずすみません。
import time
from pprint import pprint
import requests
import json
import hmac
import hashlib
from datetime import datetime
import python_bitbankcc
import winsound
import sys
import csv
from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
import gspread
filepath = '*******************************************'
gfile = ''
def Gspreadsheet():
global gfile
scopes = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/spreadsheets']
json_file = filepath+'*******************************************'
credentials = ServiceAccountCredentials.from_json_keyfile_name(json_file, scopes=scopes)
http_auth = credentials.authorize(Http())
doc_id = '*******************************************'
client = gspread.authorize(credentials)
gfile = client.open_by_key(doc_id)#読み書きするgoogle spreadsheet
order_amount = 0
active_order = 0 #注文ID
trade_id = 0 #取引ID
prev_trade_id = 0
current_BTC = 0
prev_BTC = 0
bitbank_limit_order = 0
prev_bitbank_limit_order = 0
pair = 'btc_jpy'
JPYasset=0
BTCasset=1
#GMO
apiKey = '*******************************************'
secretKey = '*******************************************'
endPoint = 'https://api.coin.z.com/private'
def GMOPrvCommon(method, path, text):
timestamp = '{0}000'.format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + text
sign = hmac.new(bytes(secretKey.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest()
headers = {
"API-KEY": apiKey,
"API-TIMESTAMP": timestamp,
"API-SIGN": sign
}
return headers
def GMO_order(order_amount,side):
method = 'POST'
path = '/v1/order'
reqBody = {
"symbol": "BTC",
"side": side,
"executionType": "MARKET",
"size": order_amount
}
text = method + path + json.dumps(reqBody)
headers = GMOPrvCommon(method, path, text)
res = requests.post(endPoint + path, headers=headers, data=json.dumps(reqBody))
print (json.dumps(res.json(), indent=2))
#CSVwrite([json.dumps(res.json(), indent=2)])
def GMO_asset(pair):
i = 0
while i == 0:
try:
method = 'GET'
path = '/v1/account/assets'
text = method + path
sign = hmac.new(bytes(secretKey.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest()
headers = GMOPrvCommon(method, path, text)
response = requests.get(endPoint + path, headers=headers)
json_data = response.json()
GMO_asset = json_data['data'][pair]['available']
i = 1
except Exception as e:
print(e)
#CSVwrite([e])
print('retry json_data')
time.sleep(1)
continue
return float(GMO_asset)
def GMO_CannotBuy():
current_BTC_price = int(python_bitbankcc.public().get_ticker('btc_jpy')["sell"])
GMO_JPYasset=GMO_asset(JPYasset)
print('JPY資金=',GMO_JPYasset)
if bitbank_amount * current_BTC_price * 2 > GMO_JPYasset:
print('JPY資金不足です')
#CSVwrite(['JPY資金不足です'])
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
return True
return False
def PriceOrder(order_amount, side):
endPoint = 'https://api.coin.z.com/public'
path = '/v1/orderbooks?symbol=BTC'
response = requests.get(endPoint + path)
json_data = response.json()
i = 0
size_sum = 0
price_sum = 0
taker_price = 0
while size_sum < order_amount:
j = 0
while j == 0:
try:
size_sum = size_sum + float(json_data["data"][side][i]["size"])
j = 1
except Exception as e:
print(e)
#CSVwrite([e])
print('retry json_data')
time.sleep(1)
response = requests.get(endPoint + path)
json_data = response.json()
price_sum = price_sum + float(json_data["data"][side][i]["price"])
taker_price = taker_price + float(json_data["data"][side][i]["price"]) * (float(json_data["data"][side][i]["size"]))
i = i + 1
delta = size_sum - order_amount
return taker_price - float(json_data["data"][side][i-1]["price"]) * delta
def GMOStatus():
i = 0
while i == 0:
try:
endPoint = 'https://api.coin.z.com/public'
path = '/v1/status'
response = requests.get(endPoint + path)
json_data = response.json()["data"]["status"]
if json_data == 'OPEN':
i = 1
else:
print('GMO closed')
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
time.sleep(10)
except Exception as e:
print(e)
#CSVwrite([e])
print('retry json_data')
time.sleep(1)
return
#bitbank
class BitBankPubAPI:
def get_ticker(pair):
pub = python_bitbankcc.public()
try:
value = pub.get_ticker(pair)
return value
except Exception as e:
print(e)
#CSVwrite([e])
return None
class BitBankPrvAPI:
def __init__(self):
API_KEY = '*******************************************'
API_SECRET = '*******************************************'
self.prv = python_bitbankcc.private(API_KEY, API_SECRET)
def get_asset(self):
try:
value = self.prv.get_asset()
return value
except Exception as e:
print(e)
#CSVwrite([e])
print('retry get_asset')
#CSVwrite(['retry get_asset'])
time.sleep(1)
value = self.prv.get_asset()
return value
def order(self, pair, price, amount, side, order_type):
try:
value = self.prv.order(pair, price, amount, side, order_type)
return value
except Exception as e:
print(e)
#CSVwrite([e])
return None
def get_active_order(self, pair):
try:
value = self.prv.get_active_orders(pair)
value = value['orders'][0]["order_id"]
return value
except Exception as e:
print(e)
#CSVwrite([e])
return 0
def cancel_order(self, pair, active_order):
try:
value = self.prv.cancel_order(pair, active_order)
return value
except Exception as e:
print(e)
#CSVwrite([e])
return None
def get_trade_history(self, pair, order_count):
try:
value = self.prv.get_trade_history(pair, order_count)
return value
except Exception as e:
print(e)
#CSVwrite([e])
return None
prv_set = BitBankPrvAPI()
pub_set = BitBankPubAPI()
def bitbank_Order(price, side):
global prev_BTC
global current_BTC
global prev_bitbank_limit_order
current_BTC = prv_set.get_asset()['assets'][1]['onhand_amount']
prev_BTC = current_BTC
print('BTC=',current_BTC)
prev_bitbank_limit_order = bitbank_limit_order
amount = bitbank_amount
order_type = 'limit'
prv_set.order(pair, price, amount, side, order_type)
print(pair, price, amount, side, order_type)
#CSVwrite(['price-amount-side-order_type', price, amount, side, order_type])
def Sound():
winsound.Beep(800, 300)
time.sleep(0.3)
winsound.Beep(800, 300)
time.sleep(0.3)
winsound.Beep(800, 300)
time.sleep(0.3)
def Sound2():
winsound.Beep(1000, 1500)
def Sound3():
winsound.Beep(900, 500)
winsound.Beep(1000, 500)
def CSVwrite(csvdata):
i = 0
while i == 0:
try:
with open(filepath+'GMO買いbitbank売りarbitrage-20200224.csv', 'a', newline="") as f:
writer = csv.writer(f)
writer.writerow(csvdata)
i = 1
except Exception as e:
print(e)
#CSVwrite([e])
print('retry CSV write')
time.sleep(1)
continue
def GsheetUpdate(cell, data):
i = 0
while i == 0:
try:
worksheet.update_acell(cell,data)
i = 1
except Exception as e:
print(e)
#CSVwrite([e])
print('retry update_acel')
Gspreadsheet()
time.sleep(1)
continue
active_order = prv_set.get_active_order(pair)
prv_set.cancel_order(pair, active_order)
prev_trade_id = prv_set.get_trade_history(pair,'1')['trades'][0]['trade_id']
print('prev_trade_id=',prev_trade_id)
max_count = 5
count = max_count-1
Gspreadsheet()
SUM_GMObitbank = 0
while 1:
dt = datetime.now()
print(dt)
GMOStatus()
active_order = prv_set.get_active_order(pair)
print('active_order = ',active_order)
#CSVwrite([dt])
#Googleスプレッドシートでパラメータ取得
print('count=',count)
count = count + 1
if count == max_count:
Gspreadsheet()
count = 0
i = 0
while i == 0:
try:
worksheet = gfile.sheet1
i = 1
except Exception as e:
print(e)
#CSVwrite([e])
print('retry gfile.sheet1')
Gspreadsheet()
continue
print('Loading OK')
cell = worksheet.acell('B1').value
print(cell)
if cell == '0':
print('cell=0')
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
time.sleep(10)
count=max_count-1
continue
bitbank_amount = float(worksheet.acell('B2').value) #発注数量
print('order_unit=', bitbank_amount)
margin = int(worksheet.acell('B3').value) #差額計算時の調整用
print('margin=',margin)
buffer = int(worksheet.acell('B4').value) #指値注文時の価格調整用
print('buffer=',buffer)
GsheetUpdate('B5',str(dt))
GsheetUpdate('B6',str(SUM_GMObitbank))
GsheetUpdate('B7',str(current_BTC))
#売却余力確認
current_BTC = prv_set.get_asset()['assets'][1]['onhand_amount']
G_current_BTC = GMO_asset(BTCasset)
time.sleep(0.1)
SUM_GMObitbank = float(current_BTC) + float(G_current_BTC)
print('SUM GMO and bitbank ',SUM_GMObitbank)
if bitbank_amount > float(current_BTC):
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
print('売却BTC不足です')
#CSVwrite(['売却BTC不足です'])
time.sleep(10)
continue
#購入余力確認
if GMO_CannotBuy():
count = max_count-1
time.sleep(10)
continue
#差額計算
price_order = PriceOrder(1, 'asks')
bitbank_limit_order = int(python_bitbankcc.public().get_ticker('btc_jpy')["sell"]) #※指値でMaker取引をするためbuyではなくsell(売り注文)の値を取得
print('bitbank_limit_order=',bitbank_limit_order)
print('prev_bitbank_limit_order=',prev_bitbank_limit_order)
price_fee = price_order * 0.0005 #GMO taker fee
limit_fee = bitbank_limit_order * -0.0002 #bitbank maker fee
print('テイカー手数料は',price_fee,'円')
print('メイカー手数料は',limit_fee,'円')
print(price_order,'円で買って(テイカー)')
print(bitbank_limit_order,'円で売れば(メイカー)')
profit = bitbank_limit_order - price_order - price_fee - limit_fee
print(profit,'円の利益!')
transfer_fee = 0 #GMOの場合送金手数料無料
#bitbankで売却
if profit > transfer_fee + margin:
if active_order == 0:
bitbank_Order(bitbank_limit_order + buffer, 'sell')
elif prev_bitbank_limit_order - bitbank_limit_order > 0 :
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
bitbank_Order(bitbank_limit_order + buffer, 'sell')
Sound()
else:
if active_order != 0:
prv_set.cancel_order(pair, active_order)
print('order canceled. order_id =', active_order)
#GMOでの購入処理
done_order = prv_set.get_trade_history(pair,'20')['trades']
i = 0
print('done_trade_id=',done_order[i]['trade_id'])
while prev_trade_id != done_order[i]['trade_id']:
order_amount = done_order[i]['amount']
print('done_order_id[',i,']=',done_order[i])
#CSVwrite(['done_order_id[',i,']=',done_order[i]])
print('order_amount=',order_amount)
print('GMOで購入', order_amount)
#CSVwrite(['GMOで購入', order_amount])
GMO_order(order_amount,"BUY")
GsheetUpdate('B9',str(dt))
Sound2()
i = i + 1
prev_trade_id = done_order[0]['trade_id']
print('prev_trade_id=',prev_trade_id)
time.sleep(1)
ゼロ送金時間アービトラージ手法の紹介はこちら↓
https://tsurezure.info/arbitrage/index.php/2020/01/26/post-326/
ディスカッション
コメント一覧
はじまめまして。
YouTubeを拝見されていただきました。
プログラムの制作・修正に大変だと思いますが頑張ってください。応援しつつ、参考になります。
コメントありがとうございます!励みになります!