中頻度取引botの作成④

機械学習を用いて板情報のプロットからn秒後の価格の騰落を予想する

下記の記事で分類した価格のプロットを機械学習にかけて、板情報のプロットからn秒後の価格の騰落を予測出来るか検討する。

xpppp.hatenablog.com

機械学習については、下記の資料を参考にした ディープラーニングで近藤春菜、角野卓三、マイケルムーアを判別する(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’フォルダに保存される様にした。

板情報の取得は下記を参照

xpppp.hatenablog.com

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

ipadpythonしたい方いましたらご参考ください。

中頻度取引botの作成②

板情報を取得する

bitFlyerFXの板情報を1秒おきに取得し、CSV・DBに保存し、Pandasデータフレームとして出力するPython3スクリプトを参照して板情報を取得する(googledriveへ保存する様にし、1回分の板情報を保存するように変更)

取得した板情報をグラフ化しやすいように編集する

qiita.com

上記の記事を参考に編集していく

行列の操作方法はこちらを参照

プロットしたグラフの保存方法

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()

中頻度取引botの作成①

板情報を取得し終値の騰落を予測する

板情報の分布の様子から中央値の騰落を予測する

作業内容

  1. 板情報の分布図を作成する
  2. 作成した分布図から画像ファイルを作成する
  3. n秒後の買い、売り、期待値幅を予想する。

参考 1 ローソクチャート画像を用いた株価の変動予測 画像作成&解析

参考 2 TensorFlow (ディープラーニング)で為替(FX)の予測をしてみる CNN編 画像の取り込み技術

参考 3 CCXTを使ってOrderbook情報をDepthChartとして"オシャレに"描画する 板情報のプロット

両建て手法の開発③

closeを取得してjson形式で保存する

xpppp.hatenablog.com

予測した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

f:id:xpppp:20191119215700p:plain

他のサイトでも解説されている通り、過去の値動きをトレースするような動きとなり、各値動きのLSTMだけではエッジがない。

一応、今回の取り組みを定量評価?するために、 性能を以下のように定義すると

| ( 予測値 - 実際の値 ) / 実際の値 |

今回の値は0.0000706となった。

https://github.com/PP-lib/Bot_materials/blob/master/Deal_csv.ipynb

次回の計画

板情報から価格の上昇、下降を予測出来るか検討する。

両建て手法の開発②

目標

close, high, low を予測し、同一グラフ内にプロットする

  1. closeを予測し、df変換後json形式に変換。

  2. 任意のdriveに保存

  3. high, close 共に同手順で保存

  4. close, high, low を呼び出し、matplot.libで描画

  5. 実際のcloseと予想したhigh, low を見て、提案する手法に優位性があるかどうかを検討する。

作業

closeを予測し、df変換後json形式に変換する

以下、作業結果コード

xpppp.hatenablog.com

# テストデータを使って予測&プロット
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)

f:id:xpppp:20191111202325p:plain

#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ファイルを新規作成して書き込む”を参照