[BTC][Bot] [Python] 第三回 取引所の取引データを保存する
はじめに
こんにちは _santa365です。
第一回 はじめのBot環境構築 ではベースとなるプロジェクトの作成、第二回 取引所の取引データを取得する では実際の取引所と通信をしてデータの取得を行いました。
今回は第二回の内容を少し発展し、取引所の実際の取引データを取得し、保存していこうと思います。取引データを保存することでバックテスト(過去のデータを使ってBotの有効性をテストする)をすることができるようになります。
取引所の取引データを保存する
前回の最終的なコードは以下のようになってました
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
今回は、これを改良して手元にデータを保存するようにします。
方針
方針としては簡単です。データ保存用のHandlerを作成し、それを`pybotters.print_handler` の代わりに使います。
まずpybottersのprint_handlerの中身を見てみると下記のような形になっています(Code)。
def print_handler(msg: Any, ws: aiohttp.ClientWebSocketResponse):
print(msg)
これと同様の引数の形式をもつ関数`save_to_csv_handler`を定義します。今回はws引数は使用しないため引数名を_にしています。
from typing import Any
import aiohttp
def save_to_csv_handler(msg: Any, _: aiohttp.ClientWebSocketResponse):
print(msg)
pybotters.print_handlerの部分をsave_to_csv_handlerに書き換えます。ここまでのコードをまとめると下記のようになります。
書き終えたコードを実行してみてください。挙動は `pybotters.print_handler` のときと同じですが、中身は定義した関数を使うようになっています。
import asyncio
import pybotters
import aiohttp
from typing import Any
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=save_to_csv_handler,
)
await wstask
pybotters.FTXDataStore()
def save_to_csv_handler(msg: Any, _: aiohttp.ClientWebSocketResponse):
print(msg)
def main():
try:
asyncio.run(ftx())
except KeyboardInterrupt:
pass
次に、`save_to_csv_handler` の中身を変更して受信したデータをファイルに保存する処理にします。
Websocketによって受信するデータは主に以下のようになっています。
{'type': 'pong'}
{'type': 'subscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
{'channel': 'trades', 'market': 'BTC-PERP', 'type': 'update', 'data': [{'id': 1514850859, 'price': 39022.0, 'size': 0.0128, 'side': 'buy', 'liquidation': False, 'time': '2021-07-30T15:37:06.154989+00:00'}]}
上記の情報では `pong` や `subscribed` といった不必要なデータが含まれています。ファイルを保存する前にデータの不必要な部分を削除するため関数の中身を少し書き換えます。
def save_to_csv_handler(msg: Any, _: aiohttp.ClientWebSocketResponse):
# msgに`data`がなければ、Trade情報ではない
if 'data' in msg:
channel: str = msg['channel']
market: str = msg['market'] if 'market' in msg else ''
datas: Any = msg['data']
# Trade情報の場合、msgの`channel`は`trades`になる
if msg['channel'] == 'trades':
for data in datas:
print(data)
やってることはシンプルです。トレード情報のデータには`data`キーが絶対含まれているので、まず受信したデータの中に`data`キーがあるかチェック。その後、受信したデータの中からさらに必要なデータのを書き抜きます。
これを再度実行すると表示は以下のようになります
$ poetry run pybot
{'id': 1514858964, 'price': 39066.0, 'size': 0.0828, 'side': 'sell', 'liquidation': False, 'time': '2021-07-30T15:40:07.506434+00:00'}
{'id': 1514858965, 'price': 39066.0, 'size': 0.0172, 'side': 'sell', 'liquidation': False, 'time': '2021-07-30T15:40:07.506434+00:00'}
{'id': 1514858972, 'price': 39066.0, 'size': 0.0019, 'side': 'sell', 'liquidation': False, 'time': '2021-07-30T15:40:07.586899+00:00'}
必要な情報のみを取得することができましたね。上記のデータをファイルに保存していきます。今回はCSVファイルに保存します。また一つのファイルがすごく長くなるのを避けるため、日付毎にファイルを分けます
import os
import csv
from datetime import datetime as dt
def save_to_csv_handler(msg: Any, _: aiohttp.ClientWebSocketResponse):
if 'data' in msg:
channel: str = msg['channel']
market: str = msg['market'] if 'market' in msg else ''
datas: Any = msg['data']
if msg['channel'] == 'trades':
for data in datas:
dir_path = 'data/ftx/raw'
file_name = data['time'][0:10];
file_path = f'{dir_path}/{file_name}.csv';
if not os.path.isdir(dir_path):
os.makedirs(dir_path, exist_ok=True)
if not os.path.isfile(file_path):
with open(file_path, 'w') as f:
writer = csv.writer(f)
writer.writerow(['time', 'side', 'price', 'size'])
with open(file_path, 'a') as f:
writer = csv.writer(f)
writer.writerow([data['time'], data['side'], data['price'], data['size']])
処理の内容は上から順番にせ大きく3つに別れています。
1. 保存する先のディレクトリがなければ作成する。今回は、`data/ftx/raw`に保存する。
2. 保存ファイルが無ければ、作成する。CSVなのでファイル作成時はHead情報をはじめに書き加えています。
3. 実際のトレードデータを保存する
今回保存したデータは生データ(raw)になるのでここからローソク足の作成やバックテストに必要なデータを作成をすることができます。
以上で取引データの保存は完了です。おつかれさまでした!
次は保存した生データを使ってローソク足の作成にトライしていきます!
Twitterで最新記事情報等流しています!お見逃しがないようフォローまたはリストに追加していただけると幸いです!