10月初め、大学主催のクオンツ金融コンペ(CSI300 Challenge 2026)に参加した。CSI300の構成銘柄300銘柄に毎日スコアをつけ、順位づけの精度を競う大会だ。クオンツコンペの経験はまったくなかったので、AIアシスタントに頼るしかなかった。私が要望を出し、判断し、問い直す。課題の読み解きから学習、提出用パッケージの作成、提出まではすべてAI任せ。いわゆるvibe codingで、その過程で私も必要な知識を学んでいった。前半はCodexを使ったが、成績は伸び悩んだ。後半にClaude Codeへ切り替えると、約20分で大会を通じて最大の改善につながる点を見つけてくれた。この記事は、私の会話ログとプロジェクト文書をもとにAIがまとめたものだ。数値もそれらの記録に基づいている。大会を終えて、何をしたのか、何を学んだのか、どこで遠回りしたのかを振り返り、最後に結果を紹介する。どんなコンペだったかWhiteboardルールは難しくない。使えるのは主催者が配布した2016〜2022年の3つのテーブル(市場データ、33個のファクター、10個のBarraスタイルファクター)だけで、外部データの持ち込みは禁止。プラットフォームが毎日、提出したpredictを呼び出し、最大120日分の過去データを渡す。こちらが300銘柄にスコアをつけると、主催者のバックテストライブラリが制約に従ってポートフォリオを組む。総合スコアはRankIC(毎日のスコアとその後のリターンとの順位相関)が70%、IR(ベンチマークに対する超過リターンをトラッキングエラーで割った値)が30%を占める。ランキングには公開順位と非公開順位があり、それぞれ異なる未公開の期間で評価される。非公開順位に使われるのは最後の提出だけ。提出は1日3回までで、締め切りは10月14日だった。主催者による抜き打ちチェックもあり、train.pyで公開データから再学習して結果が一致しなければ、成績は無効になる。2週間の記録Whiteboard10月初め、Codexに課題を読み解いてもらった。公式PDFを3本すべて読み、「課題の確認メモ」にまとめてくれた。さらにAGENTS.mdを作らせ、方針を決めた。モデル選びは「前年までで学習し、翌年で検証する」時系列の前進検証で進め、公開順位に合わせたパラメータ調整はしない。私からは追加で、2022年は学習に使わずテスト用に残すよう指示した。これが後で間違いだったとわかる。その後の数日間はCodexを使った。実装や運用の手堅さは見事だった。実験の記録、バックテスト、パッケージ化、動作確認を重ね、最終的には実験ディレクトリが約200個、バックテストが1239回、分析文書が354本に達した。なのに成績は振るわない。初回の提出はRankIC 0.0495、IR 0.74で104人中87位。その後も目立った改善はなかった。利用枠も問題だった。1アカウントではまったく足りず、もともとCodex(ChatGPT Plus)のアカウントを2つ交互に使っていた。それでも足りないとわかり、月額100ドルのProも契約した。1〜2日間、休みなく動かしたが、まったく成果が出ず、かなりがっかりした。当時はChatGPTのモデル自体も特に遅く、出力速度(tps)の問題がさらに足を引っ張った。どうにもならず、10月9日にClaude Codeを試すことにした。公式ルールの原文と照らし合わせ、違反がないか確認してもらった。すると約20分で、公式には2016〜2022年の全データでの学習が明確に許可されており、「2022年を使わない」のは私がAGENTS.mdに書き込んだ独自の制限にすぎないと判明した。2022年を加えると、同じ手法のまま公開順位のRankICが約0.054から約0.073へ上がった。大会全体で最大の改善だった。新しい技術は何も使わず、自分で設けた制限を1つ外しただけだ。その後の学習(LightGBMとCatBoostのアンサンブル)、動作確認、最終提出用パッケージの作成は、すべてClaude Codeで済ませた。2022年を追加した後、アンサンブルの前進検証ICは0.0905〜0.0915で頭打ちになった。最後の数日間は、思いつく方向をClaude Codeに一通り試してもらったが、ほとんどは効果なしか、差し引きでマイナスだった。試したアプローチと結果(クリックして表示)モデルでは、XGBoost、dart、TabM、ランダムフォレスト、2種類のMASTER風の系列モデルを試した。アンサンブルの改善幅は0〜+0.0004。系列モデル単体のICはわずか0.06で、GBDTは約0.085だった。特徴量では、関連銘柄、ストップ高・ストップ安、業績更新イベント、長い参照期間、3万5000個のランダムな式によるファクターの自動探索を試した。単体モデルの成績は横ばいか悪化だった。学習方法では、約100回のハイパーパラメータ実験、複数シードの平均、分散度に応じた重みづけを試した。アンサンブルの改善は+0.0002〜+0.0005で、ノイズの範囲だった。ポートフォリオ構築では、EMAによる平滑化、前日に採用した銘柄への加点、低ボラティリティ銘柄への傾斜、業種中立化、大まかなビン分割、関連銘柄間のスコア平滑化を試した。ICとIRの一方が上がるともう一方が下がり、総合スコアに換算すると横ばいかマイナスだった。Warning途中には、実はリークだった「改善」も2件あり、どちらもAIが自分で見つけた。GRUを組み合わせた際の「+0.0025」は、テスト期間を含む全サンプルの平均を使っていたためだった。また、データの「名称」列は最新の銘柄名なので、そこからST指定の有無を推定すると将来情報の参照になる。この列は処理パイプラインでは一度も使っていない。提出まわりでもいくつかあった。約52 MBの大きなパッケージでは、計3回「judger stopped responding」と出たが、同じファイルを再提出すると通った。23 MB以下の小さなパッケージは一度も失敗しなかった。変化の遅いシグナルの比率を30%と60%にしたテスト用パッケージもAIに作らせ、判定基準は提出前に決めておいた。60%は明らかに悪化(IRが0.94低下)、30%は横ばいで、元のパッケージがすでに最適点だったと結論づけた。忘れてはいけないのは、非公開順位は最後の提出だけで決まるため、テスト後には堅実なパッケージをもう一度提出して最後にしておく必要がある点だ。また、チャットグループでは、predict内で参照期間中にすでに確定したリターンを使い、閉形式のリッジ回帰をその場で計算する案が出た。AIはガイドラインを文面どおりに解釈し、これは「評価段階での再fit」に当たるとして、先に書面で確認を取るよう勧めた。オフラインでの改善も小さく(組み合わせても最大+0.0005)、結局採用しなかった。大会終了後、まずディスクを整理した。再生成できる中間ファイルを削除し、プロジェクトは67 GBから26 GBになった。再現に必要なコード、設定、予測結果は残してある。その後、優勝者が公開したコード(CSI300-Challenge-2026)を読み、自分たちとの違いを一つずつ確認した。成績と差がついたところ私の公開順位はRankIC 0.0773、IR 2.58で153人中41位。非公開順位はRankIC 0.0708、IR 4.37で90人中11位だった。優勝者の非公開順位の成績はRankIC 0.0825、IR 5.21。両ランキングは人数が違うので順位を直接比較はできないが、覚えておきたいことが3つある。まず、差がついたのはIRではなくRankICだった。非公開順位での私と優勝者の総合スコア差は0.145。その約83%がRankICによるもので、IRは約17%にすぎなかった。それなのに私はIRを上げる工夫に多くの労力を割いていた。公開順位のIRはノイズが大きい。私のIRは2.58から4.37に上がり、優勝者は5.57から5.21に下がった。他の参加者も、両ランキングの間で数ポイント動くことが珍しくなかった。Whiteboard次に、ローカルでは負けておらず、差は「期間が変わるとどれだけ落ちるか」にあった。ローカル検証のRankICは私が約0.092、優勝者が0.0887で、私のほうが低いわけではなかった。ところが公開順位から非公開順位に移ると、私は約8.4%低下したのに対し、優勝者は約2.9%しか低下しなかった。Whiteboardそして、ローカル検証の見積もりは実際と合っていた。学習の終了時点を1年、2年前にずらした、学習と評価の間隔が長いテストでは、予測ICがそれぞれ約0.077と0.069だった。実際は公開順位で0.0773、非公開順位で0.0708と、おおむね一致している。公開順位ではなく、この検証でモデルを選ぶ方針は間違っていなかった。やりながら学んだことクオンツの基礎知識はほぼなかったので、学び方は単純だった。AIにやってもらい、その後でしつこく質問する。結論が出るたびに「なぜ?」「過学習では?」「公開順位と非公開順位は似ているの?」と聞く。AIがデータで答えたら、別のアシスタントに検証してもらう。そうするうちに、いくつかのことが大まかにわかってきた。モデルの良し悪しをどう判断するか。ローカルでは前進検証を使う。前年までで学習し、翌年で検証する。学習に使った年でスコアを出してはいけない。公開順位は照合用にとどめる。ノイズが大きいからだ。AIの推定では、公開順位で使われる短い期間の標準誤差はRankICで約±0.01、IRで約±1.4。数ポイントの差が実力なのか運なのかは区別できない。何度も提出して最も高い結果を選ぶ人は、さらに選択効果で成績が上振れする。「改善」が本物かどうかをどう判断するか。改善があったら、まず将来情報を見ていないか疑う。大会中の2件のリークも、そうして見つかった。さらに一歩進めて、別の期間でも通用するかを見る。非公開順位はもっと後の別期間のデータで決まり、モデルはもう更新されない。だから、ローカルのスコアよりも、学習と評価の間隔を空けたテストでの低下のほうが重要になる。こうした理解は主にAIの説明と今回の実験結果から得たもので、体系的に学んだわけではない。細部にはまだ不正確なところがあるかもしれない。1つのサービスに頼り切らず、同種のサービスなら大差ないとも思い込まないこと。以前はChatGPT Plusと同種のサブスクリプションに大差はなく、ChatGPTだけで十分だと思っていた。今回の体感はまったく違った。Codexでは、20ドルのPlusはこのような高負荷の使い方にはほとんど足りず、2アカウントを交互に使っても不足した。100ドルのProを契約して1〜2日連続で動かしても成果は出なかった。一方、Claude Codeでは20ドルのProしか使わなかったのに、利用枠はあの100ドルのProとほぼ変わらず、速くて的確だった。これはあくまで今回の使用感で、モデルもプランも変わり続けている。それでも、行き詰まったら1つのツールに固執せず、いくつか乗り換えて試すべきだとわかった。振り返りまず、うまくできた点から。モデル選びは公開順位に頼らず、前進検証、1年を丸ごと除外する交差検証、学習と評価の間隔を空けたテストという3段階で進めた。「改善」があれば必ずテスト期間をのぞいていないか確認し、2件のリークもそこで見つけた。テスト用パッケージの判定基準は事前に書き、最終パッケージもあらかじめ決め、公開順位をよく見せるために変更することはなかった。train.pyはローカルで独立に再実行し、抽出した日の予測値がすべて一致することも確認した。自分で設けた制限が、公式ルールより厳しかった。「2022年を学習に使わない」と決めたせいで、Codexを使っていた間はずっとその前提で実験を続け、最大の改善を得るのが何日も遅れた。発見時にもAGENTS.mdにはその記述が残っていて、新しいセッションでは再び2022年が除外される状態だった。次回は、独自ルールには理由と解除条件を明記し、数日おきに公式原文と照合して見直す。認められているものは使う。ローカルのバックテストがプラットフォームと揃っていなかった。Codex側のバックテストは初期の代用設定のままで、保有銘柄数、制約、コストが公式とは違っていた。そのため算出したIRはプラットフォームと比較できなかった。大会後に優勝者のコードを見て、初めて気づいた。優勝者のIRはローカルで約5.2、公開順位で5.57、非公開順位で5.21と整合していた。公式サンプルの制約とコストをそのままローカルのバックテストに取り込んでいたからだ。次回は最初の1週間で評価環境を再現し、ローカルのIRがプラットフォームと合うまではIRの最適化をしない。頭打ちになった方向で派生案を増やし、力の入れどころも間違えていた。100近い派生案も100回以上のハイパーパラメータ実験も、効果はノイズの範囲だった。平滑化、ヒステリシス帯、大まかなビン分割、中立化といったIR向けの工夫も、総合スコアでは横ばいかマイナスだった。本当の差は、サンプル外でRankICがどれだけ落ちるかにあった。優勝者に効いていたのは別のアプローチだ。ファクターネットワークを凍結したうえで、似たスタイルを持つ近傍銘柄の間で相対的な強弱を学習する。さらに、直近20個の確定済みラベルから、その場で閉形式の補正を計算する。どちらも「期間の変化」を意識した設計だった。次回はサンプル外での低下を主指標にし、間隔を空けた検証を定例化する。各方向に使う予算を決め、何回か続けて改善がなければ別の方向に切り替える。ルールの補足説明を追う役がいなかった。私たちは閉形式のリッジ回帰を見送ったが、優勝者は主催者の補足説明を引用して採用し、ローカルのRankICを約+0.004改善していた。非公開順位でどれだけ効いたかはわからないが、情報の差で逃した機会だった。次回は公式グループと公式サイトを毎日確認し、口頭の説明は書面にしてもらう。判断がつかないものも、まずオフラインで改善幅を測る。実装・運用面にも2つのリスクが残った。52 MBの大きなパッケージでは、プラットフォーム上で3回失敗した。非公開順位の評価時に一時的な障害と重なれば、影響は最も大きい。最終パッケージはもっと小さくし、軽量な予備パッケージも事前に用意すべきだった。AGENTS.mdも約80 KBまで膨らんでいた。新しいセッションのたびにまずこれを読むので、コンテキストを消費するうえ、古い条項に引きずられやすい。有効な条項だけを残すべきだ。Tip3つだけ覚えておくなら、まず評価条件を再現すること。自分で設けた制限は公式原文と照合して見直すこと。そして、「期間が変わってもスコアを落とさない」ことに力を注ぐことだ。Vibe Codingについてこの2週間、私が主にしていたのは、要望を出し、判断し、疑問をぶつけることだった。「なぜそれをやらないの?」「順位がまだ低いけど、どうする?」「上位の人たちは過学習しているのでは?」。それ以外はすべてAIがやっていた。今回のコンペでは、CodexとClaude Codeの働き方に明確な違いがあった。Codexは実装や運用が堅実だったが、私の書いたルールを守り続け、「2022年を使わない」という制限を問い直さなかった。Claude Codeは先に公式原文を読み、私の独自制限と照合して、すぐに問題の核心を見つけた。もちろん、これは1回のコンペでの経験にすぎない。引き継いだ段階も、プロンプトも、コンテキストも違うので、両ツールについての一般的な結論にはできない。確実に言えるのは、同じ問題でも別の目で見て、公式原文と照らして再点検するほうが、その場で実験を増やし続けるよりはるかに低コストだということだ。全体として、AIは大量の作業をこなすことと、決めた手順を守ることが得意だ。大量の実験、リークの点検、判定基準の事前作成、再現性の確認をこなし、自分で誤りを直すこともある。一方、誰かに促されずに方向を変えるのは苦手で、慣れた系統のモデルの微調整にとどまりやすい。ルールの解釈は保守的で、提示する確率も大まかな目安にしかならない。進む方向、ルールのグレーゾーンに踏み込むか、いつ見切りをつけるか、「公開順位ばかり追わない」といった判断は、やはり人が担う必要がある。アシスタントを1つ、レビューとルール確認の専任にするのも有効だ。最大の改善点は、まさにそうして見つかった。最大の改善は自分で設けた制限を外したことで生まれ、考え方が最も大きく変わったのは大会後に非公開順位を見たときだった。本当の差はサンプル外のRankICの頑健性にあり、私が多くの労力を注いだIRの工夫にはなかった。未経験者の私にとって、このコンペで最大の収穫は、結果が本物かどうかを問い直す習慣がついたことだ。将来情報を見ていないか。期間が変わっても通用するか。実力なのか、それとも公開順位での運なのか。次回はまず評価条件を揃え、ルールをしっかり追い、「期間が変わってもスコアを落とさない」ことに力を注ぎたい。最後に結果を大会には、情報学部の学生、大学1年生、情報学部以外の学生という3つの部門があった。私は情報学部以外の学生部門で、非公開順位の総合では90人中11位、部門内では2位となり、賞金200元をもらった。部門1位の人は、総合の非公開順位でも私の1つ上だった。情報学部の学生にはかなわないが、総合の非公開順位では大学1年生全員より上だった。正直、運はよかった。公開順位ではそれほど上位ではなく、非公開順位でようやく上がってきた。前に書いたとおり、公開順位はノイズが大きいので、そこには運の要素もある。それ以上に驚いたのはAIの力だ。クオンツコンペの経験がまったくない人間でも、AIを頼れば同じランキングの参加者と競えるものを作れ、その過程で多くを学べた。賞金は多くないが、とても意味のある経験だった。
10月初め、大学主催のクオンツ金融コンペ(CSI300 Challenge 2026)に参加した。CSI300の構成銘柄300銘柄に毎日スコアをつけ、順位づけの精度を競う大会だ。クオンツコンペの経験はまったくなかったので、AIアシスタントに頼るしかなかった。私が要望を出し、判断し、問い直す。課題の読み解きから学習、提出用パッケージの作成、提出まではすべてAI任せ。いわゆるvibe codingで、その過程で私も必要な知識を学んでいった。前半はCodexを使ったが、成績は伸び悩んだ。後半にClaude Codeへ切り替えると、約20分で大会を通じて最大の改善につながる点を見つけてくれた。
この記事は、私の会話ログとプロジェクト文書をもとにAIがまとめたものだ。数値もそれらの記録に基づいている。大会を終えて、何をしたのか、何を学んだのか、どこで遠回りしたのかを振り返り、最後に結果を紹介する。
どんなコンペだったか
ルールは難しくない。使えるのは主催者が配布した2016〜2022年の3つのテーブル(市場データ、33個のファクター、10個のBarraスタイルファクター)だけで、外部データの持ち込みは禁止。プラットフォームが毎日、提出したpredictを呼び出し、最大120日分の過去データを渡す。こちらが300銘柄にスコアをつけると、主催者のバックテストライブラリが制約に従ってポートフォリオを組む。総合スコアはRankIC(毎日のスコアとその後のリターンとの順位相関)が70%、IR(ベンチマークに対する超過リターンをトラッキングエラーで割った値)が30%を占める。
ランキングには公開順位と非公開順位があり、それぞれ異なる未公開の期間で評価される。非公開順位に使われるのは最後の提出だけ。提出は1日3回までで、締め切りは10月14日だった。主催者による抜き打ちチェックもあり、train.pyで公開データから再学習して結果が一致しなければ、成績は無効になる。
2週間の記録
10月初め、Codexに課題を読み解いてもらった。公式PDFを3本すべて読み、「課題の確認メモ」にまとめてくれた。さらにAGENTS.mdを作らせ、方針を決めた。モデル選びは「前年までで学習し、翌年で検証する」時系列の前進検証で進め、公開順位に合わせたパラメータ調整はしない。私からは追加で、2022年は学習に使わずテスト用に残すよう指示した。これが後で間違いだったとわかる。
その後の数日間はCodexを使った。実装や運用の手堅さは見事だった。実験の記録、バックテスト、パッケージ化、動作確認を重ね、最終的には実験ディレクトリが約200個、バックテストが1239回、分析文書が354本に達した。なのに成績は振るわない。初回の提出はRankIC 0.0495、IR 0.74で104人中87位。その後も目立った改善はなかった。
利用枠も問題だった。1アカウントではまったく足りず、もともとCodex(ChatGPT Plus)のアカウントを2つ交互に使っていた。それでも足りないとわかり、月額100ドルのProも契約した。1〜2日間、休みなく動かしたが、まったく成果が出ず、かなりがっかりした。当時はChatGPTのモデル自体も特に遅く、出力速度(tps)の問題がさらに足を引っ張った。
どうにもならず、10月9日にClaude Codeを試すことにした。公式ルールの原文と照らし合わせ、違反がないか確認してもらった。すると約20分で、公式には2016〜2022年の全データでの学習が明確に許可されており、「2022年を使わない」のは私がAGENTS.mdに書き込んだ独自の制限にすぎないと判明した。2022年を加えると、同じ手法のまま公開順位のRankICが約0.054から約0.073へ上がった。大会全体で最大の改善だった。新しい技術は何も使わず、自分で設けた制限を1つ外しただけだ。その後の学習(LightGBMとCatBoostのアンサンブル)、動作確認、最終提出用パッケージの作成は、すべてClaude Codeで済ませた。
2022年を追加した後、アンサンブルの前進検証ICは0.0905〜0.0915で頭打ちになった。最後の数日間は、思いつく方向をClaude Codeに一通り試してもらったが、ほとんどは効果なしか、差し引きでマイナスだった。
試したアプローチと結果(クリックして表示)
途中には、実はリークだった「改善」も2件あり、どちらもAIが自分で見つけた。GRUを組み合わせた際の「+0.0025」は、テスト期間を含む全サンプルの平均を使っていたためだった。また、データの「名称」列は最新の銘柄名なので、そこからST指定の有無を推定すると将来情報の参照になる。この列は処理パイプラインでは一度も使っていない。
提出まわりでもいくつかあった。約52 MBの大きなパッケージでは、計3回「judger stopped responding」と出たが、同じファイルを再提出すると通った。23 MB以下の小さなパッケージは一度も失敗しなかった。変化の遅いシグナルの比率を30%と60%にしたテスト用パッケージもAIに作らせ、判定基準は提出前に決めておいた。60%は明らかに悪化(IRが0.94低下)、30%は横ばいで、元のパッケージがすでに最適点だったと結論づけた。忘れてはいけないのは、非公開順位は最後の提出だけで決まるため、テスト後には堅実なパッケージをもう一度提出して最後にしておく必要がある点だ。また、チャットグループでは、predict内で参照期間中にすでに確定したリターンを使い、閉形式のリッジ回帰をその場で計算する案が出た。AIはガイドラインを文面どおりに解釈し、これは「評価段階での再fit」に当たるとして、先に書面で確認を取るよう勧めた。オフラインでの改善も小さく(組み合わせても最大+0.0005)、結局採用しなかった。
大会終了後、まずディスクを整理した。再生成できる中間ファイルを削除し、プロジェクトは67 GBから26 GBになった。再現に必要なコード、設定、予測結果は残してある。その後、優勝者が公開したコード(CSI300-Challenge-2026)を読み、自分たちとの違いを一つずつ確認した。
成績と差がついたところ
私の公開順位はRankIC 0.0773、IR 2.58で153人中41位。非公開順位はRankIC 0.0708、IR 4.37で90人中11位だった。優勝者の非公開順位の成績はRankIC 0.0825、IR 5.21。両ランキングは人数が違うので順位を直接比較はできないが、覚えておきたいことが3つある。
まず、差がついたのはIRではなくRankICだった。非公開順位での私と優勝者の総合スコア差は0.145。その約83%がRankICによるもので、IRは約17%にすぎなかった。それなのに私はIRを上げる工夫に多くの労力を割いていた。公開順位のIRはノイズが大きい。私のIRは2.58から4.37に上がり、優勝者は5.57から5.21に下がった。他の参加者も、両ランキングの間で数ポイント動くことが珍しくなかった。
次に、ローカルでは負けておらず、差は「期間が変わるとどれだけ落ちるか」にあった。ローカル検証のRankICは私が約0.092、優勝者が0.0887で、私のほうが低いわけではなかった。ところが公開順位から非公開順位に移ると、私は約8.4%低下したのに対し、優勝者は約2.9%しか低下しなかった。
そして、ローカル検証の見積もりは実際と合っていた。学習の終了時点を1年、2年前にずらした、学習と評価の間隔が長いテストでは、予測ICがそれぞれ約0.077と0.069だった。実際は公開順位で0.0773、非公開順位で0.0708と、おおむね一致している。公開順位ではなく、この検証でモデルを選ぶ方針は間違っていなかった。
やりながら学んだこと
クオンツの基礎知識はほぼなかったので、学び方は単純だった。AIにやってもらい、その後でしつこく質問する。結論が出るたびに「なぜ?」「過学習では?」「公開順位と非公開順位は似ているの?」と聞く。AIがデータで答えたら、別のアシスタントに検証してもらう。そうするうちに、いくつかのことが大まかにわかってきた。
モデルの良し悪しをどう判断するか。ローカルでは前進検証を使う。前年までで学習し、翌年で検証する。学習に使った年でスコアを出してはいけない。公開順位は照合用にとどめる。ノイズが大きいからだ。AIの推定では、公開順位で使われる短い期間の標準誤差はRankICで約±0.01、IRで約±1.4。数ポイントの差が実力なのか運なのかは区別できない。何度も提出して最も高い結果を選ぶ人は、さらに選択効果で成績が上振れする。
「改善」が本物かどうかをどう判断するか。改善があったら、まず将来情報を見ていないか疑う。大会中の2件のリークも、そうして見つかった。さらに一歩進めて、別の期間でも通用するかを見る。非公開順位はもっと後の別期間のデータで決まり、モデルはもう更新されない。だから、ローカルのスコアよりも、学習と評価の間隔を空けたテストでの低下のほうが重要になる。こうした理解は主にAIの説明と今回の実験結果から得たもので、体系的に学んだわけではない。細部にはまだ不正確なところがあるかもしれない。
1つのサービスに頼り切らず、同種のサービスなら大差ないとも思い込まないこと。以前はChatGPT Plusと同種のサブスクリプションに大差はなく、ChatGPTだけで十分だと思っていた。今回の体感はまったく違った。Codexでは、20ドルのPlusはこのような高負荷の使い方にはほとんど足りず、2アカウントを交互に使っても不足した。100ドルのProを契約して1〜2日連続で動かしても成果は出なかった。一方、Claude Codeでは20ドルのProしか使わなかったのに、利用枠はあの100ドルのProとほぼ変わらず、速くて的確だった。これはあくまで今回の使用感で、モデルもプランも変わり続けている。それでも、行き詰まったら1つのツールに固執せず、いくつか乗り換えて試すべきだとわかった。
振り返り
まず、うまくできた点から。モデル選びは公開順位に頼らず、前進検証、1年を丸ごと除外する交差検証、学習と評価の間隔を空けたテストという3段階で進めた。「改善」があれば必ずテスト期間をのぞいていないか確認し、2件のリークもそこで見つけた。テスト用パッケージの判定基準は事前に書き、最終パッケージもあらかじめ決め、公開順位をよく見せるために変更することはなかった。train.pyはローカルで独立に再実行し、抽出した日の予測値がすべて一致することも確認した。
自分で設けた制限が、公式ルールより厳しかった。「2022年を学習に使わない」と決めたせいで、Codexを使っていた間はずっとその前提で実験を続け、最大の改善を得るのが何日も遅れた。発見時にもAGENTS.mdにはその記述が残っていて、新しいセッションでは再び2022年が除外される状態だった。次回は、独自ルールには理由と解除条件を明記し、数日おきに公式原文と照合して見直す。認められているものは使う。
ローカルのバックテストがプラットフォームと揃っていなかった。Codex側のバックテストは初期の代用設定のままで、保有銘柄数、制約、コストが公式とは違っていた。そのため算出したIRはプラットフォームと比較できなかった。大会後に優勝者のコードを見て、初めて気づいた。優勝者のIRはローカルで約5.2、公開順位で5.57、非公開順位で5.21と整合していた。公式サンプルの制約とコストをそのままローカルのバックテストに取り込んでいたからだ。次回は最初の1週間で評価環境を再現し、ローカルのIRがプラットフォームと合うまではIRの最適化をしない。
頭打ちになった方向で派生案を増やし、力の入れどころも間違えていた。100近い派生案も100回以上のハイパーパラメータ実験も、効果はノイズの範囲だった。平滑化、ヒステリシス帯、大まかなビン分割、中立化といったIR向けの工夫も、総合スコアでは横ばいかマイナスだった。本当の差は、サンプル外でRankICがどれだけ落ちるかにあった。優勝者に効いていたのは別のアプローチだ。ファクターネットワークを凍結したうえで、似たスタイルを持つ近傍銘柄の間で相対的な強弱を学習する。さらに、直近20個の確定済みラベルから、その場で閉形式の補正を計算する。どちらも「期間の変化」を意識した設計だった。次回はサンプル外での低下を主指標にし、間隔を空けた検証を定例化する。各方向に使う予算を決め、何回か続けて改善がなければ別の方向に切り替える。
ルールの補足説明を追う役がいなかった。私たちは閉形式のリッジ回帰を見送ったが、優勝者は主催者の補足説明を引用して採用し、ローカルのRankICを約+0.004改善していた。非公開順位でどれだけ効いたかはわからないが、情報の差で逃した機会だった。次回は公式グループと公式サイトを毎日確認し、口頭の説明は書面にしてもらう。判断がつかないものも、まずオフラインで改善幅を測る。
実装・運用面にも2つのリスクが残った。52 MBの大きなパッケージでは、プラットフォーム上で3回失敗した。非公開順位の評価時に一時的な障害と重なれば、影響は最も大きい。最終パッケージはもっと小さくし、軽量な予備パッケージも事前に用意すべきだった。AGENTS.mdも約80 KBまで膨らんでいた。新しいセッションのたびにまずこれを読むので、コンテキストを消費するうえ、古い条項に引きずられやすい。有効な条項だけを残すべきだ。
3つだけ覚えておくなら、まず評価条件を再現すること。自分で設けた制限は公式原文と照合して見直すこと。そして、「期間が変わってもスコアを落とさない」ことに力を注ぐことだ。
Vibe Codingについて
この2週間、私が主にしていたのは、要望を出し、判断し、疑問をぶつけることだった。「なぜそれをやらないの?」「順位がまだ低いけど、どうする?」「上位の人たちは過学習しているのでは?」。それ以外はすべてAIがやっていた。
今回のコンペでは、CodexとClaude Codeの働き方に明確な違いがあった。Codexは実装や運用が堅実だったが、私の書いたルールを守り続け、「2022年を使わない」という制限を問い直さなかった。Claude Codeは先に公式原文を読み、私の独自制限と照合して、すぐに問題の核心を見つけた。もちろん、これは1回のコンペでの経験にすぎない。引き継いだ段階も、プロンプトも、コンテキストも違うので、両ツールについての一般的な結論にはできない。確実に言えるのは、同じ問題でも別の目で見て、公式原文と照らして再点検するほうが、その場で実験を増やし続けるよりはるかに低コストだということだ。
全体として、AIは大量の作業をこなすことと、決めた手順を守ることが得意だ。大量の実験、リークの点検、判定基準の事前作成、再現性の確認をこなし、自分で誤りを直すこともある。一方、誰かに促されずに方向を変えるのは苦手で、慣れた系統のモデルの微調整にとどまりやすい。ルールの解釈は保守的で、提示する確率も大まかな目安にしかならない。進む方向、ルールのグレーゾーンに踏み込むか、いつ見切りをつけるか、「公開順位ばかり追わない」といった判断は、やはり人が担う必要がある。アシスタントを1つ、レビューとルール確認の専任にするのも有効だ。最大の改善点は、まさにそうして見つかった。
最大の改善は自分で設けた制限を外したことで生まれ、考え方が最も大きく変わったのは大会後に非公開順位を見たときだった。本当の差はサンプル外のRankICの頑健性にあり、私が多くの労力を注いだIRの工夫にはなかった。未経験者の私にとって、このコンペで最大の収穫は、結果が本物かどうかを問い直す習慣がついたことだ。将来情報を見ていないか。期間が変わっても通用するか。実力なのか、それとも公開順位での運なのか。次回はまず評価条件を揃え、ルールをしっかり追い、「期間が変わってもスコアを落とさない」ことに力を注ぎたい。
最後に結果を
大会には、情報学部の学生、大学1年生、情報学部以外の学生という3つの部門があった。私は情報学部以外の学生部門で、非公開順位の総合では90人中11位、部門内では2位となり、賞金200元をもらった。部門1位の人は、総合の非公開順位でも私の1つ上だった。情報学部の学生にはかなわないが、総合の非公開順位では大学1年生全員より上だった。
正直、運はよかった。公開順位ではそれほど上位ではなく、非公開順位でようやく上がってきた。前に書いたとおり、公開順位はノイズが大きいので、そこには運の要素もある。それ以上に驚いたのはAIの力だ。クオンツコンペの経験がまったくない人間でも、AIを頼れば同じランキングの参加者と競えるものを作れ、その過程で多くを学べた。賞金は多くないが、とても意味のある経験だった。