移植 A_Share_DP 引擎;本地缓存与 60s tip;月线由日线 UTC 聚合;不碰主站 analyze/缠论叠层。 Co-authored-by: Cursor <cursoragent@cursor.com>
79 lines
2.7 KiB
Python
79 lines
2.7 KiB
Python
"""Phase Engine — Phase A–E via Rule Registry."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from crypto_wyckoff.domain_models import EngineResult, WyckoffPhase
|
||
from crypto_wyckoff.rules.registry import rule_registry
|
||
|
||
|
||
class PhaseEngine:
|
||
name = "Phase"
|
||
version = "1.0.0"
|
||
|
||
def run(self, cycle: EngineResult, feature: EngineResult, timeframe: str) -> EngineResult:
|
||
if feature.payload.get("insufficient") or cycle.payload.get("cycle") == "Unknown":
|
||
return EngineResult(
|
||
name=self.name,
|
||
version=self.version,
|
||
confidence=20.0,
|
||
score=30.0,
|
||
reasons=["数据/周期不足,Phase=None"],
|
||
warnings=["insufficient_features"],
|
||
payload={
|
||
"phase": WyckoffPhase.NONE.value,
|
||
"timeframe": timeframe,
|
||
"cycle": cycle.payload.get("cycle"),
|
||
"structure_score": 30.0,
|
||
},
|
||
)
|
||
|
||
context = {
|
||
"features": feature.payload,
|
||
"cycle": cycle.payload,
|
||
"timeframe": timeframe,
|
||
}
|
||
hits = []
|
||
for rule in rule_registry.by_category("phase", timeframe):
|
||
hit = rule.evaluate(context)
|
||
if hit and hit.phase:
|
||
hits.append(hit)
|
||
|
||
if not hits:
|
||
return EngineResult(
|
||
name=self.name,
|
||
version=self.version,
|
||
confidence=40.0,
|
||
score=cycle.score * 0.5,
|
||
reasons=["未识别明确 Phase"],
|
||
payload={
|
||
"phase": WyckoffPhase.NONE.value,
|
||
"timeframe": timeframe,
|
||
"cycle": cycle.payload.get("cycle"),
|
||
"structure_score": cycle.score * 0.5,
|
||
},
|
||
)
|
||
|
||
best = max(hits, key=lambda h: h.confidence)
|
||
structure_score = best.score
|
||
# Phase D/E stronger structure
|
||
if best.phase in (WyckoffPhase.D.value, WyckoffPhase.E.value):
|
||
structure_score = max(structure_score, 80.0)
|
||
elif best.phase == WyckoffPhase.C.value:
|
||
structure_score = max(structure_score, 72.0)
|
||
|
||
return EngineResult(
|
||
name=self.name,
|
||
version=self.version,
|
||
confidence=best.confidence,
|
||
score=structure_score,
|
||
reasons=best.reasons,
|
||
metrics=best.metrics,
|
||
payload={
|
||
"phase": best.phase,
|
||
"timeframe": timeframe,
|
||
"cycle": cycle.payload.get("cycle"),
|
||
"rule_id": best.rule_id,
|
||
"structure_score": structure_score,
|
||
},
|
||
)
|