見出し画像

FX機械学習入門(5/6):正解データの作成

記事には何をマークアップ関数に渡しているのかよくわからなかったけど、終値を渡しておきました。

import numpy as np
import pandas as pd

def markup_data(data, target_column, label_column, markup_ratio=0.00002):
    # 新しいDataFrameを作成し、元のデータをコピーします。
    new_data = data.copy()

    # 指定されたターゲット列に基づいて、新しいラベル列を計算します。
    # 次の値が現在の値+マークアップ比率より大きい場合は1、そうでなければ0を設定します。
    new_data.loc[:, label_column] = np.where(
        new_data.loc[:, target_column].shift(-1) > new_data.loc[:, target_column] + markup_ratio, 1, 0
    )

    # ラベル列でNaNがある場合は0で埋めます。
    new_data.loc[new_data[label_column].isna(), label_column] = 0

    # マークアップされた価格変更の数を出力します。
    print(f"マークアップ比率を超える価格変更の数: {new_data[label_column].sum()}")

    # 新しいDataFrameを返します。
    return new_data

augmented_data = markup_data(raw_data, 'close', 'label', 0.00002)


これに

import numpy as np
import pandas as pd
import random
from datetime import datetime
import MetaTrader5 as mt5
import time
import concurrent.futures
from tqdm import tqdm
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.utils import class_weight
from imblearn.under_sampling import RandomUnderSampler

def label_data(data, symbol, min=2, max=48):

    # MT5ターミナルの初期化
    if not mt5.initialize():
        print("MetaTrader 5ターミナルへの接続エラー")
        return

    # 指定された通貨ペアの情報を取得
    symbol_info = mt5.symbol_info(symbol)
    stop_level = 100 * symbol_info.point  # ストップレベルの計算
    take_level = 800 * symbol_info.point  # テイクレベルの計算

    labels = []  # ラベルを格納するリスト

    # 各データポイントに対してラベルを生成
    for i in range(data.shape[0] - max):
        rand = random.randint(min, max)  # ランダムな将来のポイントを選択
        curr_pr = data['close'].iloc[i]  # 現在の価格
        future_pr = data['close'].iloc[i + rand]  # 将来の価格
        min_pr = data['low'].iloc[i:i + rand].min()  # 該当期間の最低価格
        max_pr = data['high'].iloc[i:i + rand].max()  # 該当期間の最高価格

        price_change = abs(future_pr - curr_pr)  # 価格変動

        # ラベル付けの条件判断
        if price_change > take_level and future_pr > curr_pr and min_pr > curr_pr - stop_level:
            labels.append(1)  # 成長
        elif price_change > take_level and future_pr < curr_pr and max_pr < curr_pr + stop_level:
            labels.append(0)  # 下落
        else:
            labels.append(None)  # 条件に合わない場合はNone

    # ラベル付け後のデータを整理
    data = data.iloc[:len(labels)].copy()
    data['labels'] = labels

    # Noneを含む行を削除
    data.dropna(inplace=True)

    # 特徴量とラベルを分ける
    X = data.drop('labels', axis=1)
    y = data['labels']

    # データのバランスを取る
    rus = RandomUnderSampler(random_state=2)
    X_balanced, y_balanced = rus.fit_resample(X, y)

    # バランスを取ったデータセットを再構成
    data_balanced = pd.concat([X_balanced, y_balanced], axis=1)

    # 最終的なデータセットを返す
    return data_balanced


balanced_data = label_data(augmented_data, symbol)


1. markup_data関数

何をやっているか:
この関数は、与えられたデータセットに対して、特定の列(target_column)の次の値が現在の値プラス指定されたマークアップ比率(markup_ratio)を超えるかどうかを判断し、その結果に基づいて新しいラベル列(label_column)に1または0を割り当てます。関数はラベル付けされた新しいデータフレームを返します。
なぜやっているか:
このプロセスは、データセットを教師あり学習モデルのトレーニング用に準備するために行われます。特定の価格変動が予め定義された閾値(マークアップ比率)を超えるかどうかを示すラベルを割り当てることで、モデルは価格の上昇または下降の傾向を予測するためにこれらのラベルを学習することができます。このようなラベル付けにより、モデルの精度と一般化能力が向上し、訓練と評価が容易になります。

スプレッドを超えるボラティリティかのフィルターかな?

2. label_data関数

何をやっているか:
この関数は、MetaTrader 5 (MT5) ターミナルから取得した通貨ペアの情報を用いて、より複雑な条件に基づいてデータにラベルを割り当てます。具体的には、将来の価格変動がテイクレベルを超え、かつ特定のストップレベルを下回らない場合に、成長(1)または下落(0)のラベルを割り当てます。この関数も、条件に合致しないデータポイントにはNoneを割り当て、その後、Noneを含む行を削除してからデータのバランスを取り、バランスの取れたデータセットを返します。
なぜやっているか:
この関数は、特に金融市場の予測などのタスクにおいて、トレーディング戦略の開発やリスク管理のために利用できるよう、より現実に近いトレーディングのシナリオを模倣したデータのラベル付けを行います。ストップレベルとテイクレベルを設定することで、実際のトレーディングの決定をシミュレートし、その結果として得られるラベルを使用して、価格の動きを予測するモデルをトレーニングすることができます。バランスの取れたデータセットを生成することで、クラス不均衡による学習の偏りを減らし、モデルの性能を向上させることができます。

label_data()って毎回正解変わるよね?


はい、その通りです。label_data関数内でrandom.randint(min, max)を使用してランダムに選択される将来の時点(rand)があるため、関数が呼び出されるたびに異なるラベルが生成される可能性があります。このランダム性は、特定の時点からランダムに選択された未来の価格と現在の価格との比較に基づいてラベルを割り当てるためです。
この挙動は、特に以下の点で重要な影響を及ぼします:

  • データの多様性: 同じデータセットに対して複数回label_data関数を実行すると、異なるラベル付けされたデータセットが生成され、学習データの多様性が増します。これは、モデルが様々なシナリオに対応できるようにするために有益ですが、一方でデータセット間での一貫性が欠けることにもなります。

  • 再現性の欠如: 研究や実験で再現性を保証するためには、ランダムな要素を制御下に置く必要があります。この関数では、random.randint(min, max)によるランダム性が結果に影響を及ぼすため、同じ結果を得るためには乱数のシードを固定する等の対策が必要になります。

  • モデルの評価と比較: 異なるランダムラベルが割り当てられるため、同じアルゴリズムやパラメーター設定でも、トレーニングされたモデルの性能が異なる結果になる可能性があります。これにより、モデルの評価や異なるモデル間の比較が複雑になる場合があります。

これらの点を考慮すると、label_data関数を使用する際は、ランダム性による影響を理解し、必要に応じて乱数生成のシードを設定するなどして、結果の再現性を確保することが重要です。また、異なるラベル付けされたデータセットに対するモデルの性能を検証することで、モデルの堅牢性を評価することもできます。




この記事が気に入ったらサポートをしてみませんか?