開発financial-data

決算ビート監視ページ(beat-monitoring)に、AI・電力インフラ系の米国株を6銘柄まとめて追加した。AVGO(ブロードコム)、GLW(コーニング)、MRVL(マーベル)、VRT(ヴァーティブ)、ETN(イートン)、PWR(クアンタ)。一日かけて入れ終えたが、肝は「銘柄追加の単純作業」ではなく、過去のアナリスト予想がKoyfinで取れない四半期をどう埋めるかだった。結論から言うと、決算系インフルエンサーのX投稿から拾った。その試行錯誤を残しておく。

/add-ticker をスラッシュコマンドに切り出すところから

最初は単純な疑問だった。「ブロードコムを追加したいけど、この手順ってスキルになってたっけ?」。調べさせたら、銘柄追加はスキルにもスラッシュコマンドにもなっていなかった。手順は過去記事に文章で残っているだけで、しかも一部は陳腐化していた(参照しているファイルパスが古い)。

そこで /add-ticker という新規スラッシュコマンドに切り出させた。第1引数に追加対象のティッカー(大文字)、第2引数にtier、第3引数にセクターを渡す形。tierとセクターは省略すればリサーチ結果から確定させる。これでAVGO以降の追加が、毎回ゼロから手順を思い出さずに済むようになった。

データ構造はシンプルで、app/data/tripleBeat/ に銘柄ごとのJSONを1本置き、tickerMeta.ts(tier・セクター・時価総額)に1行足し、summaries.ts を再生成し、Koyfin→Turso経由でバリュエーション(株価・フォワードPER)を入れる。tierは「構造転換済み」「ビート継続・成長期待」「継続ウォッチ」の3区分ある。

AVGO追加で詰まった4つの罠

最初のAVGO(ブロードコム)追加が、いちばん指示の迷いが出た。ここで踏んだ罠が、そのあとの5銘柄を楽にしてくれた。

1つめ。Koyfinの銘柄IDが検索で引けない。 バリュエーション取り込みにはKoyfin内部の銘柄ID(KID)が要るが、検索APIに {query} だけ投げても0件しか返ってこない。searchStringcategoriesdomainsprimaryOnly の全フィールドを揃えて初めてAVGOのKIDが解決できた。

2つめ。バリュエーション再生成が既存銘柄の株価を巻き込んで消した。 valuation.ts を再生成したら、NVDA・MU・SNDKの株価がnullになってテストが3件落ちた。原因は、日次の /check-earnings がアナリスト予想だけ(株価なし)でTursoにスナップショットを作っていて、再生成がその「最新だけど株価が空の行」を引いて上書きしてしまったこと。3銘柄を株価込みで取り直して緑に戻した。

3つめ。tier判断とテストの連動。 AVGOを最初「構造転換済み」に入れたら、gaapValuation.test.ts が「構造転換済みの銘柄はGAAP散布図データ必須」と弾いてきた。ここで立ち止まって考えた。ブロードコムは売上もガイダンスも強いが、まだ構造転換と断じるには早い。「ビート継続・成長期待」に置くのが実態に合う。tierを移したら、GAAPデータが不要になってテストも自然に緑になった。

4つめ。コミットの範囲。 別セッションでAVGO本体の作業が並行していたので、/add-ticker のコマンド本体とメモだけをステージしてコミットした。git add -A で全部巻き込みかけて、AVGO成果物に触れる手前で止めた。並行作業がある日は、対象ファイルを明示してコミットするに限る。

AVGOが終わったあと、ここで踏んだ罠を全部 /add-ticker の指示書に書き戻させた。KID検索の正しいbody、構造転換済みtierではGAAPが必須なこと、株価巻き込みnullの注意。指示が複雑で迷ったところを、次の自分が迷わないように潰しておく作業だ。

最大の難所 — Koyfinで取れない過去のアナリスト予想

GLW(コーニング)を追加していて、ユーザー(自分)が画面を見て気づいた。「アナリスト予想が一切入ってないんですけど」。

ここがこの日いちばん粘ったところ。決算ビートを見るには、**その四半期発表当時のアナリスト予想(コンセンサス)**が要る。実績がいくらで予想がいくら、だから何%ビートした、という形だ。ところがKoyfinから取れるのは「現在の予想」であって、過去のある時点の予想は履歴として残っていない。GLWの何四半期かが、コンセンサス欄が空のままだった。

そこで /add-ticker のリサーチ規律を書き換えた。「当時のpoint-in-timeコンセンサスは、Koyfinの履歴推定をやめてXサーチ(Grok経由のX検索)で取る」。決算インフルエンサーが発表直後に「売上 X.XXB vs X.XX Est」と書いている投稿を拾い、その中央値・平均を当時のコンセンサスとして使う方針だ。

実際にXサーチをかけたら、これが効いた。@wallstengine の「Est.」表記と @TheValueist のBloomberg転載が、当時の予想数値をちゃんと持っていた。GLWの5四半期のうち4つは、X投稿から実績コンセンサスと次Qガイドのコンセンサスを埋められた。自分が手で入れていた値より、X投稿引用のほうが精度が高い箇所もあった(売上コンセンサスが3.83B→3.86Bなど、小数点以下が動いた)。

取れなかった四半期もあった

ただし全部は埋まらなかった。GLWの2025年Q4(2026年1月28日発表)だけは、次Q(Q1 2026)の事前コンセンサス数値がX上に存在しなかった

これは何度も確認した。最初アカウントを名指しで引いて出ず、次に名指しを外して全体検索し、期間も1月下旬〜2月中旬まで広げた。計4回サーチした。結果、@finsquawk_@wallstengine も、Q1のガイドは「4.2-4.3B / 0.66-0.70」とレンジで書くだけで、いつもの「vs X est」が付いていなかった。Q4の「実績」コンセンサス(4.36B / $0.70)は取れていて入っている。ないのは「次Qガイドの対コンセンサス」だけ。

途中で「ガイダンス出てるなら予想もあったはずでは」と自分が混乱した。整理すると、1月28日の発表に出てくる「予想」は2種類ある。Q4実績に対する予想と、会社が出したQ1 2026ガイド(EPS 4.25付近)に対するアナリストの事前予想。前者は取れて入っている。後者だけがX上に数値で書かれていなかった。捏造を避けてn/aのまま残した。「取れるはずのものが取れない」ときは、無理に埋めず空けておく。

MRVL — ビート幅が小さい銘柄をどのtierに置くか

MRVL(マーベル)のビート幅を見て判断した。2桁%のビートではない。売上もEPSも予想を上回ってはいるが、幅が小さい。これは構造転換というより「ビート継続・成長期待」だな、と。

このカテゴリに入る銘柄は、まだフォワードPERが高いという共通点がある。成長期待が株価に乗っているが、決算が評価軸を切り替えるほどのサプライズは出していない、という段階。MRVLもそこに置いた。GLWも同じ理由(2桁ビートなし)で「ビート継続・成長期待」のまま動かさなかった。tierは数字の大小だけでなく、ビートの幅と株価の織り込み具合を合わせて決めている。

VRT・ETN・PWR — 通年ガイダンス銘柄の描画とXサーチ補完

VRT・ETN・PWRの3銘柄は前セッションからの引き継ぎメモ(memo/2026-06-01/add-ticker-vrt-etn-pwr-handoff.md)を読んで継続した。この3社は12月決算で、次Qではなく通年ガイダンス主体。ここで表示の問題にぶつかった。

テーブルは次Qのガイダンス(guidance.revenue / guidance.eps)しか描画していなかった。引き継ぎメモ通り「次Qレグはnull、通年を使う」にすると、テーブルのガイダンス欄が全部n/aになって表示が壊れる。そこで共有コンポーネント(TripleBeatTable.vue[ticker].vue)に、既存銘柄に影響しない通年フォールバック分岐を足した。DELL(次Q+通年の両方を持つ既存銘柄)が従来通り描画されることを確認してから入れた。

そしてここでまたやらかした。3銘柄を入れ終えて目視確認したら、通年ガイダンスのコンセンサスが空。Xサーチを飛ばして、通常のWeb検索で「見つからない→n/a」と処理していた。GLWで決めた「コンセンサスはXサーチで取る」というルールを、自分で飛ばしていた。やり直してXサーチをかけたら、全14ポイント中10点が実データで埋まった。残り4点だけ信頼できる値が取れずn/a。VRTのFY26(株価+24.5%の最重要点)も @wallstengine の「Est.」できれいに取れた。

途中、PowerShellのcp932でen-dash(–)がエンコードできずに抽出スクリプトが落ちたり、正規表現が小数点で切れて数字が欠けたりした。PYTHONIOENCODING=utf-8 を付け、最後はXサーチのanswer全文を出して数値を目で拾った。コンセンサスの数字は記事の肝なので、ここは雑に正規表現任せにしない。

成果物とテスト

  • app/data/tripleBeat/ にJSONを6本追加: AVGO・GLW・MRVL・VRT・ETN・PWR
  • tickerMeta.ts に6行、新セクター「光部材/コネクティビティ」「電力インフラ」を追加
  • valuation.ts / gaapValuation.ts / summaries.ts を再生成
  • 共有コンポーネント TripleBeatTable.vuebeat-monitoring/[ticker].vue に通年ガイダンスのフォールバック分岐
  • テスト追加: tests/gaapValuation.test.tstests/triple-beat-fullyear.test.ts(通年ガイドのbeatPct再計算・株価騰落率の自己計算・FYラベル整合)

テストは関連スイートを通して緑を確認した。全体スイートでは無関係な既存failure(連結精算表エンジン・OGメタタグ・コンテンツID連番など)が出るが、自分が触ったファイルを参照していないことを毎回確認してから先に進んだ。dev環境では、最初に立てた古いインスタンス(ポート3000)が import.meta.glob のキャッシュで新銘柄を404にする罠があったので、新しく立てたサーバーで描画を確認し、最後はスクリーンショットで通年ガイドチャートとテーブルを目視した。

Tursoバリュエーション(株価・フォワードPER)の取り込みは、Koyfinのログイン済みタブが手元で開いていない銘柄が残ったので、カードの株価/PERが「—」表示の状態でfollow-upに回した。壊れてはいない、degradedなだけ。作業の区切りで何度かステージング&コミットしておいた。

この日の学び

  • 過去のアナリスト予想はKoyfinに残らない。Xサーチ(決算インフルエンサー投稿)で取る。 これを /add-ticker のリサーチ規律に固定した。次回からは最初からXサーチに行く。
  • 取れないものは無理に埋めない。 GLW Q4の次Qコンセンサスは4回サーチしても出なかった。捏造せずn/aで残す。
  • tierは数字の大小だけでなく、ビート幅と株価の織り込みで決める。 2桁ビートでないMRVL・GLWは「ビート継続・成長期待」。
  • 指示書は、迷った直後に書き戻す。 AVGOで踏んだ罠を /add-ticker に反映したから、後続5銘柄が速かった。