Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 88 additions & 2 deletions agents/macro_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,87 @@ def _fmt(val, fmt=".1f", default="N/A") -> str:
return default


def _format_drawdown_leg(substrate: dict) -> str:
"""Render the deterministic drawdown de-risk leg (3rd ensemble leg)
+ the composed ``effective_regime`` as a continuous, market-grounded
statement.

Absent-key fallback: when the upstream substrate carries no
``drawdown`` block (pre-#176/#179 producer, or producer omitted it),
returns ``""`` so the prompt is byte-identical to the prior HMM-only
path — zero behavior change for the macro agent.

Portfolio-unavailable fallback: when ``drawdown.excess.available`` is
False (paper NAV short/gappy or not wired), the SPY leg still renders
and the excess line states it is unavailable — never raises.
"""
dd = substrate.get("drawdown")
if not isinstance(dd, dict):
return ""

spy = dd.get("spy") or {}
excess = dd.get("excess") or {}
spy_dd = spy.get("drawdown")
spy_tier = spy.get("tier", "N/A")
spy_off = (
f"{-float(spy_dd) * 100:.1f}% off its trailing peak"
if isinstance(spy_dd, (int, float))
else "depth N/A"
)

if excess.get("available"):
nav_dd = excess.get("nav_drawdown")
depth = excess.get("excess_depth")
nav_off = (
f"{-float(nav_dd) * 100:.1f}% off NAV high-water mark"
if isinstance(nav_dd, (int, float))
else "NAV depth N/A"
)
depth_str = (
f"{float(depth) * 100:.1f}pp deeper than the market"
if isinstance(depth, (int, float))
else "excess depth N/A"
)
excess_line = (
f" - book: {nav_off}; {depth_str} "
f"(tier = {excess.get('tier', 'N/A')})\n"
)
else:
excess_line = (
" - book-vs-market excess: UNAVAILABLE (paper NAV "
"short/gappy or not wired) — the SPY leg still acts.\n"
)

eff = substrate.get("effective_regime") or {}
if isinstance(eff, dict):
eff_label = eff.get("effective_regime", "N/A")
drivers = eff.get("drivers", {}) or {}
driver_str = ", ".join(
f"{k}={v}" for k, v in drivers.items() if v
) or "none escalating"
else:
# latest.json sidecar carries effective_regime as a bare string
eff_label = eff if isinstance(eff, str) else "N/A"
driver_str = "n/a (sidecar shape)"

return (
"\n"
" DETERMINISTIC DRAWDOWN DE-RISK LEG (3rd ensemble leg — "
"pure-level hysteresis, zero estimation risk):\n"
" This is the continuous, market-grounded reframe of the HMM "
"filter run-length above — a real peak-to-trough statement, not "
"a label-stability artifact.\n"
f" - SPY: {spy_off} (tier = {spy_tier})\n"
f"{excess_line}"
f" - composed effective_regime = {eff_label} "
f"(most-protective over {{{driver_str}}})\n"
" The composed effective_regime is what the discrete gates "
"(entry halt, bear caps, veto) act on downstream — observe-mode "
"until promoted. You remain the FINAL authority on the regime "
"narrative; weigh this leg as a strong de-risk prior.\n"
)


def _format_regime_substrate(substrate: Optional[dict]) -> str:
"""Render the quantitative regime substrate into a compact prompt
block for the LLM. Returns a fallback message when None.
Expand Down Expand Up @@ -169,8 +250,13 @@ def _format_regime_substrate(substrate: Optional[dict]) -> str:
f" - P(bear) = {_fmt(probs.get('bear'), '.2f')}\n"
f" - P(neutral) = {_fmt(probs.get('neutral'), '.2f')}\n"
f" - P(bull) = {_fmt(probs.get('bull'), '.2f')}\n"
f" - argmax = {hmm.get('argmax', 'N/A')}, "
f"weeks_in_current_state = {hmm.get('weeks_in_current_state', 'N/A')}\n"
f" - argmax = {hmm.get('argmax', 'N/A')}\n"
f" - filter run-length = "
f"{hmm.get('weeks_in_current_state', 'N/A')} week(s) "
f"(HMM filter-argmax stability DIAGNOSTIC — NOT a "
f"market-duration statement; see the drawdown leg below for the "
f"continuous market-grounded view)\n"
f"{_format_drawdown_leg(substrate)}"
"\n"
f" Composite intensity (AQR-style risk-on/risk-off, positive = risk-on):\n"
f" - intensity_z = {_fmt(composite.get('intensity_z'), '+.2f')} "
Expand Down
61 changes: 53 additions & 8 deletions graph/research_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -2270,8 +2270,19 @@ def _change_of(a: dict):
cs = a.get("regime_change_signal")
return bool(cs)

def _weeks_in_state(a: dict):
return (a.get("hmm") or {}).get("weeks_in_current_state")
def _eff_of(a: dict) -> str:
eff = a.get("effective_regime")
if isinstance(eff, dict):
return eff.get("effective_regime") or "—"
# latest.json sidecar carries it as a bare string
return eff if isinstance(eff, str) else "—"

def _spy_dd_cell(a: dict) -> str:
spy = ((a.get("drawdown") or {}).get("spy")) or {}
dd = spy.get("drawdown")
if not isinstance(dd, (int, float)):
return "—"
return f"{-dd * 100:.1f}% ({spy.get('tier', '?')})"

def _fmt_iz(iz) -> str:
return f"{iz:+.2f}" if isinstance(iz, (int, float)) else "—"
Expand All @@ -2280,17 +2291,25 @@ def _fmt_iz(iz) -> str:
f"**Weekly regime substrate — last {len(artifacts)} run(s) "
f"(oldest → newest):**",
"",
"| Date | HMM Regime | Intensity-z | BOCPD Change | Weeks in State |",
"|------|------------|-------------|--------------|----------------|",
"| Date | HMM Regime | Intensity-z | BOCPD Change | "
"SPY Drawdown | Effective |",
"|------|------------|-------------|--------------|"
"--------------|-----------|",
]
for a in artifacts:
wic = _weeks_in_state(a)
wic_str = str(wic) if isinstance(wic, (int, float)) else "—"
lines.append(
f"| {_date_of(a)} | {_argmax_of(a)} | {_fmt_iz(_iz_of(a))} | "
f"{'yes' if _change_of(a) else 'no'} | {wic_str} |"
f"{'yes' if _change_of(a) else 'no'} | {_spy_dd_cell(a)} | "
f"{_eff_of(a)} |"
)
lines.append("")
lines.append(
"_HMM filter run-length (\"weeks in state\") is intentionally "
"omitted — it is a label-stability diagnostic, not a "
"market-duration statement; the continuous drawdown depth below "
"is the market-grounded view._"
)
lines.append("")

if len(artifacts) == 1:
only = artifacts[0]
Expand Down Expand Up @@ -2336,7 +2355,33 @@ def _fmt_iz(iz) -> str:
else:
gr_summary = "no guardrail breached"

lines.append(f"**Summary:** {iz_summary}; {gr_summary}.")
# Continuous drawdown statement (latest artifact) — the
# market-grounded reframe of the dropped "weeks in state" count.
# Absent-key fallback: omit the clause entirely when the producer
# wrote no drawdown block (pre-#176/#179) — no behavior change.
dd = latest.get("drawdown") or {}
spy = dd.get("spy") or {}
spy_dd = spy.get("drawdown")
dd_clause = ""
if isinstance(spy_dd, (int, float)):
parts = [
f"SPY {-spy_dd * 100:.1f}% off trailing peak "
f"(tier {spy.get('tier', '?')})"
]
ex = dd.get("excess") or {}
if ex.get("available"):
nav_dd = ex.get("nav_drawdown")
depth = ex.get("excess_depth")
if isinstance(nav_dd, (int, float)):
parts.append(f"book {-nav_dd * 100:.1f}% off NAV HWM")
if isinstance(depth, (int, float)):
parts.append(f"{depth * 100:.1f}pp deeper than market")
else:
parts.append("book NAV unavailable — SPY leg only")
eff = _eff_of(latest)
dd_clause = f" Drawdown leg: {'; '.join(parts)}; effective={eff}."

lines.append(f"**Summary:** {iz_summary}; {gr_summary}.{dd_clause}")
return lines


Expand Down
104 changes: 103 additions & 1 deletion tests/test_email_redesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ def _artifact(
change: bool = False,
weeks_in_state: int = 1,
guardrails: dict | None = None,
drawdown: dict | None = None,
effective_regime: dict | str | None = None,
) -> dict:
return {
art = {
"run_id": run_id,
"trading_day": trading_day,
"calendar_date": trading_day,
Expand All @@ -73,6 +75,12 @@ def _artifact(
"active_severity_floor": None,
},
}
# Additive drawdown leg (present only post-#176/#179 producer).
if drawdown is not None:
art["drawdown"] = drawdown
if effective_regime is not None:
art["effective_regime"] = effective_regime
return art


def _base_state(**overrides) -> dict:
Expand Down Expand Up @@ -357,3 +365,97 @@ def test_guardrail_breach_surfaced_in_summary(self):
lines = _build_regime_trend(am, n_weeks=8)
joined = "\n".join(lines)
assert "guardrail breached: vix_bear_breached" in joined

# ── Drawdown leg (3rd ensemble leg, #176/#179) ──────────────────────

def _dd_block(self, *, spy_dd, spy_tier, excess=None):
block = {
"spy": {
"tier": spy_tier,
"drawdown": spy_dd,
"peak": 600.0,
"regime_contribution": (
{"risk_on": None, "caution": "caution",
"risk_off": "bear"}.get(spy_tier)
),
},
"excess": excess or {
"available": False, "tier": "risk_on",
"nav_drawdown": None, "excess_depth": None,
"regime_contribution": None,
},
}
return block

def test_drawdown_columns_and_continuous_summary(self):
"""The dropped 'weeks in state' count is reframed to a
continuous SPY-drawdown column + composed effective regime, and
the summary carries the market-grounded continuous statement."""
am = _FakeArchiveManager([
_artifact(run_id="2605010000", trading_day="2026-05-01",
argmax="neutral", iz=0.1,
drawdown=self._dd_block(spy_dd=-0.012, spy_tier="risk_on"),
effective_regime={"effective_regime": "neutral",
"drivers": {"hmm": "neutral"}}),
_artifact(run_id="2605080000", trading_day="2026-05-08",
argmax="bear", iz=1.2,
drawdown=self._dd_block(
spy_dd=-0.082, spy_tier="caution",
excess={"available": True, "tier": "alpha_bleed",
"nav_drawdown": -0.115,
"excess_depth": 0.033,
"regime_contribution": "bear"}),
effective_regime={"effective_regime": "bear",
"drivers": {"hmm": "bear",
"drawdown_excess": "bear"}}),
])
lines = _build_regime_trend(am, n_weeks=8)
joined = "\n".join(lines)
# New columns present; legacy column header gone.
assert "SPY Drawdown" in joined and "Effective" in joined
assert "Weeks in State" not in joined
# Continuous depth + tier in the row, composed regime surfaced.
assert "8.2% (caution)" in joined
assert "| bear |" in joined
# Run-length explicitly de-emphasised as a diagnostic.
assert "label-stability diagnostic" in joined
# Continuous market-grounded summary clause.
assert "Drawdown leg:" in joined
assert "SPY 8.2% off trailing peak" in joined
assert "book 11.5% off NAV HWM" in joined
assert "3.3pp deeper than market" in joined
assert "effective=bear" in joined

def test_drawdown_absent_key_no_behavior_change(self):
"""Pre-#176/#179 artifacts (no drawdown block) render '—' in the
new cells and the summary carries no Drawdown-leg clause."""
am = _FakeArchiveManager([
_artifact(run_id="2605010000", trading_day="2026-05-01",
argmax="neutral", iz=0.1),
_artifact(run_id="2605080000", trading_day="2026-05-08",
argmax="neutral", iz=0.3),
])
lines = _build_regime_trend(am, n_weeks=8)
joined = "\n".join(lines)
assert "**Summary:**" in joined
assert "Drawdown leg:" not in joined # absent-key fallback
assert "| — | — |" in joined # SPY DD + Effective both em-dash

def test_drawdown_portfolio_unavailable_falls_back_to_spy_only(self):
am = _FakeArchiveManager([
_artifact(run_id="2605010000", trading_day="2026-05-01",
argmax="neutral", iz=0.1,
drawdown=self._dd_block(spy_dd=-0.02, spy_tier="risk_on"),
effective_regime={"effective_regime": "neutral",
"drivers": {}}),
_artifact(run_id="2605080000", trading_day="2026-05-08",
argmax="caution", iz=0.9,
drawdown=self._dd_block(spy_dd=-0.061, spy_tier="caution"),
effective_regime={"effective_regime": "caution",
"drivers": {"drawdown_spy": "caution"}}),
])
lines = _build_regime_trend(am, n_weeks=8)
joined = "\n".join(lines)
assert "SPY 6.1% off trailing peak" in joined
assert "book NAV unavailable — SPY leg only" in joined
assert "effective=caution" in joined
6 changes: 4 additions & 2 deletions tests/test_max_tokens_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@
# critic ever generates verbose output.
# Line moved 462 → 476 by the all-agents-strict rework (added the
# langchain_utils import + an explicit max_retries=
# SECTOR_TEAM_LLM_MAX_RETRIES kwarg on the critic ChatAnthropic).
# SECTOR_TEAM_LLM_MAX_RETRIES kwarg on the critic ChatAnthropic),
# then 476 → 562 by the drawdown-leg surface (added
# _format_drawdown_leg + the continuous-statement reframe).
# Same intentional 512-literal critic call, just relocated.
"agents/macro_agent.py": {476},
"agents/macro_agent.py": {562},
}


Expand Down
Loading
Loading