中頻度取引botの作成④
機械学習を用いて板情報のプロットからn秒後の価格の騰落を予想する
下記の記事で分類した価格のプロットを機械学習にかけて、板情報のプロットからn秒後の価格の騰落を予測出来るか検討する。
機械学習については、下記の資料を参考にした ディープラーニングで近藤春菜、角野卓三、マイケルムーアを判別する(Kerasで画像分類)
import keras from keras.utils import np_utils from keras.models import Sequential from keras.layers.convolutional import Conv2D, MaxPooling2D from keras.layers.core import Dense, Dropout, Activation, Flatten import numpy as np from sklearn.model_selection import train_test_split from PIL import Image import glob folder = ['up','down'] image_size_X = 432 image_size_X = 288 # 画像の読み込み、リサイズ、ndarrayへの格納 X = [] Y = [] for index, name in enumerate(folder): dir = 'keras_image/' + name files = glob.glob(dir + '/*.png') for i, file in enumerate(files): image = Image.open(file) image = image.convert('RGB') image = image.resize((image_size_X, image_size_Y)) data = np.asarray(image) X.append(data) Y.append(index) X = np.array(X) Y = np.array(Y) # RGBデータの正規化 X = X.astype('float32') X = X / 255.0 # 正解ラベルの形式を変換 Y = np_utils.to_categorical(Y, 3) # 訓練データとテストデータの分配(2割をテストデータへ) X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.20) # CNNのパラメータ設定 model = Sequential() model.add(Conv2D(32, (3, 3), padding='same',input_shape=X_train.shape[1:])) # レイヤー1 model.add(Activation('relu')) model.add(Conv2D(32, (3, 3))) # レイヤー2 model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(64, (3, 3), padding='same')) # レイヤー3 model.add(Activation('relu')) model.add(Conv2D(64, (3, 3))) # レイヤー4 model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) # レイヤー5 model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(3)) # レイヤー6 model.add(Activation('softmax')) # コンパイル model.compile(loss='categorical_crossentropy',optimizer='SGD',metrics=['accuracy']) #訓練 model.fit(X_train, Y_train,batch_size=32, epochs=100) #評価 & 評価結果出力 score = model.evaluate(X_test, Y_test) print('loss=',score[0]) print('accuracy=',score[1])
https://github.com/PP-lib/Bot_materials/blob/master/Keras_practice.ipynb
結果
Epoch 98/100 388/388 [==============================] - 8s 21ms/step - loss: 0.2662 - acc: 0.9253 Epoch 99/100 388/388 [==============================] - 8s 21ms/step - loss: 0.1183 - acc: 0.9691 Epoch 100/100 388/388 [==============================] - 8s 21ms/step - loss: 0.1044 - acc: 0.9665 98/98 [==============================] - 1s 11ms/step loss= 2.002868954016238 accuracy= 0.5
認識率が50%という事で全く予想できていないという結果だった。
考察
今回は1秒間の板情報から1秒後の価格を予想した。
結果としては次回は、板情報の期間と認識率の依存性について検討する。
中頻度取引botの作成③
量産した板情報のプロットを価格の騰落別に分けて保存する
練習用として、1秒後に価格が上昇した板情報のプロットを‘up’, 下降したプロットを‘down’, それ以外を‘unknown’フォルダに保存される様にした。
板情報の取得は下記を参照
import pandas as pd import numpy as np import matplotlib.pyplot as plt import itertools import os from google.colab import drive drive.mount('./gdrive') #板情報のファイルパス read_path = './gdrive/My Drive/Bot_materials/materials/bitflyerfx_hourly_board_day_27_init_4_48_end_6_48.csv' write_path = './gdrive/My Drive/Bot_materials/materials' #板情報の読み込み def make_order_book(): global df #現在の価格をを抜き出すための前準備 current_df = df[i:i+1] #1つ後の価格を抜き出すための前準備 future_df = df[i+1:i+2] #現在の板情報の抜き出し df_single_row = df[i:i+1] #価格の抽出 mid_price = df_single_row['mid_price'] future_mid_price = future_df.iloc[:,1] current_mid_price = current_df.iloc[:,1] #df_single_row = df[i:i+1] # #価格の抽出 # mid_price = df['mid_price'] # future_mid_price = future_df.iloc[:,1] # current_mid_price = current_df.iloc[:,1] future_mid_price = future_mid_price[i+1] current_mid_price = current_mid_price[i] plt.figure() #askのx軸を準備 ask_x = df_single_row.iloc[:,2:102] ask_x = ask_x.values.tolist() ask_x = list(itertools.chain.from_iterable(ask_x)) #askのy軸を準備 ask_y = df_single_row.iloc[:,102:202] ask_y = ask_y.values.tolist() ask_y = list(itertools.chain.from_iterable(ask_y)) #bidのx軸を準備 bid_x = df_single_row.iloc[:,202:302] bid_x = bid_x.values.tolist() bid_x = list(itertools.chain.from_iterable(bid_x)) #bidのy軸を準備 bid_y = df_single_row.iloc[:,302:402] bid_y = bid_y.values.tolist() bid_y = list(itertools.chain.from_iterable(bid_y)) plt.fill_between(ask_x,ask_y, color="green") plt.fill_between(bid_x,bid_y, color="red") if not os.path.exists('{}/pictures'.format(write_path)): os.mkdir('{}/pictures'.format(write_path)) # picturesディレクトリが無ければ作成する os.mkdir('{}/pictures/up'.format(write_path)) # upディレクトリが無ければ作成する os.mkdir('{}/pictures/down'.format(write_path)) # downディレクトリが無ければ作成する os.mkdir('{}/pictures/unknown'.format(write_path)) # unknownディレクトリが無ければ作成する #1つ後の価格が上昇した際のグラフを保存 if future_mid_price > current_mid_price: plt.savefig('{}/pictures/up/{}.png'.format(write_path,i)) #1つ後の価格が下降した際のグラフを保存 elif future_mid_price < current_mid_price: plt.savefig('{}/pictures/down/{}.png'.format(write_path,i)) #不明のグラフを保存 else: plt.savefig('{}/pictures/unknown/{}.png'.format(write_path,i)) if __name__ == '__main__': #csvファイルの読み込み df = pd.read_csv('{}'.format(read_path)) df = df.drop(["Unnamed: 0"],axis=1) #列Unnamed: 0を削除 #データ数をを調べる len_df = len(df) -1 for i in range(len_df): make_order_book() print(i) # print(df)
https://github.com/PP-lib/Bot_materials/blob/master/make_OrderBook_plot.ipynb
ipadでGooglecolab をストレス無く使用する方法
ipadでgooglecolabを使用するための環境構築
いくつかのブログ等でiPadでgooglecolabを使用する際は十字キーが使えなかったり、コピペが使えない等の不具合があり、コーディングするにはpythonistaやJunoを使用している様だ。
しかし、pythonistaはstashを使用してもpandasが使用できなかったりする。(Junoは試していない)また、GooglecolabとGoogledrive、GitHubは互換性が良く、ブラウザ上で処理が行われるので端末のスペックはほとんど関係がないため、iPadでコーディングするにはGooglecolabが最適であると思う。
筆者がiPadでストレス無くGooglecolab を使用するために整えた環境を共有する。
使用端末
・iPad air 2 (13.1.3)
・magickeyboard (Apple)
・logicool PEBBLE M350
ポイント
Googlecolabを開いた際に、PC用画面表示にして作業することでストレス無くコピペ、十字キー操作が可能になる。
また、元に戻るはcontrol+Z
中頻度取引botの作成②
板情報を取得する
bitFlyerFXの板情報を1秒おきに取得し、CSV・DBに保存し、Pandasデータフレームとして出力するPython3スクリプトを参照して板情報を取得する(googledriveへ保存する様にし、1回分の板情報を保存するように変更)
取得した板情報をグラフ化しやすいように編集する
上記の記事を参考に編集していく
行列の操作方法はこちらを参照
プロットしたグラフの保存方法
https://qiita.com/koichifukushima/items/e63e642431db92178188
オーダーブック描画の関数化.
import pandas as pd import numpy as np import matplotlib.pyplot as plt import itertools def get_order_plot(): #csvファイルの読み込み df = pd.read_csv('./gdrive/My Drive/Bot_materials/materials/bitflyerfx_hourly_board_day_21_init_7_59_end_7_59.csv') #中央値の抽出 mid_price = df['mid_price'] #askのx軸を準備 ask_x = df.iloc[:,3:103] ask_x = ask_x.values.tolist() ask_x = list(itertools.chain.from_iterable(ask_x)) #askのy軸を準備 ask_y = df.iloc[:,103:203] ask_y = ask_y.values.tolist() ask_y = list(itertools.chain.from_iterable(ask_y)) #bidのx軸を準備 bid_x = df.iloc[:,203:303] bid_x = bid_x.values.tolist() bid_x = list(itertools.chain.from_iterable(bid_x)) #bidのy軸を準備 bid_y = df.iloc[:,303:403] bid_y = bid_y.values.tolist() bid_y = list(itertools.chain.from_iterable(bid_y)) plt.fill_between(ask_x,ask_y, color="green") plt.fill_between(bid_x,bid_y, color="red") plt.savefig('./gdrive/My Drive/Bot_materials/materials/bitflyerfx_hourly_board_day_21_init_7_59_end_7_59.png') get_order_plot()
板情報の履歴から、板情報をグラフ化した画像を量産する
def get_order_plot(i): #csvファイルの読み込み df = pd.read_csv('./gdrive/My Drive/Bot_materials/materials/bitflyerfx_hourly_board_day_25_init_10_20_end_10_21.csv') df = df.drop(["Unnamed: 0"],axis=1) #列Unnamed: 0を削除 #中央値の抽出x mid_price = df['mid_price'] df = df[i:i+1] #askのx軸を準備 ask_x = df.iloc[:,2:102] ask_x = ask_x.values.tolist() ask_x = list(itertools.chain.from_iterable(ask_x)) #askのy軸を準備 ask_y = df.iloc[:,102:202] ask_y = ask_y.values.tolist() ask_y = list(itertools.chain.from_iterable(ask_y)) #bidのx軸を準備 bid_x = df.iloc[:,202:302] bid_x = bid_x.values.tolist() bid_x = list(itertools.chain.from_iterable(bid_x)) #bidのy軸を準備 bid_y = df.iloc[:,302:402] bid_y = bid_y.values.tolist() bid_y = list(itertools.chain.from_iterable(bid_y)) plt.fill_between(ask_x,ask_y, color="green") plt.fill_between(bid_x,bid_y, color="red") # plt.set_title("a") plt.savefig('./gdrive/My Drive/Bot_materials/materials/pictures/{}.png'.format(i)) plt.figure() # plt.axvline(x=mid_price, ymin=0, ymax=1) if __name__ == '__main__': if not os.path.exists('./gdrive/My Drive/Bot_materials/materials/pictures'): os.mkdir('./gdrive/My Drive/Bot_materials/materials/pictures') # dataディレクトリが無ければ作成する #r = len(df) #i = 0 for i in range(60): get_order_plot(i) df.head()
両建て手法の開発③
closeを取得してjson形式で保存する
予測したpd.DataFrameをjson形式に変換するためにこちらを参照
同様の手順でHightとLowも予測する。
実際のcloseと予想したclose, High, Low をプロットする。
プロット結果2019/11/18
json形式は取り扱いが難しかったため、csvファイルを使用することにした。
csvファイルの操作は以下のコードを使用する
#csvの書き込み pred_target.to_csv('./gdrive/My Drive/Bot_materials/materials/pred_{}.csv'.format(target)) actual_target.to_csv('./gdrive/My Drive/Bot_materials/materials/actual_{}.csv'.format(target)) #csvの読み込み pred_close = pd.read_csv('./gdrive/My Drive/Bot_materials/materials/pred_close.csv') pred_close = pred_close['predict_close'] pred_close
プロット結果
実線:実際の値
破線:予測値
青:LOW
緑:CLOSE
赤:HIGH
他のサイトでも解説されている通り、過去の値動きをトレースするような動きとなり、各値動きのLSTMだけではエッジがない。
一応、今回の取り組みを定量評価?するために、 性能を以下のように定義すると
| ( 予測値 - 実際の値 ) / 実際の値 |
今回の値は0.0000706となった。
https://github.com/PP-lib/Bot_materials/blob/master/Deal_csv.ipynb
次回の計画
板情報から価格の上昇、下降を予測出来るか検討する。
両建て手法の開発②
目標
close, high, low を予測し、同一グラフ内にプロットする
closeを予測し、df変換後json形式に変換。
任意のdriveに保存
high, close 共に同手順で保存
close, high, low を呼び出し、matplot.libで描画
実際のcloseと予想したhigh, low を見て、提案する手法に優位性があるかどうかを検討する。
作業
closeを予測し、df変換後json形式に変換する
以下、作業結果コード
# テストデータを使って予測&プロット fig, ax1 = plt.subplots(1,1) ax1.plot(df[df['time']>= split_date]['time'][window_len:], test['close'][window_len:], label='Actual', color='blue') ax1.plot(df[df['time']>= split_date]['time'][window_len:], ((np.transpose(yen_model.predict(test_lstm_in))+1) * test['close'].values[:-window_len])[0], label='Predicted', color='red') ax1.grid(True)
#np形式でcloseの予想値を表示 pred_close = ((np.transpose(yen_model.predict(test_lstm_in))+1) * test['close'].values[:-window_len])[0] pred_close
#列名を設定 pred_close.columns = ['close'] pred_close.head()
jsonの書き出しには “Python jsonファイルを新規作成して書き込む”を参照