Scan M15/H1/D1/W1 only; grade symbols + legend on all messages
- SCAN_TIMEFRAMES: drop H4, add W1 (4 unique TFs → fewer API calls) - Confirmations updated to use only the 4 scan TFs (no H4 dependency) - Add _grade_symbol(): 🔥A+ ✅A 👍B ⚠️C 📉D ❌F - _GRADE_LEGEND shown on every /signal and /scan message - 🧠 icon on Signal Analysis and Scan Complete headers - /help grade guide updated with full symbol legend Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+25
-12
@@ -40,22 +40,24 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
# ── Config ──────────────────────────────────────────────────────────
|
# ── Config ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
SCAN_TIMEFRAMES = ["M15", "H1", "H4", "D1"]
|
SCAN_TIMEFRAMES = ["M15", "H1", "D1", "W1"]
|
||||||
|
|
||||||
_TF_MAP = {
|
_TF_MAP = {
|
||||||
"M5": Timeframe.M5, "M15": Timeframe.M15,
|
"M5": Timeframe.M5, "M15": Timeframe.M15,
|
||||||
"M30": Timeframe.M30, "H1": Timeframe.H1,
|
"M30": Timeframe.M30, "H1": Timeframe.H1,
|
||||||
"H4": Timeframe.H4, "D1": Timeframe.D1,
|
"H4": Timeframe.H4, "D1": Timeframe.D1,
|
||||||
|
"W1": Timeframe.W1,
|
||||||
}
|
}
|
||||||
|
|
||||||
_TF_CONFIRMATIONS = {
|
_TF_CONFIRMATIONS = {
|
||||||
"M15": [Timeframe.M5, Timeframe.H1],
|
"M15": [Timeframe.H1, Timeframe.D1],
|
||||||
"H1": [Timeframe.M15, Timeframe.H4],
|
"H1": [Timeframe.M15, Timeframe.D1],
|
||||||
"H4": [Timeframe.H1, Timeframe.D1],
|
"D1": [Timeframe.H1, Timeframe.W1],
|
||||||
"D1": [Timeframe.H4, Timeframe.W1],
|
"W1": [Timeframe.D1],
|
||||||
}
|
}
|
||||||
|
|
||||||
_GRADE_RANK = {"A+": 0, "A": 1, "B": 2, "C": 3, "D": 4, "F": 5}
|
_GRADE_RANK = {"A+": 0, "A": 1, "B": 2, "C": 3, "D": 4, "F": 5}
|
||||||
|
_GRADE_LEGEND = "Grade scale: 🔥 A+ · ✅ A · 👍 B · ⚠️ C · 📉 D · ❌ F"
|
||||||
_EST = ZoneInfo("America/New_York")
|
_EST = ZoneInfo("America/New_York")
|
||||||
|
|
||||||
# ── Formatting helpers ──────────────────────────────────────────────
|
# ── Formatting helpers ──────────────────────────────────────────────
|
||||||
@@ -75,6 +77,10 @@ def _signal_action(signal: SignalStrength) -> str:
|
|||||||
}.get(signal, "NEUTRAL")
|
}.get(signal, "NEUTRAL")
|
||||||
|
|
||||||
|
|
||||||
|
def _grade_symbol(quality: str) -> str:
|
||||||
|
return {"A+": "🔥", "A": "✅", "B": "👍", "C": "⚠️", "D": "📉"}.get(quality, "❌")
|
||||||
|
|
||||||
|
|
||||||
def _indicator_condition(ind) -> str:
|
def _indicator_condition(ind) -> str:
|
||||||
desc = ind.description
|
desc = ind.description
|
||||||
if " — " in desc:
|
if " — " in desc:
|
||||||
@@ -114,8 +120,9 @@ def _build_combined_signal(
|
|||||||
MTF detail block (folded to one line), news unless non-neutral.
|
MTF detail block (folded to one line), news unless non-neutral.
|
||||||
"""
|
"""
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
lines.append(f"🌐 <b>{_h(display)} — Signal Analysis</b>")
|
lines.append(f"🌐 🧠 <b>{_h(display)} — Signal Analysis</b>")
|
||||||
lines.append(f"🕐 {now_str}")
|
lines.append(f"🕐 {now_str}")
|
||||||
|
lines.append(f"<i>{_GRADE_LEGEND}</i>")
|
||||||
|
|
||||||
for tf in SCAN_TIMEFRAMES:
|
for tf in SCAN_TIMEFRAMES:
|
||||||
reports = results_by_tf.get(tf, [])
|
reports = results_by_tf.get(tf, [])
|
||||||
@@ -137,10 +144,11 @@ def _build_combined_signal(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
action = _signal_action(r.final_signal)
|
action = _signal_action(r.final_signal)
|
||||||
|
sym = _grade_symbol(r.signal_quality)
|
||||||
|
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("────────────────────────")
|
lines.append("────────────────────────")
|
||||||
lines.append(f"<b>{tf} · {action} · Grade {_h(r.signal_quality)}</b>")
|
lines.append(f"{sym} <b>{tf} · {action} · Grade {_h(r.signal_quality)}</b>")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
|
|
||||||
# ── Trade setup (always kept intact) ─────────────────────────
|
# ── Trade setup (always kept intact) ─────────────────────────
|
||||||
@@ -207,15 +215,17 @@ def _build_scan_message(
|
|||||||
Full entry/TP/SL preserved; no indicator list (use /signal to drill in).
|
Full entry/TP/SL preserved; no indicator list (use /signal to drill in).
|
||||||
"""
|
"""
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
lines.append(f"📊 <b>Scan Complete</b> · {now_str}")
|
lines.append(f"📊 🧠 <b>Scan Complete</b> · {now_str}")
|
||||||
lines.append(f"Timeframes: <code>{_h(tfs_str)}</code> | Best signal per pair")
|
lines.append(f"Timeframes: <code>{_h(tfs_str)}</code> | Best signal per pair")
|
||||||
|
lines.append(f"<i>{_GRADE_LEGEND}</i>")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
|
|
||||||
for tf, r in actionable:
|
for tf, r in actionable:
|
||||||
action = _signal_action(r.final_signal)
|
action = _signal_action(r.final_signal)
|
||||||
|
sym = _grade_symbol(r.signal_quality)
|
||||||
|
|
||||||
lines.append(
|
lines.append(
|
||||||
f"<b>{_h(r.display_name)} · {action}</b>"
|
f"{sym} <b>{_h(r.display_name)} · {action}</b>"
|
||||||
f" · {_h(r.signal_quality)} · {tf}"
|
f" · {_h(r.signal_quality)} · {tf}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -325,9 +335,12 @@ class ForexTelegramBot:
|
|||||||
" /help — This message\n\n"
|
" /help — This message\n\n"
|
||||||
f"<b>Timeframes analyzed:</b> <code>{tfs}</code>\n\n"
|
f"<b>Timeframes analyzed:</b> <code>{tfs}</code>\n\n"
|
||||||
"<b>Signal Grades:</b>\n"
|
"<b>Signal Grades:</b>\n"
|
||||||
" A / A+ — High confidence, consider entry\n"
|
" 🔥 A+ — Strongest signal, MTF aligned, high confidence\n"
|
||||||
" B — Decent setup, wait for confirmation\n"
|
" ✅ A — Strong signal, MTF aligned\n"
|
||||||
" C / D — Low confidence, watch only\n\n"
|
" 👍 B — Decent setup, wait for confirmation\n"
|
||||||
|
" ⚠️ C — Weak signal, watch only\n"
|
||||||
|
" 📉 D — Very weak, no action\n"
|
||||||
|
" ❌ F — No clear signal\n\n"
|
||||||
"<i>⚠️ Educational use only. Not financial advice.</i>"
|
"<i>⚠️ Educational use only. Not financial advice.</i>"
|
||||||
)
|
)
|
||||||
await update.message.reply_text(text, parse_mode=ParseMode.HTML)
|
await update.message.reply_text(text, parse_mode=ParseMode.HTML)
|
||||||
|
|||||||
Reference in New Issue
Block a user