💹

richmanbtcさんのForce Entry Priceがよく分からなかったので、自分なりにまとめてみた

2022/03/07に公開

botter必読書

  • 日給300万円のSS級トレーダーが明かすbotterのリアル

https://amzn.to/3hUFlfm
いわずと知れたリッチマンさんの著書です。
ぼんやりと仮想通貨のトレードで儲けたいと考えていた僕を、
botterの道へ明確に導くキッカケになった本。

botterになろうと考えている人は、botterのメリット、
狙い目などの概略的な部分が知れて良いと思います。

  • Kaggleで勝つ技術

https://amzn.to/3MD6iCf
リッチマンさん推奨の本。分からなくなったら読めと書いてあった。
僕はデータの前処理や学習モデルを作っているとき、「???」となることがあった。
そのとき読んでクリアできた。

文系で機械学習未経験の僕が、richmanBTCさんのチュートリアルをやってbotterになるまでの流れ

https://zenn.dev/flutternyumon/articles/4fa5f97b0c4ba3

最初に

書いてあることが間違っている可能性があるので、注意して読んでいただけると助かります。

Force Entry Priceについて

Force Entry Priceは買うと決めてから約定するまで指値で追いかけた場合に、実際に約定する価格です。独自用語です。指値の出し方は任意です。entryと名前がついていますがexitも同じ計算なので区別はないです

つまりどういうことか

指値注文をして、エントリーの約定ができる価格を調べている。
ちなみに約定できた場合、約定するまでかかった時間を調べるためにForce Entry Timeも算出している。

約定 と 決済 の違いを知っておかないと理解が難しい気がする

約定を決済と同じ意味合いで使っている人が多く、勘違いしやすい気がする。
https://finance.yahoo.co.jp/brokers-hikaku/experts/questions/q10201432715

  • 約定 注文が成立すること。つまりエントリー時の注文も約定、利確損切りといった決済(エグジット)も約定。
    約定のイメージ

  • 決済(エグジット) 利確や損切りの際の約定のこと。

算出する目的

機械学習の正解データを作るためのパーツ
約定できなかったら、そもそもエントリーできないので勝敗を求めることが出来ない。

正解データの作り方 (この記事では②まで扱う)

  1. 毎時刻、あるルールで計算された指値距離(limit_price_dist)に基づいて、買い指値を出す
  2. 買い指値が約定しなかった場合のyはゼロとする
  3. 買い指値が約定した場合、一定時間(horizon)だけ待ってから、Force Entry Priceの執行方法でエグジットする
  4. エグジット価格 / エントリー価格 - 1 - 2 * feeをyとする
    約定(エントリー)できたら、次の工程

使い方

各足ごとにエントリーできるか探っていくイメージ
エントリーできた場合、

def calc_force_entry_price(entry_price=None, lo=None, pips=None):
    y = entry_price.copy()
    y[:] = np.nan
    force_entry_time = entry_price.copy()
    force_entry_time[:] = np.nan
    for i in range(entry_price.size):
        for j in range(i + 1, entry_price.size):
            if round(lo[j] / pips) < round(entry_price[j - 1] / pips):
                y[i] = entry_price[j - 1]
                force_entry_time[i] = j - i
                break
    return y, force_entry_time

この関数の引数にentry_priceを入れていく。
entry_priceに入れる値を一貫するために、ATRという指標を使って、
買い指値なら['buy_price'] 、売り指値なら['sell_price']を作る。

ATRは、ボラティリティ(値幅)を測定するために使うインジケーター。
算出方法は以下三つの式で計算して、一番大きいものをトゥルーレンジ(本当の値幅)として扱う。

①時間足の高値 - 時間足の安値 =(例 10pips)
②時間足の安値 - 時間足の終値 =(例 15pips)
③時間足の高値 - 時間足の安値 =(例 8pips)

こうすることによって、一番値幅が大きいものはなにか調べることができる。
ちなみに、上の場合、②がトゥルーレンジとして利用される。

ちなみに、ATRをインジケーターとして使う場合は、これを各足で計算して、移動平均を求める。
一般的に、日足で使われる場合は14日間の移動平均値が使われる。
なお、今回はエントリーの算出に使うだけなので、移動平均は求めない。

もし一貫していないと、データの整合性がなくなる。
これはサンプルなので、独自の指標を作ってエントリー判定しても良いとある。

pips = 1
limit_price_dist = df['ATR'] * 0.5 #ATRはTa-libを使って定義済み
limit_price_dist = np.maximum(1, (limit_price_dist / pips).round().fillna(1)) * pips

# 終値から両側にlimit_price_distだけ離れたところに、買い指値と売り指値を出します
# これがエントリーの一貫した価格として使われる。
df['buy_price'] = df['cl'] - limit_price_dist
df['sell_price'] = df['cl'] + limit_price_dist

買い指値 : 終値 - ATR
売り指値 : 終値 + ATR  を一貫したエントリー価格として使う。

# 指値が約定したかどうか (0, 1)
df['buy_executed'] = ((df['buy_price'] / pips).round() > (df['lo'].shift(-1) / pips).round()).astype('float64')

エントリーできたかどうかを0,1の形にする。
ここでは指値が一本後に約定したかどうかを判定している。

約定したらTrueなので1,できなかったらFalseなので0になる。

※実際のコードではこのコードは以下のコードの下にあります。

# Force Entry Priceの計算
df['buy_fep'], df['buy_fet'] = calc_force_entry_price(
    entry_price=df['buy_price'].values,
    lo=df['lo'].values,
    pips=pips,
)

df['buy_fep'] にエントリーできた価格
df['buy_fet']にエントリーまでにかかった時間 が返ってくる。

sellの方もあるが、マイナスにしたらできるので割愛

出典

約定シミュレーション「https://note.com/btcml/n/n9f730e59848c」
約定と決済「https://rinofx.xbiz.jp/fx-yakujou-kessai/
richmanbtcさんのgithub「https://github.com/richmanbtc/mlbot_tutorial」

Discussion