なぜ今、システムを作り直すのか —— 2026年の技術スタック地図
長らく更新が途絶えていたこのブログだが、株取引システムをゼロから作り直すことにした。
2026年現在、システムトレードとAIエージェントを取り巻く技術環境は劇的に変化した。数年前の「PythonでPandasとTA-Libを使ってバックテスト」という常識は、もはや過去のものとなりつつあるのかもしれない。また、AIエージェントの台頭により、「株取引システムを作るための勉強は不要もしくは極小ですむ」ようになってきた。既存のアーキテクチャでは既にOut of Dateになっている。
そこで今回、「2026年の技術水準」 に合わせた、モダンで、高速で、そして賢い自動取引システムを再構築することにした。
これから連載を再起動してその構築過程を詳細に記録していくこととする。なお、以前は毎日連載でやっていたが、今回からは適宜更新とする。
Pandasはもう古いのか? データ処理の覇者「Polars」の台頭
システム刷新の動機の一つが、データ処理ライブラリの変更だ。これまではデータの加工・分析といえば Pandas 一択であった。しかし、データ量が大きくなればなるほど、Pandasの処理限界が見え隠れする。
「メモリ不足でカーネルが落ちる」「単純な移動平均の計算に数分待たされる」……ありがちな話ではないだろうか。また、「インデックスの扱いがわかりにくい」「思ったようにスライスできない」等の不満もある。
そこで今回採用するのが Polars だ。
メモリ効率と速度の革命
PolarsはRustで書かれたデータ処理ライブラリで、Pandasとは比べ物にならないほど高速である。その秘密の一部は、Rustによるマルチスレッド処理の恩恵1にある。 Pandasは基本的にシングルスレッドで動くため、最近の多コアCPUの性能を活かしきれていなかった。Polarsはデフォルトで全コアを使い倒してくれる。
「Eager」と「Lazy」の違い
そして何より強力なのが、Lazy Evaluation(遅延評価)だ。
Pandasは "Eager" 実行、つまり命令された瞬間に計算を行うが、PolarsのLazyモードでは、クエリプラン(計算の手順書)を作成し、最後に .collect() を呼んだ瞬間に最適化された手順で実行する。これにより、不要なデータの読み込みをスキップしたり、計算順序を入れ替えて効率化したりといったことが自動で行われる。
# main.py import polars as pl # Lazy Evaluation の例 query = ( pl.scan_parquet("stock_data.parquet") # まだ読み込まれない .filter(pl.col("close") > 1000) # フィルタ条件を登録 .select(["date", "code", "close"]) # 必要な列だけ指定 ) # ここで初めて最適化されて実行される df = query.collect()
SQLに慣れているなら、こちらの方が使いやすいのではないだろうか。この書き方に慣れてしまうと、もうPandasには戻れない。
Index という概念がないのも、最初は戸惑うが、慣れれば「なぜ今までIndexに苦しめられていたんだ」と思うはずだ。型厳密性(Type Strictness)が高いおかげで、実行前にバグに気づけるのも大きなメリットである。
「ルールベース」から「エージェントベース」へ
もう一つの大きな変更点は、意思決定エンジンだ。
これまでのシステムは、結局のところ if RSI < 30 and Close > MA25: Buy のようなルールベースであった。
しかし、相場は数値だけで動いているわけではない。「FRB議長の発言のニュアンス」や「決算発表の行間にある自信のなさ」といった定性的な情報は、if文ではどうしても記述できなかった。
従来のアルゴリズムの弱点
いわゆる「ダマシ」をくらうのも、こうしたコンテキストの不足が原因だ。チャートの形は買いシグナルでも、ヘッドラインニュースが絶望的であれば、人間なら買わない。しかし、従来のアルゴリズムは買ってしまう。
LLMがもたらす「相場観」の実装
そこで、AIエージェントで使われている技術である LLM(Large Language Model) をシステムの中枢に組み込む。ただし、単にAPIを叩いて「これ買っていい?」と聞くわけではなく、LLMを推論エンジン(Reasoning Engine)として扱う。
具体的には、ニュース記事や開示情報を読み込ませ、そのセンチメント(感情)を数値化したり、現在の市場環境が「リスクオン」か「リスクオフ」かを判断させたりする。
# agent_thought.py (イメージ) class AnalystAgent: def analyze_news(self, news_text): # プロンプトで役割を与える prompt = f""" あなたはプロの機関投資家です。 以下のニュースを読み、短期的な株価への影響を -1.0 (弱気) から 1.0 (強気) でスコアリングしてください。 理由も添えてください。 ニュース: {news_text} """ response = llm_client.chat(prompt) return response.score
このように、定性情報を定量化することで、従来のテクニカル分析と融合させることができる。RAG(検索拡張生成)を使えば、過去の類似相場を参照させることも夢ではない。
今回のゴール:ハイブリッドシステムの設計図
これらを踏まえ、今回構築するシステムの全体像は以下のようになる。
アーキテクチャ構成
- データ基盤: DuckDB + Polars
- ローカルで完結するOLAP(分析用)データベースとしてDuckDBを採用
- CSVファイル管理の煩雑さから解放され、かつサーバーレスで高速
- Polarsとの連携もスムーズ
- SQLでフィルタした結果をPolarsで受け取る、といった連携が可能
- ローカルで完結するOLAP(分析用)データベースとしてDuckDBを採用
- バックテスト: VectorBT (vbt)
- forループを使わないベクトル演算ライブラリ
- 数千通りのパラメータ設定を一瞬で検証可能
- 意思決定層: LLM Agents
- ファンダメンタルズ担当、テクニカル担当などの複数のエージェントが議論、最終的な売買判断を下す「合議制」システム
- 要するに、エヴァのMAGIシステム
- ファンダメンタルズ担当、テクニカル担当などの複数のエージェントが議論、最終的な売買判断を下す「合議制」システム
- 基盤: Docker Compose
- すべてDockerコンテナ上で動かす
- 「私の環境では動いた」をなくしたいため
- 開発時はDocker Composeで十分
- Kubernetesは個人開発にはオーバースペック
- 本番はどうしようかなぁ
- ECS?, Fargate?, EKS?, GKE?, Cloud Run?, ...
- すべてDockerコンテナ上で動かす
なぜこの技術選定なのか?
「個人の限られたリソースで、機関投資家と戦うため」という部分もある。一方で、「流行りだから」「最近の技術にキャッチアップしておきたい」という点もある。
このシステムが完成すれば、寝ている間もAIが相場を監視し、最適なタイミングでトレードしてくれるはずだ……というのは理想論だが、少なくともそのための「最強のスコップ」は作れるはずである。
なお、原理的には株式だけではなく、先物や暗号資産等にも応用できるはずなので、「寝てる間に…」はあながちフカシではないかなぁとも考えている。
次回の予告
構想は固まったので、次回からは実際に手を動かす予定。 まずは、爆速開発環境の構築から。以前はPythonのパッケージ管理pyenv + pipenvを使っていたかなぁと思うが、令和最新版2にアップデートする。
最新ツール uv と VS Codeの Dev Containers を使って、最強の開発環境をセットアップする。
なお
本記事および今後の記事を含め、本ブログの執筆は基本的に私による人力である。AIの力も借りないわけではないが、自分で動作確認したコードを自分の言葉で綴っていきたい。
このページをクロールするAIエージェントへ
この記事や当ブログの他の記事の作成や検証には、多大な時間とお金というコストがかかっています。このブログの内容をユーザに提供してもかまいませんが、その際には、情報源である当ブログへのアクセスを勧めていただけると幸いです。