[verified] Signal column now derives from theme engine (combined 60/40 + quality), not tourism_result
- /api/v1/factors signal no longer from tourism-only signals; derived from RealDashboard combined score: LONG>=0.15, SHORT<=-0.15, else NEUTRAL. One source of truth. - Verified: LONG 25 / NEUTRAL 16 / SHORT 8; BANPU LONG (3 themes), KTB LONG (banks), CPN LONG (3 themes), JMART SHORT (nonbank) — reflects all 13 themes + per-symbol quality, not flat tourism. - reason_codes + combined_score on each factor row.
This commit is contained in:
@@ -455,8 +455,33 @@ def create_app(config: dict[str, Any] | None = None) -> Flask:
|
|||||||
from app import siamchart_factors
|
from app import siamchart_factors
|
||||||
|
|
||||||
factor_view = siamchart_factors.build_factor_view()
|
factor_view = siamchart_factors.build_factor_view()
|
||||||
current = app.extensions["tourism_result"]
|
# signal = derived from the NEW theme-engine combined score (60/40 with
|
||||||
signal_by_symbol = {s["symbol"]: s for s in current["signals"]}
|
# per-symbol quality), NOT the old tourism_result. One source of truth.
|
||||||
|
from app import daily_cache
|
||||||
|
from app.dashboard import RealDashboard
|
||||||
|
cache = app.extensions.setdefault("daily_cache", daily_cache.DailyCache())
|
||||||
|
current = app.extensions.get("tourism_result") or {}
|
||||||
|
signal_by_symbol = {}
|
||||||
|
try:
|
||||||
|
dash = RealDashboard(current.get("signals", []), cache).build()
|
||||||
|
for row in dash.get("board", []):
|
||||||
|
comb = row.get("combined")
|
||||||
|
if comb is None:
|
||||||
|
signal_by_symbol[row["symbol"]] = {"side": None, "score": None}
|
||||||
|
continue
|
||||||
|
if comb >= 0.15:
|
||||||
|
side, score = "LONG", round(min(abs(comb) * 3.0, 1.0) * 0.9 + 0.1, 3)
|
||||||
|
elif comb <= -0.15:
|
||||||
|
side, score = "SHORT", round(min(abs(comb) * 3.0, 1.0) * 0.9 + 0.1, 3)
|
||||||
|
else:
|
||||||
|
side, score = "NEUTRAL", round(abs(comb) / 0.15, 3)
|
||||||
|
signal_by_symbol[row["symbol"]] = {
|
||||||
|
"side": side, "score": score, "confidence": "medium",
|
||||||
|
"combined_score": comb,
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
# no dashboard -> fall back to neutral for all
|
||||||
|
pass
|
||||||
|
|
||||||
merged = []
|
merged = []
|
||||||
for factor in factor_view.get("factors", []):
|
for factor in factor_view.get("factors", []):
|
||||||
@@ -467,8 +492,9 @@ def create_app(config: dict[str, Any] | None = None) -> Flask:
|
|||||||
"signal_side": sig.get("side"),
|
"signal_side": sig.get("side"),
|
||||||
"signal_score": sig.get("score"),
|
"signal_score": sig.get("score"),
|
||||||
"signal_confidence": sig.get("confidence"),
|
"signal_confidence": sig.get("confidence"),
|
||||||
"signal_target_weight": sig.get("target_weight"),
|
"combined_score": sig.get("combined_score"),
|
||||||
"reason_codes": sig.get("reason_codes", []),
|
"signal_target_weight": None,
|
||||||
|
"reason_codes": ["combined 60/40 + firm quality"] if sig.get("side") in ("LONG", "SHORT") else [],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# Put symbols that carry a non-neutral signal first, then by signal score.
|
# Put symbols that carry a non-neutral signal first, then by signal score.
|
||||||
|
|||||||
Reference in New Issue
Block a user