agent_panel: plain-language output — simple, short, no jargon/acronyms

Owner request: panel notes and rationale must read like plain everyday
English for a non-trader. Style rule added to the shared take contract
and synthesizer prompt, all few-shot examples rewritten in the target
voice (examples carry the style), and the Telegram votes line now spells
out full stances ("macro: support") instead of "macro:sup".

Before: "BUY against Bollinger SELL and price above upper band; 4h
neutral, mixed MTF"  →  After: "The price is above its usual range, and
the bigger picture is not clearly rising, so buying now is risky."

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SisdfkxnXNL9iZsXxN3T15
This commit is contained in:
Harwinder Sekhon
2026-08-07 22:50:10 -04:00
parent e85ca9409e
commit 764cbc8a3d
3 changed files with 17 additions and 6 deletions
+15 -4
View File
@@ -77,6 +77,11 @@ geopolitical stress / weak dollar are gold-bullish.
_TAKE_CONTRACT = """\ _TAKE_CONTRACT = """\
Your review is advisory research on an already-generated signal; you are Your review is advisory research on an already-generated signal; you are
one voice on a panel, not the decision maker. one voice on a panel, not the decision maker.
Write the note in plain everyday English for someone who has never
traded: short simple sentences, no trading jargon, no acronyms, no
abbreviations. Say "profit versus loss", not "RR"; "the 4-hour chart",
not "H4"; describe what an indicator MEANS ("the price has climbed
unusually fast"), never its name or number.
Reply with ONLY JSON: Reply with ONLY JSON:
{"stance": "support"|"oppose"|"neutral", "confidence": <0-100>, {"stance": "support"|"oppose"|"neutral", "confidence": <0-100>,
"note": "<max 25 words>"} "note": "<max 25 words>"}
@@ -98,7 +103,7 @@ high-impact event is a reason for lower confidence, not a direction.
""" + _GOLD_DOCTRINE + """\ """ + _GOLD_DOCTRINE + """\
Example: brief direction BUY, headlines dominated by hawkish Fed Example: brief direction BUY, headlines dominated by hawkish Fed
repricing and a hot CPI print -> {"stance": "oppose", "confidence": 70, repricing and a hot CPI print -> {"stance": "oppose", "confidence": 70,
"note": "hot CPI and hawkish repricing lift real yields against gold"} "note": "Inflation is running hot, so interest rates should stay high — that usually pushes gold down."}
""" + _TAKE_CONTRACT """ + _TAKE_CONTRACT
_TECH_SYSTEM = """\ _TECH_SYSTEM = """\
@@ -115,7 +120,7 @@ disagreeing, price pressed into a key level, or an exhausted move being
chased. chased.
Example: brief direction SELL in regime trending_up with H1 and H4 both Example: brief direction SELL in regime trending_up with H1 and H4 both
BUY -> {"stance": "oppose", "confidence": 80, BUY -> {"stance": "oppose", "confidence": 80,
"note": "counter-trend sell against aligned higher timeframes"} "note": "This bets on gold falling while the bigger picture still points up."}
""" + _TAKE_CONTRACT """ + _TAKE_CONTRACT
_RISK_SYSTEM = """\ _RISK_SYSTEM = """\
@@ -132,7 +137,7 @@ to hit. A missing setup means the signal graded too low for one —
oppose unless the rest is exceptional. oppose unless the rest is exceptional.
Example: RR 1.4 with volatility extreme and a high-impact event due -> Example: RR 1.4 with volatility extreme and a high-impact event due ->
{"stance": "oppose", "confidence": 65, {"stance": "oppose", "confidence": 65,
"note": "thin reward for extreme volatility into event risk"} "note": "The possible profit is small for such wild price swings, and big economic news is due soon."}
""" + _TAKE_CONTRACT """ + _TAKE_CONTRACT
_CONTRARIAN_SYSTEM = """\ _CONTRARIAN_SYSTEM = """\
@@ -147,7 +152,7 @@ and "support" when even the skeptic finds nothing that bites.
""" + _GOLD_DOCTRINE + """\ """ + _GOLD_DOCTRINE + """\
Example: a BUY whose own engine lists three bearish reasons and a Example: a BUY whose own engine lists three bearish reasons and a
counter-trend warning -> {"stance": "oppose", "confidence": 60, counter-trend warning -> {"stance": "oppose", "confidence": 60,
"note": "engine's own bearish evidence outweighs the entry trigger"} "note": "The system's own list of negatives looks stronger than its reason to buy."}
""" + _TAKE_CONTRACT """ + _TAKE_CONTRACT
_SYNTH_SYSTEM = """\ _SYNTH_SYSTEM = """\
@@ -159,6 +164,12 @@ Weigh the takes into ONE consensus on whether to act on the signal:
or "NEUTRAL" (genuinely split or low conviction). Weigh a high- or "NEUTRAL" (genuinely split or low conviction). Weigh a high-
confidence oppose from any single analyst seriously — one strong veto confidence oppose from any single analyst seriously — one strong veto
can outweigh two lukewarm supports. Do not average blindly. can outweigh two lukewarm supports. Do not average blindly.
Write the rationale in plain everyday English for someone who has never
traded: short simple sentences, no trading jargon, no acronyms, no
abbreviations.
Example rationale: "Three of four analysts are against this: the
possible profit is too small and the price has already climbed
unusually fast. Only the news backdrop supports buying."
Reply with ONLY JSON: Reply with ONLY JSON:
{"verdict": "AGREE"|"NEUTRAL"|"OPPOSE", "confidence": <0-100>, {"verdict": "AGREE"|"NEUTRAL"|"OPPOSE", "confidence": <0-100>,
"rationale": "<max 40 words>"} "rationale": "<max 40 words>"}
+1 -1
View File
@@ -417,7 +417,7 @@ def format_signal_message(report: SignalReport) -> str:
f"{_escape_md(report.panel_rationale)}") f"{_escape_md(report.panel_rationale)}")
if report.panel_takes: if report.panel_takes:
votes = " · ".join( votes = " · ".join(
f"{t['persona']}:{t['stance'][:3]}" for t in report.panel_takes) f"{t['persona']}: {t['stance']}" for t in report.panel_takes)
extra.append(f" _{_escape_md(votes)}_") extra.append(f" _{_escape_md(votes)}_")
if extra: if extra:
lines += [""] + extra lines += [""] + extra
+1 -1
View File
@@ -7252,7 +7252,7 @@ def _():
msg = tb.format_signal_message(report) msg = tb.format_signal_message(report)
assert "AI Panel" in msg and "OPPOSE" in msg and "(64%)" in msg assert "AI Panel" in msg and "OPPOSE" in msg and "(64%)" in msg
assert "counter-trend against aligned H4" in msg assert "counter-trend against aligned H4" in msg
assert "macro:sup" in msg and "technical:opp" in msg assert "macro: support" in msg and "technical: oppose" in msg
@test("backtest parity: analyze_from_dataframes never populates panel") @test("backtest parity: analyze_from_dataframes never populates panel")