【Tips】 ccxtのfetch_open_ordersが使えないことと個人的な対策

あれ、ccxtのfetch_open_orders関数使えなくない?
と、個人的にここで結構詰まってしまいました。
ということで、今回はこの問題への対策を共有したいと思います。
ちなみに、想定対象の取引所はbitflyerです。

本番用Botを作成する上で、自身の注文状況の情報を取得できなければ、当たり前ですが話になりません。
ccxtはBot作成においてコード効率化を図る上でとても有用なライブラリです。
しかし、バージョン変化による仕様の差がかなりあるため、それまで問題なかった部分も、突然使えなくなることもあるようです。
今回の事例もまさしくそれで、2〜3年前のネットに存在する手法で試しても、上手くいかずハマってしまいました。

現状、fetch_open_orders関数が使えないことに対し、日本語ソースで根本的な解決に至るものは見当たりませんでした。
そこで最終的には少し変則的な形で解決を試みました。
以下、メモ書きを引用しただけなので、だいぶ雑ですが参考になれば幸いです。

個人的なメモ

問題

ccxtを使ってfetch_open_orders関数から、bitflyerに出した注文状況を取得しようとしても、[]しか返ってこない。


試したこと

・symbol、paramsそれぞれで、引数を限定してみる
・symbolのパラメータを"FX_BTC_JPY", "BTC_JPY", "BTC/JPY"などに変えてみる
・paramsのパラメータを{"product_code" : "FX_BTC_JPY"}、以下同順に変えてみる
・fetch_orders関数などを試してみる
・fetchOpenOrdersなど関数の書き方を変えてみる
・ccxtのバージョンを最新にする(2022/8/1 執筆時点のバージョン 1.91.42)
・その他、ccxt公式ドキュメントを見たり、他サイト情報を確認して試行錯誤するも有力な対処法なし


なぜダメか

・おそらく情報自体を取ってこれていない
・つまりうまくAPIを経由してアクセスできていない
・もはや対応していない?


個人的な解決法

・ccxtのfetch_open_orders関数を使うことを諦め、別の方向から解決を試みる
・bitflyerの公式APIからorderの情報を取ってくるようにする
・ccxtの内部関数を用いることで、ccxt経由でbitflyerのAPIを呼び出す
・直接APIを呼び出すより、ccxtを経由した方がコード的に楽


で、どうすればいいの

・以下のコードで情報の取得に成功した

orders = bitflyer.private_get_getchildorders(params = {"product_code" : "FX_BTC_JPY"})


ちょっとした欠点

・余計な情報まで取ってきてしまうため少し面倒
・open以外の約定済のorderなども含まれてしまう
・他の処理に使う時は、条件分けなどで部分的に対処する必要がある
・そのため、実際はcountなどで情報数を絞って注文状況をBotに利用する


結論

・コード的な負担が増えるとはいえ、情報取得できることに限る、目標はとりあえず達成
・fetch_open_orders使えた方が楽と言えば楽
・ただし、バージョンダウンなど管理面での負担増えるからなんとも言えない
・最新verでの問題解決が理想だが、現状はこの方法で対処しようと思う


解説

以上、個人的なメモをつらつらと並べました。
筆者の場合はこの方法(ccxt経由の内部関数)に統一して、注文状況、約定状況などを取得しています。

解決の部分のコード解説を少ししておくと、まず変数bitflyerにAPIキーとシークレットキーを渡す必要があります。(Private APIのため)

bitflyer = ccxt.bitflyer({
    'apiKey' : "*****",
    'secret' : "*****"
})

次にccxtを経由して、取引所のAPIを叩くことで、関数を呼び出します。
取引所のAPIの仕様を理解できれば、スムーズにコードを書けます。
公式サイトを見るのが一番早くて確実です。(ここではbitflyer)

ccxtを経由してbitflyerのAPIを叩く方法には以下の決まりがあります。

bitflyer.1_2_3()

1. APIの種類:Public / Private
2. APIのメソッド:GET / POST
3. APIのパス

今回は"注文の一覧を取得する"というAPIを叩きたいので、上記を参考に書くと、
1. Private
2. GET
3. getchildorders
のため、bitflyer.private_get_getchildordersとなるわけです。

しかし、当初のccxtのfetch_open_ordersであれば、未約定の注文状況のみの情報を取得できたものの、bitflyerの公式APIにはピンポイントのやつがありません。
そのため、約定済/未約定含めた注文一覧の情報を取得した上で、未約定の注文情報を取り出す必要があります。

レスポンス例を挙げます。(公式サイトより一部引用)

[
  {
    "id": 138398,
    "child_order_id": "JOR20150707-084555-022523",
    "product_code": "BTC_JPY",
    "side": "BUY",
    "child_order_type": "LIMIT",
    "price": 30000,
    "average_price": 30000,
    "size": 0.1,
    "child_order_state": "COMPLETED",
    "expire_date": "2015-07-14T07:25:52",
    "child_order_date": "2015-07-07T08:45:53",
    "child_order_acceptance_id": "JRF20150707-084552-031927",
    "outstanding_size": 0,
    "cancel_size": 0,
    "executed_size": 0.1,
    "total_commission": 0,
    "time_in_force": "GTC"
  },

このうち、約定の有無を判定するには、"child_order_state"を見ます。
ここが"ACTIVE"であれば、未約定の注文です。
そのため、未約定の注文のみ取り出したい時は、例えば、

orders = bitflyer.private_get_getchildorders(params = {"product_code" : "FX_BTC_JPY", "count" : 10})

for i in range(len(orders)):
    if orders[i]["child_order_state"] == "ACTIVE":
        pprint(orders[i])

とかにすれば、未約定注文に限定して情報を取得・表示できます。
実際のBotにコードを載せるときは、countで数を限定するのが現実的です。
countで制限しないと、過去全ての注文情報を取ってきてしまうので時間がかかりますので。
上記コード例で言うと、直近10件のみの注文状況を取得できます。


結論、ccxtのfetch_open_ordersが結局使えず、代わりにccxtを経由して取引所APIを使うという方法のTips記事でした。


この記事が気に入ったらサポートをしてみませんか?