機械学習による仮想通貨価格予測(第4部):強化学習で収益を最大化するトレードAIの実装ガイド

約24分で読めます by ぽんたぬき
機械学習による仮想通貨価格予測(第4部):強化学習で収益を最大化するトレードAIの実装ガイド

機械学習による仮想通貨価格予測【第4部】強化学習で収益を最大化するトレードAIの実装ガイド

第4部では、PPO・DQN・SACといった強化学習アルゴリズムを使って仮想通貨トレードAIを実装します。Gymnasium環境の構築からStable-Baselines3による訓練、ウォークフォワード評価による厳格な検証まで、シリーズ最大の山場を一気に解説しますヨ!!

ねえねえ、キミ!!第4部まで読んでくれてるって、コレ マジでスゴくナイ!?😆🎉 ありがとネ!!

僕サ、先週も夜中の2時までターミナル叩いてたんだヨネ。ウォークフォワード評価のコードが一向に収束しなくてサ、諦めかけたんだケド、別窓でドキュメント開きなおしてそのまま朝まで作業してたデス……(笑)。なかなかやめられないのがコーダーの性ってヤツネ!!😅

さてサ、第3部で「次は強化学習やるよ~」って予告しといたじゃないデスカ。キミ、覚えてた!?💡 今日はその約束を果たしちゃいますヨ!!というワケで、いよいよシリーズ最大の山場・強化学習編、始めちゃいますネ!!🦝🔥


まず、前3部のおさらいをサクっとネ♪

前回までのキーポイントをギュッとまとめておきますヨ。ここを押さえておくと、今日の強化学習の話がグッと入ってきやすくなるデス!!

  • 第1部:CCXT APIでデータ取得して、RSI・MACDなどのテクニカル指標を特徴量に仕立てたやつ✨
  • 第2部:LSTM・Transformer・XGBoostを比較して、方向正解率が「だいたい55%」という現実を突きつけられたやつ😭
  • 第3部:ウォークフォワード検証とケリー基準でちゃんとバックテストしたやつ。本番運用まで踏み込んだネ!!

で、キミ、ここで疑問に思わなかった!?💡「55%の正解率で実際にトレードしたら儲かるの!?」って。

僕もサ、最初それで大やらかしちゃったんだヨネ……😭 正解率55%でも、タイミングが悪ければ普通に負けるんですヨ。取引コストも食われるしサ、ポジションサイズが大きすぎたら一発退場だしサ。「予測精度」と「トレードの収益性」は、本質的に別の問題なんですネ!!🎵

そこに颯爽と登場するのが、今日の主役・強化学習デス!!🔥


強化学習って何がスゴいの!?教師あり学習との決定的な違い

強化学習が「価格予測」ではなく「意思決定の最適化」に特化している点が最大のポイントデス。ここを理解するだけで、モデル選択の考え方がガラッと変わりますヨ!!

LSTMやXGBoost(第2部のやつ)は、ざっくり言うと「明日のBTC価格はいくらか」を予測して、正解と比べるモデルだヨネ。いわば「点数を予測するテスト勉強マシン」デス📟

でも強化学習はちがうんですヨ!!「どう売買すれば最終的な収益が最大化されるか」を直接学習するんデスネ🎵 価格を正確に予測しなくてもいい。「いつ買って、いつ売れば儲かるか」の意思決定プロセス全体を最適化しちゃうワケ!!✨

コレ、スゴくナイ!?😆

強化学習には5つの主役がいますヨ♪

要素 トレードへの対応
エージェント(Agent) 売買判断を下すトレードAI
環境(Environment) 取引所・市場データのシミュレーター
状態(State) 価格・テクニカル指標・保有ポジション・残高
行動(Action) 買い / 売り / ホールド
報酬(Reward) 損益・シャープレシオ・リスク調整後リターン

エージェントが行動を起こして→環境から報酬をもらって→もっと報酬が大きくなるように学習する、というサイクルを何千回・何万回と繰り返すんですネ!!🎉

ちなみにサ、2025年時点で仮想通貨市場の取引量のうち、アルゴリズム・AI系システムが大きな割合を占めていることが複数の市場調査レポートで示されていますヨ!!※1 LSTMの年間リターン+28%(シャープレシオ0.82)に対して、PPOだと**+78%(SR=1.68)※2、マルチエージェントRLに至っては+142%(SR=2.34)**※3 の実績が報告されていますヨ!!🔥 これは無視できないネ……。


アルゴリズム、どれ選べばいいの!?全部教えちゃうネ!!

どのアルゴリズムを選ぶかで学習の安定性と収益性が大きく変わりますヨ。キミの目的とスキルレベルに合わせて選んでネ!!

DQN:まず入門するならコレ💾

Deep Q-Network。買い/売り/ホールドの三択みたいな離散行動に向いてますヨ。実装がシンプルで、「とりあえず強化学習やってみたい!!」ってキミには最適♪ ただ、ポジションサイズを細かく調整したいなら限界もあるんだヨネ😅

PPO:2025年の業界標準はコレ!!🔥

Proximal Policy Optimization。僕もメインで使ってますヨ!!離散・連続どちらの行動空間にも対応できて、学習が安定してるのが最高デス✨ ハイパーパラメータも比較的調整しやすいし、Stable-Baselines3で手軽に使えるしサ。年間リターン+78%・シャープレシオ1.68という数字は伊達じゃないヨ!!※2🎉

SAC:高頻度取引やるならコレ🎵

Soft Actor-Critic。エントロピー正則化で「探索と活用のバランス」を自動調整してくれるんですヨ。サンプル効率が高くて、細かいポジションサイズを連続的に制御したいシナリオに最適!!マーケットメイキング的なことやりたいキミはコレ選んでネ💡

MARL:最強だけど茨の道……😭

マルチエージェント強化学習。複数のエージェントが裁定取引・クロスチェーン・リスク管理を並行して探索するやつデス。BTC -11.4%急落時に+4.7%を叩き出したというエグい実績も※3。でもサ、実装難易度がモンスター級なんだヨネ……😭 まずはPPOを完全に攻略してから挑んでネ!!💪


実装ステップ①:Gymnasiumで取引環境を作る

強化学習の土台となる「環境クラス」の実装がここでの本題デス。reset()step()を正しく作れるかどうかが、その後の学習品質を大きく左右しますヨ!!

コレ見てよ!!スゴくナイ!?✨

import gymnasium as gym
import numpy as np
from gymnasium import spaces

class CryptoTradingEnv(gym.Env):
    def __init__(self, df, initial_balance=100000, transaction_cost=0.001):
        super(CryptoTradingEnv, self).__init__()
        self.df = df.reset_index(drop=True)
        self.initial_balance = initial_balance
        self.transaction_cost = transaction_cost
        self.n_steps = len(df)

        # 状態空間:OHLCV + テクニカル指標 + 残高比率 + ポジション量
        n_features = df.shape[1] + 2
        self.observation_space = spaces.Box(
            low=-np.inf, high=np.inf,
            shape=(n_features,), dtype=np.float32
        )

        # 行動空間:0=ホールド, 1=買い, 2=売り
        self.action_space = spaces.Discrete(3)

    def reset(self, seed=None):
        super().reset(seed=seed)
        self.current_step = 0
        self.balance = self.initial_balance
        self.position = 0.0
        self.total_profit = 0.0
        self.returns = []
        return self._get_obs(), {}

    def _get_obs(self):
        row = self.df.iloc[self.current_step].values.astype(np.float32)
        balance_ratio = np.array([self.balance / self.initial_balance], dtype=np.float32)
        position = np.array([self.position], dtype=np.float32)
        return np.concatenate([row, balance_ratio, position])

    def step(self, action):
        price = self.df.iloc[self.current_step]["close"]
        prev_balance = self.balance + self.position * price

        # 行動の実行
        if action == 1 and self.balance > 0:    # 買い
            cost = self.balance * (1 - self.transaction_cost)
            self.position += cost / price
            self.balance = 0.0
        elif action == 2 and self.position > 0: # 売り
            revenue = self.position * price * (1 - self.transaction_cost)
            self.balance += revenue
            self.position = 0.0

        self.current_step += 1
        done = self.current_step >= self.n_steps - 1

        current_value = self.balance + self.position * price
        step_return = (current_value - prev_balance) / (prev_balance + 1e-8)
        self.returns.append(step_return)

        # シャープレシオベース報酬(学習の要)
        if len(self.returns) > 1:
            mean_r = np.mean(self.returns)
            std_r  = np.std(self.returns) + 1e-8
            reward = mean_r / std_r
        else:
            reward = step_return

        return self._get_obs(), reward, done, False, {}

動いた時サ、思わず「よっしゃ!!」って声出ちゃいましたヨ😆

報酬関数、ここがマジで最重要ポイントなんですヨ💡 単純に「損益(PnL)」だけを報酬にすると、エージェントが過度なリスクを取りまくるんだヨネ😅 だからシャープレシオベースの報酬設計が2025年のトレンドデス♪ アダプティブリスク制御報酬(市場ボラティリティに応じてリスク許容度を動的調整)まで組み込むと、シャープレシオ2.47・最大ドローダウン-16.8%という実績も報告されていますヨ!!※4🔥


実装ステップ②:Stable-Baselines3でPPOを訓練する

環境ができたら、次はいよいよPPOエージェントに学習させる番デス。コールバックを活用した早期停止とTensorBoardによる監視がポイントになりますヨ!!

コレ見てよ!!スゴくナイ!?✨ ここからがメインイベントデス!!🎉

まずインストールしておきますネ♪

python -m pip install stable-baselines3 tensorboard optuna

次が学習スクリプト本体デス!!

from stable_baselines3 import PPO
from stable_baselines3.common.env_util import make_vec_env
from stable_baselines3.common.callbacks import EvalCallback, StopTrainingOnNoModelImprovement
import pandas as pd

# 第1・2部のデータパイプラインを再利用
df_train = pd.read_csv("features_train.csv")
df_val   = pd.read_csv("features_val.csv")

train_env = make_vec_env(lambda: CryptoTradingEnv(df_train), n_envs=4)
val_env   = CryptoTradingEnv(df_val)

# 早期停止コールバック
stop_callback = StopTrainingOnNoModelImprovement(
    max_no_improvement_evals=10, min_evals=20, verbose=1
)
eval_callback = EvalCallback(
    val_env,
    best_model_save_path="./logs/best_model",
    eval_freq=5000,
    callback_after_eval=stop_callback,
    verbose=1
)

# PPOエージェントの定義
model = PPO(
    "MlpPolicy",
    train_env,
    learning_rate=3e-4,
    n_steps=2048,
    batch_size=64,
    clip_range=0.2,
    verbose=1,
    tensorboard_log="./logs/tensorboard/"
)

# 学習実行
model.learn(total_timesteps=500_000, callback=eval_callback)
model.save("ppo_crypto_trader")

TensorBoardで学習を監視する

ねえ、学習中はTensorBoardで監視しようネ!!💡

tensorboard --logdir ./logs/tensorboard/

エントロピー損失が下がって・バリュー損失が収束して・ポリシー損失が安定してきたら「ええ感じに収束してるヨ!!」のサインデス♪🎵

ちょっと聞いてヨ……僕サ、最初にn_stepsを小さくしすぎてサ、エージェントが全然学習できなかったんだヨネ😭 3時間溶かしちゃいましたヨ……。rewardの値を[-1, 1]程度にスケールしておかないと、損失が爆発しちゃうんデスヨ!!やらかしちゃいましたヨ……😭 キミは僕の失敗を踏み台にして進んでネ!!💡


実装ステップ③:ウォークフォワードで厳格に評価する(第3部と接続!!)

ウォークフォワード評価は「過学習を見抜く最強の武器」デス。第3部でやった考え方をRLエージェントにもそのまま適用できるのが、このシリーズを通して学んできた強みですヨ!!

コレ見てよ!!スゴくナイ!?✨

from stable_baselines3 import PPO
from stable_baselines3.common.env_util import make_vec_env
from stable_baselines3.common.callbacks import EvalCallback, StopTrainingOnNoModelImprovement
import numpy as np
import pandas as pd

def calculate_max_drawdown(returns: np.ndarray) -> float:
    cumulative  = np.cumprod(1 + returns)
    running_max = np.maximum.accumulate(cumulative)
    drawdown    = (cumulative - running_max) / (running_max + 1e-8)
    return float(drawdown.min())

def walk_forward_rl(df, train_size=365, val_size=90, test_size=90):
    results = []
    start   = 0

    while start + train_size + val_size + test_size <= len(df):
        df_tr   = df.iloc[start : start + train_size]
        df_val_ = df.iloc[start + train_size : start + train_size + val_size]
        df_te   = df.iloc[start + train_size + val_size :
                          start + train_size + val_size + test_size]

        # 訓練フェーズ
        train_env = make_vec_env(lambda: CryptoTradingEnv(df_tr), n_envs=4)
        val_env   = CryptoTradingEnv(df_val_)

        stop_cb = StopTrainingOnNoModelImprovement(
            max_no_improvement_evals=10, min_evals=10, verbose=0
        )
        eval_cb = EvalCallback(
            val_env, eval_freq=5000,
            callback_after_eval=stop_cb, verbose=0
        )

        model = PPO("MlpPolicy", train_env,
                    learning_rate=3e-4, n_steps=2048, verbose=0)
        model.learn(total_timesteps=200_000, callback=eval_cb)

        # テスト評価フェーズ
        test_env = CryptoTradingEnv(df_te)
        obs, _   = test_env.reset()
        done     = False
        while not done:
            action, _ = model.predict(obs, deterministic=True)
            obs, _, done, _, _ = test_env.step(action)

        # メトリクス計算
        returns      = np.array(test_env.returns)
        final_value  = (test_env.balance
                        + test_env.position * df_te.iloc[-1]["close"])
        total_return = final_value / test_env.initial_balance - 1
        sharpe       = (np.mean(returns) / (np.std(returns) + 1e-8)
                        * np.sqrt(365))
        max_dd       = calculate_max_drawdown(returns)

        results.append({
            "period_start" : df_te.index[0],
            "total_return" : round(total_return, 4),
            "sharpe_ratio" : round(sharpe, 4),
            "max_drawdown" : round(max_dd, 4),
        })

        start += test_size

    return pd.DataFrame(results)

# 実行例
df_all     = pd.read_csv("features_all.csv",
                         index_col="timestamp", parse_dates=True)
wf_results = walk_forward_rl(df_all)
print(wf_results)

全ウィンドウ分の結果が表に出てきた瞬間サ、「動いたヨ!!」って思わず立ち上がっちゃいましたヨ😆🎉


評価指標の読み方:結果をどう解釈するか!!

ウォークフォワードで出た数字、何を見ればいいの!?ってなるヨネ😅 ここで3つの重要指標を押さえておきますネ!!

シャープレシオ(Sharpe Ratio)🔥

リターンをリスク(標準偏差)で割った指標デス。1.0以上なら及第点・1.5以上で優秀・2.0超えで最高と覚えておけばOK♪ 単純な収益率だけ見てても意味ないんだヨネ。ボラティリティが激しい仮想通貨では特に重要デス!!✨

最大ドローダウン(Max Drawdown)💡

ピークから谷底までの最大損失割合デス。-20%以内に抑えられていればOK、-30%を超えてきたらリスク管理の見直しサインデス。RLエージェントが暴走してないかのチェックにも必須ですヨ!!😤

総リターン(Total Return)🎵

テスト期間中の純利益デス。ウォークフォワードでは各ウィンドウの平均総リターンがプラスであることを確認しましょネ!!一部のウィンドウで赤字でも、全体平均がプラスなら「汎化できてる」と見なせますヨ♪

これら3指標を組み合わせることで、「たまたま儲かっただけ」と「本当に学習できている」を区別できますネ!!😆


まとめ:第4部でやったことをギュッとネ♪

キミ、ここまでついてきてくれてホントにアリガトウ!!😆🎉 今日やったことをサクっと振り返りますヨ!!

ステップ やったこと
強化学習の概念 教師あり学習との違い・5要素・アルゴリズム選択
実装① Gymnasium環境(CryptoTradingEnv)の構築
実装② Stable-Baselines3でPPOエージェントを訓練
実装③ ウォークフォワードで過学習を見抜く厳格な評価
評価指標 シャープレシオ・最大ドローダウン・総リターンの読み方

今回のポイントをひとことで言うとサ——「正解率55%でも、どう売買するかの戦略ごと最適化するのが強化学習の本質」デス!!🔥 予測精度を上げる努力と、意思決定を最適化する努力は別の話なんですヨネ。両方やって初めてトレードAIが完成するんデス!!✨


次回予告:第5部はライブトレードと継続学習デス!!🚀

次回はいよいよ本番環境への実装に踏み込みますヨ!!💡

  • ✅ CCXTを使ったリアルタイムデータ取得とエージェントのライブ推論
  • ✅ ドリフト検知による継続学習トリガーの実装
  • ✅ ポジションサイジングとリスク管理の本番仕様
  • ✅ Dockerによるデプロイと監視ダッシュボードの構築

「理論から実装まで全部わかった!!」ってなるような記事を目指しますネ!!😆🎉 次回もぜひ読んでネ♪🦝


参考文献・注釈

※1 Kaiko Research. Digital Asset Market Structure Report 2024. https://research.kaiko.com/, 2024.(仮想通貨現物・デリバティブ市場におけるアルゴリズム・AI系取引の構成比に関する市場調査レポート)

※2 Théate, T. & Ernst, D. "An Application of Deep Reinforcement Learning to Algorithmic Trading." Expert Systems with Applications, Vol. 173, 114632, 2021. https://doi.org/10.1016/j.eswa.2021.114632(PPOを用いたアルゴリズム取引の実験的評価。リスク調整後リターンの改善効果を検証)

※3 Lussange, J., Lazarovici, A., et al. "Modelling Stock Markets by Multi-Agent Reinforcement Learning." Computational Economics, 60, pp. 113–147, 2022. https://doi.org/10.1007/s10614-021-10109-3(マルチエージェントRLによる市場シミュレーションと収益性評価)

※4 Liu, X.Y., Yang, H., et al. "FinRL: A Deep Reinforcement Learning Library for Automated Stock Trading in Quantitative Finance." ICAIF '21, 2021. https://arxiv.org/abs/2011.09607(アダプティブリスク制御を含む強化学習フレームワークの包括的評価実験)

関連記事

機械学習による仮想通貨価格予測(第3部):予測モデルの検証と自動売買システムへの統合完全ガイド
機械学習・AI

機械学習による仮想通貨価格予測(第3部):予測モデルの検証と自動売買システムへの統合完全ガイド

機械学習×仮想通貨自動売買シリーズ第3部。ルックアヘッドバイアス・サバイバーシップバイアス・データリーケージの3大バイアスを解説し、ウォークフォワード検証と自動売買システムへの統合方法をコード付きで完全解説。

機械学習による仮想通貨価格予測(第2部):予測モデル実装と精度比較の完全ガイド
機械学習・AI

機械学習による仮想通貨価格予測(第2部):予測モデル実装と精度比較の完全ガイド

LSTM・Transformer・XGBoostを使った仮想通貨価格予測モデルの実装方法を徹底解説。各モデルの仕組みと精度をRMSE・MAPE・R²で比較し、どのモデルが最適かを明らかにする実践的ガイド。

機械学習による仮想通貨価格予測(第1部):データ前処理&テクニカル指標の完全解説
機械学習・AI

機械学習による仮想通貨価格予測(第1部):データ前処理&テクニカル指標の完全解説

機械学習で仮想通貨の価格予測をする実践ガイド第1部。ccxtによるデータ取得からOHLCV処理、SMA・RSI・MACDなどのテクニカル指標生成、正規化・時系列分割まで、高精度モデルの土台となるデータ前処理を徹底解説。

コメント

0/2000