前提:やりたいこと
投資信託だけでなく個別株式投資をしたい。数多存在する銘柄の選定を効率化できないか?
| 課題 | 詳細 |
|---|---|
| 対象が多すぎ | 東証プライム市場だけで約1,600銘柄 |
| 指標だけでは不安 | PER/PBRが割安でも実態はわからない |
| 報告書はなるべく読みたくない | 1社あたり100ページ超の決算資料 |
| 全部手動AI分析は非現実的 | 1,600社から選定 -> 報告書収集 -> AI分析 |
解決策 → 定量で絞り込み → 報告書と乖離がないか上位だけAI分析
用語集(株式指標)
| 用語 | 説明 |
|---|---|
| PER | 株価収益率(株価÷1株利益)低いほど割安 |
| PBR | 株価純資産倍率(株価÷1株純資産)1未満は割安or低評価 |
| ROE | 自己資本利益率(利益÷自己資本)高いほど効率的 |
| 配当利回り | 年間配当÷株価(%)高いほど株主還元が多い |
| 時価総額 | 株価×発行株式数(企業の市場評価額) |
システム全体像
┌─────────────────────────────────────────────────────────┐ │ 投資分析パイプライン │ ├─────────────────────────────────────────────────────────┤ │ [Step 1] 株式指標定量スクリーニング │ │ → yfinanceで株価・財務指標を取得 │ │ → 独自ロジックでスコアリング → 上位10銘柄に絞り込み │ │ │ │ [Step 2] 報告書収集 │ │ → 決算短信・有報・説明会資料を自動ダウンロード │ │ │ │ [Step 3] Claude API 分析 │ │ → PDFから財務数値・定性評価を抽出しスコア化 │ │ │ │ [Step 4] 3軸統合スコアリング │ │ → 3軸スコア(市場・業績・経営)を統合 │ └─────────────────────────────────────────────────────────┘
Step 1: 株式指標定量スクリーニング
8つの評価軸で自動スコアリング
| 評価軸 | 条件 | 狙い |
|---|---|---|
| バリュー | PBR<1 & ROE>=10% | 真の割安株 |
| PEG | PER÷成長率<1 | 成長の割に安い |
| ROE | >=15% | 稼ぐ力が高い |
| 配当 | >=4% | インカム狙い |
| 財務 | 負債比率<50% | 倒産リスク低 |
| 成長 | 利益成長>15% | 伸びている |
| トレンド | 上昇傾向 | 順張り |
→ 合計スコアで上位銘柄を抽出
Step 2: 報告書収集
Playwrightで各種サイトから自動取得
| 収集対象 | 取得元 |
|---|---|
| 決算短信 | Yahoo!ファイナンス 適時開示 |
| 有価証券報告書 | IRBank |
| 決算説明会資料 | ullet.com |
→ PDFをダウンロードしてテキスト抽出(pdfplumber)
Step 3: Claude API 分析
PDFテキスト + 市場データをClaudeに送信 → 構造化データを抽出
- 決算短信・有報・説明会資料のテキストを入力
- 財務数値(売上、利益、成長率等)を抽出
- 定性評価(業績トーン、見通し、リスク等)をスコア化
1. Instructor + Pydantic で型安全な構造化データ抽出
| 従来の方法 | Instructor + Pydantic |
|---|---|
| プロンプトにJSONスキーマを記述 | Pydanticモデルで定義 |
| レスポンスを手動でJSONパース | 自動でPydanticオブジェクトに変換 |
| 型チェックなし | Literalで値を制限、自動バリデーション |
| パースエラー時の再試行が手動 | 自動リトライ機能内蔵 |
2. コード例:Pydanticスキーマ定義
抽出したいデータ構造をPythonクラスで定義
class QualitativeScores(BaseModel): """定性評価スコア(各0-20点)""" earnings_tone_score: int = Field(ge=0, le=20) # 0-20の範囲制約 business_outlook_score: int = Field(ge=0, le=20) risk_score: int = Field(ge=0, le=20) class AnalysisResult(BaseModel): earnings_tone: Literal["ポジティブ", "ニュートラル", "ネガティブ"] # 3択に制限 revenue_million: Optional[int] = None # 数値抽出(nullも許容) qualitative_scores: QualitativeScores # ネスト可能 summary: str = Field(description="投資判断に役立つ要約")
→ LLMが不正な値を返すと自動で再試行
2. コード例:API呼び出し
スキーマを指定してClaudeを呼び出すだけ
client = instructor.from_anthropic(Anthropic())
result = client.messages.create(
model="claude-sonnet-4-20250514",
response_model=AnalysisResult, # スキーマを指定するだけ
messages=[{"role": "user", "content": prompt}]
)
# result.earnings_tone → "ポジティブ"(型安全)
# result.qualitative_scores.risk_score → 15(int保証)
3. 定性評価のスコア化
Claudeが5項目を採点(各20点、計100点)
| 項目 | 採点基準 |
|---|---|
| 業績トーン | 増収増益=20、横ばい=10、減収減益=0 |
| 事業見通し | 拡大=20、安定=12、縮小=0 |
| 財務健全性 | 無借金=20、普通=10、高負債=0 |
| 成長要因 | 強い要因あり=20、限定的=10 |
| リスク | 軽微=20、要注意=10、重大=0 |
Step 4: 3軸統合スコアリング
┌─────────────────────────────────────────────────────┐
│ 統合スコア(各100点満点) │
├─────────────────┬─────────────────┬─────────────────┤
│ 市場スコア │ 業績実績スコア │ 経営評価スコア │
│ (yfinance) │ (決算数値) │ (Claude分析) │
├─────────────────┼─────────────────┼─────────────────┤
│ PER/PBR/ROE │ 売上成長率 │ 業績トーン │
│ 配当利回り │ 利益成長率 │ 事業見通し │
│ トレンド │ 業績予想 │ 財務健全性 │
└─────────────────┴─────────────────┴─────────────────┘
↓
3つを平均して最終スコア算出
実行結果(2026/1/9)
セクター分散で10銘柄を分析
| 銘柄 | セクター | 株価 | 時価総額 | 統合 | トーン | 見通し | 評価 |
|---|---|---|---|---|---|---|---|
| 内田洋行 | 卸売業 | 11,000 | 1,085億 | 89.7 | ポジティブ | 成長 | 割安 |
| タツモ | 機械 | 2,169 | 313億 | 88.3 | ポジティブ | 成長 | 割安 |
| モリタHD | 輸送用機器 | 2,826 | 1,207億 | 87.0 | ポジティブ | 成長 | 割安 |
| サンフロンティア | 不動産業 | 2,481 | 1,204億 | 85.0 | ポジティブ | 成長 | 割安 |
| フルヤ金属 | その他製品 | 3,710 | 911億 | 84.0 | ポジティブ | 成長 | 割安 |
| 日本カーボン | ガラス・土石 | 4,470 | 494億 | 83.7 | ポジティブ | 成長 | 割安 |
| エムティーアイ | 情報・通信 | 734 | 407億 | 81.0 | ポジティブ | 成長 | 適正 |
| 極洋 | 水産・農林業 | 4,945 | 587億 | 80.3 | ポジティブ | 成長 | 割安 |
| MS&AD | 保険業 | 3,851 | 5.7兆 | 79.3 | ポジティブ | 成長 | 割安 |
| アルプスアルパイン | 電気機器 | 1,941 | 3,787億 | 63.3 | ネガティブ | 安定 | 割安 |
9/10銘柄「整合」 = 市場評価と書類分析が一致(アルプスアルパインは為替影響で乖離)
まとめ
作ったもの - 東証プライム1,610銘柄の自動スクリーニング - 決算資料PDFの自動収集 - Claude APIで財務データ+定性評価を抽出 - 3軸統合スコアリング
技術スタック - yfinance(株価データ) - Playwright(PDF収集) - Claude API + Instructor(構造化データ抽出) - Pydantic(型バリデーション) - pandas(データ処理)
本当にやりたかったこと - 全1,600銘柄の報告書を収集 → AI分析 → 真のランキング作成 - 今回は定量スクリーニングで絞り込んでからAI分析(コスト・時間の制約)