🕌

High-frequency trading in a limit order bookと戯れる

2022/11/13に公開

きっかけ

もともとRichman先生のチュートリアルのような、1分〜1時間足くらいで上下に指値をするBotを作りたいと思っていたのですが、色々あって上下指値型Botはマーケットメイキングと同様、価格変動のノイズを収益源としたBotだということをよしそさんから教えてもらいました。ありがとうございます。

であれば、まずはマーケットメイキングについてある程度の理解があった方がよいと思ったので、UkiさんのBlogの記事 マーケットメイク戦略の理論で紹介されている理論的な背景となる論文を読んでみることにしました。

やること

  • 論文を読む
  • 論文の数値シミュレーションを手元で再現する

論文本体はこちらです。
https://www.semanticscholar.org/paper/High-frequency-trading-in-a-limit-order-book-Avellaneda-Stoikov/98e6e6d759ac60bff783c76a8bcc60bb4282b311

DeepLで翻訳をかけたものはこちらです。
https://drive.google.com/file/d/1yJd2Ci1-2TyCtGb3IWEN18FGgDqVloe1/view?usp=share_link

論文を読んだ結果

指値を求める数式を導出する途中で、ハミルトン-ヤコビ-ベルマン方程式を解いているのですが、この計算ができません。確率微分方程式をきちんと学ぶ必要があるなあ、と感じています。

教科書を買ってみたので、これをじっくり読んでみようと思います。高校時代から続く数学アレルギーを克服できるとよいのですが。

https://www.amazon.co.jp/dp/4254209444

数値シミュレーションを再現するために、中核となる数式を読んでおく

気を取り直して論文で出てきた数値シミュレーションを再現します。

この論文では、エージェントのステートとエージェントを取り巻く環境に対応して指値幅を変化させてリスクを調整します。

  • エージェントは在庫qを持っています
  • エージェントは未来の時刻Tで自分の資産の期待値を最大化しようとしています
  • 現在時刻はtです
  • 時刻tでのオーダーブックのBest BidとBest Askの平均値はsです
  • パラメータ\gammaでエージェントのリスク回避度を設定します
    • 論文の数値シミュレーションでは0.1が使われています
  • パラメータkは、マーケットで成行注文が発生したときの価格変化(マーケットインパクト)に関係のある数値です
    • 論文の数値シミュレーションでは1.5が使われています
  • パラメータ\sigmaは価格系列のノイズの標準偏差を示しています
    • 論文の数値シミュレーションでは2が使われています

この時、エージェントが時刻tで出す売り指値と買い指値の平均価格rは以下の式で表されます。

r(s, t) = s - q \gamma \sigma^2 (T-t)

そして論文ではrから上下対称に売り指値と買い指値をするのですが、rと買い指値の差\delta^aと、rと売り指値の差\delta^bを足し合わせたものは以下のようになります。

\delta^a + \delta^b = \gamma \sigma^2 (T-t) + \frac {2} {\gamma} \ln \left(1 + \frac {\gamma} {k} \right)

コード

論文の数値シミュレーションを再現したコードはこちらです。

約定したか否かの判定を確率で行うところが特徴的だと思いました。また、ランダムに変化する価格系列がランダムウォークで作られています。

https://github.com/WannabeBotter/binance_exercise/blob/main/LimitedOrderBookHFT_exercise.ipynb

結果

論文の提案手法は在庫を考慮して指値幅を上下非対称に調整するというものです。提案アルゴリズムのシミュレーションを1000回繰り返したところ、最終利益の統計的性質は以下のような結果になりました。

count    1000.000000
mean       64.196688
std         5.658909
min        45.354892
25%        60.211394
50%        63.941811
75%        67.965680
max        84.352479

1000回の試行のうち最後の一回はこのような形になっています。

続けて、比較対象として指値幅を上下対象にするアルゴリズムのシミュレーションを1000回繰り返したところ、最終利益の統計的性質は以下のようになりました。

count    1000.000000
mean       67.388864
std        13.770087
min         4.467965
25%        60.211779
50%        67.921807
75%        75.058784
max       114.347901

1000回の試行のうち最後の一回はこのような形になっています。

このふたつアルゴリズムの最終利益の平均値と標準偏差は、論文の中に示されている結果とよく似ていますので、実装はおそらく成功しているのだと思います。提案手法は利益の標準偏差が小さく、より安定した利益を上げることに成功しているようです。

気になったこと

仮にこの論文をBTCUSDT 5秒足に適応するとして、問題になりそうな所を書いておきます。

論文では指値を0.005秒間隔で修正していますが、5秒足でも同じことができる?

できません。

論文では0.005秒間隔で成行注文が成立するものと仮定し、0.005秒間隔で仲値sを更新して、それに基づいてrを計算し、買い指値\delta^aと売り指値\delta^bを調整しています。(約定ごとに調整しているのと同等の処理です)

一方で、5秒足には仲値の概念はありません。仕方がないので、最新のクローズ時間を代わりに使う必要があります。

さらに、タイムバーのクローズ価格は更新時間間隔が論文で使っている間隔よりもずっと長い (1000倍!!)ので、そのままの数式で指値幅を計算することはできないと思います。

\sigmaをどう求めるのか?

マーケットメイキングはノイズから利益を得るので、ノイズの強さ\sigmaはとても大事なパラメータだと思っています。

論文では価格ドリフトがないことを前提に人工的に標準偏差\sigmaのノイズ系列を作っていますが、実際のBTCUSDTの値動きはドリフトだらけで、単純にクローズ価格の標準偏差を求めると、ドリフト成分も混ざってしまうでしょう。

ノイズ抽出について簡単に検索してみると、カルマンフィルタというキーワードが出てきたので、少し調べてみようと思います。Pythonで楽に実行する方法があるといいのですが。

論文内の近似がBTCUSDTで通用するか分からない

マーケットインパクトの大きさの近似で使われている式\Delta p \propto \ln(Q)f^Q(x) \propto x^{-1-\alpha}は他の論文の株式市場の分析等から借用されています。\alphaの値がマーケットインパクトを近似するキモなのですが、株式市場で観測された\alphaの値がそのままBinanceのBTCUSDTでも使えるかはわかりません。また、近似式自体ももしかすると通用しないかもしれません。

真面目にやるなら仮想通貨のオーダーブック履歴と約定履歴から、マーケットインパクト\Delta pと成行注文のサイズQのモデル化をするか、モデルをそのまま使うならパラメータ\alphaの推定をするのがよいのだと思います。

Discussion