GT MTF 프로필·캘리브레이션과 04 매칭/시뮬/실거래 파이프라인을 추가한다.
3분~일봉 GT 타점 분석(03c), leg 체결 순서 수정, 총자산 90% 검증 루프, walk-forward Go/No-Go 시뮬, monitor·live_trader 및 reference 문서를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
86
deepcoin/matching/live_eval.py
Normal file
86
deepcoin/matching/live_eval.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
05 연동: 최신 봉에서 matched 규칙 평가.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from config import CHART_LOOKBACK_DAYS, MATCH_LIVE_CACHE_SEC, MATCH_LIVE_LOOKBACK_DAYS, SYMBOL
|
||||
from deepcoin.data.mtf_bb import load_frames_from_db
|
||||
from deepcoin.matching.load_rules import load_monitor_rules
|
||||
from deepcoin.matching.rule_eval import (
|
||||
build_mtf_scan_frame,
|
||||
conditions_columns,
|
||||
eval_conditions,
|
||||
)
|
||||
from deepcoin.ops.monitor import Monitor
|
||||
|
||||
_cache: dict[str, Any] = {"ts": 0.0, "frame": None, "rules_key": ""}
|
||||
|
||||
|
||||
def evaluate_live_rules(
|
||||
rules: list[dict[str, Any]] | None = None,
|
||||
*,
|
||||
lookback_days: int | None = None,
|
||||
force_refresh: bool = False,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
최신 완성 3분봉에서 활성 규칙 발화 여부를 검사합니다.
|
||||
|
||||
Args:
|
||||
rules: 규칙 목록. None이면 matched_rules에서 로드.
|
||||
lookback_days: DB 조회 일수(기본 MATCH_LIVE_LOOKBACK_DAYS).
|
||||
force_refresh: 캐시 무시.
|
||||
|
||||
Returns:
|
||||
발화한 규칙 정보 리스트 (rule_id, side, dt, close).
|
||||
"""
|
||||
active = rules if rules is not None else load_monitor_rules()
|
||||
if not active:
|
||||
return []
|
||||
|
||||
lb = lookback_days if lookback_days is not None else MATCH_LIVE_LOOKBACK_DAYS
|
||||
rules_key = ",".join(r["rule_id"] for r in active)
|
||||
now = time.time()
|
||||
global _cache
|
||||
if (
|
||||
not force_refresh
|
||||
and _cache.get("frame") is not None
|
||||
and now - float(_cache.get("ts", 0)) < MATCH_LIVE_CACHE_SEC
|
||||
and _cache.get("rules_key") == rules_key
|
||||
):
|
||||
frame = _cache["frame"]
|
||||
else:
|
||||
mon = Monitor(cooldown_file=None)
|
||||
days = min(lb, CHART_LOOKBACK_DAYS)
|
||||
frames = load_frames_from_db(mon, SYMBOL, lookback_days=days)
|
||||
needed = conditions_columns(active)
|
||||
frame = build_mtf_scan_frame(frames, needed)
|
||||
_cache["ts"] = now
|
||||
_cache["frame"] = frame
|
||||
_cache["rules_key"] = rules_key
|
||||
|
||||
if frame.empty:
|
||||
return []
|
||||
|
||||
ts = frame.index[-1]
|
||||
row_frame = frame.iloc[[-1]]
|
||||
fired: list[dict[str, Any]] = []
|
||||
close_col = "close"
|
||||
for rule in active:
|
||||
if not eval_conditions(row_frame, rule["conditions"]).iloc[0]:
|
||||
continue
|
||||
fired.append(
|
||||
{
|
||||
"rule_id": rule["rule_id"],
|
||||
"side": rule["side"],
|
||||
"kind": rule.get("kind", ""),
|
||||
"dt": ts.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"close": float(row_frame[close_col].iloc[0]),
|
||||
}
|
||||
)
|
||||
return fired
|
||||
Reference in New Issue
Block a user