Linux活用レシピ > 仮想通貨に活用 > RaspberryPiで仮想通貨の自動取引システムを作る | |
このページでは、「Raspberry Pi」と、それで動作するOS「Raspbian」を利用して、低電力の仮想通貨の自動取引システム(自動取引bot)を作る方法を紹介します。 |
|
└ 説明 準備 ├ ハードウェア ├ 開発環境準備 └ 取引所準備 取引 ├ バックテスト ├ APIの確認 └ 自動取引 製品 このレシピで作成した「日本語版 Rapbian (LibreOffice付) インストール済SDカード」\1800 は以下の販売チャネルで。 |
はじめに
◆RaspberryPiで自動取引システム(自動取引bot)を作る◆ |
pi@raspberrypi:~ $ vi coincheck_ticker.py[ENTER] |
import requests
import json
URL = 'https://coincheck.com/api/ticker'
coincheck = requests.get(URL).json()
for key, item in coincheck.items():
print("%-9s : %-10.9s " % (key, item))
pi@raspberrypi:~ $ python3 coincheck_ticker.py[ENTER] |
last : 6295052.0 bid : 6294007.0 ask : 6295999.0 high : 6328233.0 low : 6145001.0 volume : 1870.4447 timestamp : 162000241 |
RESPONSE | ITEMS |
last | 最後の取引の価格 |
bid | 現在の買い注文の最高価格 |
ask | 現在の売り注文の最安価格 |
high | 24時間での最高取引価格 |
low | 24時間での最安取引価格 |
volume | 24時間での取引量 |
timestamp | 現在の時刻 |
Pythonプログラムは以下になります。
pi@raspberrypi:~ $ vi coincheck_order_books.py[ENTER] |
import requests
import json
URL = 'https://coincheck.com/api/order_books'
coincheck = requests.get(URL).json()
for key in coincheck.keys():
print(key, ":")
for value in coincheck[key]:
print(value)
print()
pi@raspberrypi:~ $ python3 coincheck_order_books.py[ENTER] |
asks : ['6314959.0', '0.1'] ['6314960.0', '0.028'] ['6314962.0', '0.01'] ['6316236.0', '0.0163328'] ['6316315.0', '0.025'] ['6316611.0', '0.015'] ['6316612.0', '0.07'] ['6317542.0', '0.025'] ['6317794.0', '0.02444'] ['6318586.0', '0.1'] ['6319098.0', '0.049'] ['6319099.0', '0.15'] ['6319571.0', '0.015'] ['6319572.0', '0.0332'] ['6319667.0', '0.1'] ['6319812.0', '0.02'] ['6319999.0', '0.01'] ['6320203.0', '0.0138'] ['6321745.0', '0.01'] ['6322163.0', '0.15'] ['6322292.0', '0.015'] ['6322499.0', '0.005'] ['6322527.0', '0.01'] ['6323000.0', '0.07'] ['6324999.0', '0.005'] ['6325469.0', '0.005'] ['6325471.0', '0.01384774'] ['6325478.0', '0.2'] ['6325772.0', '0.0668'] ['6326735.0', '0.005'] ['6327499.0', '0.0034656'] ['6327894.0', '0.01'] ['6328582.0', '0.01'] ['6328728.0', '0.1933'] ['6329000.0', '0.075'] ['6329900.0', '0.0071'] ['6329999.0', '0.025'] ['6330000.0', '0.124'] ['6331401.0', '0.00738097'] ['6331442.0', '0.025'] ['6332442.0', '0.025'] ['6332499.0', '0.005'] ['6332711.0', '0.00843265'] ['6332771.0', '0.02'] ['6333000.0', '0.01'] ['6333976.0', '0.2'] ['6334900.0', '0.01'] ['6334999.0', '0.005'] ['6335000.0', '0.055'] ['6336205.0', '0.01386209'] ['6336208.0', '0.01382359'] ['6336213.0', '0.05'] ['6336592.0', '0.005'] ['6336594.0', '0.01383955'] ['6336596.0', '0.0138616'] ['6336597.0', '0.0138575'] ['6336628.0', '0.6736'] ['6337499.0', '0.005'] ['6337688.0', '0.2'] ['6337735.0', '0.00794'] ['6337787.0', '0.005'] ['6337931.0', '0.01'] ['6339019.0', '0.1'] ['6339900.0', '0.0071'] ['6339995.0', '0.005'] ['6339999.0', '0.01'] ['6340000.0', '0.34764551'] ['6341000.0', '0.1'] ['6341214.0', '0.02'] ['6342499.0', '0.01'] ['6343000.0', '0.1'] ['6344000.0', '0.11'] ['6344999.0', '0.005'] ['6345000.0', '0.305'] ['6345002.0', '0.025'] ['6345630.0', '0.05'] ['6347000.0', '0.005'] ['6347499.0', '0.005'] ['6348507.0', '0.00502'] ['6349500.0', '0.01687'] ['6349586.0', '0.15'] ['6349603.0', '0.04'] ['6349900.0', '0.0071'] ['6349999.0', '0.01'] ['6350000.0', '1.56763995'] ['6350540.0', '0.0077875'] ['6352499.0', '0.01'] ['6354714.0', '0.2'] ['6354999.0', '0.005'] ['6355000.0', '0.077'] ['6355800.0', '0.01595686'] ['6356000.0', '0.01'] ['6356129.0', '0.01'] ['6356616.0', '0.00794'] ['6356865.0', '0.01'] ['6357770.0', '0.01'] ['6359900.0', '0.0071'] ['6359995.0', '0.005'] ['6359999.0', '0.01'] ['6360000.0', '0.09143472'] ['6360247.0', '5.2976'] ['6361050.0', '0.02700496'] ['6362499.0', '0.005'] ['6363636.0', '0.02'] ['6364347.0', '0.04303697'] ['6364724.0', '0.01'] ['6364999.0', '0.01'] ['6365000.0', '1.0'] ['6365380.0', '0.5'] ['6365630.0', '0.05'] ['6365877.0', '0.0195'] ['6369900.0', '0.0071'] ['6369999.0', '0.01'] ['6370000.0', '0.46'] ['6371000.0', '0.04'] ['6372000.0', '0.1'] ['6372143.0', '0.01'] ['6372499.0', '0.005'] ['6373650.0', '0.0125'] ['6373939.0', '0.00611866'] ['6374000.0', '0.005'] ['6374999.0', '0.005'] ['6375000.0', '0.055'] ['6375106.0', '0.005'] ['6376000.0', '0.01213567'] ['6379000.0', '0.01'] ['6379900.0', '0.0071'] ['6379995.0', '0.005'] ['6379999.0', '0.01'] ['6380000.0', '0.65801518'] ['6380975.0', '3.1933'] ['6382000.0', '0.105'] ['6382403.0', '0.01'] ['6382499.0', '0.005'] ['6384241.0', '0.01077264'] ['6384999.0', '0.005'] ['6385000.0', '0.079'] ['6385657.0', '0.08'] ['6386001.0', '0.01'] ['6387499.0', '0.005'] ['6388000.0', '0.01'] ['6388507.0', '0.00502'] ['6388952.0', '0.22'] ['6389900.0', '0.0071'] ['6389999.0', '0.015'] ['6390000.0', '0.20927011'] ['6390200.0', '0.3'] ['6392000.0', '0.12064455'] ['6392499.0', '0.005'] ['6393939.0', '0.00609952'] ['6394000.0', '0.005'] ['6394999.0', '0.205'] ['6395000.0', '0.22619289'] ['6398000.0', '0.019'] ['6398300.0', '0.009'] ['6399551.0', '0.005'] ['6399876.0', '0.005'] ['6399900.0', '0.0071'] ['6399910.0', '0.01385817'] ['6399995.0', '0.005'] ['6399999.0', '0.31955596'] ['6400000.0', '3.12532399'] ['6400583.0', '0.2'] ['6402000.0', '0.005'] ['6402499.0', '0.005'] ['6403506.0', '0.05'] ['6404000.0', '0.01'] ['6404307.0', '0.05'] ['6404999.0', '0.005'] ['6405489.0', '0.03122322'] ['6406853.0', '0.01'] ['6407000.0', '0.01'] ['6407695.0', '0.01'] ['6409900.0', '0.0285'] ['6409999.0', '0.065'] ['6410000.0', '0.7436664'] ['6410380.0', '0.01'] ['6411000.0', '0.01'] ['6411111.0', '0.3'] ['6412499.0', '0.005'] ['6413271.0', '0.01'] ['6414999.0', '0.005'] ['6415000.0', '0.02540053'] ['6415106.0', '0.005'] ['6417623.0', '0.006'] ['6418000.0', '0.01'] ['6419397.0', '0.00607533'] ['6419480.0', '0.016'] ['6419900.0', '0.0071'] ['6419995.0', '0.005'] ['6419999.0', '0.03'] ['6420000.0', '0.22693749'] ['6420380.0', '0.01'] ['6421000.0', '0.01'] ['6421007.0', '0.005'] ['6422000.0', '0.1'] ['6422499.0', '0.005'] ['6423000.0', '0.34516445'] ['6423858.0', '0.005'] ['6424999.0', '0.005'] bids : ['6312171.0', '0.0196'] ['6311868.0', '0.025'] ['6311867.0', '0.375'] ['6311770.0', '0.07'] ['6311758.0', '0.025'] ['6311568.0', '0.02519'] ['6311319.0', '0.055'] ['6311221.0', '0.02'] ['6310747.0', '0.5685'] ['6310554.0', '0.015'] ['6310553.0', '0.028'] ['6310404.0', '0.01'] ['6310001.0', '0.015'] ['6310000.0', '0.1828'] ['6309376.0', '0.025'] ['6309200.0', '0.01'] ['6307503.0', '0.015'] ['6307502.0', '0.2'] ['6307501.0', '0.005'] ['6307392.0', '0.15'] ['6306988.0', '0.121'] ['6306655.0', '0.15'] ['6305362.0', '0.01418307'] ['6305328.0', '0.2'] ['6305177.0', '0.005'] ['6305001.0', '0.01'] ['6303767.0', '0.015'] ['6303766.0', '0.2'] ['6302603.0', '0.0668'] ['6301422.0', '0.01'] ['6301226.0', '0.005'] ['6300001.0', '0.015'] ['6300000.0', '0.09142857'] ['6299601.0', '0.2'] ['6299374.0', '0.02'] ['6298959.0', '0.01'] ['6296509.0', '0.1933'] ['6295001.0', '0.015'] ['6294241.0', '0.79522174'] ['6290500.0', '0.01386793'] ['6290164.0', '0.01888793'] ['6290005.0', '0.005'] ['6290001.0', '0.015'] ['6290000.0', '0.005'] ['6289677.0', '0.0538'] ['6288269.0', '0.02'] ['6286238.0', '0.00504'] ['6285186.0', '0.01386209'] ['6285183.0', '0.01'] ['6285181.0', '0.02768729'] ['6285180.0', '0.01382359'] ['6285179.0', '0.0138616'] ['6285178.0', '0.0138575'] ['6285172.0', '0.6736'] ['6285001.0', '0.015'] ['6285000.0', '0.01'] ['6282807.0', '0.04'] ['6282502.0', '0.05'] ['6280238.0', '0.00502'] ['6280033.0', '1.60120767'] ['6280001.0', '0.015'] ['6280000.0', '1.1528'] ['6279600.0', '1.0'] ['6275001.0', '0.01'] ['6274000.0', '0.00501'] ['6272502.0', '0.05'] ['6272501.0', '0.005'] ['6271238.0', '0.00504'] ['6270005.0', '0.005'] ['6270001.0', '0.015'] ['6270000.0', '0.02'] ['6269008.0', '0.0074514'] ['6265050.0', '0.146'] ['6265001.0', '0.005'] ['6264836.0', '0.074'] ['6264803.0', '5.1971'] ['6262210.0', '0.00794'] ['6260001.0', '0.01953076'] ['6260000.0', '0.02'] ['6255001.0', '0.005'] ['6253257.0', '0.0074514'] ['6252010.0', '0.08'] ['6250005.0', '0.005'] ['6250001.0', '0.02'] ['6250000.0', '0.105448'] ['6249622.0', '0.00794'] ['6245001.0', '0.005'] ['6245000.0', '0.005'] ['6240500.0', '0.05'] ['6240001.0', '0.015'] ['6240000.0', '0.52'] ['6238135.0', '0.00819654'] ['6235001.0', '0.005'] ['6235000.0', '0.00611'] ['6232000.0', '0.01'] ['6231500.0', '0.05'] ['6230778.0', '3.2711'] ['6230741.0', '0.00794'] ['6230005.0', '0.005'] ['6230001.0', '0.015'] ['6230000.0', '0.0442'] ['6227501.0', '0.005'] ['6227251.0', '0.005'] ['6225001.0', '0.005'] ['6225000.0', '0.01'] ['6223644.0', '0.00819654'] ['6220001.0', '0.015'] ['6220000.0', '0.005'] ['6217608.0', '0.016'] ['6215001.0', '0.01'] ['6215000.0', '0.013'] ['6213000.0', '0.1925'] ['6210005.0', '0.005'] ['6210001.0', '0.015'] ['6210000.0', '0.01305152'] ['6209783.0', '0.00894168'] ['6207548.0', '0.005'] ['6205001.0', '0.015'] ['6205000.0', '0.00805801'] ['6204000.0', '0.00501'] ['6200001.0', '0.015'] ['6200000.0', '1.32568962'] ['6199000.0', '0.005'] ['6196552.0', '0.00894168'] ['6196000.0', '0.005'] ['6195630.0', '0.05'] ['6195001.0', '0.005'] ['6193000.0', '0.005'] ['6190005.0', '0.005'] ['6190001.0', '0.015'] ['6190000.0', '0.12501'] ['6189000.0', '0.005'] ['6188946.0', '0.5'] ['6186456.0', '0.6'] ['6185834.0', '0.005'] ['6185630.0', '0.05'] ['6185001.0', '0.005'] ['6185000.0', '0.01'] ['6184834.0', '0.005'] ['6183951.0', '0.00968682'] ['6183834.0', '0.005'] ['6182501.0', '0.005'] ['6182495.0', '1.3452'] ['6180123.0', '0.005'] ['6180001.0', '0.015'] ['6180000.0', '0.20118122'] ['6177000.0', '0.005'] ['6175001.0', '0.005'] ['6175000.0', '0.19701'] ['6171980.0', '0.00968682'] ['6170150.0', '0.01'] ['6170005.0', '0.005'] ['6170001.0', '0.015'] ['6170000.0', '1.7924149'] ['6168200.0', '0.3'] ['6168150.0', '0.01'] ['6165001.0', '0.005'] ['6165000.0', '0.005'] ['6164000.0', '0.00501'] ['6163200.0', '0.005'] ['6162550.0', '0.2'] ['6162499.0', '0.01'] ['6162010.0', '0.2'] ['6161100.0', '0.00697927'] ['6161020.0', '0.08115539'] ['6161018.0', '0.11184223'] ['6160639.0', '0.01043196'] ['6160493.0', '0.005'] ['6160248.0', '0.0071716'] ['6160001.0', '0.02'] ['6160000.0', '0.31996184'] ['6159780.0', '0.005'] ['6159572.0', '0.02435234'] ['6158966.0', '0.05'] ['6158501.0', '0.05'] ['6158000.0', '0.00501'] ['6157900.0', '0.0055'] ['6156901.0', '0.01'] ['6156660.0', '0.05'] ['6156510.0', '0.1'] ['6155001.0', '0.005'] ['6155000.0', '0.005'] ['6152086.0', '0.005'] ['6151200.0', '0.3'] ['6151100.0', '0.00699061'] ['6151000.0', '0.05'] ['6150500.0', '0.3795'] ['6150005.0', '0.005'] ['6150001.0', '0.015'] ['6150000.0', '0.44018208'] ['6149000.0', '0.015'] ['6148770.0', '0.2'] ['6148567.0', '0.2047595'] ['6148021.0', '0.01234465'] ['6147600.0', '0.01'] ['6146000.0', '0.00501'] ['6145001.0', '0.00867047'] ['6145000.0', '0.005'] ['6143200.0', '0.005'] ['6142000.0', '0.01369846']
asks | 売り注文の情報 |
bids | 買い注文の情報 |
*order_type | 注文のタイプ("sell" or "buy") |
*pair | 取引ペア。現在は "btc_jpy" "etc_jpy" "fct_jpy" "mona_jpy"が利用可能です。 |
amount | 注文での量。(例)0.1 |
price | 注文での金額。(例)28000 |
Pythonプログラムは以下になります。
pi@raspberrypi:~ $ vi coincheck_rate.py[ENTER] |
import requests
import json
URL = 'https://coincheck.com/api/exchange/orders/rate'
params = {'order_type': 'sell', 'pair': 'btc_jpy', 'amount': 0.1}
coincheck = requests.get(URL, params=params).json()
print(coincheck)
params = {'order_type': 'buy', 'pair': 'btc_jpy', 'price': 280000}
coincheck = requests.get(URL, params=params).json()
print(coincheck)
pi@raspberrypi:~ $ python3 coincheck_rate.py[ENTER] |
{'success': True, 'rate': '6360000.15', 'amount': '0.1', 'price': '636000.015'} {'success': True, 'rate': '6361560.18172', 'amount': '0.04401436', 'price': '280000.0'}
売り注文で、取引ペアが「btc_jpy」の数量0.1の場合 | 金額は636000.015円 |
買い注文で、取引ペアが「btc_jpy」の金額280000円の場合 | 数量は0.04401436ビットコイン |
Pythonプログラムは以下になります。
pi@raspberrypi:~ $ vi coincheck_rate_pair.py[ENTER] |
import requests
import json
coins = {'BTC': 'btc_jpy', 'ETH': 'eth_jpy',
'XEM': 'xem_jpy', 'BCH': 'bch_jpy',
'MONA': 'mona_jpy'}
URL = 'https://coincheck.com/api/rate/'
for key, item in coins.items():
coincheck = requests.get(URL+item).json()
print("%-4s : %-10s" % (key, coincheck['rate']))
pi@raspberrypi:~ $ python3 coincheck_rate.py[ENTER] |
BTC : 6242660.5 ETH : 365323.9261125 XEM : 38.01780549 BCH : 110598.1036065 MONA : 309.13657272 |
ビットコイン | 金額は6242660.5円 |
イーサリアム | 金額は365323.9261125円 |
ネム | 金額は38.01780549円 |
ビットコインキャッシュ | 金額は110598.1036065円 |
モナコイン | 金額は6242660.5円 |
また、実際にお金が動きますので、くれぐれも自己責任でお願いします。
なお、プログラムは、前半のクラスの定義と後半の取引の指示に分かれます。
また、プログラム中に以下の部分が出てきますので、こちらにご自身のアカウントのAPIキーを入れてください。
Pythonプログラムは以下になります。
pi@raspberrypi:~ $ vi coincheck_privateapi.py[ENTER] |
import json
import requests
import time
import hmac
import hashlib
class Coincheck:
def __init__(self, access_key, secret_key, url='https://coincheck.com'):
self.access_key = access_key
self.secret_key = secret_key
self.url = url
def get(self, path, params=None):
if params != None:
params = json.dumps(params)
else:
params = ''
nonce = str(int(time.time()))
message = nonce + self.url + path + params
signature = self.getSignature(message)
return requests.get(
self.url+path,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def post(self, path, params):
params = json.dumps(params)
nonce = str(int(time.time()))
message = nonce + self.url + path + params
signature = self.getSignature(message)
return requests.post(
self.url+path,
data=params,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def delete(self, path):
nonce = str(int(time.time()))
message = nonce + self.url + path
signature = self.getSignature(message)
return requests.delete(
self.url+path,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def getSignature(self, message):
signature = hmac.new(
bytes(self.secret_key.encode('ascii')),
bytes(message.encode('ascii')),
hashlib.sha256
).hexdigest()
return signature
def getHeader(self, access_key, nonce, signature):
headers = {
'ACCESS-KEY': access_key,
'ACCESS-NONCE': nonce,
'ACCESS-SIGNATURE': signature,
'Content-Type': 'application/json' # 超重要。
}
return headers
access_key = '取得したアクセスキー'
secret_key = '取得したシークレットキー'
# インスタンスを作りましょう。
coincheck = Coincheck(access_key, secret_key)
# 1000円分のビットコインを成行買い注文
path_orders = '/api/exchange/orders'
params = {
"pair": "btc_jpy",
"order_type": "market_buy",
"market_buy_amount": 1000, # 量ではなく金額
}
result = coincheck.post(path_orders, params)
print(result)
pi@raspberrypi:~ $ python3 coincheck_privateapi.py[ENTER] |
{'success': False, 'error': 'Amount 量が最低量(0.005 BTC)を下回っています'} |
2021/05/04時点のCoincheck取引所、最小注文数量は、以下の通りです。
(BTC/JPY) | 0.005BTC以上 かつ 500円(相当額)以上から |
(FCT/JPY) | 500円(相当額)以上から |
(ETC/JPY) | 500円(相当額)以上から |
(MONA/JPY) | 500円(相当額)以上から |
「624万円」の「0.005 BTC」は2万7千円弱です。
ただの確認にこんな冒険はしたくないので、ここはモナコインを1000円分買うコードに変更します。
Pythonプログラムは以下になります。
pi@raspberrypi:~ $ vi coincheck_privateapi_mona.py[ENTER] |
import json
import requests
import time
import hmac
import hashlib
class Coincheck:
def __init__(self, access_key, secret_key, url='https://coincheck.com'):
self.access_key = access_key
self.secret_key = secret_key
self.url = url
def get(self, path, params=None):
if params != None:
params = json.dumps(params)
else:
params = ''
nonce = str(int(time.time()))
message = nonce + self.url + path + params
signature = self.getSignature(message)
return requests.get(
self.url+path,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def post(self, path, params):
params = json.dumps(params)
nonce = str(int(time.time()))
message = nonce + self.url + path + params
signature = self.getSignature(message)
return requests.post(
self.url+path,
data=params,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def delete(self, path):
nonce = str(int(time.time()))
message = nonce + self.url + path
signature = self.getSignature(message)
return requests.delete(
self.url+path,
headers=self.getHeader(self.access_key, nonce, signature)
).json()
def getSignature(self, message):
signature = hmac.new(
bytes(self.secret_key.encode('ascii')),
bytes(message.encode('ascii')),
hashlib.sha256
).hexdigest()
return signature
def getHeader(self, access_key, nonce, signature):
headers = {
'ACCESS-KEY': access_key,
'ACCESS-NONCE': nonce,
'ACCESS-SIGNATURE': signature,
'Content-Type': 'application/json' # 超重要。
}
return headers
access_key = '取得したアクセスキー'
secret_key = '取得したシークレットキー'
# インスタンスを作りましょう。
coincheck = Coincheck(access_key, secret_key)
# 1000円分のMONAコインを成行買い注文
path_orders = '/api/exchange/orders'
params = {
"pair": "mona_jpy",
"order_type": "market_buy",
"market_buy_amount": 1000, # 量ではなく金額
}
result = coincheck.post(path_orders, params)
print(result)
pi@raspberrypi:~ $ python3 coincheck_privateapi_mona.py[ENTER] |
{'success': True, 'id': NNNNNNNNNN, 'amount': None, 'rate': None, 'order_type': 'market_buy', 'pair': 'mona_jpy', 'created_at': '2021-05-03T16:00:28.000Z', 'market_buy_amount': '1000.0', 'stop_loss_rate': None} |