決算ビートモニタリングを13→20銘柄へ拡張し、3区分の親子構造へ作り替えた
朝に画面を開いたら、モニタリング中の銘柄が13個並んでいた。半導体とソフトウェアが入り混じったカードの列を見て、「これはもう銘柄を足すだけじゃ追いつかない、棚の組み方ごと変えるタイミングだ」と判断した。一日かけて20銘柄まで広げ、見出しの軸を「セクター」から「モニタリング区分」へ丸ごとひっくり返した。
やったこと(全体像)
- 銘柄を 13 → 20 へ拡張した
- DELL を8四半期分(Q2 FY25〜Q1 FY27)新規作成し、ServiceNow(NOW) と SNDK / INTC / STX / WDC / AMD を追加した
- 表示構造を「セクター大見出し」から「区分(tier)大見出し+セクターはカード内タグ」へ逆転させた
- 途中で DELL がインデックスから消える事故、新規5銘柄が dev で 404 になる事象を踏んだ
DELL を8四半期分まるごと組む
きっかけは Q1 FY27 の決算で、売上 43.8B(+88%)・非GAAP EPS 4.86(+64%ビート)・通年ガイドを 140B→167B へ上方修正という桁違いの数字を見たことだった。これは継続観察に入れるべきだと決めて、過去8四半期(Q2 FY25〜Q1 FY27)を一気に組ませた。
このページに銘柄を足す作業は、毎回この3点セットで決まっている。
app/data/tripleBeat/{TICKER}.jsonを新規作成(四半期データ本体)tickerMeta.tsにエントリ登録(区分・セクター・概算時価総額)summaries.tsを再生成(インデックス用のサマリ)
数値は SEC の 8-K 一次情報を中心に裏取りさせた。Q1 FY27 だけは「翌日終値」がまだ確定していなかった。朝の時点で米国は 5/28 の時間外取引中で、5/29 通常取引の終値が存在しない。いったん時間外値 $439.67(+38.7%、5/28 19:46 EDT時点)を暫定値として入れ、注記に「暫定」と書き残しておいた。
5社は5つのリサーチエージェントを並列で走らせた
SNDK / INTC / STX / WDC / AMD の5社は互いに独立している。「サンディスクは構造転換済みだと思うが、他はそこまでガイダンスが良かったか確認できていない」という疑問もあったので、確認も兼ねて5つのリサーチエージェントを並列起動し、各社の決算履歴を分担して調べさせた。
精度が命なので、指示には2つの縛りを入れた。
- 各数値にソースを付けること
- 見つからない値は推測せず
n/aにすること
返ってきた結論はこうだった。
- SNDK / STX / WDC → ガイダンスが実際に大幅ビート&レイズ。構造転換は数字で裏付けが取れた
- INTC → 株価は2026 YTDで大きく伸びているが、ガイダンスのビートは直近1回のみ。期待先行と判断し「継続ウォッチ」へ
後日、SNDK のアナリスト予想が単一ソース依存で怪しい箇所が見つかり、x-search で複数ソースから取り直した。Q1 FY26 の EPS 予想だけが既存データ 0.58(MarketBeat)に対しX投稿群が予想 0.88 を示唆し、2倍近く乖離していた。複数の高品質ソース(FactSet 明示)で決着させ、旧データ 0.58 は誤りで 0.88 が正しいと確定して直した。「1ソースだけで数字を置くと事故る」を地で踏んだ。
株式分割への対応
ServiceNow(NOW) は2025年12月に5対1の株式分割を実施している。EPS も株価も、分割前の四半期は実値÷5 にして全期間を分割調整後ベースに統一した。ここは新しく作った仕組みではなく、先に NVDA で10対1分割を入れたときの前例にそのまま揃えた。
epsLabel/stockLabelに「分割調整後」を明記するtableNotesに分割の事実と「率(ビート率・YoY・騰落率)は分割の影響を受けない」を注記する
前例があると、こういう例外処理を毎回ゼロから悩まずに済む。
表示構造の親子逆転リファクタ
これが今日の本丸だった。これまでは「セクター」が大見出しで、その下に銘柄カードが並んでいた。半導体だけで GPU・光通信・メモリ・CPU と分かれていて、見出しがどんどん細かくなる。一方で本当に見たいのは「この銘柄は構造転換まで行ったのか、まだビート継続の途中なのか、それとも様子見か」という温度感だった。
そこでデータモデルに区分(tier)を足し、見出しの軸を入れ替えた。
export const TIER_LIST = [
{ name: '構造転換済み', note: 'AIインフラの本命' },
{ name: 'ビート継続・成長期待', note: '' },
{ name: '継続ウォッチ', note: 'ビート鈍化・様子見' },
] as const
index.vue 側は「区分でグルーピングし、各区分の中はセクター順 → 時価総額降順で並べる」computed に書き換えた。セクターは大見出しから降格させ、各カードの中のタグ(バッジ)として残した。CSS も .sector-* を .tier-* へ書き換えた。同じセクターのカードが隣り合うように2段階ソートにしてあるので、降格してもセクターのまとまりは視覚的に保てている。
最終的な区分はこうなった。
- 構造転換済み(9): NVDA / AMD / MU / ALAB / CRDO / SNDK / STX / WDC / DELL
- 継続ウォッチ: INTC / 4062 / SMCI / APP / NOW ほか
踏んだ事故と切り分け
DELL がインデックスから消えた
tier を導入して tickerMeta.ts を再構成した際、DELL のエントリが丸ごと消えていた。インデックスは TICKER_META を回して銘柄を並べる作りなので、メタに無い銘柄は黙って表示されなくなる。「Dell 入れたはずなのに出ない」と気づいて grep したら tickerMeta に DELL が引っかからず、再構成のときに落ちたのが原因だと特定できた。構造転換済み区分へ再追加して復活させた。リストを手で組み直すと、こういう取りこぼしが起きる。
AMD だけ EPS ガイダンスが null
AMD は会社が次Q EPS ガイドを出さない方針で、guidance.eps が null という既存銘柄に無いパターンだった。テーブルのコンポーネントを確認すると、hasEpsGuidance が四半期の guidance.eps を見て false になり、「次Q EPSガイダンスを公表していない」という注記行に切り替わる作りになっていた。実際に AMD ページを開いて、その注記行が出ていることを目で確認した。consensus: "n/a" や beatPct: null も optional chaining で安全に描画されていた。
新規5銘柄が dev で 404
JSON は正しくパースされ配置も合っているのに、新規5銘柄のページだけ 404 を返した。既存銘柄は 200 で、ファイル内容も検証済み。ここで「データの問題ではない」と切り分けられた。原因は dev サーバーの Vite が import.meta.glob を再スキャンしていなかったこと。loader.ts は import.meta.glob('./*.json') で銘柄を自動 discovery するが、ファイルを足しても glob のキャッシュが更新されず、新規分が見えていなかった。loader.ts に HMR トリガーを与えて glob を再評価させたら、5銘柄すべて 200 になった。
学び
- 銘柄が増えてカードが横に伸びてきたら、見出しの軸そのものを疑う。今回は「セクター → 区分」へ逆転させたら、見たい温度感が一目で分かるようになった
- リストを手で組み直すリファクタは、既存エントリが黙って消える。DELL 消失は grep で一発だったが、表示が消えるだけでエラーは出ないので気づきにくい
- データが正しいのにページが 404 のときは、まず「ビルドツールが新ファイルを認識しているか」を疑う。
import.meta.globは黙ってキャッシュを返す - 数値は1ソースで置かない。SNDK の
0.58 →0.88 は、複数ソースで突き合わせなければ間違ったまま公開していた
明日以降やること
- DELL Q1 FY27 の翌日終値を、5/29 の通常取引終値が確定したら暫定値から差し替える
-
import.meta.globの再スキャン対応を、新銘柄追加のたびに HMR で踏まないか手順として残すか検討する