Rename core/scorer.py to core/scoring.py
Browse files- core/{scorer.py → scoring.py} +20 -18
core/{scorer.py → scoring.py}
RENAMED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
from __future__ import annotations
|
| 2 |
-
from typing import Dict, Any
|
| 3 |
-
import math
|
| 4 |
|
| 5 |
def _nz(x):
|
| 6 |
try:
|
|
@@ -11,6 +10,10 @@ def _nz(x):
|
|
| 11 |
def clamp(x, lo=0, hi=100): return max(lo, min(hi, x))
|
| 12 |
|
| 13 |
def score_company(fin: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
bs = fin.get("balance_sheet", {}) or {}
|
| 15 |
pl = fin.get("income_statement", {}) or {}
|
| 16 |
|
|
@@ -22,26 +25,26 @@ def score_company(fin: Dict[str, Any]) -> Dict[str, Any]:
|
|
| 22 |
opinc = _nz(pl.get("operating_income"))
|
| 23 |
netinc = _nz(pl.get("net_income"))
|
| 24 |
|
| 25 |
-
#
|
| 26 |
-
equity_ratio = equity / assets if assets > 0 else 0.0
|
| 27 |
-
current_ratio = curA / curL if curL > 0 else (2.0 if curA > 0 else 0.0)
|
| 28 |
op_margin = opinc / sales if sales > 0 else 0.0
|
| 29 |
net_margin = netinc / sales if sales > 0 else 0.0
|
| 30 |
roa = netinc / assets if assets > 0 else 0.0
|
| 31 |
|
| 32 |
-
#
|
| 33 |
-
s_equity = clamp(equity_ratio * 200) # 50%で100
|
| 34 |
-
s_liquid = clamp((current_ratio / 2.0) * 100) # 200%で100
|
| 35 |
-
s_opm = clamp(op_margin * 400) # 25%で100
|
| 36 |
-
s_npm = clamp(net_margin * 400) # 25%で100
|
| 37 |
-
s_roa = clamp(roa * 1000) # 10%で100
|
| 38 |
|
| 39 |
details = [
|
| 40 |
-
{"metric": "自己資本比率", "value": round(equity_ratio*100, 2), "score": round(s_equity,1)},
|
| 41 |
-
{"metric": "流動比率", "value": round(current_ratio*100, 1), "score": round(s_liquid,1)},
|
| 42 |
-
{"metric": "営業利益率", "value": round(op_margin*100, 2), "score": round(s_opm,1)},
|
| 43 |
-
{"metric": "純利益率", "value": round(net_margin*100, 2), "score": round(s_npm,1)},
|
| 44 |
-
{"metric": "ROA", "value": round(roa*100, 2), "score": round(s_roa,1)},
|
| 45 |
]
|
| 46 |
|
| 47 |
total = round(sum(d["score"] for d in details) / len(details), 1)
|
|
@@ -49,5 +52,4 @@ def score_company(fin: Dict[str, Any]) -> Dict[str, Any]:
|
|
| 49 |
"A" if total >= 70 else
|
| 50 |
"B" if total >= 55 else
|
| 51 |
"C" if total >= 40 else "D")
|
| 52 |
-
|
| 53 |
-
return {"total_score": total, "grade": grade, "details": details}
|
|
|
|
| 1 |
from __future__ import annotations
|
| 2 |
+
from typing import Dict, Any
|
|
|
|
| 3 |
|
| 4 |
def _nz(x):
|
| 5 |
try:
|
|
|
|
| 10 |
def clamp(x, lo=0, hi=100): return max(lo, min(hi, x))
|
| 11 |
|
| 12 |
def score_company(fin: Dict[str, Any]) -> Dict[str, Any]:
|
| 13 |
+
"""
|
| 14 |
+
すべて『円』換算済みの fin を前提
|
| 15 |
+
数量スケールの違いで比率が歪まないよう、原則として比率/マージン/回転率ベースで採点
|
| 16 |
+
"""
|
| 17 |
bs = fin.get("balance_sheet", {}) or {}
|
| 18 |
pl = fin.get("income_statement", {}) or {}
|
| 19 |
|
|
|
|
| 25 |
opinc = _nz(pl.get("operating_income"))
|
| 26 |
netinc = _nz(pl.get("net_income"))
|
| 27 |
|
| 28 |
+
# 比率
|
| 29 |
+
equity_ratio = equity / assets if assets > 0 else 0.0
|
| 30 |
+
current_ratio = curA / curL if curL > 0 else (2.0 if curA > 0 else 0.0)
|
| 31 |
op_margin = opinc / sales if sales > 0 else 0.0
|
| 32 |
net_margin = netinc / sales if sales > 0 else 0.0
|
| 33 |
roa = netinc / assets if assets > 0 else 0.0
|
| 34 |
|
| 35 |
+
# スコア(100点換算)
|
| 36 |
+
s_equity = clamp(equity_ratio * 200) # 50%で100
|
| 37 |
+
s_liquid = clamp((current_ratio / 2.0) * 100) # 200%で100
|
| 38 |
+
s_opm = clamp(op_margin * 400) # 25%で100
|
| 39 |
+
s_npm = clamp(net_margin * 400) # 25%で100
|
| 40 |
+
s_roa = clamp(roa * 1000) # 10%で100
|
| 41 |
|
| 42 |
details = [
|
| 43 |
+
{"metric": "自己資本比率", "value": round(equity_ratio*100, 2), "score": round(s_equity,1), "unit":"%"},
|
| 44 |
+
{"metric": "流動比率", "value": round(current_ratio*100, 1), "score": round(s_liquid,1), "unit":"%"},
|
| 45 |
+
{"metric": "営業利益率", "value": round(op_margin*100, 2), "score": round(s_opm,1), "unit":"%"},
|
| 46 |
+
{"metric": "純利益率", "value": round(net_margin*100, 2), "score": round(s_npm,1), "unit":"%"},
|
| 47 |
+
{"metric": "ROA", "value": round(roa*100, 2), "score": round(s_roa,1), "unit":"%"},
|
| 48 |
]
|
| 49 |
|
| 50 |
total = round(sum(d["score"] for d in details) / len(details), 1)
|
|
|
|
| 52 |
"A" if total >= 70 else
|
| 53 |
"B" if total >= 55 else
|
| 54 |
"C" if total >= 40 else "D")
|
| 55 |
+
return {"total_score": total, "grade": grade, "details": details, "assumption":"金額は円換算済み"}
|
|
|