前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。
参考にしたソースコードはこちら。
これで勉強するhttps://t.co/UHt7mkgI9M
— よだか(夜鷹/yodaka) (@yodakablog) December 18, 2023
また、今回の記事からasyncとpybottersというライブラリを使うため、そのための基礎学習も並行して行なっていきます。
この点に関しては、非同期処理の知識があることが前提です。
概要
ひとまず、ChatGPTにざっくりコードの解説をさせてみます。
このコードが何をしているのか説明して。
(以下、ソースコードの貼り付け)
このコードは、Pythonの非同期プログラミングを使用してビットコインFXのマーケットメイキング(Market Making)ロボットを実装しています。
以下に、コードの主な機能と動作を説明します。
- Status クラス: マーケットの状態を管理するクラスです。板情報の自動更新、指値の計算、保有ポジションの管理などが含まれています。
- EventWatcher クラス: データストアの変更を監視するための抽象クラスです。具体的なイベントに対する監視クラスはこのクラスを継承して作成されます。
- ChildOrderEventWatcher、ExecutionWatcher、CancelWatcher クラス: イベント監視クラスの具体的な実装で、それぞれ子注文のイベント、約定のイベント、キャンセルのイベントを監視します。
- limit_order、cancel_order 関数: 注文を出すための非同期関数です。指定された条件で注文を出し、キャンセルを行います。
- market_making 関数: メインのマーケットメイキングロジックが実装されています。指定された条件でスプレッドが開いた時に、両サイドに対して注文を出すロジックが記述されています。
- main 関数: メインのエントリーポイントで、引数を受け取り、非同期でマーケットメイキングを実行します。WebSocketを使用してリアルタイムなデータの更新を監視し、指定された条件でメイキングを行います。
- parser: コマンドライン引数を処理するための argparse パーサーが定義されています。このスクリプトはコマンドラインから実行されることを想定しています。
- try-except ブロック: キーボード割り込み(Ctrl+C)を受け取ることでプログラムを停止できるようにしています。
これらの要素が組み合わさり、指定された条件が満たされた際にマーケットメイキングを実施するロボットが構築されています。
これだけでは、いまいち理解できないのでもっと絞り込んで質問してみます。
このコードは何をしているの
from __future__ import annotations
from typing import TYPE_CHECKING, Callable
このコードの最初の行は __future__
モジュールを使用して、新しいバージョンのPythonで導入された新機能や言語仕様を、現在のバージョンで使用できるようにするためのものです。具体的には、annotations
オプションを有効にしています。annotations
オプションは、関数やメソッドの引数や返り値に型アノテーションを使うためのものです。
2行目からは、typing
モジュールから TYPE_CHECKING
と Callable
をインポートしています。
TYPE_CHECKING
は通常の実行時ではなく、型ヒントの検証などのために型チェッカーが実行されているときにのみ特定のコードを実行するためのものです。通常、TYPE_CHECKING
ブロック内のコードは型チェッカーが実行されている場合にだけ実行され、ランタイムでは無視されます。Callable
は、関数の型アノテーションに使用されるジェネリック型です。Callable[[Arg1Type, Arg2Type], ReturnType]
のように使用され、引数の型と戻り値の型を指定します。
このような型の宣言や型ヒントは、コードの可読性を向上させ、静的解析ツールによるコードの品質向上をサポートします。Python 3.7以降では、型ヒントが言語仕様に正式に組み込まれているため、__future__
モジュールを使わなくても型ヒントを使用できますが、このコードでは互換性のために __future__
を使用している可能性があります。
各項目ごとに解説させると、少し分かりやすくなりましたね。
各項目ごとの解説
最初の質問で提示したコードの説明を各項目ごとにもっと詳しく解説して
提供されたコードを以下の項目ごとに詳しく解説します。
1. インポートと future モジュール
from __future__ import annotations from typing import TYPE_CHECKING, Callable
__future__
モジュールのインポートを行っています。annotations
オプションを有効にしています。これは、Python 3.7以降で導入された型アノテーションの新しい構文を使用するために必要です。これにより、型アノテーションを使った型ヒントがより効果的に利用できます。TYPE_CHECKING
およびCallable
をtyping
モジュールからインポートしています。TYPE_CHECKING
は通常の実行時ではなく、型チェッカーが実行されているときにのみ特定のコードを実行するためのフラグです。Callable
は、関数の型アノテーションに使用されるジェネリック型です。
2. Status クラス
class Status: # ... (クラスの中身は省略)
Status
クラスは、マーケットの状態を管理するためのクラスです。主な機能は次の通りです。
- 初期化メソッドでデータストアや最大ポジション数などの情報を受け取ります。
auto_update_board
メソッドは非同期で板情報を自動更新するタスクを開始します。get_limit_price
メソッドは指定したサイド(askまたはbid)に対する指値を計算します。- 他にもポジションの取得や残りサイズの取得、板情報のプロパティなどがあります。
3. EventWatcher クラスおよびそのサブクラス
class EventWatcher: # ... (クラスの中身は省略) class ChildOrderEventWatcher(EventWatcher): # ... (クラスの中身は省略) class ExecutionWatcher(ChildOrderEventWatcher): # ... (クラスの中身は省略) class CancelWatcher(ChildOrderEventWatcher): # ... (クラスの中身は省略)
EventWatcher
はデータストアの変更を監視するための抽象クラスで、_watch
メソッドでデータストアを監視しています。継承先のクラスで_is_trigger
メソッドをオーバーライドして特定のイベントが発生したかどうかを判定します。ChildOrderEventWatcher
は特定の子注文イベントを監視するクラスで、_is_trigger
メソッドで特定の注文IDと条件に一致するかどうかを判定します。ExecutionWatcher
とCancelWatcher
はそれぞれ約定とキャンセルのイベントを監視します。
4. limit_order および cancel_order 関数
async def limit_order(client, symbol, side, size, price, time_in_force="GTC"): # ... (関数の中身は省略) async def cancel_order(client, symbol, order_id): # ... (関数の中身は省略)
limit_order
関数は指定した条件で注文を出す非同期関数で、注文が成功した場合には注文IDを返します。cancel_order
関数は指定した注文IDに対してキャンセルを行う非同期関数で、キャンセルが成功したかどうかをブール値で返します。
5. market_making 関数
async def market_making( client, store: pybotters.bitFlyerDataStore, status: Status, symbol: str, t: float, d: int, s_entry: float, s_update: float, size: float, logger: loguru.Logger ): # ... (関数の中身は省略)
market_making
関数はメインのマーケットメイキングロジックを実装しています。指定された条件でスプレッドが開いた場合に、両サイドに対して注文を出すロジックが記述されています。
6. main 関数
async def main(args): # ... (関数の中身は省略)
main
関数はプログラムのメインのエントリーポイントで、コマンドライン引数を受け取り、非同期でマーケットメイキングを実行します。WebSocketを使用してリアルタイムなデータの更新を監視し、指定された条件でメイキングを行います。
7. parser
if __name__ == "__main__": # ... (parser の定義および引数の解析)
__name__
が "__main__"
の場合に、コマンドライン引数を解析して main
関数を非同期で実行するための部分です。この部分が実行されると、プログラムが起動します。
まとめ
main関数を見てから、それにまつわる関数を一つずつ読み込んでいくことで、コードの概要を掴みやすくなります。
次回以降の記事では、各項目ごとに必要な知識を学びながら、コードの解析を進めていきます。
#39(2023/12/20)「MMBotの開発④MMBotとは?/マーケットメイキング(MM)戦略のコスト分析」に続く...