本記事は、
- bitFlyerの取引所で、Pythonにより、仮想通貨の自動取引システムを作りたい方
を対象にした記事です。
本記事は、下記記事に対する、追加記事になります。
基本的な、自動取引システムの作り方は、下記記事にてご紹介しています。
まだ読まれていない方は、先にこちらをどうぞ。
本記事で紹介する内容は、以下の通りです。
- 特殊注文(親注文)を出す方法
(具体的には、以下の項目になります。)- IFD、OCO、IFDOCO 注文
- ストップ注文
- ストップ・リミット注文
- トレーリング・ストップ注文
- 発注した特殊注文(親注文)を、キャンセルする方法
IFD注文? と思われた方、大丈夫です。
それぞれの、用語の解説も、併せてご紹介します。
冒頭に出てきた、用語(IFD注文 等々)の解説
ご存知の方は、この章をスキップして下さい。
IFD注文
イフダン注文と呼ばれます。由来は、イフダン(if – done)から、きています。
新規の注文と、その注文に対する、決済注文が同時に出せる注文方式です。
つまり、どういう事ですか?
- つまり、〇〇円でになったら、新規発注をしたい
- それが、△△円になったら、決済したい
というオーダーが、同時に発注できる注文方式です。
具体例を使って、解説します。
例えばですが、現在価格が100円とします。
IFD注文を使えば、
- 新規買いを、98円なったら購入
- 上記の買い注文が成立した場合で、105円になったら決済
という事ができます。
上記の例では、指値発注を例にしましたが、ストップ(逆指値)発注も可能です。
例えば、
- 105円になったら、「売り」
- それが、90円になったら、決済
といったパターンが、そちらに該当します。
OCO注文
名前は、「One side done then Cancel the other order」から、きています。
「オーシーオー」注文と呼ばれます。
2種類の注文を出し、どちらかが約定すれば、もう一方は、自動的キャンセル処理される、発注方式です。
こちらも、具体例を使って、解説します。
現在価格が、またまた、100円とします。
OCO注文を使えば、
- 新規買い注文を、105円で「買い」で発注
- 新規売り注文を、97円で「売り」で発注
という事が、同時に発注できます。
上記は、発注時を例にしましたが、
- 既に発注していて、決済時の注文
にも使用可能です。
IFDOCO注文
IFD注文と、OCO注文を、組み合わせたものです。
IFDOCO注文を使えば、
- 発注時を金額を設定する事ができ(指値 or 逆指値)、
- もし発注されれば、
- 利益確定の金額と
- 損切りの金額
を設定する事が、できるようになります。
具体的なイメージは、以下になります。
ストップ注文
逆指値注文のことです。
「買い」で入る場合、
- 指値注文は、「設定した金額」以下になれば、成行で発注
になりますが
- ストップ(逆指値)注文は、「設定した金額」以上になれば、成行で発注
になります。
「売り」で入る場合は、逆の挙動になります。
- 指値発注:「設定した価格」以上で成行発注
- ストップ発注:「設定した価格」以下で成行発注
「設定した価格」は、トリガー価格 と呼ばれています。
ストップ・リミット発注
ストップ注文と似ています。
違いは、
- ストップ注文が、設定価格になると、「成行注文」になりますが、
- ストップ・リミット注文は、設定価格になると、「指値発注」
になります。
トレーリング・ストップ注文
高値安値に合わせて、ストップ注文のトリガー価格を、リアルタイムに自動修正するものです。
価格が有利な方向に動いた場合、「設定した金額幅」に応じて、ストップ注文も、一定幅ずつ、スライドしていく注文方式です。
下図のようなイメージです。(「買い」の場合 )
価格が上がっていくと、
- トレーリング価格も上昇
価格が下がり出すと、
- トレーリング価格で決済
する方式になります。
特殊注文(親注文)の、Python コード紹介
ここまで紹介してきた注文方式は、bitFlyerさんでは、親注文という方式で実施します。
bitFlyerさんでは、
- 成行注文
- 指値注文
のみ、「子注文」という扱いになっています。
bitFlyerさんでは、「空売り」をするためには、
- Lightning FX
を利用する必要があります。
本記事では取り扱いません。
ただし、本APIで「FXの自動取引」も可能です。
具体的には、bitFlyerさんのサイトで、「FXの使用許可」処理を実行した上で、コード中の変数
- market_type
- product_code
に、FX用の文字列を代入します。
詳細は、bitFlyerさんのAPI Documentationをご参照下さい。
紹介する順番
以下の順番で、ご紹介していきます。
- 「IFD、OCO、IFDOCO 注文」全てで、共通するコード
- IFD注文のコード
- OCO注文のコード
- IFDOCO注文のコード
- ストップ注文
- ストップ・リミット注文
- トレーリング・ストップ注文 は、
IFD注文等を紹介している中で、具体的なコードという形で、ご紹介しています。
冒頭で紹介した「前回記事」でご紹介した、下記2点は、今回も使用します。
- requestsパッケージ
- 認証に関するコード(関数 header( ) で定義した部分)
注文コードの雛形
IFD、OCO、IFDOCO 共通する、コードの雛形です。
def parent_order():
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/sendparentorder"
body = {
"order_method": "IFD", # 注文方式 IFD or OCO or IFDOCO
"minute_to_expire": 1000, # 期限切れまでの時間(分) 1000は仮です。
"time_in_force": "GTC", # 執行数量条件 GTC or IOC or FOK
"parameters": [
{
# 1つ目の発注条件を記載
},
{
# 2つ目の発注条件を記載
},
{
# 3つ目の発注条件を記載 (もしあれば)
}
]
}
body = json.dumps(body)
headers = header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.json()
コード中の「body」変数に代入されている、辞書型の各Keyを解説します。
- order_method: 注文方式を設定します。(IFD or OCO or IFDOCO)
- minute_to_expire:期限切れまでの時間。省略すると、43200(30日)になります。
- time_in_force:執行数量条件。省略すると、GTC になります。
- parameters: 売買条件を記載していきます。次章で、具体的に記しています。
実行結果
上記の parent_order()を呼んだ結果です。
JSONで返ってきたものを、辞書型に変換しています。
下記の「API受付ID」は、キャンセル処理する際に、使用します。
{
"parent_order_acceptance_id": "JRF20220508-020351-145960" # 発注時の「API受付ID」
}
エラーが発生すると、下記のように、statsu=-200 が返ってきます。
{'status': -200, 'error_message': 'Insufficient funds', 'data': None}
上記は、日本円が足らずに、ビットコインを購入しようとしたケースです。
IFD注文のコード
前章で紹介した、注文コードの雛形をベースに、IFD発注の事例で具体的に記しました。
下記のコードは、
- 「IFD注文」で、
- 最初の発注は、「LIMIT」注文で買い
- 損切りとして「STOP」注文で売り
で発注したケースです。
def parent_order():
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/sendparentorder"
body = {
"order_method": "IFD",
"minute_to_expire": 10000,
"time_in_force": "GTC",
"parameters": [{
"product_code": "btc_jpy", # ビットコインの場合
"condition_type": "LIMIT",
"side": "BUY",
"price": 400000,
"size": 0.1 # 発注数量
},
{
"product_code": "btc_jpy",
"condition_type": "STOP",
"side": "SELL",
"trigger_price": 390000, # STOP注文のトリガー価格
"size": 0.1 # 売却数量
}]
}
body = json.dumps(body)
headers = header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.json()
OCO注文のコード
前章で紹介した、注文コードの雛形をベースに、OCO発注の事例で具体的に記しました。
下記のコードは、
- 「OCO注文」で、
- 新規買い注文を、「LIMIT」注文
- 新規売り注文を、「STOP・LIMIT」注文
で発注したケースです。
def parent_order():
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/sendparentorder"
body = {
"order_method": "OCO",
"minute_to_expire": 10000,
"time_in_force": "GTC",
"parameters": [{
"product_code": "btc_jpy", # ビットコインの場合
"condition_type": "LIMIT",
"side": "BUY",
"price": 4100000, # 指値価格
"size": 0.1 # 発注数量
},
{
"product_code": "btc_jpy",
"condition_type": "STOP_LIMIT",
"side": "SELL",
"trigger_price": 3900000, # STOP・LIMIT注文のトリガー価格,
"price": 3950000, # STOP・LIMIT注文の指値価格
"size": 0.1 # 売却数量
}]
}
body = json.dumps(body)
headers = header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.json()
IFDOCO注文のコード
前章で紹介した、注文コードの雛形をベースに、IFDOCO発注の事例で具体的に記しました。
下記のコードは、
- 「IFDOCO注文」で、
- 最初の発注は、「LIMIT」注文で買い
- 利確として「LIMIT」注文で売り、
- 損切りとして「TRAIL」注文で売り
で発注したケースです。
def parent_order():
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/sendparentorder"
body = {
"order_method": "IFDOCO",
"minute_to_expire": 10000,
"time_in_force": "GTC",
"parameters": [{
"product_code": "btc_jpy", # ビットコインの場合
"condition_type": "LIMIT",
"side": "BUY",
"price": 4000000,
"size": 0.1 # 発注数量
},
{
"product_code": "btc_jpy",
"condition_type": "LIMIT",
"side": "SELL",
"price": 4100000, # 利確注文の価格
"size": 0.1 # 売却数量
},
{
"product_code": "btc_jpy",
"condition_type": "TRAIL",
"side": "SELL",
"offset": 1000, # トレーリング・ストップ注文のトレール幅
"size": 0.1 # 売却数量
}]
}
body = json.dumps(body)
headers = header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.json()
注文結果の確認方法
約定された事を確認する
親注文の一覧を取得して、
- 発注済みの、「parent_order_id」を確認の上、
- 「parent_order_state」が、COMPLETED になっている事を確認します。
を確認します。
◆ 確認コード
def list_parent_order(self):
params = {
"product_code": "btc_jpy", # BTCの場合
"parent_order_state": "active" # オープンな注文一覧を取得する場合
}
endpoint_for_header = endpoint + '?'
for k, v in params.items():
endpoint_for_header += k + '=' + v
endpoint_for_header += '&'
endpoint_for_header = endpoint_for_header[:-1]
headers = self.header('GET', endpoint=endpoint_for_header, body='')
response = requests.get(self.base_url + endpoint, headers=headers, params=params)
return response.json()
5行目の「parent_order_state」は、以下の項目が指定できます。
ACTIVE
: オープンな注文の一覧を取得COMPLETED
: 全額が取引完了した注文の一覧を取得CANCELED
: ユーザーが、キャンセルした注文EXPIRED
: 有効期限に到達したため、取り消された注文の一覧を取得REJECTED
: 失敗した注文
省略した場合、全て返ってきます。
◆ 実行結果
下記結果の、「parent_order_state」が、COMPLETEDになっていれば、全取引が完了です。
[
{
"id": 138398,
"parent_order_id": "JCO20150707-084555-022523",
"product_code": "BTC_JPY",
"side": "BUY",
"parent_order_type": "STOP",
"price": 30000,
"average_price": 30000,
"size": 0.1,
"parent_order_state": "COMPLETED", # ← ここに着目
"expire_date": "2015-07-14T07:25:52",
"parent_order_date": "2015-07-07T08:45:53",
"parent_order_acceptance_id": "JRF20150707-084552-031927",
"outstanding_size": 0,
"cancel_size": 0,
"executed_size": 0.1,
"total_commission": 0
},
{
"id": 138397,
"parent_order_id": "JCO20150707-084549-022519",
"product_code": "BTC_JPY",
"side": "SELL",
"parent_order_type": "IFD",
"price": 30000,
"average_price": 0,
"size": 0.1,
"parent_order_state": "CANCELED", # ← ここに着目
"expire_date": "2015-07-14T07:25:47",
"parent_order_date": "2015-07-07T08:45:47",
"parent_order_acceptance_id": "JRF20150707-084547-396699",
"outstanding_size": 0,
"cancel_size": 0.1,
"executed_size": 0,
"total_commission": 0
}
]
発注した特殊注文(親注文)を、キャンセルする方法
特定の注文のみ、キャンセルする(未約定の場合のみ)
オーダー時に発行された、「API受付ID」が必要になります。
キャンセルに成功すれば、ステータスコードとして、200 が返ってきます。
import json
def order_cancel(self):
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/cancelparentorder"
body = {
"product_code": 'btc_jpy',
"parent_order_acceptance_id": "JRF20150707-033333-099999"
}
body = json.dumps(body)
headers = self.header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.status_code
全ての注文をキャンセルする
下記コードの、endpoint変数に、「/v1/me/cancelallchildorders」が代入されています。
親発注でも、全オーダーキャンセル時は、こちらのendpointをご使用下さい。
import json
def all_order_cancel():
base_url = 'https://api.bitflyer.com'
endpoint = "/v1/me/cancelallchildorders"
body = {
"product_code": 'btc_jpy'
}
body = json.dumps(body)
headers = self.header('POST', endpoint=endpoint, body=body)
response = requests.post(base_url + endpoint, data=body, headers=headers)
return response.status_code
実行結果
正しく処理された場合は、ステータスコードの「200」が返ってきます。
最後に
最後に参考として、bitFlyerさんのAPI Documentationを、記載しておきます。
また冒頭の繰り返しになりますが、本記事は、下記記事の補足記事になります。
基本的な、bitFlyerさんの自動取引システムの作り方は、全てこちらで紹介しております。
本記事で、ご紹介した以外の機能を知りたい方は、下記までどうぞ。
最後まで読んで頂き、ありがとうございました。
また、お会いしましょう!