[BTC][Bot] [Python] 第二回 取引所の取引データを取得する

はじめに

こんにちは _santa365です。本業でエンジニアをやっています。
第一回 はじめのBot環境構築 ではBot構築するにあたってまず基本的なプロジェクトの作成を行いました。
今回はトレードするのにも必要な取引データの取得を試みます

取引データを取得する前に

今回の内容はネットワークやプログラミングの知識が少し必要ですので簡単にですが解説しておきます(ガチ勢じゃないので簡単にしか説明できない)。長いので飛ばしてもらっても構いませんしあとから読んでも構いません。

取引所との通信について
取引所との通信には、「HTTP」と「Websocket」があります。
共通点
両方に共通する部分としては実際に通信したいものを送る前にまず「あなたと通信してもよいですかという確認フロー(コネクション)」が行われます。
「HTTP」の場合
コネクションを確立したあとに実際のデータのやり取りを行います。やり取りが終わるとコネクションを切断します。そのため再度データのやり取りを行いたい場合は、コネクションからやり直す必要があります。RESTと書かれているのもこちらの方式です。RESTは単なるエンドポイントの命名規則みたいなものなのですが、だいたいの取引所でRESTと書かれている場合はHTTPによる通信を表している事が多いです。
「Websocket」の場合
コネクションを確立したあとに、実際のデータのやり取りを行います。HTTPとは異なりそのコネクションを維持することができます。コネクションが維持されている間はコネクションのフローをやり直さずに再度データを送ることができたり、また逆に相手側からデータを送る事もできます。何度もやり取りをする場合は無駄が少ないという利点があります。しかしながら、なんらかの原因によってWebsocketが急に切断される可能性を考慮する必要があるため扱いはHTTPより難しいです。

非同期処理について
pythonにはasyncioと呼ばれるライブラリを使って非同期処理をすることができます。asyncioはシングルコアによる並行処理によって非同期処理を実現しています。シングルコアなので厳密に同時に二つのことを実行することはできません。並行処理によって複数の処理をあたかも同時に行っているように処理しています。
ではわざわざ非同期処理をする理由はなぜなのでしょうか。具体例で説明します。websocketによって接続されたデータは絶えず取引所から送られてきます。仮に1秒に1回ぐらい送られるとします。送られたデータを使って何らかの処理をします(例えばMACDを計算して注文する)。これが2秒かかるとします。非同期処理でない場合、データの受信ごとに2秒かかるため処理を行います。つまり、1回の処理ごとのたびに1秒次の処理を開始するのが遅くなります。非同期処理を使うと2秒かかる処理を並行して行ってくれるので、次のデータ受信に対してすぐ処理を開始することができます。

取引データを取得する

では本題に入りましょう。取引データを実際に取得していきます。取引データを取得するには、x秒ごとにHTTPによる通信をリクエストしてもよいですが、Websocketでコネクションを確立し取引所から送られてきたデータを受信するほうが楽です。なので今回は、Webscoketを使います。

取引データを取得するためにはOSSのライブラリを使います。ライブラリを使わず1から実装することもできますが巨人の肩の上に立つと言うように使えるものは使いましょう。有名なライブラリにはccxtと呼ばれるものがあるのですが、ccxtでwebsocketを使うのは有料会員にならないと使えないので今回はMtkN1/pybottersを使います。pybottersは日本語ドキュメントが豊富でまた例も多くコード自体もわかりやすいので初めての方にはぜひおすすめです。

まずは、pybottersをinstallしましょう(第一回 はじめのBot環境構築の続きです)

$ poetry add pybotters

今回はFTX取引所のデータを取得するためのコードを書きます。まず使用するライブラリ群をimportします。今回はpybottersに加えてasyncioもimportしています。

import asyncio
import pybotters

とりあえず取引データを表示するためのメソッドを作ります。
FTXのwebsocketのURLに関しては、Websocket API – API Documentation を見るのが良いかと。またpybottersの使い方に関してはこの辺を見るのが良いかと。今回はBTC-PERPをsubscribeします。

async def ftx():
   async with pybotters.Client() as client:
       wstask = await client.ws_connect(
           'wss://ftx.com/ws/',
           send_json=[
               {'op': 'subscribe', 'channel': 'trades', 'market': 'BTC-PERP'},
           ],
           hdlr_json=pybotters.print_handler,
       )
       await wstask
       

 `{'op': 'subscribe', 'channel': 'trades', 'market': 'BTC-PERP'},` はFTXの公式ページにも書いてあるようにBTC-PERPのトレードをsubscribeするためのリクエストです。hdlr_jsonにはpybottersに用意されているprint_handlerを入れることで受信した内容を表示させています。

mainのメソッドの中身も変更します。

def main():
   try:
       asyncio.run(ftx())
   except KeyboardInterrupt:
       pass

それでは以上で完成です。
これらを合わせるとだいたい以下のようになります

import asyncio
import pybotters

async def ftx():
   async with pybotters.Client() as client:
       wstask = await client.ws_connect(
           'wss://ftx.com/ws/',
           send_json=[
               {'op': 'subscribe', 'channel': 'trades', 'market': 'BTC-PERP'},
           ],
           hdlr_json=pybotters.print_handler,
       )
       await wstask

def main():
   try:
       asyncio.run(ftx())
   except KeyboardInterrupt:
       pass

これを実行すると無事取引データを取得することができます。

$ poetry run pybot
{'type': 'pong'}
{'type': 'subscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
{
   'channel': 'trades',
   'market': 'BTC-PERP',
   'type': 'update',
   'data': [
       {
           'id': 1510304937,
           'price': 39829.0,
           'size': 0.1004,
           'side': 'sell',
           'liquidation': False,
           'time': '2021-07-29T16:38:50.271221+00:00'
       },
       {
           'id': 1510304938,
           'price': 39829.0,
           'size': 0.0032,
           'side': 'sell',
           'liquidation': False,
           'time': '2021-07-29T16:38:50.271221+00:00'
       }
   ]
}
...

以上で取引データの取得は完了です。お疲れさまでした。

次は取得したデータを実際に保存していきましょう!
Twitterで最新記事情報等流しています。見逃さないようにフォローまたはリストに追加おねがいします!

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