AIエージェントで作る銘柄評価基盤②—評価尺度の仕組み

銘柄評価システムで「スコア」という言葉を一つだけ使うと、何を測っているのかが曖昧になります。割安な会社と良い会社は同じではなく、値動きが強い会社と事業の競争力が高い会社も同じではありません。さらに、今日の株価で変わる指標と、四半期ごとに見直す事業評価を同じ頻度で更新する必要もありません。
今回の実装では、評価尺度を次の4種類に分けています。
1. **定量スコア**:構造化データから毎日計算する広いスクリーニング
2. **事業スコア**:AIが公開情報を確認して定期的に作る価格非依存の評価
3. **統合スコア**:有効な事業評価と毎日の割安度・モメンタムを組み合わせた順位用の値
4. **Tier**:評価の高さそのものではなく、次にいつ再確認するかを管理する運用状態
この4つを分けたことで、「株価が下がって割安になった」「事業評価が改善した」「評価期限が来た」「未評価なので暫定Tierにいる」といった状態を混同せず説明できます。
この記事の銘柄名、数値例、評価結果はすべて架空です。実在企業のスコアや順位は掲載しません。
> 本記事は評価システムの設計解説であり、投資助言ではありません。数値は候補を比較するための補助情報であり、将来の株価や収益を保証しません。
なぜ「一つの総合点」から始めなかったのか
最初からAIへ「この銘柄を100点満点で評価してください」と頼むと、回答は作れます。しかし、その100点には割安度、成長性、人気、ニュースの印象、企業規模などが混ざります。日によって参照した情報も変わり、モデルを変更した時に何が変わったのか追えません。
反対に、財務指標だけを加重平均すると、参入障壁、顧客基盤、新製品、資本政策、ガバナンスといった文章資料に現れる情報を取り込みにくくなります。
そこで、「計算できるもの」と「読まなければ分からないもの」を分離しました。
“`mermaid
flowchart TB
subgraph Q[毎日更新する定量系]
Q1[価格・出来高・財務] –> Q2[特徴量]
Q2 –> Q3[市場×業種内で正規化]
Q3 –> Q4[5ピラーの定量スコア]
Q3 –> Q5[割安度・モメンタム]
end
subgraph B[低頻度で更新する事業系]
B1[財務パッケージ・公開資料] –> B2[AIのカテゴリ採点]
B2 –> B3[コードで検証・合計]
B3 –> B4[事業スコア・グレード]
end
Q5 –> T[統合スコア]
B4 –> T
B4 –> R[Tierと再評価周期]
“`
定量スコアは候補の発掘と暫定順位に使い、事業スコアは会社の質を表し、統合スコアは有効評価のある銘柄を比較します。Tierは事業評価グレードをもとに再評価周期を決めます。
まず生データを評価可能な形へ直す
スコア計算の前に、価格と財務のデータをそのまま使えない理由があります。特に日本企業の四半期開示では、1Q、2Q、3Qが期首からの累計値として提供されることがあります。2Q累計と1Q累計を同じ「一四半期の利益」として並べると、成長率や利益率が壊れます。
実装では次の順番で変換します。
“`text
累計開示値
↓ 同じ会計年度内で差分を取る
単独四半期フロー
↓ 直近4四半期を合計する
TTM(直近12か月)
↓
成長率・ROE・ROA・営業利益率
“`
たとえば、架空企業Aの営業利益が1Q累計10、2Q累計24、3Q累計39、通期55なら、単独四半期は10、14、15、16です。この4つを合計した55が直近12か月の流れになります。決算期がずれる企業も、会計年度と期末を見ながら並べます。
同じ期末について訂正開示や複数レコードがある場合は、開示日時と開示番号から最新を採用します。AIに「どれが正しい決算か」を判断させず、データ整形の規則として固定しています。
価格系特徴量は調整後価格を中心にする
株式分割や併合があると、未調整の終値には大きな段差ができます。その段差を通常の下落として扱うと、リターン、ボラティリティ、最大ドローダウン、テクニカル指標が壊れます。
そのため、リターンや高値・安値を使う計算では調整後価格を優先します。日々の売買可能性を見るため、次の特徴量も計算します。
| 特徴量 | 役割 | 主な注意点 |
|—|—|—|
| 20日中央値売買代金 | 継続的な流動性 | 平均より一時的な大商いの影響が小さい |
| 20日中央値出来高 | 取引量の補助 | 株価水準だけで比較しない |
| 60日無商い率 | 取引が成立しない頻度 | 0出来高を通常日と分ける |
| Amihud型指標 | 売買代金に対する価格変動 | 気配値がない場合の流動性代理 |
| 20日実現ボラティリティ | 短期的な値動きの大きさ | 年率換算して比較 |
| 60日最大ドローダウン | 直近高値からの下落 | 分割の見かけ上の段差を除く |
| 60日リターン | 統合スコアのモメンタム | 定量スコア本体には混ぜない |
PBRは当日の終値だけでなく、20日平均株価をBPSで割って計算します。一日の価格変動で割安度が過度に動くことを抑えるためです。
ハードフィルターは「評価対象として扱えるか」を見る
スコアの前に、現行設定では次のような条件を確認します。これは実装時点の設定例であり、普遍的な投資基準ではありません。
- 20日中央値売買代金が一定額以上
- 60日無商い率が一定割合以下
- 株価が設定下限以上
- PBRが正
- 自己資本が正
現行の初期値は、売買代金5,000万円以上、無商い率5%以下、株価300円以上です。市場ごとに別の値へ変更できる構造ですが、現在は同じ初期値を使っています。
ハードフィルターを通過しない場合、定量スコアそのものは計算できても、候補順位のpercentileは付けません。これにより、流動性条件を満たさない銘柄が「業種内で割安」という理由だけで通常の上位候補へ混ざることを防ぎます。
業種の違いをロバストに正規化する
PBR、利益率、自己資本比率、売買代金の分布は業種によって大きく違います。さらに、市場区分によって企業規模や流動性も異なります。全企業を一つの平均と標準偏差で比べると、特定業種や大企業が有利になりやすくなります。
そこで、各指標を**市場×33業種**のグループ内で相対化します。正規化には中央値とMAD(中央値絶対偏差)を使います。
“`text
robust_z = 0.6745 × (値 − グループ中央値) / MAD
“`
外れ値の影響を抑えるため、z値は-3から+3に切ります。高いほど良い指標はそのまま、PBRやボラティリティのように低いほど良い指標は符号を反転し、次の形で0〜100へ写します。
“`text
score = clip(50 + robust_z × 10, 0, 100)
“`
中央値付近は50、同じ市場・業種の中で相対的に良いほど50より上、悪いほど下になります。MADが0、つまりグループ内の値がほぼ同じ場合は、差を作らず中立の50として扱います。
この方法の利点は、極端な一社が平均と標準偏差を押し動かしにくいことです。一方で、グループ内の企業数が少ない業種では順位が不安定になりやすいという制約があります。少数業種をより大きな業種分類へフォールバックする設計は、今後の改善候補です。
定量スコアの5ピラー
指標ごとの0〜100点を平均し、5つの柱へまとめます。現行の初期重みは次の通りです。
| ピラー | 重み | 主な指標 | 点が高くなる方向 |
|—|—:|—|—|
| 割安度 | 25% | PBR | 同業より低い |
| 成長 | 25% | 売上・営業利益の3年成長、会社予想 | 同業より高い |
| クオリティ | 25% | ROE、ROA、営業利益率、自己資本比率 | 同業より高い |
| 流動性 | 15% | 売買代金、出来高、無商い率、Amihud型指標 | 売買しやすい |
| リスク | 10% | 実現ボラティリティ、最大ドローダウン | 値動きが相対的に穏やか |
合成式は次の形です。
“`text
quant_score
= value × 0.25
+ growth × 0.25
+ quality × 0.25
+ liquidity × 0.15
+ risk × 0.10
“`
あるピラーの指標がすべて欠ける場合は、そのピラーを中立の50として合成します。欠損を0点にすると、データがないことを悪い評価と誤認するためです。ただし、PBRや自己資本などハードフィルターに必要な項目が欠ける場合は、候補順位の対象外になります。
架空の定量計算例
銘柄Aが、同じ市場・業種内で次のピラースコアになったとします。
| ピラー | 架空スコア | 加重後 |
|—|—:|—:|
| 割安度 | 62 | 15.50 |
| 成長 | 54 | 13.50 |
| クオリティ | 68 | 17.00 |
| 流動性 | 58 | 8.70 |
| リスク | 42 | 4.20 |
| **定量スコア** | | **58.90** |
58.9点は「絶対的に良い会社」という意味ではありません。同じ市場・業種の分布に対して、5つの定量軸を重み付けした相対位置です。さらに、候補順位はハードフィルターを通過した企業だけを母集団に、市場別でpercentileへ変換します。
AIの事業評価は価格を見ない
定量層が割安度と値動きを担当するため、AIの事業評価では株価、PBR、PERの水準を採点対象から外します。AIへ求めるのは「今の価格が安いか」ではなく、「事業の質が高いか、改善する具体的根拠があるか」です。
固定ルーブリックは次の6項目です。
| カテゴリ | 配点 | AIが確認する内容 |
|—|—:|—|
| 収益力・資本効率 | 0〜25 | ROE、利益率、持続性、キャッシュ創出力 |
| 成長性 | 0〜25 | 売上・利益トレンド、会社予想、市場の追い風 |
| 事業の質 | 0〜20 | 競争優位、参入障壁、顧客基盤、ビジネスモデル |
| カタリスト | 0〜15 | 中計、還元強化、新製品、再編などの時期と確度 |
| 経営・資本政策 | 0〜15 | 資本コスト意識、IR姿勢、株主還元方針 |
| リスク | -15〜0 | 業績下振れ、特損、競争激化、ガバナンスなど |
平均的な企業が極端な高得点にならないよう、市場ごとに採点水準を明示します。各カテゴリで配点の60%を超える点は、数値や開示事実の具体的根拠がある場合だけにします。確認できない強みを期待だけで加点せず、カタリストには時期と確度を求めます。
このキャリブレーションは、AIモデルが全体的に甘い点を付ける問題を抑えるためのものです。同時に、異なる市場の事業スコアを直接比較しないことも重要です。市場ごとに評価母集団とシステムプロンプトを分け、レポートの順位も市場別にします。
AI出力はそのまま信用しない
AIは次のような構造化データを返します。例は架空です。
“`json
{
"scores": {
"profitability": 16,
"growth": 15,
"moat": 12,
"catalyst": 7,
"management": 9,
"risk": -5
},
"summary": "架空の評価要約",
"catalysts": ["架空の確認事項"],
"risks": ["架空の主要リスク"],
"confidence": "medium"
}
“`
コード側は、JSONオブジェクトであること、必要なカテゴリがあること、点数が整数で範囲内にあること、要約とリストがあることを検証します。範囲外なら拒否し、修正要求を加えて再試行します。
事業スコアは、正のカテゴリの合計へリスク減点を加え、0〜100へ切った値です。架空例では次の計算になります。
“`text
16 + 15 + 12 + 7 + 9 − 5 = 54
“`
グレードはコード側の固定境界で決まります。
| 事業スコア | グレード |
|—:|—:|
| 80以上 | 5 |
| 65以上80未満 | 4 |
| 45以上65未満 | 3 |
| 30以上45未満 | 2 |
| 30未満 | 1 |
銘柄Aの架空事業スコア54はグレード3です。AIが文章の中で「グレード4相当」と書いても、最終グレードはコードが54から計算します。
定量スコアと統合スコアは別物
統合スコアは、5ピラーの定量スコア全体をそのまま使いません。事業評価と意味が重なる成長・クオリティを二重に加えないためです。現行実装では、次の3成分を合成します。
“`text
total_score
= biz_score × 0.60
+ value_score × 0.25
+ momentum_score × 0.15
“`
- `biz_score`:AI深掘りから確定した、価格非依存の事業評価
- `value_score`:毎日更新する同業内の割安度
- `momentum_score`:60日リターンを同業内で相対化した補助値
銘柄Aの事業スコアが54、割安度が62、モメンタムが57なら、架空の統合スコアは次の通りです。
“`text
54 × 0.60 + 62 × 0.25 + 57 × 0.15
= 32.40 + 15.50 + 8.55
= 56.45
“`
事業評価がない、または有効期限を過ぎている場合は、統合スコアを付けません。0点にはしません。割安度やモメンタムが欠ける場合だけ、中立の50で補完します。
この区別によって、次の3つを別に読めます。
- 定量スコアが高い:構造化データ上、同業内で複数条件が良い
- 事業スコアが高い:公開情報を含む固定ルーブリックで事業評価が高い
- 統合スコアが高い:有効な事業評価があり、現在の割安度・モメンタムも加味すると上位
Tierは「点数」ではなく再評価の予定表
TierはS、A、B、C、Nの5種類です。Nは未評価を表します。評価済みのTierは事業グレードから直接決めます。
| グレード | Tier | 再評価周期の初期値 |
|—:|—|—:|
| 5 | S | 10営業日 |
| 4 | A | 20営業日 |
| 3 | B | 60営業日 |
| 1〜2 | C | 120営業日 |
| 未評価 | N | 初回一周の対象 |
Tierを統合スコアから決めない理由は、毎日の価格変動で再評価周期が揺れるのを避けるためです。良い事業が一時的に割高になったからといって、事業調査の頻度まで急に下げる必要はありません。反対に、低Tierの銘柄でも定量順位が急上昇すれば、敗者復活枠で早めに確認できます。
未評価または評価失効中の銘柄には、定量percentileから暫定Tierを付けます。現行の区切りは、上位10%をS、次の20%をA、中間をB、残りをCとする形です。これは事業評価済みのTierと区別するため、`provisional` 状態を保存します。
ヒステリシスで一日の変化に振り回されない
確定済みTierが別のTier条件に移った場合、一回だけでは変更せず、同じ方向の条件が連続した時に遷移します。これをヒステリシスと呼びます。
たとえば、Tier Aの銘柄が一度だけグレード2になった場合、すぐCへ落とさず「C候補・連続1回」と記録します。次回もグレード2ならCへ変更し、元の水準へ戻れば候補状態を解除します。
“`mermaid
stateDiagram-v2
[*] –> A
A –> A: 1回だけC条件
A –> C: C条件が連続
A –> A: 条件が回復
C –> C: 1回だけA条件
C –> A: A条件が連続
“`
ただし、未評価の暫定Tierから初めて正式な事業グレードが付いた時は、暫定状態との比較に意味がないため即時に確定Tierへ移します。
当日枠は複数の入口から配る
各市場の日次評価枠は、現行実装では次のように分かれます。
| 枠 | 初期件数 | 役割 |
|—|—:|—|
| イベント | 10 | 決算、急変、売買代金急増など |
| 発掘 | 5 | 高評価企業の競合として見つかった未評価候補 |
| 期限超過 | 30 | Tierの再評価期限を過ぎた対象 |
| 敗者復活 | 5 | B/Cだが定量percentileが上位へ浮上 |
期限超過枠では、超過日数、Tierの緊急度、定量順位を組み合わせます。未評価Nは初回一周を進めるため、定量スコア上位を優先します。イベント枠では直接イベントを優先し、競合関係から伝播した波及イベントが全枠を占有しないよう上限を設けます。
この配分は、AIの推論予算をどこへ使うかという「エージェントの入口設計」です。AIモデルの性能を変えなくても、対象選定を改善するだけで実用性が変わります。
一目均衡表は表示専用にした
日足・週足・月足の一目均衡表シグナルも計算しますが、導入時点では定量スコアや統合スコアに入れていません。レポート表示と検証用の補助シグナルです。
新しい指標を思いつくたびに本番スコアへ追加すると、何が効いたのか分からなくなります。そのため、まず充足率、日次変化、遷移整合性、代表ケースを検証レポートへ出し、一定期間問題がないことを確認してから表示を有効化します。スコアへの組み込みは、その後の分布と事後成績を見て判断します。
スコア設計で避けたこと
1. 未評価を0点にする
AIがまだ見ていないだけの銘柄を低評価と扱うと、初回一周の順序が結果を左右します。未評価は欠損、低評価は低い事業スコアとして分けます。
2. AIに合計とグレードまで自由に決めさせる
カテゴリ点と合計が矛盾する可能性があります。AIは根拠整理とカテゴリ採点、コードは検証・合計・グレードを担当します。
3. 市場を跨いで同じ順位表へ入れる
企業規模、流動性、PBR分布、採点水準が異なります。定量正規化、percentile、AIキャリブレーション、ランキングを市場別にします。
4. 将来の情報を今日のスコアへ混ぜる
特徴量は対象日以前のデータだけを使います。学習用の事後リターンは、将来日が実際に到来した後に別テーブルへ確定し、今日の過去スコアを書き換えません。
5. 新しい指標をすぐ本番へ入れる
表示専用、検証運転、shadow運転、機能フラグを使い、本番の順位やTierへ影響しない期間を設けます。
評価尺度を設計する時のチェックリスト
- [ ] その点数は何を測り、何を測らないか説明できる
- [ ] 更新頻度の違う情報を一つの評価へ無理に混ぜていない
- [ ] 欠損、未評価、低評価を区別している
- [ ] 業種や市場の分布差を考慮している
- [ ] 外れ値で基準が大きく動かない
- [ ] AIの出力を型と範囲で検証している
- [ ] プロンプト版と評価条件を履歴に残している
- [ ] 新しい指標は本番へ入れる前に並走評価している
- [ ] Tierや再評価周期が日次ノイズで振動しない
- [ ] スコアを投資判断そのものとして表示していない
まとめ
この実装では、定量スコア、事業スコア、統合スコア、Tierを別々の役割にしました。定量層は全銘柄を毎日、同じ市場・業種内でロバストに比較します。AIは価格を採点せず、公開資料から事業の質を固定ルーブリックで評価します。統合スコアは有効な事業評価がある銘柄だけに付け、Tierは再評価周期を管理します。
重要なのは「100点満点を作ること」ではなく、点数の意味、更新頻度、欠損時の扱い、最終確定の責任を分けることです。AIの判断を使いながら、計算と運用の再現性をコード側に残せます。
次回は、このパイプラインをHermes AgentのcronとGatewayでどのように毎営業日動かし、スキップ・失敗・通知・再実行を管理しているかを説明します。
実装確認に使った主なファイル
- `stock_brand_eval_agent/screener/features.py`
- `stock_brand_eval_agent/screener/quant_score.py`
- `stock_brand_eval_agent/screener/integrate.py`
- `stock_brand_eval_agent/evaluator/rubric.py`
- `stock_brand_eval_agent/rotation/scheduler.py`
- `stock_brand_eval_agent/config.py`
- `tests/features/scoring.feature`
- `tests/features/evaluation.feature`
- `tests/features/integration.feature`
