fix(web): 自动刷新保留 K 线视窗;威科夫与图表增量更新
自动刷新改用 tail update 与 scrollToPosition 恢复视窗,避免 setData 后跳到最右;拆分 chart_tv 模块并扩展 analyze/recent API。同步威科夫分析、pipeline 增量构建及相关策略与配置。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""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,
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user