created at

Posted by Coin News Main

オンライン推定を用いたシステムトレード

初めまして。CoinNewsMainと申す者です。ここでクリプトニュースを垂れ流すかたわら記事を書いています。

Botter Advent Calender11日目の記事であります。Botter Advent Calenderということで仮想通貨Botに関する記事を書いていこうと思います。

オンライン推定とは?

トレーディングをしていると色々なパラメータを設定する必要が出てくると思います。典型的なのは機械学習や統計学を用いたモデルになりますが、マーケットメイク戦略やアービトラージ(閾値の設定)においてもそうです。

このようなパラメータをみなさまはどう選択されているでしょうか。もちろん理想的なのはヒストリカルデータを用い、統計的に妥当と思われる値を推定することだと思います。あるいは過去のデータから経験則的に鞘がこの位開いたらアービトラージを実行するという方法をとる場合もあります。

では、ヒストリカルデータが十分にないような状況や全くない、あるいはデータとして取ることが難しいような場合はどうでしょうか。このような状況では、一般的に使用されるパラメータ手法を使用することは難しくなってきます。

今回紹介させていただくのはヒストリカルデータを使わずにパラメータを推定するオンライン推定という手法です。ヒストリカルデータを使わないことで、実際にBotを実装する際にメモリを節約することもできます。また、データが一個一個入ってくる度にパラメータを更新する動的パラメータを設定することもできます。

オフライン推定とオンライン推定

一般的に使われる最小二乗法のような推定手法がバッチ推定(オフライン推定)と呼ばれるのに対して、この記事で扱うのが逐次推定(オンライン推定)です。

バッチ推定を用いてモデルを組む場合は、一度ヒストリカルデータからモデルを学習させ、そこで得られたパラメータをもとに実践投入という感じになると思います。ここで最適化されたパラメータは基本的に変わることはありません(これを静的パラメータと言うこともあります)。

オンライン推定の場合は、次々とストリーミングされるデータに対して、逐一パラメータを更新していきます。

オフライン推定のイメージ

オンライン推定のイメージ

何言ってるのか分かんないという方、実はそんなに難しくないです。

時系列データX1,....,XnX_1,....,X_nがあるとします。例えば、これの平均μn\mu_nを普通に求めるのならば、

μn=X1+....+Xnn\mu_n = \frac{X_1 + .... + X_n}{n}

ですが、一期前の平均の値μn1\mu_{n-1}は時刻T=nT=nですでにわかっていますよね。これを使ってμn\mu_nを表そうとすると、

μn=X1+....+Xnn=(X1+....+Xn1n1)×(n1)+Xnn=μn1×(n1)+Xnn\begin{aligned} \mu_n &= \frac{X_1 + .... + X_n}{n} \\ &= \frac{(\frac{X_1 + .... + X_{n-1}}{n-1}) \times (n-1) + X_n}{n} \\ &= \frac{\mu_{n-1} \times (n-1) + X_n}{n} \end{aligned}

となって、一期前までのデータX1,....,Xn1X_1,....,X_{n-1}を使わずに平均を求めることができます。また、ここに新しいデータXn+1X_{n+1}が来たときに、μn\mu_nを使ってμn+1\mu_{n+1}をヒストリカルを参照することなく求めることもできます。今回は簡単な例ですが、こういった計算式上のテクニックを使えば、より効率的に求めたいパラメータを推定できることが分かります。

色々なパラメータ推定法

パラメータの推定手法というのは異なる分野で色々なアプローチがあります。オンライン推定においても同様で、使われるデータの種類や状況によって適切なモデルを選択する必要があります。これらの手法を、(具体的な数式の説明はここでは置いといて)ざっくり紹介していきます。

逐次最小二乗法

最小二乗法を逐次推定できるように改良したものが逐次最小二乗法です。最小二乗法の時刻ttt1t-1の関係を漸化式で表すことで逐次化に成功しました。古典的なモデルではありますが、それゆえに実装も比較的容易で高速に動作します。

一変数での逐次最小二乗法のPython実装

class SequentialLeastSquares:
    def __init__(self):
        self.theta = 0  
        self.P = 1000  

    def update(self, x, y):
        K = self.P * x / (x**2 * self.P + 1)
        self.theta += K * (y - x * self.theta)
        self.P -= K * x * self.P

    def predict(self, x):
        return x * self.theta

オンライン凸最適化

オンライン凸最適化(Online Convex Optimization, OCO)は、逐次的に入手できるデータを使って最適化問題を解く機械学習で用いられる逐次最適化の手法です。分布の形にとらわれず、目的関数が凸であればいいので、広範な最適化問題に対して有効です。

統計畑の方にはあまり馴染みがないかもしれませんが、オンラインニュートン法やニューラルネットワークの学習でよく使われるADAM系のアルゴリズムが有名です。

シンプルな線形回帰問題をオンラインニュートン法で解くPythonのクラス

import numpy as np

class OnlineNewtonStep:
    def __init__(self, dim, eta, lambda_reg):
        self.theta = np.zeros(dim)
        self.A = lambda_reg * np.eye(dim)
        self.eta = eta
        self.lambda_reg = lambda_reg

    def update(self, x, y):
        grad = -x * (y - np.dot(x, self.theta))
        self.A += np.outer(x, x)
        A_inv = np.linalg.inv(self.A)
        self.theta -= self.eta * np.dot(A_inv, grad)

    def predict(self, x):
        return np.dot(x, self.theta)

ベイズ推定

ベイズ推定 とは、ベイズの定理に基づいた統計学における推定手法の一つです。この手法は、未知のパラメーターに対する事前の信念(事前確率)と新たに得られたデータ(尤度)を組み合わせて、パラメータの推定値(事後確率)を更新していきます。

ベイジアンの特徴としてデータXXを単なる変数ではなく、確率分布と見做すことにあります。これによりパラメータやモデルの信頼度を定量的に評価することができます。その他、ヒストリカルデータから得られたパラメータを事前分布としてモデルに組み込むこともできるなど、ベイズならではのメリットはとても多いです。

最も単純な例:コインの表が出る確率をベイズ推定する方法

import numpy as np
from scipy.stats import beta
import matplotlib.pyplot as plt

# ベイズ更新関数、ここで、alphaとbetaはベータ分布のパラメーター
def bayesian_update(alpha, beta, heads, tails):
    return alpha + heads, beta + tails

# 初期パラメーター(事前知識がない場合はどちらも1)
alpha_prior = 1
beta_prior = 1

# コイン投げデータ(例: 1は表、0は裏)
coin_flips = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1]

# 逐次的にベイズ更新
# 新たなデータが到着するたびにパラメータalphaとbetaが更新されていきます。
for flip in coin_flips:
    heads, tails = int(flip == 1), int(flip == 0)
    alpha_prior, beta_prior = bayesian_update(alpha_prior, beta_prior, heads, tails)
    print(f"Updated alpha: {alpha_prior}, Updated beta: {beta_prior}")

# 事後確率分布の描画
x = np.linspace(0, 1, 100)
plt.plot(x, beta.pdf(x,  alpha_prior, beta_prior))
plt.show()

ここではベータ分布(2値問題で扱う分布)を例として使いましたが、もちろん正規分布など他の分布を使うことで応用できます。

カルマンフィルタ

オンライン推定の欠点としてはノイズに弱いということが挙げられます。新しいデータに外れ値があると、その悪いデータに引っ張られてパラメータが極端に悪化してしまいます。

そのような外れ値への対処メカニズムを兼ね備えた逐次推定手法として最も有名なのがカルマンフィルタです。新しい入力値に対してカルマンゲインという誤差補正用の変数を通してあげることで逐次推定ながら外れ値に強いのが特長です。

注意点としてはカルマンフィルタで使われるモデルのパラメータ自体は逐次推定にならないということです。カルマンフィルタは状態空間モデルの状態変数の逐次推定に使われますが、モデルのパラメータ自体の推定には直接使われません。それゆえにパラメータ自体を推定する場合は最尤推定法という手法をとられることが一般的で、厳密な意味でのオンライン推定ではないです。(パラメータ推定する際には、そのパラメータが与えられた時のモデルの対数尤度を最大化。)

Pythonではpykalmanやstatsmodelsで実装されています。ただ実際にモデルを構築する際にオリジナルの状態空間表現を使うことが多いため、パッケージなしで実装することが多いです。

カルマンフィルタ自体は線形モデルですが、非線形への応用モデルとして拡張カルマンフィルタや無香カルマンフィルタなど色々なモデルがあります。

パーティクルフィルタ

パーティクルフィルタとは、モンテカルロ法(確率的シミュレーションに基づく手法)の一種を利用した状態空間モデルの推定方法の一種です。

簡便なカルマンフィルタが実務的によく使われるのに対し、研究室レベルではこちらのパーティクルフィルタを用いることが多いです。非線形および非ガウスなシステムの状態を推定することもできます。

パーティクル(粒子)と呼ばれるサンプルを使用してシステムの状態の確率分布を表現し、新しいデータが入ってくるたびに重要度に応じてパーティクルを選別するサンプリングを行うことでパラメータの推定を行います。粒子数が十分に多い場合、拡張カルマンフィルタや無香カルマンフィルタよりも高い精度を出すことができます。ただし、計算コストが高いのが難点で、実際に使用することはなかなか無いと思われます。

オンライン推定をシステムトレードに取り入れてみよう

オンライン推定を用いたBotへの応用例を紹介します。より深掘りした話やコードへの実装は気分が向いたら書きます。

高頻度マーケットメイクBot

オンライン推定が使われる典型的なモデルがマーケットメイク戦略になると思います。次々と入ってくるデータに対して効率的にパラメータを推定したい際にベイズ更新は便利です。

マルコス・ロペス氏の名著、ファイナンス機械学習でもPIN(Probability of Information trading)の推定に際し、ベイズ更新を使用しているという紹介もありました。

This equation tells us that the critical factor that determines the price range at which market makers provide liquidity is

PINt=αtμαtμ+2ϵPIN_t = \frac{\alpha_t \mu }{\alpha_t \mu + 2\epsilon}

The subscript tt indicates that the probabilities α\alpha and δ\delta are estimated at that point in time. The authors apply a Bayesian updating process to incorporate information after each trade arrives to the market.

高頻度戦略を使う上では、ボラティリティやPINのようなパラメータを動的に推定できるのは大きなアドバンテージになります。そしてなにより高い計算効率やメモリの節約が嬉しい。

新規トークン上場戦

新規に上場するトークンのマーケットメイク戦略でもオンライン推定は強力な武器になります。

例えば、既にBinanceに上場しているトークンが今度、Bybitに上場されるらしい。出来高の多いBinanceの価格をもとにBybit上でそのトークンのマーケットメイクBotを作成したい。ただし、もちろんデータはないのでBinance-Bybit間でそのトークンの価格差がどの程度開くのかは検討がつかない。

上場後に価格データを逐次的に取得し、取引所間の価格の差分が描く分布を推定することができれば、新規上場トークンのマーケットメイクにも役立てることができます。オンライン凸最適化アルゴリズムやベイズ推定など分散自体を初期値としてモデルに組み込める場合は、分散の初期値を大きい値にしてデータの更新毎にスプレッドを徐々に狭くすることができます。

また、新規上場トークンでなくても、複数の取引所で在庫モデルを使ったマーケットメイクをする際にも、オンライン推定に価格情報を取り入れるのは有効です。

DEXでのステーブルコイン転がしBot

オンライン推定は過去データの手に入りずらい分散型取引所(DEX)でも有効です。

あるDEXにUSDTとUSDCが上場されています。ステーブルコインなので理論的には大体二つのコインはどちらも1ドル付近になるはずですが、時折価格差が開くことが観測されました。この価格差がある一定のところまで開いたところで差分をとるBotを組みたい。ではその閾値はどう設定すればよいでしょうか。(参考: はじめてのDEXアビトラbot ~C級botterからGOXまで~)

新規上場DEXや新規プールなど価格に関する情報が不足している場合、オンライン推定の出番です。一変数だけの分布の推定という話であれば、逆行列の計算を必要としないのでオンラインニュートン法や逐次最小二乗法が計算効率的に有効になります。また、事後分布に正規分布を仮定してベイズ推定するのも効率がいいです。

特段複雑な計算もないので、コントラクトを使ったオンチェーンbotを組むこともできます。毎ブロックごとに得られるUSDC-USDTスプレッドから、ヒストリカルデータを貯めることなくパラメータ(ここでは価格差の分布)を推定できます。

最後に

意外とこういった手法を知らない方も多いのではないかと思って紹介記事を書いてみました。最近はファイナンス分野に限らず、ニューラルネットxマシンパワーで殴るという戦法が流行ってきており、あまり机上の戦術は重要視されない傾向にあります。その中で、より早い時間軸での効率性を求めるオンライン推定は違った良さがあると思います。上記で挙げた応用例以外にも市場全体のトレンドの推定やNFTのフロアの推定など様々なところで適用でき、実装も簡単なので、こういったモデルも是非取り入れていただければと思います。

オンライン推定を用いたシステムトレード
コメント
新着記事
Copyright © 2023 Coin News DAO. All rights reserved.

Site Map

Twitter(X)