[{"data":1,"prerenderedAt":550},["ShallowReactive",2],{"content-/eps-per-scatter-page-guide":3,"all-pages-for-dir":530,"related-/eps-per-scatter-page-guide":531,"og-image-/eps-per-scatter-page-guide":549},{"id":4,"title":5,"body":6,"category":516,"concepts":516,"description":517,"extension":518,"meta":519,"navigation":292,"ogImage":516,"path":520,"project_name":516,"published":521,"publishedAt":522,"seo":523,"source":516,"stem":524,"tags":525,"todo":516,"unpublished":521,"updatedAt":522,"__hash__":529},"pages/2025-12/2025-12-15/eps-per-scatter-page-guide.md","散布図ページ (eps-per-scatter) 技術仕様",{"type":7,"value":8,"toc":502},"minimark",[9,13,17,44,47,57,60,66,69,73,103,106,112,115,168,174,180,184,415,418,429,432,437,440,455,458,474,477,498],[10,11,5],"h1",{"id":12},"散布図ページ-eps-per-scatter-技術仕様",[14,15,16],"h2",{"id":16},"ページ概要",[18,19,20,32,38],"ul",{},[21,22,23,27,28],"li",{},[24,25,26],"strong",{},"URL",": ",[29,30,31],"code",{},"/financial-quiz/eps-per-scatter",[21,33,34,37],{},[24,35,36],{},"機能",": 100社のEPS成長率予想とPER（Forward）を散布図でプロット",[21,39,40,43],{},[24,41,42],{},"切り替え機能",": 年度（2026-2029）、Adjusted/GAAP",[14,45,46],{"id":46},"ファイル構成",[48,49,54],"pre",{"className":50,"code":52,"language":53},[51],"language-text","apps/web/\n├── app/\n│   ├── pages/\n│   │   └── financial-quiz/\n│   │       └── eps-per-scatter.vue    # ページ本体\n│   └── composables/\n│       └── scatter-data.ts            # 軽量データ（自動生成）\n├── scripts/\n│   └── generate-scatter-data.mjs      # データ生成スクリプト\n└── data/\n    └── koyfin.db                      # 元データ（SQLite）\n","text",[29,55,52],{"__ignoreMap":56},"",[14,58,59],{"id":59},"データパイプライン",[48,61,64],{"className":62,"code":63,"language":53},[51],"koyfin.db (SQLite)\n    ↓\ngenerate-scatter-data.mjs (スクリプト)\n    ↓\nscatter-data.ts (TypeScript静的データ)\n    ↓\neps-per-scatter.vue (ページ)\n",[29,65,63],{"__ignoreMap":56},[14,67,68],{"id":68},"データ更新方法",[70,71,72],"p",{},"SQLiteのデータが更新された場合、以下のコマンドで再生成：",[48,74,78],{"className":75,"code":76,"language":77,"meta":56,"style":56},"language-bash shiki shiki-themes vitesse-light vitesse-light","cd apps/web\nnode scripts/generate-scatter-data.mjs\n","bash",[29,79,80,93],{"__ignoreMap":56},[81,82,85,89],"span",{"class":83,"line":84},"line",1,[81,86,88],{"class":87},"sz8Xr","cd",[81,90,92],{"class":91},"sdGka"," apps/web\n",[81,94,96,100],{"class":83,"line":95},2,[81,97,99],{"class":98},"senZ8","node",[81,101,102],{"class":91}," scripts/generate-scatter-data.mjs\n",[70,104,105],{},"出力例：",[48,107,110],{"className":108,"code":109,"language":53},[51],"SQLite データベースを読み込み中...\n企業数: 101\n出力完了: app/composables/scatter-data.ts\nファイルサイズ: 52.6 KB\n",[29,111,109],{"__ignoreMap":56},[14,113,114],{"id":114},"なぜ軽量データを使うのか",[116,117,118,134],"table",{},[119,120,121],"thead",{},[122,123,124,128,131],"tr",{},[125,126,127],"th",{},"データファイル",[125,129,130],{},"サイズ",[125,132,133],{},"内容",[135,136,137,153],"tbody",{},[122,138,139,145,150],{},[140,141,142],"td",{},[29,143,144],{},"actual-consensus-data.ts",[140,146,147],{},[24,148,149],{},"35MB",[140,151,152],{},"全メトリクス（売上、利益、マージン、EPS、PER等）× 年次・四半期",[122,154,155,160,165],{},[140,156,157],{},[29,158,159],{},"scatter-data.ts",[140,161,162],{},[24,163,164],{},"52KB",[140,166,167],{},"EPS成長率とPERのみ × 2026-2029年",[70,169,170,173],{},[24,171,172],{},"問題",": 35MBのファイルをインポートするとNuxtのSSR時にワーカーがメモリ不足でクラッシュ",[70,175,176,179],{},[24,177,178],{},"解決",": 散布図で使う4メトリクスだけを抽出 → 99.8%削減",[14,181,183],{"id":182},"scatter-datats-のデータ構造","scatter-data.ts のデータ構造",[48,185,189],{"className":186,"code":187,"language":188,"meta":56,"style":56},"language-typescript shiki shiki-themes vitesse-light vitesse-light","export interface ScatterYearData {\n  epsGrowthAdj: number | null   // EPS成長率（Adjusted）\n  epsGrowthGaap: number | null  // EPS成長率（GAAP）\n  perAdj: number | null         // PER（Adjusted）\n  perGaap: number | null        // PER（GAAP）\n}\n\nexport interface ScatterCompanyData {\n  name: string\n  sector: string | null\n  years: Record\u003Cnumber, ScatterYearData>  // 2026, 2027, 2028, 2029\n}\n\nexport const scatterData: Record\u003Cstring, ScatterCompanyData>\nexport const scatterCompanyList: string[]\n","typescript",[29,190,191,209,230,247,264,281,287,294,306,317,333,361,366,371,398],{"__ignoreMap":56},[81,192,193,197,201,205],{"class":83,"line":84},[81,194,196],{"class":195},"sHkkW","export",[81,198,200],{"class":199},"stQ0i"," interface",[81,202,204],{"class":203},"sSkh3"," ScatterYearData",[81,206,208],{"class":207},"shFtX"," {\n",[81,210,211,215,217,220,223,226],{"class":83,"line":95},[81,212,214],{"class":213},"s4oTP","  epsGrowthAdj",[81,216,27],{"class":207},[81,218,219],{"class":203},"number",[81,221,222],{"class":207}," | ",[81,224,225],{"class":199},"null",[81,227,229],{"class":228},"sxvE3","   // EPS成長率（Adjusted）\n",[81,231,233,236,238,240,242,244],{"class":83,"line":232},3,[81,234,235],{"class":213},"  epsGrowthGaap",[81,237,27],{"class":207},[81,239,219],{"class":203},[81,241,222],{"class":207},[81,243,225],{"class":199},[81,245,246],{"class":228},"  // EPS成長率（GAAP）\n",[81,248,250,253,255,257,259,261],{"class":83,"line":249},4,[81,251,252],{"class":213},"  perAdj",[81,254,27],{"class":207},[81,256,219],{"class":203},[81,258,222],{"class":207},[81,260,225],{"class":199},[81,262,263],{"class":228},"         // PER（Adjusted）\n",[81,265,267,270,272,274,276,278],{"class":83,"line":266},5,[81,268,269],{"class":213},"  perGaap",[81,271,27],{"class":207},[81,273,219],{"class":203},[81,275,222],{"class":207},[81,277,225],{"class":199},[81,279,280],{"class":228},"        // PER（GAAP）\n",[81,282,284],{"class":83,"line":283},6,[81,285,286],{"class":207},"}\n",[81,288,290],{"class":83,"line":289},7,[81,291,293],{"emptyLinePlaceholder":292},true,"\n",[81,295,297,299,301,304],{"class":83,"line":296},8,[81,298,196],{"class":195},[81,300,200],{"class":199},[81,302,303],{"class":203}," ScatterCompanyData",[81,305,208],{"class":207},[81,307,309,312,314],{"class":83,"line":308},9,[81,310,311],{"class":213},"  name",[81,313,27],{"class":207},[81,315,316],{"class":203},"string\n",[81,318,320,323,325,328,330],{"class":83,"line":319},10,[81,321,322],{"class":213},"  sector",[81,324,27],{"class":207},[81,326,327],{"class":203},"string",[81,329,222],{"class":207},[81,331,332],{"class":199},"null\n",[81,334,336,339,341,344,347,349,352,355,358],{"class":83,"line":335},11,[81,337,338],{"class":213},"  years",[81,340,27],{"class":207},[81,342,343],{"class":203},"Record",[81,345,346],{"class":207},"\u003C",[81,348,219],{"class":203},[81,350,351],{"class":207},", ",[81,353,354],{"class":203},"ScatterYearData",[81,356,357],{"class":207},">  ",[81,359,360],{"class":228},"// 2026, 2027, 2028, 2029\n",[81,362,364],{"class":83,"line":363},12,[81,365,286],{"class":207},[81,367,369],{"class":83,"line":368},13,[81,370,293],{"emptyLinePlaceholder":292},[81,372,374,376,379,382,384,386,388,390,392,395],{"class":83,"line":373},14,[81,375,196],{"class":195},[81,377,378],{"class":199}," const ",[81,380,381],{"class":213},"scatterData",[81,383,27],{"class":207},[81,385,343],{"class":203},[81,387,346],{"class":207},[81,389,327],{"class":203},[81,391,351],{"class":207},[81,393,394],{"class":203},"ScatterCompanyData",[81,396,397],{"class":207},">\n",[81,399,401,403,405,408,410,412],{"class":83,"line":400},15,[81,402,196],{"class":195},[81,404,378],{"class":199},[81,406,407],{"class":213},"scatterCompanyList",[81,409,27],{"class":207},[81,411,327],{"class":203},[81,413,414],{"class":207},"[]\n",[14,416,417],{"id":417},"関連ページ",[18,419,420,426],{},[21,421,422,425],{},[29,423,424],{},"/financial-quiz/actual-consensus"," - 個別企業の詳細データ（35MBのデータを使用）",[21,427,428],{},"散布図からティッカーをクリックすると actual-consensus ページにリンク",[14,430,431],{"id":431},"トラブルシューティング",[433,434,436],"h3",{"id":435},"ssrエラー-worker-exited-with-code-0","SSRエラー: \"worker exited with code 0\"",[70,438,439],{},"原因: 大きなデータファイルを使用している\n対策:",[441,442,443,448],"ol",{},[21,444,445,447],{},[29,446,159],{}," を使用しているか確認",[21,449,450,451,454],{},"または ",[29,452,453],{},"\u003CClientOnly>"," でラップ",[433,456,457],{"id":457},"データが古い",[48,459,460],{"className":75,"code":76,"language":77,"meta":56,"style":56},[29,461,462,468],{"__ignoreMap":56},[81,463,464,466],{"class":83,"line":84},[81,465,88],{"class":87},[81,467,92],{"class":91},[81,469,470,472],{"class":83,"line":95},[81,471,99],{"class":98},[81,473,102],{"class":91},[433,475,476],{"id":476},"新しいメトリクスを追加したい",[441,478,479,489,492],{},[21,480,481,484,485,488],{},[29,482,483],{},"scripts/generate-scatter-data.mjs"," の ",[29,486,487],{},"METRIC_KEYS"," を編集",[21,490,491],{},"スクリプトを再実行",[21,493,494,497],{},[29,495,496],{},"eps-per-scatter.vue"," を更新",[499,500,501],"style",{},"html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .sSkh3, html code.shiki .sSkh3{--shiki-default:#2E8F82;--shiki-dark:#2E8F82}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}",{"title":56,"searchDepth":95,"depth":95,"links":503},[504,505,506,507,508,509,510,511],{"id":16,"depth":95,"text":16},{"id":46,"depth":95,"text":46},{"id":59,"depth":95,"text":59},{"id":68,"depth":95,"text":68},{"id":114,"depth":95,"text":114},{"id":182,"depth":95,"text":183},{"id":417,"depth":95,"text":417},{"id":431,"depth":95,"text":431,"children":512},[513,514,515],{"id":435,"depth":232,"text":436},{"id":457,"depth":232,"text":457},{"id":476,"depth":232,"text":476},null,"EPS成長率 vs PER散布図ページのデータ生成・更新方法","md",{},"/eps-per-scatter-page-guide",false,"2025-12-15T00:00:00.000Z",{"title":5,"description":517},"2025-12/2025-12-15/eps-per-scatter-page-guide",[526,527,528],"financial-quiz","scatter-plot","data-pipeline","BE92zUVu_iyNlAJ1JcC09asjiWVqxB3ZfKR-eMGW6j4",[],[532,536,540,543,546],{"title":533,"path":534,"publishedAt":535},"P/L Waterfallチャート構造変更案","/pl-waterfall-redesign","2025-12-26T00:00:00.000Z",{"title":537,"path":538,"publishedAt":539},"チャートX軸整列の学び - 個別修正 vs 共通化リファクタリング","/financial-quiz-chart-alignment-lessons","2025-12-22T00:00:00.000Z",{"title":541,"path":542,"publishedAt":539},"financial-quizディレクトリ構造の整理計画","/financial-quiz-directory-structure",{"title":544,"path":545,"publishedAt":539},"Financial Quiz 引き継ぎメモ","/financial-quiz-handoff",{"title":547,"path":548,"publishedAt":539},"ウォーターフォールチャートのテスト設計","/waterfall-chart-testing","https://log.eurekapu.com/og/blog/eps-per-scatter-page-guide.png?v=2025-12-15T00%3A00%3A00.000Z&title=%E6%95%A3%E5%B8%83%E5%9B%B3%E3%83%9A%E3%83%BC%E3%82%B8%20(eps-per-scatter)%20%E6%8A%80%E8%A1%93%E4%BB%95%E6%A7%98&author=Kei%20Komatsu&sig=7400058132f5c733",1785654678416]