BitflyerFXでCCXTを使って成行注文を出しその執行価格を取得する方法

Bitflyerの自動売買BOTで成行注文を出す場合、その執行価格を把握しておきたい場面があると思います。この記事では成行注文の執行価格を表示するpythonコードを紹介しておきます。

前提

CCXTライブラリを使う

CCXT経由でBitflyerに成行注文を出す方法は、以前にこちらの記事で解説しているので参考にしてください。

pythonコード


# 成行注文の執行状況を確認する関数
def check_market_order( id,lot ):
	while True:
		try:
			size = []
			price = []
			
			executions = bitflyer.private_get_getexecutions( params = { "product_code" : "FX_BTC_JPY" })
			for exec in executions:
				if exec["child_order_acceptance_id"] == id:
					size.append( exec["size"] )
					price.append( exec["price"] )
			
			# 全部約定するまで待つ
			if round(sum(size),2) != lot:
				time.sleep(20)
				print("注文がすべて約定するのを待っています")
			else:
				# 平均価格を計算する
				average_price = round(sum( price[i] * size[i] for i in range(len(price)) ) / sum(size))
				print("すべての成行注文が執行されました")
				print("執行価格は平均 {}円です".format(average_price))
				return average_price
				
		except ccxt.BaseError as e:
			print("BitflyerのAPIで問題発生 : ",e)
			print("20秒待機してやり直します")
			time.sleep(20)

コードの解説

まずは以下のコードでBitflyerから約定履歴の一覧を取得しています。

executions = bitflyer.private_get_getexecutions( params = { "product_code" : "FX_BTC_JPY" })

BitflyerのAPIでは「 GET /v1/me/getexecutions 」で自分の約定履歴の一覧を取得することができます。取得した約定履歴の一覧からは、[size]で数量、[price]で執行価格を取得することができます。

(参考)
BitflyerのAPI仕様書の説明ページ
CCXT経由で個別のAPIを使用する方法

基本的な流れ

成行注文の場合、注文がいくつかに分割されて異なる価格で執行されることも多いです。そのため、上記の関数では以下の2つの情報を必要としています。

(1)成行注文を送ったときに返ってくる注文ID
(2)成行注文を出したときの注文数量

成行注文は、分割されて約定しても全て同一の注文ID(order_acceptance_id)で記録されます。例えば、以下のような感じです。

# 例)0.09BTC の売りの成行注文が、0.08BTC と 0.01BTCに割れて執行された場合

[{'child_order_acceptance_id': 'JRF20180424-060559-396699',
  'child_order_id': 'JFX20180424-021850-855859F',
  'commission': 0.0,
  'exec_date': '2018-04-24T02:18:50.45',
  'id': 215522439,
  'price': 958028.0,
  'side': 'SELL',
  'size': 0.08},
 {'child_order_acceptance_id': 'JRF20180424-060559-396699',
  'child_order_id': 'JFX20180424-021850-855859F',
  'commission': 0.0,
  'exec_date': '2018-04-24T02:18:50.45',
  'id': 215522439,
  'price': 958290.0,
  'side': 'SELL',
  'size': 0.01}
]

そのため、成行注文を出したときに注文ID(order_acceptance_id)を覚えておいて、その注文IDで約定履歴を検索すれば、分割されて執行されたすべての注文を捕捉することができます。

1.注文がすべて執行されたことを確認する

成行注文を送った後に、20秒ごとに約定履歴をAPIで取得して、注文IDが一致している注文の「価格」と「数量」を取得します。それが以下の部分です。

for exec in executions:
	if exec["child_order_acceptance_id"] == id:
		size.append( exec["size"] )
		price.append( exec["price"] )

そして「数量」の合計が、最初に送った注文数量と一致すれば、すべて約定したと判断します。一致しなければ、一致するまで20秒ごとに確認を繰り返します。(秒数は適当に変更してください)

# 全部約定するまで待つ
if round(sum(size),2) != lot:
	time.sleep(20)
	print("注文がすべて約定するのを待っています")
	# ここでwhileループの先頭に戻る

一致したらすべての注文が執行されたものとして次に進みます。

2.執行価格の平均を計算する

すべての注文数量が約定したことを確認できたら、執行価格を計算します。これは以下の式で計算できます。

A)注文1の価格 × 注文1の数量 + 注文2の価格 × 注文2の数量 + 注文3の価格 × 注文3の数量 +….
B)注文数量の合計

執行価格の平均 A ÷ B

これをpythonで1行で書くと以下のようになります。

# 平均価格を計算する
average_price = round(sum( price[i] * size[i] for i in range(len(price)) ) / sum(size))

3.注文サイズの計算方法の注意点

もう1つだけ注意点があります。それが小数点の計算です。pythonでは2進法で小数を計算するため、成行注文が細かく割れてしまった場合には、注文サイズが送ったものと一致しなくなることがあります。

具体例

例えば、0.21BTCを成行注文で出した場合を仮定してください。そして注文が以下のように割れて約定したとします。

▽ 0.21BTCの注文

注文1) 0.11634476 BTC
注文2) 0.08175024 BTC
注文3) 0.011905 BTC

合計 0.21BTC

ご自身で確認していただくとわかりますが、これは電卓で計算すると丁度 0.21BTCになります。それではpythonで同じ計算をしてみましょう。


size1 = 0.11634476
size2 = 0.08175024
size3 = 0.011905

print(size1 + size2 + size3)

#----- 実行結果 ------
0.21000000000000002

この計算結果は、なんとpythonでは 0.21000000000000002 になってしまいます。そこでround()を使って、注文したときと同じ桁数に小数点を丸める必要があります。それが以下の箇所です。


# 全部約定するまで待つ
if round(sum(size),2) != lot:

これを最初私はよくわかっていなかったのですが、note読者の方に症状を教えていただき発見できました。いつも計算が一致しないわけではなく、細かい単位で注文が割れた場合の一部のケースでこの症状がおこるようです。

参考:「pythonの浮動小数点演算の問題

成行注文のコードと組み合わせる

最後に成行注文を出すコードと組み合わせたパターンも書いておきます。

以下のコードで成行注文を出せば、約定後にその執行価格を返すところまでセットで実行できます。損益やスリッページの計算、建値の計算、損切価格ラインの決定などに使ってください。

# 成行注文を出す関数
def market_order(side,lot):
	while True:
		try:
			order = bitflyer.create_order(
				symbol = 'BTC/JPY',
				type='market',
				side= side,
				amount= lot,
				params = { "product_code" : "FX_BTC_JPY" })

			# 注文時のidを記録しておく
			order_id = order["id"]
			time.sleep(30)
			
			# 執行状況を確認する関数を呼ぶ
			average_price = check_market_order( order_id, lot )
			return average_price
			
		except ccxt.BaseError as e:
			print("Bitflyerの注文APIでエラー発生",e)
			print("注文が失敗しました")
			print("30秒待機してやり直します")
			time.sleep(30)


# 成行注文の執行状況を確認する関数
def check_market_order( id,lot ):
	while True:
		try:
			size = []
			price = []
			
			executions = bitflyer.private_get_getexecutions( params = { "product_code" : "FX_BTC_JPY" })
			for exec in executions:
				if exec["child_order_acceptance_id"] == id:
					size.append( exec["size"] )
					price.append( exec["price"] )
			
			# 全部約定するまで待つ
			if round(sum(size),2) != lot:
				time.sleep(20)
				print("注文がすべて約定するのを待っています")
			else:
				# 平均価格を計算する
				average_price = round(sum( price[i] * size[i] for i in range(len(price)) ) / sum(size))
				print("すべての成行注文が執行されました")
				print("執行価格は平均 {}円です".format(average_price))
				return average_price
				
		except ccxt.BaseError as e:
			print("BitflyerのAPIで問題発生 : ",e)
			print("20秒待機してやり直します")
			time.sleep(20)

CCXT経由でBitflyerFXの現在のポジションの平均建値とサイズを取得する

BitflyerFXからAPIで現在のポジションの建値やサイズを取得する方法を解説します。具体的な使い道として以下のような場面を想定しています。

(1)BOTを再稼働させたときにポジション情報を取得する
(2)注文拒否や二重約定などでBOTがポジションを見失った場合
(3)ループのたびにポジション情報を取得する仕様にする場合

前提

CCXTライブラリを使います。

CCXTライブラリのGithubページ
CCXTライブラリって何?を解説
CCXTライブラリで取引所のAPIを直接使う方法

Pythonコード


import ccxt

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = ''
bitflyer.secret = ''

def check_bf_positions():
	while True:
		try:
			size = []
			price = []
			positions = bitflyer.private_get_getpositions( params = { "product_code" : "FX_BTC_JPY" })
			if not positions:
				print("現在ポジションは存在しません")
				return 0,0,None
			for pos in positions:
				size.append( pos["size"] )
				price.append( pos["price"] )
				side = pos["side"]
			
			# 平均建値を計算する
			average_price = round(sum( price[i] * size[i] for i in range(len(price)) ) / sum(size))
			sum_size = round(sum(size),2)
			print("保有中の建玉:合計{}つ\n平均建値:{}円\n合計サイズ:{}BTC\n方向:{}".format(len(price),average_price,sum_size,side))
			
			# 価格・サイズ・方向を返す
			return average_price,sum_size,side
				
		except ccxt.BaseError as e:
			print("BitflyerのAPIで問題発生 : ",e)
			print("20秒待機してやり直します")
			time.sleep(20)

# 実行処理
price,size,side = check_bf_positions()

保有中の建玉の価格とサイズ、エントリーの方向の3つをセットで返す関数です。複数のポジションを保有している場合は、平均建値と合計サイズを計算して返します。

BitflyerFXでは両建てはできないので、方向(BUYかSELLか)は、複数ポジションのうち1つを参照すれば大丈夫です。そのため、最後に取得したポジションの方向を参照しています。

ポジションが存在しない場合

もしポジションが存在しなければ、price=0, size=0, side=None を返します。これらのいずれかを使えば、外部から以下のように「ポジション無し」を判定できます。

▽ ポジションの有無を判定したい場合


price,size,side = check_bf_positions()
if size == 0:
	print("ポジションは存在しません")

BitflyerのAPI

BitflyerのAPIには、建玉の一覧を取得するAPI「GET /v1/me/getpositions」を、CCXTライブラリ経由で使用しています。

BitflyerAPIの公式ページ

このAPIを使用すると、建玉の情報が配列で返ってきます。そのため、以下のような形式で情報にアクセスできます。

▽ 返り値を positions に入れた場合


positions[0]    # 最初に取得したポジションの情報
positions[-1]   # 最後に取得したポジションの情報

positions[0]["price"]  # エントリー価格
positions[0]["side"]   # エントリーの方向
positions[0]["size"]   # ポジションのサイズ


いくつポジションを保有しているかわからない場合は、for文で回して全ての情報を取得します。

サイズ計算の注意点

合計サイズは、APIで取得した各建玉のサイズの合計値を計算しています。しかしpythonは足し算などの演算を2進法で計算するため、四捨五入しないと最終的な値がおかしくなることがあります。

具体例

例えば、以下のような3つの建玉がある場合、合計サイズは普通に計算すれば 0.21BTC になります。しかしpythonが2進法で足し算をすると、これは0.21 にならず、0.21000000000002 になってしまいます。


size1 = 0.11634476
size2 = 0.08175024
size3 = 0.011905

print(size1 + size2 + size3)

#----- 実行結果 ------
0.21000000000000002

そのため、合計サイズは四捨五入して規定の小数点以下に丸めておく必要があります。例えば、ご自身のBOTがすべての注文を小数点以下2桁で管理しているなら、小数点以下2桁で丸めれば大丈夫です。

これが上記コードの以下の箇所です。

sum_size = round(sum(size),2)

Bitflyerや各取引所の個別APIをCCXTライブラリ経由で直接利用する方法

CCXTライブラリでは、どの取引所でも共通で使える関数が用意されています。

例えば、create_order()という注文を出すための関数は、Bitflyerだけでなく、Coincheck、Zaif、Bitmexなどでも共通で使えます。これはCCXTが各取引所ごとのAPIの仕様の違いを、見えない裏側で処理してまとめてくれているからです。

・参考:CCXTが便利な理由

しかし一方で、各取引所にしか存在しない独自のAPIを使いたい場合は、CCXTの共通の関数ではカバーされていない場合があります。

例:Bitflyerの特殊注文

例えば、ご存知のように、Bitflyerでは「特殊注文」ができます。これは、例えば、100万円の買い注文と同時に条件付で110万円の売り注文を出すIFD注文や、110万円の利確注文と90万円の損切注文を同時に出し、どちらか1つが通ればもう片方を自動的にキャンセルするOCO注文などです。

しかしこれらの特殊注文は、CCXTの共通の関数からは出すことができないため、BitflyerのAPIを直接使う必要があります。

各取引所のAPIを直接使う方法

最初にまず結論からいいます。
CCXTでは、基本的に取引所のすべてのAPIが「明示されない関数」として内部で実装されています。すべての取引所のAPIは、以下のようなルールで関数を作れば、CCXT経由でも使用することができます。

例)BitflyerのAPI
APIの種類 : プライベートAPI
APIのメソッド : GET方式
APIのパス : /v1/me/getcollateral

例)CCXTの内部で実装されている関数名

bitflyer.private_get_getcollateral()

つまり各取引所のAPIをCCXT経由で直接使いたい場合は、以下の3つの情報を調べればいいことになります。この3つの情報がわかれば、以下のルールで関数名を組み立てられます。

X)プライベートAPIかパブリックAPIか?
Y)メソッドはGET方式か?POST方式か?
Z)APIのリクエストURL(パス)は?

関数名 : .X_Y_Z()

例えば、今回の例であげたBitflyerのFXの証拠金や維持率を取得するためのAPI(v1/me/getcollateral)の場合、公式ドキュメントを調べれば、以下のように記載されています。


・BitflyerAPIドキュメント

個人アカウントの残高を取得するAPIが、プライベートAPIなのは明らかなので、上記のドキュメントから「.private_get_getcollateral()」が使えるんだろうな、とアタリをつけることができます。(/v1/me/ の部分は無視して構いません)

なお、どのようなパラメーターを渡すことができるか(または、どのようなパラメーターが必須か?)は、各取引所のAPIドキュメントで調べる必要があります。

プログラム初心者向けの流れ

何かやりたいことがある場合、まずはそれがCCXTの共通の関数で対応できないかを調べます。前の記事でも説明しましたが、各取引所がどのような共通の関数に対応しているかは、「.has」で調べることができます。

▽ 取引所で対応している共通関数を調べるためのコード


import ccxt

bitflyer = ccxt.bitflyer()
method_list = bitflyer.has

for key,value in method_list.items() :
	if value == True:
		print( key )


これを実行してみると、Bitflyerでは以下の共通の関数に対応していることがわかります。

共通の関数一覧

cancelOrder()
createOrder()
createMarketOrder()
createLimitOrder()
fetchBalance()
fetchL2OrderBook()
fetchMarkets()
fetchOrder()
fetchOrderBook()
fetchOrders()
fetchTicker()
fetchTrades()
withdraw()

もしこれらの関数で、やりたいことができなさそうであれば、上記の方法を使って Bitflyer のAPIを直接利用することを検討します。

なお、今回説明した内容はすべてCCXTの公式マニュアルに記載されています。プログラムのAPI仕様書や英語を読むことが苦手でない方は、そちらを読んだ方がいいと思います。公式マニュアルは以下です。

・CCXT公式マニュアル

Bitflyerの未約定の全注文をCCXTで一括でキャンセルする方法

前回の記事「CCXTでBitflyerに出した注文を管理・キャンセルする方法」の最後の練習問題の解答です。

解答


import ccxt

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'

orders = bitflyer.fetch_open_orders(
	symbol = "BTC/JPY",
	params = { "product_code" : "FX_BTC_JPY" })

for o in orders:
	bitflyer.cancel_order(
		symbol = "BTC/JPY",
		id = o["id"],
		params = { "product_code" : "FX_BTC_JPY" })


fetch_open_orders()で未約定のすべての注文を取得し、それをfor文を使って1つずつキャンセルしていきます。キャンセルする注文IDを id = o[“id”] と指定するのが、今回のポイントでした。なお、Bitflyerの場合は、product_codeを指定するのを忘れないようにしてください。

(for文の解説)

orders[0][“id”]
orders[1][“id”]
orders[2][“id”]
orders[3][“id”]
orders[4][“id”]



の順番で処理したい要素がある場合は、for o in orders : と書くことで、orders[?]までの部分を o という変数に入れて順番に処理することができます。このとき、orders[?][“id”]は、for文の中では、o[“id”]で指定できます。

CCXTでBitflyerに出した注文を管理・キャンセルする方法

前回の記事では、CCXTライブラリを使ってBitflyerの最終取引価格を取得し、それに基づいて「買い注文」をpythonのプログラムから出す方法を説明しました。

今回はその続きです。
送信した注文が約定したかどうかをチェックしたり、未約定の注文をキャンセルする方法を解説します。

事前準備

今回の説明にあたり、複数の注文があった方がいいので、前回作ったプログラムを使って3つほど注文を出してみましょう。pythonプログラムを3回実行するだけです。

以下のように、3つの注文が置かれました。

まずはこの注文情報をpythonのプログラムで取得してみましょう。

注文情報を取得する

サーバーに送ったもののまだ約定していない注文のことを(Open Order)といいます。この未約定の注文は、「fetch_open_orders()」という共通の関数で取得できます。

エディタに以下のコードを記述してください。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'


orders = bitflyer.fetch_open_orders(
	symbol = "BTC/JPY",
	params = { "product_code" : "FX_BTC_JPY" })
pprint( orders )


これを実行すると、以下のような結果が取得できます。

前回までの記事を読んでいれば、特に目新しいことはないと思うので、コードの解説は省略します。paramsに「FX_BTC_JPY」を指定するのを忘れないようにしてください。

実行結果

先ほど出した未約定の注文が3つとも取得できているのが確認できます。fetch_open_orders()で取得した注文情報には、以下の情報が含まれます。

・注文ID(例:JRF20180317-022611-288893)
・注文した日時
・指値の価格
・Buy/Sellの方向
・未約定の残高

注文をキャンセルする場合には、「注文ID」を使います。ここでは、シンプルに「注文ID」だけを表示したいので、以下のようにコードを修正しましょう。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'


orders = bitflyer.fetch_open_orders(
	symbol = "BTC/JPY",
	params = { "product_code" : "FX_BTC_JPY" })

for o in orders:
	pprint( o["id"] )


変更したのは最後の「for文」のところだけですね。

コードの解説

上記のfor文は、CryptowatchのAPIを取得する練習記事で解説したのと全く同じパターンです。

JSON形式の構造が[ {},{},{}… ] になっていることと、{}の中身が「 id : 注文ID 」になっていることを把握できれば、同じやり方でデータを取り出せます。詳しくは「API編」の記事を参考にしてください。

プログラミング未経験者の方にとって、for文は慣れるまで少しコツが必要です。最低限、for文/if文/while文だけは知らないと自動売買BOTが作れません。これらの構文を全く知らない方は、以下の記事を読んでおいてください。

最低限必要なプログラミング構文(for文/if文/while文)

実行結果

上記のコードを実行すると、以下のように注文IDだけを取得することができました。

応用:すべての注文を取得する

先ほど書いたpythonプログラムの fetch_open_orders()の部分を、fetch_orders()に変更すれば、すべての注文(約定した注文/未約定の注文)をまとめて取得できます。

何も指定しなければ直近100件のすべての注文が取得されますが、「count」というパラメーターを付ければ取得する件数を調整することができます。

また取得した注文情報の「status」を調べれば、約定したかどうかがわかります。「status : open」のままであれば未約定ですし、「status : closed」になっていれば約定しています。

これを応用して、直近10件の注文が約定しているかどうかを調べるコードを書いてみましょう。以下のようになります。

▽ 直近10件の注文と、その約定の有無を調べるコード例


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'

orders = bitflyer.fetch_orders(
	symbol = "BTC/JPY",
	params = { "product_code" : "FX_BTC_JPY",
		"count" : 10})

for o in orders:
	print( o["id"] + " : 注文状況 " + o["status"] )


コードの解説

print()の関数は、print( 変数 + 変数 )で2つの変数の中身を繋いで表示することができます。見やすく表示するために、間に文字を入れたければ、print( 変数 + “好きな文字” + 変数 ) で、間に空白や文字を入れることができます。

実行結果

上記のコードを実行すると以下のように表示されます。

さて、次はこの注文IDをもとにして、注文をキャンセルしてみましょう。

注文をキャンセルする

注文をキャンセルする場合は、cancel_order()という共通の関数を使います。注文IDがすでにわかっている場合は、以下のように書くだけでOKです。


bitflyer.cancel_order(
	symbol = "BTC/JPY",
	id = "JRF20180316-172859-799705",
	params = { "product_code" : "FX_BTC_JPY" })


注) id=””の部分に注文IDを入れてください。
またキャンセルの関数は、orders ではなく order なので間違えないようにしてください。

Bitflyerでは、注文をキャンセルした際に、サーバーからは何のデータも返ってきません。なのでキャンセルできたかどうかを確認したければ、もう1度、fetch_orders()を実行する必要があります。

上記のコードを実行した後、もう1度、fetch_orders()を実行してみましょう。

実行結果

cancelで指定した注文が消えていますね。
管理画面でも確認してみましょう。

無事、注文が無くなっています。

応用:一番新しい注文を取得してキャンセルする

せっかくなので、手動で注文IDを指定するのではなく、fetch_open_orders()で取得した注文をそのままプログラムでキャンセルしてみましょう。今回は応用として「注文のうち一番新しいもの」を自動的にキャンセルします。

Bitflyerから fetch_open_orders() で取得した注文は、以下のように古い順番に並んでいます。

[{注文1},{注文2},{注文3},….]

この配列の最後の要素(一番新しい注文)を指定したければ、orders[-1]と指定すればOKです。コードを書いてみましょう。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'

orders = bitflyer.fetch_open_orders(
	symbol = "BTC/JPY",
	params = { "product_code" : "FX_BTC_JPY"})

bitflyer.cancel_order(
	symbol = "BTC/JPY",
	id = orders[-1]["id"], #11行目
	params = { "product_code" : "FX_BTC_JPY" })


コードの解説

今まで学習したことの組み合わせなのでわかると思いますが、6行目の fetch_open_orders() で未約定の注文を取得して、cancel_order() で注文をキャンセルしています。

11行目の id = orders[-1][“id”] で、取得した未約定の注文のうち、一番後ろの注文(一番最新の注文)の注文IDを指定しています。

実行結果

実行してもう1度、注文状況を取得してみましょう。

無事、新しい方の注文が消えましたね。
管理画面でも確認しておきましょう。

新しい方の注文がキャンセルされています。

以上が、Bitflyerにpythonで出した注文の状況を管理して、注文IDを取得し、未約定の注文をキャンセルする方法でした。

練習問題

未約定の注文の一覧を取得して、それらを「すべて」一括でキャンセルするプログラムを書いてみましょう。ヒントとしては、最初の「注文IDだけを表示する」のプログラムコードを修正して、for文の中に注文キャンセルのコードを入れるとうまくいきます。

正解はこちら

CCXTライブラリでBitflyerに注文を出す方法をマスターする

さて、前々回の記事ではBitflyerのAPIを使って買い注文を出す方法を紹介しました。このとき注文を出すだけでも結構長いコードを書かなければならなかったのを覚えているでしょうか?

CCXTライブラリを使えば、これを1行で書くことができます。実際にやってみましょう!

事前準備

bitFlyer lightning の最低注文単位は0.01BTCからです。
現在(2018年4月)のレートでいうと9000円くらいですね。そのため、口座には最低1万円以上の資金が必要です。

今回はレバレッジ無しで最低単位の注文をします。一応テストなので、約定しないように注意しながら、現在価格から10%以上離れた場所に指値を入れます。そして、それをキャンセルするところまでプログラムしてみます。

bitFlyerのアカウント登録がまだの方は、ぜひこちらから登録してください。

(追記) 2018年4月から最低注文単位が0.01BTCに引き上げられました。この記事はそれ以前に作成したものなので、画像が0.001BTCのままになっています。文字部分は修正しています。

現在のBTC-FX価格を取得する

前々回の記事では、BTC-FXの画面にログインして目視で価格を確認しました。ですが、今回はより本格的に、価格を調べるところもすべてPythonのプログラムでやりましょう。

エディタを起動して以下のように記載してください。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
ticker = bitflyer.fetch_ticker('BTC/JPY', params = { "product_code" : "FX_BTC_JPY" })
pprint(ticker)


コードの解説

1行目と2行目でccxtライブラリとpprintライブラリをimportします。これは前回の記事と同じですね。pprintライブラリは配列を綺麗に表示するために使います。

3行目の「bitflyer = ccxt.bitflyer()」は、ビットフライヤーで関数を使うために必ず最初に書かなければならないコードです。準備のようなものだと思ってください。

4行目でティッカー情報を取得しています。すでに学んだように、ティッカー情報の取得はパブリックAPIなので、この時点ではAPIキーやシークレットは必要ありません。Bitflyerの場合は、FXでは「product_code」を「FX_BTC_JPY」に指定するのを忘れないようにしてください。

5行目のpprint()で、取得した ticker を黒い画面に表示しています。

実行結果

それでは、上記のコードをpythonファイルで保存して、Anacondaプロンプトで実行してみましょう。以下のように表示されました。

{'ask': 902954.0,
 'average': None,
 'baseVolume': 274827.01507782,
 'bid': 902900.0,
 'change': None,
 'close': None,
 'datetime': '2018-03-16T00:13:01.147Z',
 'first': None,
 'high': None,
 'info': {'best_ask': 902954.0,
          'best_ask_size': 0.2,
          'best_bid': 902900.0,
          'best_bid_size': 1.2837385,
          'ltp': 903111.0,
          'product_code': 'FX_BTC_JPY',
          'tick_id': 14952020,
          'timestamp': '2018-03-16T00:13:01.147',
          'total_ask_depth': 7224.20363872,
          'total_bid_depth': 5425.62384916,
          'volume': 306014.57114597,
          'volume_by_product': 274827.01507782},
 'last': 903111.0,
 'low': None,
 'open': None,
 'percentage': None,
 'quoteVolume': None,
 'symbol': 'BTC/JPY',
 'timestamp': 1521159181147,
 'vwap': None}

この中で、最終取引価格(=現在価格)だけ知りたければ、「last」の部分を見ればOKです。この記事の執筆時点では、903111円(90万3111円)ですね。

あるいは、bid(買い板の中の最高価格)を見てもいいです。売買BOTのアルゴリズムで買いシグナルが出た場合、指値注文を入れるのであれば、この「bid」か「last」のどちらかの価格で指値を入れることが多いと思います。

なお、この取得したJSONデータから最終取引価格(last)だけ取り出したければ、先ほどのpythonのプログラムの5行目を以下のように書けばOKです。


pprint( ticker["last"] )


これは「JSON形式のデータから欲しい数字だけを取り出そう!」の復習なので、わからない方はこちらを読んでください。

FXの証拠金残高を確認する

次にポジション管理のために、FXの証拠金残高などを取得してみましょう。エディタに以下のコードを書いてください。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'

collateral = bitflyer.private_get_getcollateral()
pprint( collateral )


コードの解説

今回はプライベートAPIを使うので、APIキーとAPIシークレットを準備する必要があります。4行目・5行目の’**********’の部分に各自のAPIキー・シークレットをそれぞれ入力してください。

またCCXTライブラリには、Bitflyerで BTC-FX の証拠金残高を取得する共通の関数がありません。そのため、ここではBitflyerの「v1/me/getcollateral」というAPIを使っています。(collateralは英語で「担保」という意味です)。

BitflyerのAPIドキュメント

このようにCCXTライブラリでは、共通のメソッドが見つからない場合に、各取引所で個別に提供されているAPIを、直接使うこともできます。具体的な方法については、以下の記事で紹介しています。他の場面でも困ったら参考にしてみてください。

・Bitflyerや各取引所の個別のAPIをCCXT経由で利用する方法

実行結果

上記のコードをAnacondaプロンプトで実行してみましょう。以下のような結果が表示されます。


{
  "collateral": 100000,
  "open_position_pnl": -715,
  "require_collateral": 19857,
  "keep_rate": 5.000
}


上から順番に、

・預入証拠金の評価額(collateral)
・ポジションの評価損益(open_position_pnl)
・現在の必要証拠金(require_collateral)
・現在の証拠金維持率(keep_rate)

です。

自動売買BOTでは、証拠金の残高から取得可能なポジションのサイズを自動計算させて、可変ロットで注文を出すこともできます。この方法は第7回の「資金管理編」で詳しく解説するので楽しみにしていてください。

初心者の方は、まずは固定ロット(0.1BTCなど)でちゃんと売買できるようになりましょう!

買い注文を出す

今回はテストなので、最終取引価格が90万円のところ、10%以上離して80万円で買い指値を入れてみます。数量は最低単位の0.01BTCにします。

注文には、「create_order()」というCCXTの共通の関数を使います。エディタを起動して以下のコードを書いてください。


import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
bitflyer.apiKey = '**********'
bitflyer.secret = '**********'


order = bitflyer.create_order(
	symbol = 'BTC/JPY',
	type='limit',
	side='buy',
	price='800000',
	amount='0.01',
	params = { "product_code" : "FX_BTC_JPY" })

pprint( order )


これで終わりです!

実際に注文を送るために書いたのは、order = bitflyer.create_order() の1行だけです! 見やすいように改行してるだけなので、「1行じゃねぇじゃねーか!」とか言わないでください><

コードの解説

CCXTには指値注文、成行注文を出すための関数、買い注文・売り注文を出すための関数もありますが、上記のように、create_order()で詳細を指定すれば、全パターンの注文を出せますので、この1つだけ書き方を覚えたほうが簡単です。

以下だけ覚えてください。

symbol=””の部分 ⇒ 通貨ペア
type=”” の部分 ⇒ limitが指値/marketが成行
side=”” の部分 ⇒ buyが買い/sellが売り
price=”” の部分 ⇒ 指値を入れる場合の価格
amount=””の部分 ⇒ 注文数量
params={} の部分 ⇒ 各取引所のAPIに渡せるパラメーター

Bitflyerでは、「product_code」を「FX_BTC_JPY」に指定するのを忘れないようにしてください。これを忘れると現物注文になります。

6行目で、Bitflyerのサーバーに注文を出すと、サーバーから注文IDが返ってきます。この注文IDは、今後、注文状況を確認したりキャンセルするときに使います。そのため、返ってきた値は、orderという変数で受け取り、それをpprint()で画面に表示しています。

実行結果

それでは、上記のコードをpythonファイルで保存して、Anacondaプロンプトで実行してみましょう。以下のように表示されれば成功です。

実際にBitflyerのFX画面でも、注文が通っていることが確認できます。

今回の記事はここまでです。
次回の記事では、注文状況を確認したり、まだ約定していない注文をキャンセルする方法を解説していきます!

CCXTが便利な理由!CCXTライブラリをインストールしよう

前回の記事では、BitflyerのAPIを使って実際にBTC-FXの買い注文を出す方法を解説しました。

少し長い記事だったので、疲れた方も多いかもしれませんね(笑)。でもキチンと読んでくださった方は、いきなりライブラリの利用からから入る方よりも、間違いなく「本質的な部分」の理解が深まっているはずなので自信を持ってください!

さて、今回からはCCXTという外部のライブラリを使って、全く同じ「bitFlyerに買い注文を出す」コードを、もっと簡単に実装する方法を紹介します。

CCXTライブラリのgithubページ

なぜCCXTライブラリを使うのか?

1つ目の理由は、自分で長いコードを書かなくて済むからです。

前回の記事では、「sendchildorder」というBitflyerのAPIを利用して、pythonプログラムからBitflyerのサーバーに注文を出すことができました。しかし実際には、このAPIを利用するためには、以下のような手順を踏まなければなりませんでした。

1)現在時刻のタイムスタンプを作る
2)注文価格や数量などのパラーメータを設定する
3)パラメーターをJSON形式に変換する
4)メッセージ認証コード(暗号署名)を作る
5)通信用のヘッダーを作成する
6)リクエストを送る

このうち実質的に(2)の部分以外は、すべてのAPIリクエストで共通の処理です。なので毎回、自分で書かなくても、自動的に実行してくれたら楽ですよね。

例えば、買い注文を出す場合には、「指値か/成行か」「買いか/売りか」「注文ロット数は?」「指値の価格は?」といった随時、変更したい部分だけを指定し、それ以外の部分は1つの関数にまとめておいて、いつでも呼び出せるようにしておけば、プログラムを書くのが遥かに楽になります。

これをやってくれるのがライブラリです。

取引所ごとのAPIの違いを気にしなくていい!

2つ目の理由は、取引所ごとのAPIの仕様の違いを無くすためです。

APIというのは、各取引所が独自に開発しているものなので、取引所によって仕様が違います。例えば、bitFlyerでは「sendchildorder」というAPIで注文を出しましたが、Zaifの場合は「trade」というAPIを使いますし、bitbankであれば、「order」というAPIを使います。

通信に含めるパラメーターのルールも、取引所ごとに違います。例えば、Bitflyerは「size」で注文ロット数を指定しますが、Zaifは「amount」で注文ロット数を指定しなければなりません。

このような取引所ごとのAPIの違いを気にしながら、自動売買BOTを作るのはかなり面倒です。

1つの売買ロジックを複数の取引所で試したい場合でも、取引所ごとにpythonコードを書き直さなければなりません。また、裁定取引のように取引所間の価格差を利用した売買BOTを作りたい場合、取引所ごとに注文の方法が違うと非常に厄介です。

CCXTライブラリで出来ること

CCXTなどのライブラリは、このような「各取引所ごとのAPIによる注文の違い」を、見えない裏側でまとめて処理してくれます。そのため、先頭の1行目でCCXTライブラリを読み込めば、あとはすべての取引所で共通の関数を使うことができます。

例えば、以下のような関数(メソッド)がすべての取引所で「共通」で使えます。

create_order() ・・・ 注文を出す(成行/指値)
cancel_order() ・・・ 注文をキャンセルする
fetch_ticker() ・・・ ティッカー情報を取得
fetch_balance() ・・・ 口座残高を取得
fetch_order_book() ・・・ 板情報の取得

また各取引所ごとのAPIをCCXTライブラリを経由して直接使うこともできます。例えば、bitFlyerにしか存在しないAPIを使いたい場合は、上記の共通のメソッドを使わずに、直接、BitflyerのAPIを利用することもできます。

詳しい使い方は今後の記事で説明していきます!

CCXTをインストールしよう

まずはCCXTライブラリをPythonにインストールしていきましょう。Anacondaプロンプトを起動して以下の1行を打ち込むだけです。

pip install ccxt

すると以下のようにインストールが開始されます。

「Successfully installed … 」と出て、また文字が打てる状態になれば、インストールは完了です。

Bitflyerで出来ることを確認しておく

早速、CCXTライブラリを使ってpythonプログラムを1つ書いてみましょう。今回は、BitFlyerでできることを把握するために、対応している共通の関数(メソッド)の一覧を確認してみます。

エディタを起動して以下のコードを書いてみてください。

import ccxt
from pprint import pprint

bitflyer = ccxt.bitflyer()
pprint( bitflyer.has )

コードの解説

最初の「import ccxt」は、CCXTライブラリを利用するための1文です。これは今後、CCXTを使うときには必ず記述します。

2行目の「from pprint import pprint」は、pprint()を使ってデータを綺麗に表示するためにインポートしてみました。今までの記事では、すべてprint()だけで表示していましたが、改行がないと見にくいデータは、pprint()で表示した方が綺麗です。

3行目の「bitflyer = ccxt.bitflyer()」も、Bitflyerの取引所を使う場合には最初に必ず書かなければならないコードです。準備のようなものだと思ってください。

4行目の「bitflyer.has」は、CCXTライブラリにあるBitflyerのプログラムが、どの共通関数に対応しているかを確認するためのコードです。これをpprint()を使って黒い画面に表示しています。

実行結果

それでは実行してみましょう!
以下のように表示されました。

「True」と記載されているものは、Bitflyerでも使えます。
以下のような共通関数は使えるということですね。

cancelOrder() ・・・ 注文をキャンセルする関数
createOrder() ・・・ 注文を出す(買い/売り、指値/成行)関数
fetchBalance() ・・・ 残高を確認する関数
fetchTickers() ・・・ ティッカー情報を取得
fetchOrderBook() ・・・ 板情報を取得

一方、見てのとおり、結構、使えない(Flaseになっている)関数もあります。

前回の記事の意味

前回の記事を読んでくださった方ならわかると思いますが、CCXTライブラリは結局のところ、各取引所のAPIを裏側で叩いているだけのものが多いです。そのため、各取引所が該当するAPIを提供してくれていなければ使えません。

また上記の共通メソッドにはパラメーターを渡すこともできますが、どのようなパラメーターを渡すことができるかは、各取引所のAPIの仕様によって異なります。例えば、Bitflyerで BTC-FX のデータを取得するためには、”FX_BTC_JPY”というパラメーターを渡さなければなりません。渡さないとBTC現物のデータが返ってきます。

このようなルールも、裏で各取引所のAPIが動いていることを知っていなければ、なかなか自分で気づいたり調べることが難しいと思います。そのため、前回の記事ではわざわざ1度、APIだけで注文を出す方法を学びました。

さて、次の記事では、CCXTライブラリを使って、実際に「BitflyerFXの現在価格と口座の残高を取得して、購入額と数量を決め、買い注文を出す」という多くの売買BOTで必要にな一連の流れをまとめて勉強します!

(追記)

※ 最新版 Anaconda3.7 ではCCXTのインストールができず、3.6にダウングレードするとできたという報告があるようです。もし出来ない方は参考にしてください。