はじめに
日本株向けの AI クオンツシステム「QuantG」を個人で作っています。QuantG では、因子(銘柄を選ぶための指標)のコードを LLM に書かせています。
LLM に「どこを掘るか」を伝えるのが因子定義です。この因子定義は、ここ 3 か月あまりで 3 回形が変わりました。
第1段階(〜7月上旬) 定義なし:LLM が自分で仮説を立てて掘る
↓ 掘る場所が一部のデータに偏る
第2段階(7月中旬〜) 因子テーマ + 因子定義:見るデータを LLM に割り当てる
↓ それでも残るのは価格・出来高の因子ばかり。評価の物差しが「2日後」の一本だけ
第3段階(10月下旬〜) 情報の系統 + 一つの仮説ごとの定義 + 保有期間 k
この記事では、各段階で何が起き、なぜ変えたのかを順に書きます。先に結論を言うと、LLM の探索を広げるには「何を見るか」を指定するだけでは足りず、「どれだけ待ってから評価するか」まで定義に含める必要があった、ということです。
第1段階:定義なしで、LLM に自由に掘らせる
最初は、因子研究を自動化するオープンソースのフレームワーク RD-Agent の流れを移植して使っていました。
- LLM が仮説を立てる(例:「外国人投資家の買い越しが加速している銘柄は、2 日後まで上がりやすい」)
- 仮説をもとに、因子のコードを書く
- 過去のデータで評価する
- 結果を LLM に返し、次の仮説を考えさせる
LLM に渡していたのは、J-Quants のデータから作った日次の表で、列は 45 個ありました。価格・出来高だけでなく、売上・利益・EPS・業績予想、決算発表からの日数、TOPIX、投資部門別(外国人・個人・投資信託など)の売買、市場区分、株式分割まで入っています。
データは十分にあるのに、LLM が掘る場所は狭いままでした。 出てくる仮説は、価格と出来高を使ったモメンタム・反転・ボラティリティといった定番に集まりがちで、他の列はほとんど使われません。何十もの列を渡しても、LLM は一番目立つ数列ばかりを見てしまいます。
これは LLM が悪いというより、仕組みの問題です。「何を研究するか」も「どの列を使うか」も LLM に任せている以上、探索は LLM が真っ先に思いつく方向へ寄っていきます。探索の範囲を人が制御する手段が、どこにもありませんでした。
第2段階:因子テーマと因子定義で、見るデータを割り当てる
そこで、掘る範囲を人が先に決めることにしました。二段階の「研究の地図」です。
- 因子テーマ:大きな研究の方向
- 因子定義:テーマの下にある具体的な研究課題。仮説、使ってよい入力列、探索する観点、データを使うときのルールを書く。式やコードは書かない
最初は 6 テーマ・19 定義でした。
| 因子テーマ | 因子定義 |
|---|---|
| 短期の値動き | 短期のリターン状態、日中の値動きの強弱、寄り付きのギャップ、価格の位置とトレンドの質 |
| ボラティリティと値幅 | 真の値幅、実現ボラティリティ、値幅の拡大 |
| 流動性と出来高 | 売買代金の流動性、出来高の異常、価格と出来高の関係 |
| 相対強弱と市場状態 | TOPIX との相対強弱、業種との相対強弱、市場の騰落の広がり、市場と投資部門別の状態 |
| 決算とイベント | 決算発表からの日数、決算発表後の反応、業績サプライズと予想修正 |
| ファンダメンタルとバリュエーション | 財務の質、バリュエーション |
仕組みのポイントは 2 つです。
1. LLM は、定義に書かれた列しか使えない。 たとえば「バリュエーション」の定義には、終値と、財務データの EPS・BPS・営業キャッシュフロー・期末の発行済株式数などが入力として書いてあり、LLM はそれ以外の列を読めません。定義ごとに列を割り当てておけば、データのどの領域にも、必ず誰かが手をつけることになります。
2. 因子プールは「定義ごとに 1 枠」。 各定義から、その時点で一番良い候補を 1 つだけプールに入れます。どこかの定義で良い因子が出なくても他の定義の枠は埋まるので、プール全体が一つの方向に偏りにくくなります。
その後、決算や開示のようにゆっくり出てくる情報のために、「遅い因子」の掘り方も加えました。値動き系の定義は 3 営業日ごとに区切って掘り直しますが、開示系の定義は、新しい開示がおよそ 400 件たまるごとに掘り直します。分足を使う定義も加わり、定義は 20 を超えました。
それでも、残るのは価格・出来高の因子ばかりだった
10 月中旬、模擬口座の成績が振るわない原因を調べたところ、因子プールの中身がはっきりしました。
- プールに残っていた因子は、ほとんどが日足の価格・出来高の変換(1〜20 日のリターン、値幅、出来高、相対強弱、市場の広がり)でした。
- 同じ日足から同じような期間で作っているので互いの相関が高く、合成すると「最近一番大きく動いた銘柄」、つまり高ボラティリティ銘柄を上位に選ぶだけになっていました。
- LLM は 1 回に 3 つの候補しか出さず、変わるのは書き方で、情報源ではありませんでした。
定義で列を割り当てたので、LLM は財務の列も確かに使いました。それでも、評価を通って残るのは価格・出来高の因子でした。原因は定義の「外」にありました。
- 定義そのものが価格寄りだった:19 定義のうち 14 は日足の価格・出来高や TOPIX を読む定義で、決算・財務を読むのは 5 つだけでした。
- 評価の物差しが一本だけだった:どの定義も「シグナル日の終値から 2 営業日後の終値まで」のリターンで評価していました。「遅い因子」も、変えたのは掘り直す間隔だけで、評価に使うリターンは同じ 2 日でした。
本質的だったのは 2 つ目です。割安さのような情報が株価に反映されるには、数週間かかるはずです。それを 2 日後のリターンで測れば、価格・出来高の因子に勝てないのは当然です。入口(使う列)を広げても、出口(評価の物差し)が一つなら、残るものは偏る、ということでした。
気づき:情報によって、市場が織り込むまでの時間が違う
そこで、プールに残った因子を、保有期間を変えて評価し直しました(2・5・10・20 営業日)。指標は IC(因子の順位と、その後のリターンの順位の相関)です。結果は因子ごとにばらばらでした。
- 売買代金の流動性の因子は、2 日より 20 日のほうが IC が高い(0.032 → 0.051)
- 分足を使った因子も、20 日のほうが高い(0.011 → 0.039)
- 一方で、短期のリターンや市場の広がりの因子は、20 日では向きが逆になる
回り道:全部を 10 日にして、失敗した
ここで一度、間違った方向に進みました。当時の因子をまとめて合成すると、2026 年のデータでは 10 日の IC(0.044)が 2 日より高く見えたので、全因子の保有期間を一律に 10 日へ延ばす案を検証しました。
ところが、開発に使っていない 2023〜2024 年のデータで最終検証すると、10 日の IC は 0.0023 で、ほぼゼロでした。2026 年に 10 日が良く見えたのは、その時期の相場がたまたまそうだっただけでした。逆に 2 日の IC は、2026 年でも 2023〜2024 年でも 0.015 前後で、弱いながら再現しました。
ここで分かったのは、**「長く持てば良い」のではなく、「情報の種類ごとに、ちょうど良い待ち時間がある」**ということです。
- 価格・出来高の情報は、1〜2 日で織り込まれます。それ以上持っても残りはノイズで、IC は薄まります。
- バリュエーション・財務・信用取引のような情報は、週単位で織り込まれます。持つほどシグナルは積み上がり(ノイズは日数の平方根でしか増えない)、効果が尽きるまでは IC が上がっていきます。
ちょうど良い保有期間を決めるのは、その因子を何日のリターンで掘ったかではなく、その因子が使っている情報の種類です。 これが、因子定義に保有期間 k を持たせた理由です。
第3段階:保有期間 k を持つ因子定義
10 月下旬に、因子定義を作り直しました。主な変更は 3 つです。
1. テーマを「情報の系統」に変え、系統ごとに k を決めた
| 系統 | 主な情報 | 目標の保有期間 k(営業日) |
|---|---|---|
| 価格・出来高系 | 日足のリターン、値幅、出来高 | 2、5 |
| バリュエーション・財務系 | PER・PBR・ROE、財務、業績予想 | 10、20 |
| 需給系 | 信用取引の買い残・売り残 | 5、10、20 |
| イベント系 | 業績サプライズ、業績予想の修正 | 5、10、20 |
k は一つの値ではなく候補の組です。一つの系統の中でも、どの k で一番効くかは掘ってみるまで分かりません。需給系の情報を使うために J-Quants のプランを上げて信用取引残高を取り込み、バリュエーション指標も新たに使い始めました。
2. 定義を「研究の方向」から「一つの仮説」に細かくした
第2段階では、「バリュエーション」という一つの定義に、益利回り・簿価時価比率・キャッシュフロー利回り・過去との比較という 4 つの観点がまとめて入っていました。今回は 一つの定義=一つの検証できる仮説 とし、使う列と回顧期間も絞りました。結果、29 定義になりました(価格・出来高 9、バリュエーション・財務 10、需給 6、イベント 4)。
例です(実際の定義を簡略化しています)。
{
"系統": "バリュエーション・財務",
"定義": "予想ベースの益利回り",
"仮説": "公表済みの予想利益から見た割安さは、実績利益よりも早く株価の見直しにつながる可能性がある",
"入力": ["予想PER", "予想EPS"],
"回顧期間": ["最新値", "20日", "60日"],
"目標の保有期間": [10, 20],
"ルール": [
"シグナル日の引け後に入手できた値だけを使う",
"欠損は 0 で埋めず、未来の値も使わない"
]
}
第2段階と同じく、式は書きません。式を考えるのは引き続き LLM の仕事です。データがまだ揃っていない 13 の方向(分足の値動きの経路、空売り残高の報告など)は、定義を作らずに保留にし、何が揃えば始められるかだけを記録しています。
3. 評価に使うリターンを k に合わせて揃えた
評価に使うリターンは、すべて「翌営業日の寄り付きで買い、k 営業日持って、寄り付きで売る」に揃えました。シグナルは引け後に出るので、シグナル日の終値から翌日の寄り付きまでの値動きは取れません。以前の「終値から終値」のリターンにはこの取れない部分が入っていたので、外しました。
そのうえで、どの候補も 2・5・10・15・20 日のすべてで評価して記録し、採用するかどうかは自分の系統の k でだけ判断します。一つの因子が 10 日用と 20 日用の両方に採用されることもあります。最終的には、k ごとに資金を分けて(2 日用、10 日用、…)並行して運用する計画です。
同時に、評価から業種・時価総額・ボラティリティの影響を取り除く(中立化)、1 回の候補を 3 個から 10 個に増やして 4 グループにそれぞれ別の情報源を指定する、既存の因子と似すぎた候補ははじく、といった変更も入れました。第2段階の因子が実はボラティリティへの賭けだった反省から来たものですが、長くなるので別の記事で書きます。
現在地
29 の定義はデータベースに登録済みですが、この新しい定義での発掘はまだ始めていません。系統ごとの k も、今は「情報の性質から考えた初期値」です。本当にその k で効くのかは、掘ってみて確かめます。最初はバリュエーション・財務系を 1 つ(本命)、価格・出来高系を 1 つ(比較用)掘るところから始める予定です。
まとめ
| 段階 | 因子定義が決めること | 見えた問題 |
|---|---|---|
| 第1段階 | なし(すべて LLM 任せ) | 目立つ列に探索が偏る |
| 第2段階 | 何を見るか(テーマと使う列) | 評価の物差しが 2 日の一本だけで、残るのは価格・出来高の因子 |
| 第3段階 | 何を見るか + どれだけ待って評価するか(k) | これから検証 |
振り返ると、因子定義は「LLM への指示書」から、評価の物差しまで含めた研究計画へと変わってきました。LLM の探索の偏りは、「いろいろなデータを使って」と頼むだけでは直りませんでした。どの列を見せるか、そして何日後のリターンで良し悪しを決めるか。この両方を人が設計する必要がある、というのがこの 3 か月の結論です。第3段階がうまくいくかどうかは、結果が出たらまた書きます。
※ この記事は個人の研究・開発の記録で、特定の投資を勧めるものではありません。