為替の予測をやってみた(その3 〜フォーワードテストの準備編〜)
この記事の概要
- 前回の記事の続き
- LSTMでの予測に基づいたトレードのバックテストではかなり良好な結果を得た。
- フォーワードテストのために売買のシステムを組んでみた。
- その概要について記載する。
前回のおさらい
バックテストを実施
とある2週間の過去データにて
- trades: 296回
- winrate: 0.91%
- payoff: 4.6705
と驚異的な成績を得た。
フォーワードテストのために売買システムを組んでみた
上記のバックテストの結果の様には、うまくいかないだろうと思いつつも、期待を込めて売買のシステム作製しました。
今回作製した為替自動売買システムの概要図
簡単に各機能等を以下に記載します。
Predictor
機能:Oanda APIを使用して予測で使用する直近の為替データを取得し、
LSTMモデルで将来の価格帯を予測する。
予測で使用した為替データと予測した結果をそれぞれ保存する。
今回は、5分毎に30分後の価格帯を予測します。 5分毎に実行するために、Scheduleライブラリを使用しました。
参考にした記事: qiita.com
Agent
機能:Predictorが予測した結果を基に、トレードするかしないか判断する。
トレードすると判断した場合、Oanda APIを通じて注文をする。
今回は、予測結果である「prediceted_data.json」のファイル更新を監視し、 更新をトリガーにして、処理を実行するようにしました。
ファイル更新の監視には、watchdogを使用しました。
参考にした記事: qiita.com
また、注文のAPIの使い方については以下を参考にしました。
http://www.algo-fx-blog.com/fx-api-oanda-v20-python-order/
Viewer
機能:Predictorが保存した予測した結果を、予測に使用した為替データへOverLayしてグラフ描画する。
Viewerは、フォーワードテストには関係ないです。
狙い通りに動作しているか確認するためにグラフ描画するようにしました。
実行すると以下の様に、直近のキャンドルチャートと、予測した結果を(直線で)描画するようにしました。
figure class="figure-image figure-image-fotolife" title="Viewer_exsample">
上記の例では、30分後には値が上昇すると予測しています。
グラフ描画には、Plotly Dashを使用しました。 plot.ly
次回
次の記事では、この売買システムを使用してフォーワードテストをした結果についてまとめたいと思います。
為替の予測をやってみた(その2 〜機械学習編〜)
この記事の概要
- 前回の記事の続き
- 30分後の価格帯の予測にチャレンジ
- LSTM(Long Term Short Memory)にて予測
- 予測精度としては今ひとつ。。
- 売買のシステムに組込んだと仮定してバックテストを実施
- 売買のシステムにて使用するなら非常によい結果に!
前回のおさらい
前回は予測する対象を決めるために、 3ヶ月分の為替データを分析しました。
分析内容
- 為替データを、移動平均線を中心とした-10〜+10の領域に区分けした。
- t=0と30分後(t=30)の価格の分布を確認した。
その結果、t=30の価格帯を予測するモデルを作成し、 最終的には、t=0の価格とそのモデルの予測したt=30の価格差に応じて、買い(Long)/トレードしない(NA)/売り(Short)を選択するシステムを作製することとしました。
詳しくは前回の記事を参照してください。
予測モデルの構築
さて、ここからが今回の内容になります。
モデルの選定
今回は、 LSTM(Long Term Short Memory)を選択しました。
LSTMについては、さまざまな記事がありますので、そちらをご覧ください。
私は以下などを参照にしました。
KerasでLSTMを学習する手順を整理してみた | 自調自考の旅
LSTMでFX予測をやってみよう(機械学習初心者向けチュートリアル)
選定した理由:
- 実装例など情報が豊富
- 私自身が実際に実装したことがなかったため、勉強がてら試してみたかった
まぁ、いろいろな手法と比べてみるつもりですので、興味を持った手法を試すこととしました。
モデルの構築
モデルの概要:
- 予測の対象:30分後(t=30)の価格帯
- 訓練データ:予測時点での価格とそれ以前の300分の価格(t=-300〜t=0)
- 今回は簡素化のため、インジケータは使用しませんでした
- 訓練データは、2ヶ月分。テストデータと検証データはそれぞれ半月分
- LSTMは1層
- 多層にすると精度が向上するかなどは別途検証したいと思っています
実装は以下のような感じです。
def build_model(inputs, outputs, neurons, activ_func, dropout=0.1, loss="mean_squared_error", optimizer): model = Sequential() model.add(LSTM(neurons, input_shape=(inputs.shape[1], inputs.shape[2]))) model.add(Dropout(dropout)) #model.add(Dense(units=outputs.shape[1])) model.add(Dense(units=outputs.shape[1], kernel_initializer='random_uniform', bias_initializer='zeros')) model.add(Activation(activ_func)) model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=['categorical_accuracy']) return model model = build_model(train_x_data, train_y_data, neurons = 20,activ_func="softmax",optimizer="RMSprop") history = model.fit(train_x_data, train_y_data, epochs=100, batch_size=32, verbose=1, validation_split=0.2, callbacks=[es_cb, tb_cb, cp_cb])
学習を実行すると、以下の様に学習していきました。
学習を実行すると、以下の様に学習していきました。
accuracyは60%を超えてきました!
これは期待できそうです。
次に混合行列を確認します。
区分の上の方と下の方では上下限に張り付き気味に予測されていますが、悪くないと思います。
続けて、recall, precision, f-scoreを見ていきたいと思います。
0.2...あれ?こんなもんか。。 もっといいかと思いました。
しかし、sklearnのclassification_reportが便利すぎて、地味に感動しました。
単純に予測の時点(t=0)に近い区分を、予測値(t=30)としているだけということはないだろうか...?
っと不安になったので、
t=0と、予測されたt=30とのマトリックスも確認することにしました。
おや?意外にも悪くない感じで予測ができていそうです。
では、次にt=0の価格とそのモデルの予測したt=30の価格差に応じて、買い(Long)/トレードしない(NA)/売り(Short)を選択するシステムを仮定して、 買い(Long)/トレードしない(NA)/売り(Short)での混合行列を確認してみましょう。
おぉ!恐ろしくいいですね!! ShortやLongのところで、逆の予想がないのがとっても素晴らしいです!!
recall, precision, f-scoreも良いですね。
実際のトレードだったら、もうウハウハです(笑)
モデルを使ったバックテスト
どれくらいウハウハか確認するために簡易的ですが、今回バックテストをしてみました。
フレームワークは、pybacktestを使用しました。
その結果がこちらです。
------------------------------------------ | Backtest(test, 2019-07-04 13:43 JST) | ------------------------------------------ backtest: days: 14 from: '2018-07-15 20:05:00' to: '2018-07-30 09:15:00' trades: 296 performance: PF: 48.5013 RF: 298.4667 averages: gain: 0.0007 loss: -0.0001 trade: 0.0006 payoff: 4.6705 profit: 0.1791 winrate: 0.9122
右肩上がりです!
ASKとBIDの差や滑りとかを考慮していないので、実際はもっとよくないですが、 それでも十分予測の有用性を確認できたと思います。
次回は、フォワードテストを試してみたいと思います。
為替の予測をやってみた(その1〜データ取得編〜)
この記事の概要
目的: 為替予測のためのデータ取得についての備忘録
内容:
- 為替データの入手
- OANDA API v20を利用した
- グラフ描画
- plotlyを利用した
- 予測の方針
- 30分後の価格帯を予測することとした
為替データの入手
OANDA APIの呼び出し
まず、OANDA APIを使用に必要なライブラリーとインポートし、APIキーを設定します。
from oandapyV20.contrib.factories import InstrumentsCandlesFactory from oandapyV20 import API client = API(access_token=access_token)
※OANDA APIを利用した為替データの入手には、OANDA Japan(https://www.oanda.jp/)での口座開設が必要です。 私はデモ口座を開設しています。
次に、APIに接続して過去レートを取得し、保存します。
def cnv(r, h): for candle in r.get('candles'): ctime = candle.get('time')[0:19] try: rec = "{time},{complete},{o},{h},{l},{c},{v}".format( time=ctime, complete=candle['complete'], o=candle['mid']['o'], h=candle['mid']['h'], l=candle['mid']['l'], c=candle['mid']['c'], v=candle['volume'], ) except Exception as e: print(e, r) else: h.write(rec+"\n")
_from = '2018-05-01T00:00:00Z' _to = '2018-07-31T00:00:00Z' gran = 'M5' instr = 'EUR_USD' params = { "granularity": gran, "from": _from, "to": _to } with open("/tmp/{}.{}.csv".format(instr, gran), "w") as O: for r in InstrumentsCandlesFactory(instrument=instr, params=params): print("REQUEST: {} {} {}".format(r, r.__class__.__name__, r.params)) rv = client.request(r) cnv(r.response, O)
今回は、上記の様に以下の様なデータを取得しました。
- 銘柄:EUR/USD
- 単位:5分足
- 期間:2018-05-01〜2019-07-31
また、上記のコードは、以下を参照しました。
参考: github.com
しばらくして、データの取得・保存が終わったら、データを読み出します。
df = pd.read_csv("/tmp/EUR_USD.M5.csv" ,header=None,usecols=[0,2,3,4,5,6]) df.columns = ['time','open', 'high', 'low', 'close','volume'] #df.index = 'time' df = df.set_index('time') df.head()
上記の様に、'open', 'high', 'low', 'close','volume'を読み込むことができました。
また、グラフで見てるとこんな感じです。
グラフ描画には以下を参照にして、plotlyにて描画しました。
個人的な趣味で、移動平均線(EMA)とchannelが好きなので併せて表示しています。
参考:
Pythonでローソク足チャートの表示(Plotly編) - Qiita
Python&Colab:TA-Lib でテクニカル分析、Plotly でローソク足の描画 - Investment Tech Hack
以下の記事の様に、値を予測するモデルを作成するのは面白そうです。
LSTMでFX予測をやってみよう(機械学習初心者向けチュートリアル)
しかし、ドンピシャで値を予測するのは難しそうですし、かつ、この手の予測は、結局予測する時点と同じ価格を予測値とするのが最も誤差が小さくなるという結果になるのではないか、と思っています。
そのため、今回は値をドンピシャで予測をするのではなく、ある程度の領域で区切り、その区分内に入るかどうかを予測するモデルを構築しようと考えました。
区分の分け方:
- 1区分の幅:ChannelのUpperとLowerを10分割した値
- EMAを中心にした-10〜+11区分の計21分類
- 最大・最小の区分はそれ以上・以下の領域を含む
- 対象:Closeの値
上記の分け方で、とある時間(t=0)で、Closeの値がどの区分に含まれるかをヒストグラムで表すと以下の様になりました。
当然ですが、移動平均値付近(e0,e-1)をピークにきれいに分布しているのがわかります。
※このグラフは-10〜+11区分(e-10〜e10)としています。
では、次にt=0から30分後(t=30)の値は、この区分に入るかをグラフ化してみます。
※このグラフは-10〜+11区分(e-10〜e10)としています。
値がドリフトしているためか、両端の区分が多くなっています。
両端が増加してるので、ほどほど値動きがあり、かつ、単調なトレンドがないとも読み取れると思います。
また、上記のt=0とt=30をマトリックスにすると以下の様な感じです。
やはり、あまり値が変化しないケースが多々あることが見て取れます。 ただ、思ったより値動きがありそうで期待できます。
今回は、t=0からt=30にかけて、3区分以上変化する場合に買い(Long)もしくは、売り(Short)をトレードのルールとして仮決めします。 このルールに沿って分類を総計した結果が以下です。
図らずとも、程よくよい比率になりました!
次回は、上記の動作買い(Long)/売買しない(NA)/売り(Short)を正解データ(期待する動作)とし、 為替データから予測できるか試していきたいと思います。
YOLO3でポリープ検出AI作ってみた
今回作ってみたもの
このような画像から
以下のように、ポリープを検出AIを作ってみました!
経緯
・Udemyで物体検出を学び、
・Qiitaで記事を見て、背中をそっと押してもらえたので、作ってみました。
学習
当初はルンバを改造して、何かしらを追尾させたいと思い学習を始めました。
独学より効率がよいと思い立ち以下の講座を受けました。アンカーボックスなど基本的な概念など学ぶことができました:)
実践
受講後に何作ろかと考えている時に、以下の記事を読み、自分も真似てポリープ検出AIを作ってみることに!
作成の流れ
大体記事通りですが、以下です。
データ準備
以下から内視鏡の画像データをDL。
以下のツールを使い、アノテーションファイルを作成。
記事と同様に500枚の学習データ準備。
Training
記事と同様にYOLOv3を採用。
https://github.com/qqwweee/keras-yolo3
順調に学習していたと思いきや、ResourceExhaustedErrorが発生。。。(悲)
エラー回避
GPUのメモリが足りないようなので、以下の変更で必要なメモリサイズをコンパクトにして無事動いた。
・画像サイズの削減
416x416 -> 128x128
・batchサイズの削減
64 -> 32
検出
こんな感じでわかりやすいものは検出できるようになりました!
ただ、以下の画像の様に検出できないものもありました。
まだまだ改善の余地はありますね。
人の目で見ても見づらいので、画像サイズを削減したせいでしょうか。
今後
画像サイズ削減しないで学習させてみたいと思います。