Add M5 pullback entry archetype (XAU_PB): +140R combined on 12mo
Second entry pattern alongside the Keltner-breakout: enter on the retrace to EMA21/KC-mid in an established trend (EMA >=3/4 aligned, ADX>=20, retrace 0.8-6.0 ATR, resumption bar closed back in trend direction, RSI in the pullback zone not the extended zone). Detector lives in the aggregator so live and GPU-backtest paths share one implementation. Own gates (composite floor 15, confirmation-TF agreement, MTF opposition, vol regimes) with a diagnostic funnel. PB stops anchor to the pullback swing (~$8 vs ~$25 breakout), so PB trades get their own trail arm (0.8R vs 0.6R global) via per-trade trail overrides in the backtester and strategy-aware Telegram alerts. 12mo M5 validation: PB alone +38.3R/254 trades, positive both halves and all four full quarters; core breakout trades undisturbed (+101.9R vs +105.0 baseline). Combined book: 549 trades (~10.6/wk), +140.1R, PF 1.78, DD 11.3R vs 311 trades/+105.0R before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+12
-7
@@ -255,18 +255,23 @@ def format_signal_message(report: SignalReport) -> str:
|
||||
lines.append(f"⚖️ RR: 1:{ts.risk_reward:.1f}")
|
||||
|
||||
# Trailing-stop management plan (matches backtested exit model:
|
||||
# TP1 is advisory, the trail is the exit).
|
||||
# TP1 is advisory, the trail is the exit). Pullback setups run
|
||||
# tighter stops and arm later.
|
||||
sig_cfg = PlatformConfig().signals
|
||||
if sig_cfg.trail_arm_r > 0:
|
||||
is_pb = getattr(ts, "strategy", "GENERIC") == "XAU_PB"
|
||||
arm_r = sig_cfg.pb_trail_arm_r if is_pb else sig_cfg.trail_arm_r
|
||||
dist_r = sig_cfg.pb_trail_dist_r if is_pb else sig_cfg.trail_dist_r
|
||||
if arm_r > 0:
|
||||
risk_dist = abs(ts.entry_price - ts.stop_loss)
|
||||
if ts.direction == "BUY":
|
||||
arm_price = ts.entry_price + sig_cfg.trail_arm_r * risk_dist
|
||||
arm_price = ts.entry_price + arm_r * risk_dist
|
||||
else:
|
||||
arm_price = ts.entry_price - sig_cfg.trail_arm_r * risk_dist
|
||||
trail_dist = sig_cfg.trail_dist_r * risk_dist
|
||||
arm_price = ts.entry_price - arm_r * risk_dist
|
||||
trail_dist = dist_r * risk_dist
|
||||
tag = " (pullback)" if is_pb else ""
|
||||
lines.append(
|
||||
f"🔄 Trail: once price hits `{_fmt_price(arm_price)}` "
|
||||
f"(+{sig_cfg.trail_arm_r:.1f}R), trail SL ${trail_dist:.2f} "
|
||||
f"🔄 Trail{tag}: once price hits `{_fmt_price(arm_price)}` "
|
||||
f"(+{arm_r:.1f}R), trail SL ${trail_dist:.2f} "
|
||||
f"behind best price — TP1 is a guide, let it run"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user