システムトレードのためのロジスティック回帰入門

Python
スポンサーリンク
スポンサーリンク

はじめに

システムトレードで使用するアルゴリズムの中でも「ロジスティック回帰」は、初心者でも学びやすく、幅広く活用されています。この記事では、ロジスティック回帰の基本を初学者に向けてわかりやすく解説していきます。

ロジスティック回帰とは?

ロジスティック回帰とは、ある事象が起きる確率を予測するための統計モデルです。特に「2つの選択肢」のどちらかを選ぶような場面で威力を発揮します。たとえば、「明日株価が上がるか下がるか」を予測するシステムトレードに適しています。

具体例:株価の予測 株価を例に考えてみましょう。ある株価が上がるか下がるかを予測したい場合、次のようなデータを使います:

  • 前日比上昇率
  • 出来高

ロジスティック回帰は、これらのデータをもとに次に「株価が上がる確率」を計算します。

ロジスティック回帰とシステムトレード

  1. 価格の上下を2値で表現できるシステムトレードでは、当然「買い」と「売り」の2つの判断が多く求められます。ロジスティック回帰は、これを次のようにモデル化します:
    • 1:買い
    • 0:売り
  2. 確率で判断する柔軟性 ロジスティック回帰では、「買い」や「売り」を単なる判断ではなく、確率(たとえば70%の確率で買いが有利)として出力します。この確率をもとに判断基準を柔軟に変更できます。

シグモイド関数とは?

シグモイド関数とは、入力データを0から1の範囲に変換する関数で、確率として解釈できる値を出力します。これにより、ロジスティック回帰ではある事象が発生する確率を計算できます。

シグモイド関数は、次のような形をしています:

y = 1 / (1 + e^(-z))

ここでは、

y:予測される確率

z:入力データを元に計算された値

e:自然対数(約2.718)

をそれぞれ表しています。

自然対数とは?

自然対数とは、がe(約2.718)である対数のことです。これは数学や統計学でよく使われ、成長や減衰を表すのに適しています。たとえば、複利計算や人口増加などの現象で登場します。

対数とは?

対数とは、特定の数値を得るためにを何乗するかを示す数学的な概念です(logで表されます)。例えば、2を3乗して8になる場合、8の対数が2)は3となります。つまり、log2(8) = 3 という形式で表されます。

シグモイド関数の具体的な計算例

たとえば、z = 2 の場合、シグモイド関数は次のように計算されます:

y = 1 / (1 + e^(-2))

まず、e^(-2) を計算します。e の値は約 2.718 ですので:

e^(-2) = 1 / (2.718^2) ≈ 1 / 7.389 ≈ 0.135

次に、1 + e^(-2) を計算します:

1 + 0.135 = 1.135

最後に、y を求めます:

y = 1 / 1.135 ≈ 0.88

したがって、z = 2 の場合、シグモイド関数の出力 y は約 0.88 となります。これは、確率として解釈できます。

ロジスティック回帰のステップ

システムトレードロジスティック回帰を導入する際の基本ステップを解説します。

  1. データを準備する
    まず、株価や通貨ペアの過去の価格データを用意します。たとえば、株価の「前日比上昇率」や「出来高」などです。これらのデータは、市場の動きや価格の変化を理解するのに役立ちます。具体的には以下のようなデータを準備します:
    • 前日比上昇率:前日の株価と比較して、どれだけ上昇または下落したかを示します。これにより、市場のトレンドを理解できます。
    • 出来高:特定の期間における売買の合計量です。出来高が多いほど、市場の関心が高いことを示し、トレードの方向性を判断するのに役立ちます。
    • RSI(相対力指数):市場が「買われすぎ」や「売られすぎ」の状態にあるかを示す指標です。RSIは0から100の範囲で値を取り、特定の数値を超えると「買われすぎ」や「売られすぎ」と判断できます。
  2. 特徴量を選ぶ
    特徴量とは、モデルが判断に使う情報(データ)のことです。たとえば、「過去3日間の平均価格」や「出来高の増加率」が特徴量になり得ます。特徴量を選ぶことは、モデルの性能を左右する重要な作業です。
    • 良い特徴量の例
      • 価格の移動平均:一定期間(たとえば5日間や10日間)の価格の平均を取り、その値を使います。移動平均は短期的なノイズを減らし、全体的なトレンドを把握するのに有効です。

    • 悪い特徴量の例
      • 関係のないノイズデータ:たとえば、取引とは無関係なランダムな数字や、市場と関連のない外部データなどです。これらはモデルにノイズを加えるだけで、予測精度を下げる要因となります。
    適切な特徴量を選ぶことで、モデルが効率的に学習し、より正確な予測を行えるようになります。
  3. モデルを訓練する
    次に、Pythonなどのプログラミング言語を使って、ロジスティック回帰モデルを訓練します。モデルを訓練するというのは、過去のデータを使ってパターンを学び、将来のデータを予測できるようにすることです。訓練には次の手順を踏みます:

    • パラメータの調整モデルのパフォーマンスを向上させるために、学習率や重みなどのパラメータを調整することがあります。Pythonを使うことで、複雑な計算を簡単に行うことができ、効率的にモデルを訓練することが可能です。

Pythonでの実装例

次に、Pythonを使った簡単なロジスティック回帰の実装を紹介します。

# 必要なライブラリをインポート
import pandas as pd  # データ操作用ライブラリ
from sklearn.model_selection import train_test_split  # データを訓練用とテスト用に分割するための関数
from sklearn.linear_model import LogisticRegression  # ロジスティック回帰モデルを提供するクラス
from sklearn.metrics import accuracy_score  # 予測精度を計算するための関数

# データの準備(仮のデータ)
data = {  # 株価や出来高を模擬的に作成
    "price_change": [0.1, -0.2, 0.3, -0.1, 0.05, -0.3],  # 前日比の上昇率(小数値で表現)
    "volume": [100, 150, 200, 120, 80, 60],             # 出来高(その日の取引量)
    "up_down": [1, 0, 1, 0, 1, 0]                      # 上昇(1:株価が上がった)か下落(0:株価が下がった)
}

# データをpandasのDataFrame形式に変換
# DataFrameとは、表形式のデータ構造で、行と列を持ち、データ分析に便利
df = pd.DataFrame(data)  # 辞書型データをDataFrameに変換

# 特徴量(入力データ)とラベル(出力データ)に分ける
# 特徴量:モデルが予測に使用するデータ
# ラベル:予測したい結果
X = df[["price_change", "volume"]]  # 特徴量として、前日比上昇率と出来高を使用
y = df["up_down"]  # ラベルとして、株価の上昇(1)or下落(0)を使用

# 訓練データとテストデータに分割
# 訓練データ:モデルを学習させるためのデータ
# テストデータ:モデルの性能を確認するためのデータ
X_train, X_test, y_train, y_test = train_test_split(  # train_test_split関数で分割
    X, y,  # 特徴量とラベルを入力
    test_size=0.2,  # データの20%をテストデータにする
    random_state=42  # 乱数の種を固定して、再現性を確保
)

# ロジスティック回帰モデルの作成
# LogisticRegressionクラスを使用してモデルをインスタンス化
model = LogisticRegression()  # ロジスティック回帰モデルのインスタンスを作成

# 訓練データでモデルを学習させる
# fitメソッド:訓練データ(特徴量とラベル)を入力してモデルを訓練
model.fit(X_train, y_train)  # 訓練データ(X_train, y_train)で学習

# テストデータで予測を行う
# predictメソッド:入力データ(X_test)を元に予測値を出力
y_pred = model.predict(X_test)  # テストデータ(X_test)に対する予測を実施

# 予測精度の計算
# accuracy_score関数:実際のラベル(y_test)と予測値(y_pred)を比較して正解率を計算
accuracy = accuracy_score(y_test, y_pred)  # 精度を計算してaccuracyに代入

# 予測精度を画面に表示
# print関数:計算した精度を小数点以下2桁まで表示
print(f"予測精度: {accuracy:.2f}")  # f文字列で精度を整形して出力

Pythonコードの解説

ライブラリのインポート

Pythonでは、特定の機能を使うために「ライブラリ」をインポートする必要があります。ライブラリは、他のプログラマが作った便利な道具箱のようなものです。今回使用するライブラリは以下の4つです。

pandas

  • データを扱いやすい形(表形式)にするためのライブラリです。表計算ソフト(例:Excel)のように、データを行と列で整理できます。
  • このコードでは、データを「DataFrame」という形式で管理します。
    ※DataFrameとは、行と列で構成された表形式のデータ構造で、Excelの表のようにデータを容易に整理可能にした形式の事を言います。
    import pandas as pd  # pandasライブラリをインポートし、「pd」という短い名前で使えるようにする

    train_test_split

    • scikit-learnという機械学習ライブラリの中の関数です。
    • データを「訓練用」と「テスト用」に分ける役割があります。
    • 訓練用データはモデルを学習させるために使い、テスト用データモデルの性能を確認するために使います。
    from sklearn.model_selection import train_test_split

    LogisticRegression

    from sklearn.linear_model import LogisticRegression

    accuracy_score

    • 予測した結果がどれだけ正確だったか(正解率)を計算する関数です。
    • 実際の値とモデルが出した予測値を比較して、合っていた割合を計算します。
    from sklearn.metrics import accuracy_score

    データの準備

    データはプログラムにとっての「材料」です。このプログラムでは仮のデータを用意しています。

    辞書型データの作成

    Pythonの辞書型は、{}で囲み、キーと値のペアでデータを管理します。辞書型は、名前(キー)とその内容(値)をセットで保存するデータ形式です。

    data = {
        "price_change": [0.1, -0.2, 0.3, -0.1, 0.05, -0.3],
        "volume": [100, 150, 200, 120, 80, 60],
        "up_down": [1, 0, 1, 0, 1, 0]
    }
    • price_change: 前日比上昇率を示します。
    • volume: 出来高(その日の取引量)です。
    • up_down: 株価が上がった場合は1、下がった場合は0で記録しています。

    辞書をDataFrameに変換


    pandas.DataFrameを使って、データを表形式(行と列を持つ形)に変換します。これにより、列名を指定してデータにアクセスできるようになります。

    df = pd.DataFrame(data)  # 辞書型データをDataFrameに変換

    特徴量とラベルの分割

    1. 特徴量(入力データ)の選択
      • X = df[["price_change", "volume"]]は、データの中から「price_change」と「volume」を選び出して、Xという変数に保存しています。
      • これが「特徴量」と呼ばれるもので、モデルが予測に使うデータです。

    特徴量は、モデルが予測のために利用する入力データのことです。例えば、「前日比上昇率」や「出来高」など、予測に関連する情報を指します。

    1. ラベル(予測対象)の選択
      • y = df["up_down"]は、データの中から「up_down」列を選び出して、yという変数に保存しています。
      • これが「ラベル」で、モデルが予測しようとする結果です。

    ラベルは、モデルが予測する対象(結果)のことです。例えば、「株価が上がるか下がるか」といった予測結果そのものを指します。

    訓練とテストデータの分割

    モデルを正しく評価するためには、データを「訓練用」と「テスト用」に分ける必要があります。

    1. 分割する理由
      訓練データだけでモデルを評価すると、「そのデータだけに特化したモデル」になり、未知のデータに対応できない可能性があります。これを防ぐため、データの一部をテスト用に取っておきます。
    2. train_test_splitの使い方
      • train_test_split(X, y, test_size=0.2, random_state=42)は、データを80%:20%に分割します。
      • test_size=0.2でテストデータを20%に設定しています。
      • random_state=42を設定すると、毎回同じ結果が得られるようになります。
    3. 分割結果

    モデルの訓練

    1. モデルインスタンス
    2. 訓練(学習)
      • model.fit(X_train, y_train)で、訓練データ(特徴量ラベル)を使ってモデルを学習させます。
      • fitメソッドは「データを入力して、規則性を学ぶ」ために使用します。

    予測と精度計算

    1. 予測の実行
      • y_pred = model.predict(X_test)は、テストデータ(特徴量)を使って予測を行います。
      • predictメソッドを使い、未知のデータに対して予測値を出力します。
    2. 精度の計算
      • accuracy = accuracy_score(y_test, y_pred)で、実際の値(y_test)と予測値(y_pred)を比較し、正解率を計算します。
      • 正解率は、予測が正しかった割合を示します。
    3. 結果の出力
      • print(f"予測精度: {accuracy:.2f}")で、精度を小数点以下2桁まで表示します。
      • f文字列を使うと、変数を文字列の中に埋め込むことができます

    ロジスティック回帰の限界と対策

    1. 線形分離しかできない

    ロジスティック回帰の限界:データを直線で分ける性質

    ロジスティック回帰は、「線形分離」が可能なデータに対して非常に効果的です。しかし、データの分布が複雑で、直線(または平面)では分けられない場合には十分に対応できません。


    線形分離とは?

    線形分離」とは、データを1本の直線や平面で明確に分けられる状態を指します。具体的に言うと、以下のようなイメージです:

    例1:線形分離が可能な場合

    イメージとしては、以下のように赤い点(クラス0)と青い点(クラス1)が1本の直線で分けられる状態を考えます。

    ● ● ● ● ●      ← クラス0(赤い点)
    ------------------ ← 分類境界線
    ▲ ▲ ▲ ▲ ▲      ← クラス1(青い点)
    

    この場合、ロジスティック回帰は、直線を引くことでデータを簡単に分離できます。


    例2:線形分離が不可能な場合

    一方、データが以下のように配置されている場合を考えます。

    ● ▲ ● ▲ ●      ← クラス0とクラス1が混在
    ▲ ● ▲ ● ▲

    具体例:株価データを使った線形分離の説明

    線形分離が可能なケース

    例えば、以下の条件で株価の動きを予測する場合を考えます:

    • 特徴量1(前日比上昇率):株価がどれだけ上がったか(%)
    • 特徴量2(出来高):その日の取引量
    • ラベル(結果):次の日に株価が上がる(1)か下がる(0)

    データが以下のような単純な場合、線形分離が可能です:

    前日比上昇率 (%)出来高 (100株単位)結果 (ラベル)
    5.02001
    4.51801
    -1.01500
    -2.51000

    このデータでは「前日比上昇率」と「出来高」の間に1本の直線を引くことで、結果を0と1に分類できます。

    線形分離が難しいケース

    しかし、以下のようにデータが複雑化すると直線では分類できません:

    前日比上昇率 (%)出来高 (100株単位)結果 (ラベル)
    5.02001
    -2.02200
    3.51001
    -1.51800

    この場合、データが交差しており、複雑な境界が必要です。ロジスティック回帰はこの状況では不適切です。


    2. データ量に依存する

    訓練データが少ないと、モデルの性能が低下します。また、データの質も重要です。

    限界への対策

    まとめ

    ロジスティック回帰はデータが単純で線形分離可能な場合に非常に効果的です。しかし、複雑なパターンを含むデータには非線形モデルを検討する必要があります。データの特性に応じた手法選択が重要です。

    タイトルとURLをコピーしました