PyTorchで画像分析により為替(FX)予測 ②


はじめに

前回、画像分析により翌日終値の予測では、かなり精度が出ることがわかりました。

80%程度の精度と言っても、
・翌日以降の上下を予想する場合の精度はどうなるのか?
・価格差がどの程度になるのか?
・上昇と下落の予想で精度にばらつきがあるのか?
・他の通貨の変動を予測した場合どのくらいの精度になるのか?
といった点が課題になると思います。

また、前回は訓練データと検証データをランダムに分割したのですが、20日間のグラフで訓練している性質上、データがリークしていることにもなりますので、単純に前から4000件でデータを区切ることにしました。

x_train = data['ImageName'].values[seq_len:4000]
x_val = data['ImageName'].values[4000:]
y_train = data['Up'].values[seq_len:4000]
y_val = data['Up'].values[4000:]

2日後の上下を予想させて学習した結果

前回のコードの「future_num」の値を2にして、学習を実行します。

# data['Up']を0で初期化
data['Up'] = 0

# future_num日後の終値の上下を予測
future_num = 2

for i in range(len(data)-2):
    if data['Close'][i] < data['Close'][i+future_num]:
        data['Up'][i] = 1

学習を実行したところ、訓練精度は前回ほど上がらなくなりましたが、検証精度は前回と同様80%程度を維持しています。
今回は、20日間のチャートデータより予測した結果ですので、せいぜい3、4日程度予測するのが限界かと思っています。

この分析は、短期トレードのために使用したいと思いますので、2日後の予測がある程度できれば問題ないと考えます。

精度は、以下です。

予測した確率と精度、価格差についての分析

モデルの出力結果をsoftmaxで確率として抽出したリストを作成します。
(PyTorchでは、CrossEntropy関数にsoftmaxが実装されているためモデルの出力結果は確率分布にはしていない)

# 予測結果、予測確率を記録する

pred_list = np.empty([1, 2])

i = 0

for inputs, labels in all_dataloader:
    i += 1
    #for inputs, labels in dataloaders[phase]:
    inputs = inputs.to(device)
    labels = labels.to(device)

    with torch.no_grad():
        outputs = model(inputs)
        sm = nn.Softmax(dim=1)
        outputs2 = np.array(sm(outputs))
        pred_list = np.vstack((pred_list,outputs2))

結果をDataFrameとして格納

pred_data = data[data.columns][4000:]
pred_data['p_down'] = pred_list[1:,0]
pred_data['p_up'] = pred_list[1:,1]

予測結果から指定した閾値で上昇、下降を予測した時の正解率、価格の平均変動幅を計算

#  閾値とする確率、上昇、下降のどちらを予想するか、閾値を設定した時の平均変動価格を出力する関数を作成

def print_ext(updown,rate):

    total_counter = 0
    counter = 0
    change_price = 0

    if updown == 'UP':
        col = 'p_up'
        UPtarget = 1
    else :
        col = 'p_down'
        UPtarget = 0

    for i in range(len(pred_data)):

        if pred_data[col][i] > rate:
            total_counter += 1
            if pred_data['Up'][i] == UPtarget:
                counter += 1
                change_price += pred_data['Close'][i+1] - pred_data['Close'][i]

    print('精度: {:4f}'.format(counter/total_counter))
    print('正解数: {:4f}'.format(counter))
    print('{}の数: {:4f}'.format(updown,total_counter))
    print('平均変動価格: {:4f}'.format(change_price/counter))

閾値を0.5、0.8とした場合の各種結果を出力

print('-----閾値を0.5とした時に上昇を予測した時の各種数値-----')
print_ext('UP',0.5)
print()
print('-----閾値を0.8とした時に上昇を予測した時の各種数値-----')
print_ext('UP',0.8)
print()
print('-----閾値を0.5とした時に下降を予測した時の各種数値----')
print_ext('Down',0.5)
print()
print('-----閾値を0.8とした時に下降を予測した時の各種数値----')
print_ext('Down',0.8)

出力結果

-----閾値を0.5とした時に上昇を予測した時の各種数値-----
精度: 0.826087
正解数: 285.000000
UPの数: 345.000000
平均変動価格: 0.361258

-----閾値を0.8とした時に上昇を予測した時の各種数値-----
精度: 0.911765
正解数: 186.000000
UPの数: 204.000000
平均変動価格: 0.456665

-----閾値を0.5とした時に下降を予測した時の各種数値----
精度: 0.855030
正解数: 289.000000
Downの数: 338.000000
平均変動価格: -0.366145

-----閾値を0.8とした時に下降を予測した時の各種数値----
精度: 0.928870
正解数: 222.000000
Downの数: 239.000000
平均変動価格: -0.421577

実際に利用する場合は、0.8を閾値として上昇下降の予測が出たら取引を行うというような使い方が想定されると思います。

ユーロで学習したモデルをそのまま豪ドルに適用する

学習した内容は、テクニカル分析でチャートの読み方一般を学習したということになると思います。

十分に学習ができていれば、同じスケールの為替相場一般にある程度予測はできるようになっているのではないかと思われます。

今回学習したモデルを豪ドルにも適用して、どの位の精度が出るか確かめてみました。

出力した結果は以下になります。
豪ドルデータを使って学習した方が精度は出ると思いますが、他の通貨のデータでもある程度利用できるモデルであると言えると思います。
(豪ドルとユーローは相関が高いということもあります。)
米ドルのように変動が少ない通貨、取引額が少なく変動が激しい通貨だともう少し違う結果になりそうです。

-----閾値を0.5とした時に上昇を予測した時の各種数値-----
精度: 0.792083
正解数: 1981.000000
UPの数: 2501.000000
平均変動価格: 0.560383

-----閾値を0.8とした時に上昇を予測した時の各種数値-----
精度: 0.866732
正解数: 891.000000
UPの数: 1028.000000
平均変動価格: 0.683836

-----閾値を0.5とした時に下降を予測した時の各種数値----
精度: 0.810548
正解数: 1583.000000
Downの数: 1953.000000
平均変動価格: -0.688057

-----閾値を0.8とした時に下降を予測した時の各種数値----
精度: 0.872306
正解数: 1093.000000
Downの数: 1253.000000
平均変動価格: -0.790049

今後に活用

実際には、最終的には毎日各通貨の予測を行い0.8以上で上昇下降のシグナルが出たら取引を行うというようなことを考えてます。