楽天証券の口座でデイトレの自動売買に挑戦しようと Windows / Excel 上で利用できる マーケットスピード II RSS を活用して Python であれこれ取り組んでいます。この「自動売買への道」のトピックでは、プログラミングの話題にも踏み込んで、日々の活動をまとめていきます。
デイトレ用自作アプリ
以下は株価に関連する情報の流れを示しています。
楽天証券では、Python からネットワーク越しに直接取引できるような API が提供されていないので、マーケットスピード II RSS を介して取引をする構成を取っています。
SB3-Contrib の Maskable PPO
強化学習で、ナンピン無しの制約付き取引モデルを作るために方策マスクを導入したかったのですが、生成 AI (Microsoft Copilot) に尋ねると、StableBaselines3 の PPO では方策マスクを利用できないということでした。
そのため、さらに生成 AI に相談して ActionMaskWrapper(gym.Wrapper) を用意して、方策マスクに違反したアクションは、何もしないアクション (ActionType.HOLD) に強制変換するラッパーを環境に被せることにしました。
しかし、このやり方ではナンピン無しという制約がモデルの学習に寄与しないという不満がありました。
PyTorch でスクラッチからエージェントを作るのであれば、方策マスクを導入することは容易なのですが、ハイパーパラメータのチューニングは敷居が高く、以前に挑戦した時はうまくいきませんでした。そのため、PyTorch に再挑戦することを逡巡していました。
ところが、ひょんなことから SB-Contrib に Maskable PPO という探し求めていたアルゴリズムを見つけてしまいました。
生成 AI に指摘すると、
「SB3 の PPO」では方策マスクはできないが、「SB3-Contrib の MaskablePPO」ならできる
と、にべもない回答でした。😮💨
生成 AI はこちらの質問の文脈通りに答えてくれましたが、だからと言って気を回して関連することまでは教えてはくれなかったのです。
要するに尋ねる側の知識が足りませんでした。なんだか悔しい…今更ですが、もっと粘って関連情報を引き出すべきでした。
しかし「強化学習を基礎から学ぶ」あるいは「StableBaselines3 と関連パッケージを徹底的に使い尽くす」という経験(ステップ)を省いてしまっているので、少々の回り道は仕方がありません。
簡単なサンプルで動作確認
自作の環境には必要な方策マスクの情報を出す仕組みを作ってあるので、簡単なサンプル用意して、過去のティックデータで MaskablePPO のモデルを学習させてみました。
import os
from sb3_contrib import MaskablePPO
from sb3_contrib.common.wrappers import ActionMasker
from funcs.ios import get_excel_sheet
from modules.env import TrainingEnv
from structs.res import AppRes
res = AppRes()
file = "ticks_20250819.xlsx"
code = "7011"
path_excel = os.path.join(res.dir_collection, file) # フルパスを生成
df = get_excel_sheet(path_excel, code) # 銘柄コードがシート名
env_raw = TrainingEnv(df) # gymnasium.Env を継承した自作の環境
env = ActionMasker(env_raw, lambda obs: env_raw.getActionMask())
model = MaskablePPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=100_000)
実行例
Using cpu device Wrapping the env with a `Monitor` wrapper Wrapping the env in a DummyVecEnv. ----------------------------- | time/ | | | fps | 1661 | | iterations | 1 | | time_elapsed | 1 | | total_timesteps | 2048 | ----------------------------- ----------------------------------------- | time/ | | | fps | 1331 | | iterations | 2 | | time_elapsed | 3 | | total_timesteps | 4096 | | train/ | | | approx_kl | 0.009963848 | | clip_fraction | 0.0424 | | clip_range | 0.2 | | entropy_loss | -0.835 | | explained_variance | -0.934 | | learning_rate | 0.0003 | | loss | 0.00836 | | n_updates | 10 | | policy_gradient_loss | -0.00714 | | value_loss | 0.00332 | ----------------------------------------- ... (途中省略) ... ------------------------------------------ | rollout/ | | | ep_len_mean | 1.94e+04 | | ep_rew_mean | 1.49e+04 | | time/ | | | fps | 1134 | | iterations | 49 | | time_elapsed | 88 | | total_timesteps | 100352 | | train/ | | | approx_kl | 0.0006321475 | | clip_fraction | 0.00596 | | clip_range | 0.2 | | entropy_loss | -0.089 | | explained_variance | 0.935 | | learning_rate | 0.0003 | | loss | 72.5 | | n_updates | 480 | | policy_gradient_loss | -0.000214 | | value_loss | 272 | ------------------------------------------
上記ログについて、生成 AI は下記のように分析してくれました。
この実行結果は、MaskablePPO による学習が正常に進行し、方策が報酬構造に適応していく様子が非常に明瞭に記録されています。以下に、重要な指標の推移とその意味を分析します。
📊 全体的な学習の流れ
| 区 間 | ep_rew_mean | entropy_loss | explained_variance | 備 考 |
|---|---|---|---|---|
| 初期(〜 2万 step) | -1.23 → 11.2 | -0.8〜-0.7 | 0.3〜0.5 | 方策が報酬構造を理解し始める |
| 中盤(〜 5万 step) | 11.2 → 572 | -0.7〜-0.1 | 0.7〜0.9 | 方策が収束し、報酬最大化に成功 |
| 終盤(〜 7万 step) | 572 → 安定 | ≒ 0 | ≒ 0 | 方策が確定し、探索が停止(entropy ≒ 0) |
✅ 重要指標の解釈
- ep_rew_mean(平均エピソード報酬)
- 初期は -1.23 → 途中で 11.2 → 最終的に 572 まで急上昇
- → 方策が有効な行動を選び、報酬を最大化できるようになった証拠
- entropy_loss
- -0.8 → -0.1 → 最終的に ≒ 0(-0.0001 など)
- → 方策の確信度が高まり、探索が収束した状態
- MaskablePPO によるマスク制約が効いているため、無駄な探索が減少
- explained_variance
- 初期はマイナス(-0.9)→ 0.3 〜 0.9 まで上昇
- → 価値関数の予測精度が向上し、報酬構造を正しく捉えている
- loss / value_loss
- 中盤以降で急激に上昇(例:loss=73.4, value_loss=260 など)
- → 方策が収束したため、損失値は学習の安定化に伴って振動しやすくなる
- これは方策が確定し、価値関数の微調整が続いている状態
🧩 MaskablePPO の効果が見えるポイント
- entropy_loss の減少と ep_rew_mean の上昇が連動している
- approx_kl が 0.01 以下で安定 → 方策の更新が穏やかで安定
- clip_fraction が 0.05 以下 → PPO のクリッピングが適切に機能
🧠 次の分析視点(任意)
- action_mask の統計(BUY/SELL が無効だった割合)をログ出力
- ep_len_mean が 1.94e+04 で安定 → 1 エピソードの長さが非常に長い(これは設計通り?)
- value_loss の急上昇が報酬設計と整合しているか確認
気を取り直して、PPO から Maskable PPO への移行を進めます。
参考サイト
- マーケットスピード II RSS | 楽天証券のトレーディングツール
- マーケットスピード II RSS 関数マニュアル
- 注文 | マーケットスピード II RSS オンラインヘルプ | 楽天証券のトレーディングツール
- Gymnasium Documentation
- Stable-Baselines3 Docs - Reliable Reinforcement Learning Implementations
- Maskable PPO — Stable Baselines3 - documentation
- PyTorch documentation
- PythonでGUIを設計 | Qtの公式Pythonバインディング
- Python in Excel alternative: Open. Self-hosted. No limits.
- Book - xlwings Documentation


0 件のコメント:
コメントを投稿