※記事最下部に追記あり
どうも、ryo_grid です。
以前、下のリンク先の通り、機械学習での為替予測および、その結果に基づいたルールベースでのトレードロジックで動作するエージェントを作って、シミュレーションを行ったりしていて、ある程度うまくいったのですが、
機械学習を用いたオレオレFXシステムトレーディングプログラムのロジック解説 - Qiita
折角ならトレードロジック自体も機械学習のモデルに組み込みたいということで、強化学習、特に深層強化学習での実現にトライしています。
手法としてはDQNを試しているのですが、その中で、与えるrewardを変えたり、stateをいじったりと、手を変え品を変え、試したものの全然うまくいかない(テストデータですらうまくいかない。また、ただ負けまくりといった結果なら分からなくもないが、ほとんど1つのactionのみが選択されるといった結果ばかりだった)ので、なんかひらめいたオレオレ手法で試しています。
まだ学習処理中なのでうまくいくは分からないですが、識者の方のコメントなどいただければと思い投稿します。
オレオレ手法、と認識している部分は太字で記述します、それ以外の部分は特に目新しいことはありません。
-
学習方法
- trainデータと設定した期間の為替データを一足ずつ時系列になめて、エージェントに action をとらせてあれこれする
- ランダムreplayにおいてのみNNの重みを更新
- replay用に全ての足でのエピソード [state, action, reward, next_state] の情報は memory と呼ぶ記憶領域に保持されるようにしてある
- replay用に上述のエピソードの情報を記録しておくのはreplayを行う場合普通だと思うが、オレオレ手法では、BUYした時のエピソード情報は、後からポジションで引ける(見つけられる)ようなインデックスを作っている
-
state
-
現在価格、前の足からの変化率(符号あり)、各種テクニカル指標(※1)。加えて、ポジションを保有している場合はそれらの評価損益(pipsで見た値)。ノーポジションの時は 0
-
(保有ポジションの情報はこれまで加えた場合も、加えない場合も試した)
-
action
- タスクをできるだけ単純にするため、ポジションはロングのみ扱うようにしている
- BUY
- BUYのアクションをした場合、設定した分割数(保有可能な取引通貨の塊の数)でポジションの状態になっているものも含めた総資産を分割した額の分、ロングポジションを購入する(厳密には記述されたような値にはならないが、それに近い額になるようにはしてある)
- 保有している塊の数が規定数(今のところ100にしている)を超えると、BUYのアクションをとっても購入は行われない
- これまでは保有資産全てをぶっこんで購入というロジックだったので、一度ポジションを持ってしまうと、同じ種のポジションを購入するactionを行っても何もできないという状態にすぐなっていたが、それが解消されたのは大きな変更点だと思う
- CLOSE
- 全てのポジションを決済する
- DONOT
- 何もしない
-
reward
- BUY
- 基本的には 0 だが、CLOSEされた時に更新される(後述)
- CLOSE
- ポジション全決済による獲得pips(マイナスの場合ももちろんある)
- CLOSEアクションは保有ポジション全てを決済するが、その際に保有していたポジション個別での獲得pipsを求めて、各ポジションの識別子とともに返す(environment側の挙動)
- agent側は、CLOSEアクションをとった場合、返ってきたポジション個別の獲得pipsで、memory に記録してある対応するBUYアクションのエピソード情報の reward を変更する
- このようにすることで、BUYアクションのrewardを後追いで求める。NNの重みの更新はランダムreplayでのみ更新されるので、そのうち変更されたrewardが NNで表現されるQ関数に反映される、という目論見
- DONOT
- 常に 0
- BUY
-
パラメータ
- ガンマは大体0.99といった値が用いられることが多いようだが、よくよく考えると、エージェントのとったactionによって市場が変化するわけではない、つまり、系列上の連続した2つの state を見た時に、前者から後者に遷移することは、ほぼ決定的でエージェントの action は、ほとんど影響を与えない(今回は state に保有ポジションの情報を加えており、また、エージェントのactionによって未来及び過去の stete(エピソード) で得られる reward が変化するので、ほぼ、ほとんど、としている)ので、これまで特に深い考えはなく 0.99 を採用していたが、0.3 程度に落とした
- (サーベイした論文でもそのように設定しているものがあった。※2 参照)
※1:
特徴量についてまとめたEXCEL
※2:
"Deep Reinforcement Learning for Trading,", Zihao Zhang & Stefan Zohren & Stephen Roberts, 2019. Papers 1911.10107, arXiv.org.
###■ソースコード(2020/02/09 時点でのもの。バグがあって修正が入ることもあると思います)
- 作業ブランチ
- 今回利用しているソースコード
###■参考に読んだ論文の一部
- "Robust forex trading with deep q network (dqn)", S Sornmayura - ABAC Journal, 2019
- "Learning to Trade via Direct Reinforcement", John Moody and Matthew Saffell, IEEE TRANSACTIONS ON NEURAL NETWORKS, VOL. 12, NO. 4, JULY 2001
このようなやり方ではそもそも強化学習としてうまくいかない、などあればコメントいただければ幸いです。
以上。
20/02/11追記:
上記の方法を試したところ、特定のアクションだけが起こるといったことはなかったものの、テスト期間でも負け続ける結果でした。
自分の中でそれは何故か、分析したところ、CLOSEのタイミングをエージェントがうまく判断することができないのではないかと考えました(人間でも難しい)。
そこで、以下の変更を行い、再トライ中です
- アクションをBUY, SELL, DONOT の3つにし、BUYとSELLは反対のポジションを保有していた場合は元々のCLOSEと同様に全て決済し、後追いでポジションをオープンした時のエピソードにおけるrewardを変更し、その後にポジションを新たにオープンする。rewardは決済を行った場合でも基本的には0(後追いで変更される)。
- stateから CLOSE のタイミングを判断するための情報になって欲しいと期待して与えていた保有ポジションの情報を無くした
- Q関数の基本的な考え方であるマルコフ連鎖に基づく、時系列的に後に続くstateも考慮した上で報酬の最大化を図るという、Q関数(を表現するNN)の更新式(ベルマン方程式から導かれるもの)を無視して、replay におけるNNの重みの更新では、action をとったあとに遷移した state におけるrewardを無視し、ただ、replay で選択されたエピソードで得られたrewardをそのまま教師信号として与える・・・
- おそらく、これはもうQ学習とは呼ばない気がします・・・
20/02/11追記(2):
- 戦略以前に盛大にバグっていた箇所があったので(これまで試していた手を変え品を変え、の後半半分ぐらいで、そのバグは混入していたと思われる)、上の追記で行った修正は取り消し、BUY, CLOSE, DONOT でちゃんとQ学習するものにして、さらにリトライ中です