仮想通貨MLbot探求のしおり
機械学習 大事なこと
使用ツールは lightGBM
サンプル数
データはできるだけ長期間。
約定しやすい執行戦略にしてサンプル数を上げる。サンプルが少なければまず間違いなく過学習が起きる。
機械学習を通す前段階で、執行戦略とそのリターンがかなり重要なイメージがある。
richman方式の場合、マイナス手数料の取引所では生のリターンの状態でとんでもないマイナスになる。せめてフラットなとこまで持ってく執行戦略が必要。
学習具合
cvの区間別に学習具合を確認する。
1区間でも学習が進まない場合、
- オーバーフィッティング
- 特徴量が弱すぎ
- yとの相関が低い?yの設計も考えなおす
- 目的変数のばらつきを見る
- サンプルウェイトやクラスウェイトの設定を見直す
def training_model(trn_data=None, val_data=None,params=None index=None, plot=None):
verbose_eval = 0
records = {}
clf = lgb.train(
params,
trn_data,
num_boost_round=10000,
valid_sets=val_data,
feval=self.evaluation.func if self.evaluation is not None else None,
callbacks=[lgb.early_stopping(stopping_rounds=100, verbose=True),
lgb.log_evaluation(verbose_eval),
lgb.record_evaluation(records)]
)
# 学習具合を返す
progress = records["valid_0"][metric]
return clf,progress
サンプル・クラスウェイト設定
共通
richmanさんのノートにもあった
np.abs(リターン)
ファイナンス機械学習の
- 平均独自性
- 時間減衰
分類
is_umbalance : true 必要か?
scale_pos_weight: sqrt(負例数/正例数) 強い偏り補正
scale_pos_weight: 負例数/正例数
ラベルに極端な偏りがあると学習が進まない。
分類なら、CV期間ごとの予測値のばらつきも確認した方がいい。
特徴量重要度
木ごとの特徴量利用割合を下げていった時、極端に高い・低い重要度の特徴量は除外した方がいい。
ランダムなデータを加えてその他の特徴量と比較する。
df["RANDOM"] = np.random.normal(0, 1.0, df.shape[0] )
特徴量間の相関が高いものは正しく重要度が測れない。
ファイナンス機械学習にあるように、特徴量でクラスタリングして重要度を見てみたり、PCAで次元圧縮すると正確な数値がわかるって話。やれてない。
学習器
金融時系列はS/N比が低く価格やリターン推定はほぼ無理、分類や分位点回帰を使う。
目的変数のノイズと推論分布の関係について
lightGBMで分布予測
目的変数 y
正規分布に近づけた方がいいのかな。
sqrtやlog、boxcox変換して良さそうなのを使う。
特徴量
分数次差分をとる。
金融時系列は基本的に非定常なデータです。
非定常データをそのまま用いても機械学習の予測は難しい。
非定常データを定常データに変換するためには、差分を取る必要があります。
ただ、こちらの記事にあるような1期、2期前といった整数次での差分は平均の推移の情報(メモリー)が抜け落ちてしまいます。
分数次差分では、1/2期,2/3期前といった差分の取り方が可能となり、メモリーを保持したまま定常なデータに変換できます。
機械学習で決定木を使うなら必須
詳細情報
高速な実装
メタラベリング
リターンの符号を予測するようなモデル(A)があった時、そのモデルに対してベッドサイズを決定するモデル(B)を作成する手法。
具体的には一段目の予測モデルAの推論結果と、実際のリターン符号が正しい場合は1をそれ以外は0を割り当てた目的変数(y')を学習したモデルBを作成する。
目的変数 y' =
Aが + と予測する。 => 実際のリターン符号 + => 1
Aが - と予測する。 => 実際のリターン符号 - => 1
Aが + と予測する。 => 実際のリターン符号 - => 0
Aが - と予測する。 => 実際のリターン符号 + => 0
Bはy'を学習し、Aの推論の正答率を予測する。
出力した正答率から適切なベッドサイズを決めるには、ファイナンス機械学習10章を参照。
逐次ブートストラップ
ラベルの平均独自性をもとに時系列全体の独自性を高める抽出方法
使えてない。
ファイナンス機械学習では、ランダムフォレストのブートストラップを置き換えるためのものだった。
GBDTで使う場合、bagging設定をオフにして逐次ブートストラップで抽出したデータ毎にモデルを作成して予測の平均を出すのがいいのかな。すごい過学習しそう。
本のやつよりは速い実装(間違ってるかも
@numba.jit(nopython=True)
def rand_choice_nb(arr, prob):
return arr[np.searchsorted(np.cumsum(prob), np.random.random(), side="right")]
@numba.jit(nopython=True, parallel=True)
def seq_bootstrap(num, index, probs):
'''
num : 何個の時系列を生成するか
index : ラベルのインデックス
probs: ラベルの平均独自性
'''
seq_bootstrap_arr = []
for v in numba.prange(num):
phi = np.zeros(index.size)
cal = np.ones(index.size)
master = probs
for i in range(index.size):
prob = (probs / np.sum(probs))
pick_data = rand_choice_nb(arr=index, prob=prob)
phi[i] = pick_data
pick_index = np.where(index == pick_data)[0][0]
cal[pick_index] += 1
probs = master / cal
phi = np.sort(phi)
seq_bootstrap_arr.append(phi)
return seq_bootstrap_arr
特徴量のbinning
binning : 値を代表値に分割集約する処理
過学習防止
from sklearn.preprocessing import KBinsDiscretizer
def binning(n_bins=10,df)
df = df.dropna()
for feat in x_feats:
bins[feat] = KBinsDiscretizer(n_bins=10, encode="ordinal")
bins[feat].fit(df[[feat]])
df[feat] = bins[feat].transform(df[[feat]])
#pickle_dump(bins[feat], f"../input/gresearch/bins_model/bins_{feat}.pickle")
参考コード
n_bins数は5分位がおすすめ?
ハイパーパラメータチューニング
あんまりよくわかってない。
CPCVとoptunaで組み合わせて寝てる間にベストなパラメータが出てる。
良いものをより良くできるという認識、よくないものをよくすることはできない。
CPCV
optuna
オススメハイパラ
重要だなって思うハイパラ簡単解説
n_estimators
決定木の数、earlystopping設定で勝手に学習止めるなら10000とか大きい数にする。
"learning_rate"
学習率、大きいと大雑把に学習する(スピードが速い)本番では0.01とかにする
"extra_tree" True,
上の記事に説明があるやつ、過学習防止
"max_depth"
決定木の階層数、大きすぎると過学習する
"feature_fraction"
一本の決定木に使う特徴量の割合、numeraiのサンプルでは0.1、できるだけ低くして汎化性能をあげる。
"bagging_fraction"
利用するサンプルの割合、低くして汎化性能上げる
"bagging_freq"
決定木何本に一回バギングするかの設定、
具体的な解説はこちらがわかりやすい。
本番モデルの作成法
- パージ済みCVでモデルを作成する。この時アーリーストッピングで各期間の木の本数を確定
- 各期間の木の本数の平均をとる
- 2で出した値にcvの期間数に応じて係数をかける cv数5なら1.2とか
- n_estimatorsに3の値を入れて全データで学習する。
twitterで見た感じいろんなやり方があるっぽい
直近のデータをvalidデータとして、アーリーストッピングかけるとか
正解はわからないけど、良い特徴量とyを与えてやれば決定木の本数が大きすぎても精度は下がらない。
下記記事参照
とりあえず各CVの学習進捗は確認する!
バックテストしすぎない
損益曲線を見てもいいけど、あまり意味は考えない方がいい。
全部読んだ方がいい方々のサイト
株式、機械学習
仮想通貨、bot
クオンツ、機械学習
numeralアドベントカレンダー22
仮想通貨notアドベントカレンダー22
マケデコ
参加すべきディスコード
金字塔
必読書
kaggle
bot開発
ライブラリ
今から開発するならこれ!
pybotters
pybotters-wrapper
有料だけど
ccxt
MLBotに必要な機能
- データ取得
- データ整形
- 特徴量作成
- 推論
どんな時間軸・発注方式で戦うにせよスピードは早くした方がいいんでしょうね。
止まらないbot
止まっても再起動させる
複雑なプログラムを書きたくないなら、エントリーとイグジットで難しいことをしすぎない。
複雑になりすぎたと思ったら寝る!
23/01/27
ローソク足の更新が止まってる
lambdaで動かしてるローソク足保存機能が原因?
rate limitに引っかかってる?
bot最速化計画
現状
発注まで1.5秒程度かかってる。
ごく稀に指値が成行に変わってしまう。
データ受信 0.01秒
データ前処理 0.6秒
推論 0.8秒
発注 0.1秒
推論非同期処理・並列化?
データ前処理部分を最適化する。
案
データ前処理部分
- 話題のpolars導入する
推論
- https://www.xlsoft.com/jp/blog/intel/2021/08/05/improve-the-performance-of-xgboost-and-lightgbm-inference/
- スタッキングしないモデルに関しては、非同期処理する。
- 1次オーダーに必要な推論 - 非同期
- 推論完了したらオーダー 非同期
- 2次オーダーに必要な推論 - 非同期
- 推論完了したらオーダー 非同期
執行コストを考える。
執行コスト例
執行戦略と取引コストに関する研究の進展(難しい)
- 数式が多くて難しい。
- 取引の遅延等は、指値注文の場合あまり気にしなくて良いか。。。
- マーケットインパクトは小口の場合考えない
- 指値位置分散させるのが良い?
- botでは、収益が最大になる参入価格と、実際に参入した価格の差をコストとして考えても良いかも
特徴量を考える
自動生成する?
特徴量のスクリーニング
OHLCV以外の特徴量
- oi
- liquidation
- taker makerに関する情報
強すぎる特徴量はよくない。
結局一個ずつ検証するしかない気がする
CNNについて学ぶ
MNISTで学ぶCNN
CNNわかりやすい動画解説
構造化データを使ったCNN例
まず手を動かすことから始める。
ファイナンスへの応用については、マケデコの輪読会でつかってる参考書かって考える。(載ってるのはRNNだけど)
CNN使って予測
既存の特徴量・目的変数で学習。
GBDTより学習が安定しない & 精度が低い。
中間層を適当に増やすと過学習しがち。
やり方が間違ってる?
CNNの特徴
畳み込みで特徴量間の関係を学んでいる。
パターン認識が得意
GBDTとCNNのいいとこ取りできないかな。
あん
戦略のリターン符号(手数料なし)分類
戦略リターンが往復手数料より大きいか分類
ウェイト
エントリーからイグジットまでの日数に応じてウェイトを減少させる。
=> 時間経過で予測力を失っていく。
現状分析
取引数が少ない。
=> ohlcv + a で作成した特徴量じゃ説明力がなくなっている。
ボラティリティが増える場面ではしっかりと稼いでる。
=> ノイジーなトレーダーはフォローできてる。
対策
より多くの非効率なトレードやミスプライスを発見するしかない。
具体的に
- 市場間(フィアット・国債・株式・仮想通貨)の関係性を表現できる特徴量の追加
=> データソース増やす、特徴量いっぱいつくる - 既存の特徴量からより多くのデータを取り出す。
=> CNN?
勉強になった本
MLOps関係
不確実な市場と対決する心構え