feat(lotto): evaluate_weekly 학습 신호를 forward lift로 승격
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -294,6 +294,35 @@ def evaluate_weekly() -> Dict[str, Any]:
|
||||
|
||||
winner = max(per_day, key=lambda d: d["avg_score"])
|
||||
|
||||
# 자가학습 강화: backtest forward 등수점수 lift로 winner 재선정
|
||||
latest_no = latest["drw_no"]
|
||||
runs = db.get_backtest_runs(draw_no=latest_no)
|
||||
engine_runs = [r for r in runs if r["strategy"] == "engine_w"]
|
||||
null_runs = [r for r in runs if r["strategy"] == "random_null"]
|
||||
if engine_runs and null_runs:
|
||||
random_score = prize_score_from_hist(null_runs[0])
|
||||
per_w = []
|
||||
for r in engine_runs:
|
||||
per_w.append({
|
||||
"trial_id": r["trial_id"],
|
||||
"day_of_week": int(r["weight_label"][1:]) if r["weight_label"].startswith("w") else 0,
|
||||
"weight": json.loads(r["weight_json"]) if r["weight_json"] else DEFAULT_UNIFORM[:],
|
||||
"prize_score": prize_score_from_hist(r),
|
||||
})
|
||||
lift_winner = select_winner_by_lift(per_w, random_score=random_score)
|
||||
if not lift_winner["gated"]:
|
||||
winner = {
|
||||
"trial_id": lift_winner["trial_id"],
|
||||
"day_of_week": lift_winner["day_of_week"],
|
||||
"weight": lift_winner["weight"],
|
||||
"avg_score": winner["avg_score"],
|
||||
"max_correct": winner["max_correct"],
|
||||
"lift": lift_winner["lift"],
|
||||
}
|
||||
else:
|
||||
# 노이즈 → base 유지 강제 (max_correct를 0으로 낮춰 unchanged 유도)
|
||||
winner = {**winner, "max_correct": min(winner["max_correct"], 2), "lift": lift_winner["lift"]}
|
||||
|
||||
current_base = db.get_current_base()
|
||||
new_base, reason = decide_base_update(
|
||||
winner_max_correct=winner["max_correct"],
|
||||
|
||||
@@ -135,3 +135,10 @@ def test_select_winner_by_lift_gating():
|
||||
winner2 = we.select_winner_by_lift(per_w, random_score=3.0, epsilon=2.0)
|
||||
assert winner2["gated"] is False
|
||||
assert winner2["trial_id"] == 2 # prize 9 → lift +6
|
||||
|
||||
|
||||
def test_prize_score_from_hist():
|
||||
# 등수 가중치: 1등 매우 큼, 하위는 작게
|
||||
s = we.prize_score_from_hist({"m3": 10, "m4": 2, "m5": 0, "m6": 0, "bonus_hits": 0})
|
||||
s_big = we.prize_score_from_hist({"m3": 0, "m4": 0, "m5": 0, "m6": 1, "bonus_hits": 0})
|
||||
assert s_big > s # 1등 1장이 5등 다수보다 큼
|
||||
|
||||
Reference in New Issue
Block a user