• #決算
  • #beat-monitoring
  • #earnings-beat-scan
  • #Koyfin
  • #キオクシア
  • #Kioxia
開発financial-data

決算モニタリングを毎朝の自動運用へ

半導体・メモリ決算の監視基盤をずっと手で回してきたが、今朝はそれを「毎朝勝手に回る」状態まで押し上げる作業をした。あわせてキオクシアを1銘柄追加し、トップページの並びも直した。後で自分が思い出せるように、判断したことと詰まったところを書き残す。

1. earnings-beat-scan のガイダンス突合を仕組み化する

朝の /make-diary の末尾で earnings-beat-scan を回すと、過去24時間に決算を出した米国銘柄のうち「ビート&レイズ」を X サーチで拾ってくれる。今朝の窓(2026-06-02 引け後)で引っかかったのは PANW・GTLB・ULTA の3社だった。

ところが PANW の出力が Forward Guidance: raised (surprise% n/a) で止まっていた。「上方修正した」とは書いてあるが、何%上振れたのかが空欄。これでは「ビートかどうか」を自分で判断できない。

そこで Koyfin の画面を開いて、PANW(KID: eq-1kz0lb)の次四半期コンセンサスを自分の目で確認した。会社ガイダンスは EPS 0.97・売上 3.35B、Koyfin のアナリストコンセンサスは EPS 0.938・売上 3.28B。手で並べると完全に一致した。

次四半期ガイダンス
🟢 EPS:$0.97 (予想 $0.938)
🟢 売上高:$3.35B (予想 $3.28B)

つまり「会社ガイダンス vs Koyfinコンセンサスを突き合わせてビート率を出す」手続きが earnings-beat-scan のスキルにそもそも無かったのが原因。手順を足せば次回から数字で出せる。SKILL.md に Step 1.7(突合手続き)を追加し、Forward Guidance を「次四半期/通年」の2段構成にした。今朝の記事の PANW ブロックも、空欄だった surprise% を実数値に差し替えて、生きた手本として残した。

2. GitLab・Ulta Beauty も突合してみたら明暗が割れた

「次回から全部自動で回せるようにドキュメントも整えて。GitLab と Ulta Beauty もできるならやって」と頼んで、GTLB・ULTA も同じ突合をかけさせた。

ここで予想外のことが起きた。実績はビートでも、ガイダンスを突き合わせると結論が割れたのだ。

  • GTLB: 次Q売上ガイド 272-274M、通年 1.112-1.118B。Koyfinコンセンサスと突合すると微妙な水準で、手放しのレイズとは言いにくい
  • ULTA: 次Qガイダンスを会社が出しておらず、通年 売上 13.136-13.260B・EPS 28.36-28.80 のみ。突合の土俵が片方しか無い

「実績ビート」と「ガイダンス突合の判定」は別物だ、というのを画面の数字で突きつけられた。記事のサマリ表・見出し・各銘柄ブロックを、この明暗が伝わる書き方に直した。

仕組み化で効いたのは2点。Koyfin で KID が解決できなかった銘柄は X サーチのコンセンサスにフォールバックする分岐を入れたこと。そして KID 解決の検索 API のリクエスト形を SKILL.md に具体的に書いたこと。GTLB(eq-ico28x)・ULTA(eq-r1an5d)は無料プランでも estimates が 200 で取れた。これで翌朝からは突合まで含めて全自動で回る。

3. /add-ticker でキオクシアを1本追加する

別セッションで /add-ticker を使ってキオクシア(Kioxia)を beat-monitoring に追加した。これが今日いちばん手こずった。

東証銘柄という前提を最初に潰す

キオクシアは東証上場(285A、JPY建て)。SEC 8-K も CIK も持たないし、Koyfin の <TICKER>:US でも引けない。最初は「米国外だから難しいのでは」と身構えたが、直近のコミットで韓国メモリ2社(Samsung 005930・SK Hynix 000660、KRW建て)を入れた前例があったのを思い出した。さらに日本企業のイビデン(4062)も既にデータに入っている。雛形は揃っている。

Koyfin の検索 API でキオクシアを叩くと、東証メインの 285A:JP が KID HO-dcpDpY で見つかった。isLiveTicker:false だが、IPO日の 2024-12-18 から JPY 建ての全履歴が取れる(直近終値 ¥77,540)。米国OTC(KXIAY)は2025年10月以降しか無く短いので、迷わず 285A:JP を採用した。

非GAAP予想が「無い」という壁

estimates を JPY で取りに行って、ここで詰まった。Koyfin はキオクシアの非GAAP(調整後)EPS予想を持っていないfest_esteps が全期間「データなし」)。一方、valuation の ntm_epseps_adj(非GAAP)からしか計算されない設計だった。このままだとバリュエーションカードの NTM EPS とフォワードPER が「—」になる。

対処は、estimates レスポンスに GAAP予想を eps_adj として流し込むこと。これで取込は通り、price ¥77,540・NTM EPS ¥8,978.47・フォワードPER 8.64x が入った。あわせてフロントの通貨フォーマッタが USD/KRW しか対応していなかったので、韓国KRW追加のときと同じ要領で JPY(¥)対応を横展開した。

リサーチの数字を疑う

実績・会社ガイダンスのリサーチを並列で走らせたら、Q2 FY26 のガイダンスが「5,000-5,500M / 1,000-1,500M」と返ってきた。桁が明らかにおかしい。キオクシアの規模でドル建て5,000億ドルはあり得ない。

実績(売上 ¥5,436億・営業利益 ¥1,447億)と株価反応(+7.9%)に照らすと、これは**「億円」をドルに誤抽出したもの**だった。円建て ¥5,000-5,500億 / ¥1,000-1,500億 と読めば実績とビート+株価まで完全に整合する。AIが拾ってきた数字でも、自分が単位の違和感を拾わないと事故る、というのを地で行った。会社ガイダンスは円建て・Non-GAAP で入れ直した。

散布図に点が出ない

dev で確認したら、個別ページも index カードも完璧にレンダリングされた。が、散布図にキオクシアの点が出ていない

buildScatterSplitltmEps == null の銘柄を除外する。デフォルトの Non-GAAP 基準は valuation.ts を使うが、キオクシアは Koyfin に実績EPS配列が無く ltmEps が null。だから「LTM未充足」で弾かれていた。

LTM実績EPS(IFRS純利益÷期中平均株式数 約5.42億株、Q4は Koyfin報告 ¥752.4 でアンカー)を算出して Turso に注入し、再取込した。ltm_eps ¥1,023.23・成長率 +777% が入り、散布図に13銘柄すべてがプロットされた。X軸は +856% まで自動拡張してキオクシアの +777% を収容した。NAND市況の谷からの回復で LTM が小さく、「低PER × 極端な高成長」の右下に位置する。scatter.vue の見出しも「12銘柄」→「13銘柄」に直した。

毎朝の自動取込で壊れないようにする

ここが恒久運用の肝だった。毎朝の /check-earningstickers.koyfin_kid 登録済みの全銘柄を自動列挙するよう拡張済み。285A も KID 登録したので、放っておくと翌朝から標準キー(非GAAP)で上書きされ、GAAP流し込みが効かず ntm_eps が null になってカードが壊れる。

import_koyfin_batch.py 側には compute_ntm_metrics に**「非GAAPが無ければGAAP予想にフォールバック」**を入れた。非GAAPが揃う既存27銘柄はフォールバックが発火せず挙動不変、キオクシアだけ救済される。turso のテスト20件は pass。

ただし daily が 285A を USD建てで取得する問題が残った(通貨選択は KRW だけ現地通貨扱いで、TSE は USD に落ちる)。これを直すには check-earnings.md の通貨ロジックに JPY を足す必要があるが、add-ticker タスクの認可範囲外として自己改変が拒否された。

そこで安全側に倒す判断をした。285A の koyfin_kid を NULL 化して daily の自動列挙から外す。これで検証済みの完全なスナップショット(¥77,540 / NTM ¥8,978 / LTM ¥1,023 / PER 8.64x / JPY)が保持され、毎朝の上書きで壊れない。可逆だし、KID HO-dcpDpY は手動再取込でいつでも使える。「自動化を頑張った先で、自動化の対象から1銘柄だけ手動退避させる」という落としどころになった。

最終的に beat/ticker 関連の8ファイル132テストは全 pass。tickerMeta・gaapValuation・summaries(29銘柄に)まで整合した。

4. トップの構造転換済みブロックを2段組みにする

最後はレイアウトの細かい要望。「/beat-monitoring の構造転換済みのところ、MU・NVDA・SNDK の3つを1行目に、それ以外を改行して並べて」。

最初は「散布図のゾーン分け」かと取り違えて聞き返してしまった。実際はトップページ(index.vue)の銘柄チップの並びの話だった。

各 tier の銘柄を 「主力3銘柄(MU→NVDA→SNDK)」と「その他」の2行に分割する純粋関数 splitRows を追加し、テンプレートを2段化、薄い区切り線を入れた。SSR出力を見ると、1行目が MU・NVDA・SNDK、改行して 285A・005930・000660… と続く。priority-row は構造転換済みブロックの1箇所だけに出ていて、意図どおりだった。

今日の地点

  • earnings-beat-scan に「会社ガイダンス × Koyfinコンセンサス」の突合手続きを入れ、次四半期/通年の2段で出るようにした。次回から PANW・GTLB・ULTA まで数字付きで自動運用できる
  • キオクシア(285A)を beat-monitoring に追加。東証・JPY建て・非GAAP予想欠損という三重苦を、GAAP流し込み+JPY横展開+LTM手動注入で乗り越えた。daily からは安全のため手動退避
  • トップの構造転換済みブロックを「主力3銘柄+その他」の2段組みに

人間は単位や並びの違和感を拾う係、突合とデータ整備は回させる係、という分担が今日ははっきりした。残る宿題は check-earnings.md の JPY 通貨対応で、これを入れればキオクシアも daily に戻せる。