"""DeepQuant — live paper-account monitor (Phase 0, READ-ONLY). Shows the Alpaca PAPER account: equity, cash, today's P&L, open positions, and an equity curve vs the S&P 500. No order code exists in this phase — pure observation. Auto-refreshes every 30 minutes. """ import datetime as dt import json import os import ssl import urllib.request from zoneinfo import ZoneInfo _ET = ZoneInfo("America/New_York") import gradio as gr import pandas as pd from huggingface_hub import hf_hub_download import alpaca_client as ac import rebalance_engine as eng try: import certifi _CTX = ssl.create_default_context(cafile=certifi.where()) except Exception: _CTX = ssl.create_default_context() AV = os.environ.get("ALPHAVANTAGE_API_KEY", "") def fetch_spy_daily(): if not AV: return None try: u = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=SPY&outputsize=compact&apikey={AV}" d = json.load(urllib.request.urlopen(u, timeout=25, context=_CTX)).get("Time Series (Daily)", {}) return {dt.date.fromisoformat(k): float(v["5. adjusted close"]) for k, v in d.items()} except Exception: return None def _curve_pts(h): ts, eqv = h.get("timestamp", []), h.get("equity", []) return [(dt.datetime.fromtimestamp(t, _ET).replace(tzinfo=None), v) for t, v in zip(ts, eqv) if v] def _mk_df(rows): df = pd.DataFrame(rows) df["date"] = pd.to_datetime(df["date"]).astype("datetime64[ns]") return df def fetch_spy_intraday(): if not AV: return None try: u = f"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=SPY&interval=15min&outputsize=compact&apikey={AV}" d = json.load(urllib.request.urlopen(u, timeout=25, context=_CTX)).get("Time Series (15min)", {}) return {dt.datetime.strptime(k, "%Y-%m-%d %H:%M:%S"): float(v["4. close"]) for k, v in d.items()} except Exception: return None def _frozen_history(): """Frozen daily-equity record of the predecessor brokerage account (closed Oct 2026). The fund's history must not depend on any one brokerage account surviving — the live curve is this frozen record plus the current account's history, chain-linked.""" try: h = json.load(open(hf_hub_download("s-ttp/marketfm-panel", "deepquant_live_history.json", repo_type="dataset", token=os.environ.get("HF_TOKEN"), force_download=True))) return [(dt.datetime.fromisoformat(d), float(v)) for d, v in h["daily_equity"]], h.get("successor_base") except Exception: return [], None def build_curve(): """Returns (dataframe_or_None, note). Daily fund-vs-SPY once there's history; intraday today (both lines) for a young account.""" try: daily = _curve_pts(ac.get_portfolio_history("1A", "1D")) # full history since inception, not a trailing window except Exception: daily = [] # Alpaca stamps each session's closing equity at 00:00 UTC of the NEXT day (= 8 PM ET), # which renders every close ~80% of the way toward the following day's axis tick # (Friday's close shows up under "Saturday"). Snap each point to its trading date. daily = [(dt.datetime.combine(d.date(), dt.time.min), v) for d, v in daily] note = "" frozen, succ_base = _frozen_history() if frozen: splice = frozen[-1][0] new = [(d, v) for d, v in daily if d > splice] # chain-link: the successor account restarts at its own funding value, so scale its # curve so that the funding value continues the frozen record's last close exactly. # Anchoring on the recorded funding value (successor_base) rather than the first # close keeps the successor's own first-day P&L visible instead of absorbing it. anchor = succ_base or (new[0][1] if new else None) daily = frozen + ([(d, v * frozen[-1][1] / anchor) for d, v in new] if new else []) note = ("Chain-linked series: the brokerage account was re-provisioned in Oct 2026; " "history is the predecessor account's actual record, and the successor's curve is " "linked at the splice so fund performance is continuous. Account value shown may " "therefore differ from the raw successor-account balance.") if len(daily) >= 4: # enough daily history → daily fund vs SPY base = daily[0][1] rows = [{"date": d, "series": "DeepQuant (paper)", "value": round(v, 2)} for d, v in daily] spy = fetch_spy_daily() if spy: sd, first = sorted(spy), None for d, _v in daily: prior = [x for x in sd if x <= d.date()] if not prior: continue px = spy[prior[-1]] first = first or px rows.append({"date": d, "series": "S&P 500 (SPY)", "value": round(base * px / first, 2)}) return _mk_df(rows), note try: # young account → today's intraday, fund AND SPY intr = _curve_pts(ac.get_portfolio_history("1D", "15Min")) except Exception: intr = [] if len(intr) < 2: return None, "Equity curve builds once the account has trading history." base, lo, hi = intr[0][1], intr[0][0], intr[-1][0] rows = [{"date": d, "series": "DeepQuant (paper)", "value": round(v, 2)} for d, v in intr] spy = fetch_spy_intraday() if spy: inr = sorted(k for k in spy if lo - dt.timedelta(minutes=20) <= k <= hi + dt.timedelta(minutes=20)) if inr: first = spy[inr[0]] for k in inr: rows.append({"date": k, "series": "S&P 500 (SPY)", "value": round(base * spy[k] / first, 2)}) return _mk_df(rows), "Today's intraday — fund vs S&P 500. The multi-day curve builds over the coming sessions." def refresh(): now = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S") try: a = ac.get_account() clk = ac.get_clock() pos = ac.get_positions() except Exception as e: return (f"### ⚠️ Could not reach Alpaca\n`{type(e).__name__}: {str(e)[:160]}`", pd.DataFrame(), gr.update(visible=False), gr.update(value="—", visible=True), f"_Last checked {now}_") eq, last = float(a["equity"]), float(a.get("last_equity", a["equity"])) cash = float(a["cash"]) dpl = eq - last dpct = (dpl / last * 100) if last else 0.0 mkt = "🟢 open" if clk.get("is_open") else "🔴 closed" nxt = str(clk.get("next_open", ""))[:16].replace("T", " ") invested = eq - cash summary = ( f"## ${eq:,.2f}\n" f"**Today's P&L** {dpl:+,.2f} ({dpct:+.2f}%) · account **{a.get('status')}** · market {mkt}" + ("" if clk.get("is_open") else f" (next open {nxt})") + "\n\n" f"| Cash | Invested | Open positions | Currency |\n|---|---|---|---|\n" f"| ${cash:,.2f} | ${invested:,.2f} | {len(pos)} | {a.get('currency','USD')} |\n\n" f"Long-only strategy: margin and short-selling are never used, regardless of account permissions." ) rows = [] for p in pos: qty, mv = float(p["qty"]), float(p["market_value"]) rows.append({ "Symbol": p["symbol"], "Qty": round(qty, 4), "Avg entry": f'${float(p["avg_entry_price"]):,.2f}', "Last": f'${float(p["current_price"]):,.2f}', "Mkt value": f"${mv:,.2f}", "Weight": f"{mv / eq * 100:.1f}%" if eq else "—", "Unrealized P&L": f'${float(p["unrealized_pl"]):,.2f} ({float(p["unrealized_plpc"]) * 100:+.1f}%)', }) rows.sort(key=lambda r: -float(str(r["Mkt value"]).replace("$", "").replace(",", ""))) hidden = max(0, len(rows) - 10) rows = rows[:10] if hidden: rows.append({"Symbol": f"… +{hidden} more", "Qty": "", "Avg entry": "", "Last": "", "Mkt value": "undisclosed", "Weight": "", "Unrealized P&L": ""}) df = pd.DataFrame(rows) if rows else pd.DataFrame([{"Symbol": "— no open positions —"}]) curve, cnote = build_curve() stamp = f"_Last updated {now} · auto-refreshes every 30 min_" if curve is None: return (summary, df, gr.update(visible=False), gr.update(value=f"_{cnote}_", visible=True), stamp) note_upd = gr.update(value=f"_{cnote}_", visible=True) if cnote else gr.update(visible=False) return (summary, df, gr.update(value=curve, visible=True), note_upd, stamp) def load_health(): tok = os.environ.get("HF_TOKEN") if not tok: return "" try: r = json.load(open(hf_hub_download("s-ttp/marketfm-panel", "deepquant_health.json", repo_type="dataset", token=tok, force_download=True))) icon = {"OK": "🟢", "WATCH": "🟡", "ALERT": "🔴"} lines = [f"### 🩺 System health — {icon.get(r.get('overall'), '⚪')} {r.get('overall')} (checked {r.get('date')})"] for c in r.get("checks", []): lines.append(f"- {icon.get(c['status'], '⚪')} **{c['name']}** — {c['detail']}") try: rr = json.load(open(hf_hub_download("s-ttp/marketfm-panel", "recalibration_report.json", repo_type="dataset", token=tok, force_download=True))) tr = rr.get("tracking", {}) inc = rr.get("incumbent", {}) flag = "🔁" if rr.get("changed") else ("🟡" if rr.get("triggered") else "🟢") dec = rr.get("decision", "") if dec.startswith("[agentic] "): dec = dec[10:] act = dec.partition(":")[0].strip() lines.append(f"- {flag} **Autonomous recalibration agent** (weekly) — latest decision **{act}** " f"(reasoning & live strategy config under Strategy governance below)") except Exception: pass lines.append("Deterministic daily checks: live tracking gap located in the 20-year backtest distribution, " "risk guardrails, and pipeline freshness. Flags only — the supervisor never trades.") return "\n".join(lines) except Exception: return "" def load_governance(): tok = os.environ.get("HF_TOKEN") if not tok: return "" try: rr = json.load(open(hf_hub_download("s-ttp/marketfm-panel", "recalibration_report.json", repo_type="dataset", token=tok, force_download=True))) except Exception: return "" SIGMAP = {"n_mom_12_1": "momentum (12-1)", "n_roe": "ROE", "n_fcf_yield": "FCF yield", "n_roa": "ROA", "n_vol_13w": "low volatility"} DEFMAP = {"mom60_agg20_gld20": "60% stocks + 20% bonds + 20% gold", "mom40_agg30_gld30": "40% stocks + 30% bonds + 30% gold", "agg50_gld50": "50% bonds + 50% gold", "lowvol": "low-volatility stocks"} tr = rr.get("tracking", {}) inc = rr.get("incumbent", {}) dec = rr.get("decision", "") if dec.startswith("[agentic] "): dec = dec[10:] act, _, why = dec.partition(":") why = (why.strip() .replace("adopt_rate_limit_ok=false", "a strategy change is currently rate-limited") .replace("ADOPT is infeasible", "no change is possible this cycle") .replace("validator-approved candidates", "validated better variants") .replace("impl_alert", "implementation-drift alert").replace("SPY/MTUM", "the S&P 500 and the momentum factor")) if len(why) > 420: why = why[:420].rsplit(" ", 1)[0] + "…" CONMAP = {"n60_nocap": "≈60 AI-selected large caps · 10% position cap", "n50_nocap": "≈50 AI-selected large caps · 10% cap", "n75_nocap": "≈75 AI-selected large caps · 10% cap", "abs10_sec5": "10% cap · ≤5/sector"} REGMAP = {"gate20": "crisis-only severity gate (trend break + deep-drawdown confirmation)", "gate15": "severity gate (15%)", "cross10/40": "10/40-week trend crossover"} sig = "proprietary AI-researched quality signal (undisclosed)" return (f"### 🤝 Strategy governance — the crew's latest decision\n" f"**{act.strip()}** — {why}\n" f"- **Tracking:** 8-week gap vs S&P {tr.get('gap_8w_pp', '—')}pp — the {tr.get('pctile_8w', '—')}th percentile " f"of the strategy's 20-year history · implementation drift {tr.get('impl_drift_pp', '—')}pp vs its own simulation\n" f"- **Live strategy (v{inc.get('version', '?')}):** {sig} · {REGMAP.get(inc.get('regime'), inc.get('regime'))} · " f"defense = {DEFMAP.get(inc.get('defense'), inc.get('defense'))} · {CONMAP.get(inc.get('construction'), '10% cap · ≤5/sector')} · rebalanced every {inc.get('cadence_weeks', 1)} week(s)\n" f"- **Change policy:** decided weekly by an agentic crew — Analyst → adversarial Critic → PM (Claude Opus 5) — " f"gated by a code validator. A variant is adopted only if it beats the incumbent on the full 20-year " f"walk-forward, net of costs — never a re-fit to recent weeks; at most one change per 90 days. Any AI failure " f"defaults to HOLD.\n" f"Decided {rr.get('date', '')} · the full Analyst / Critic / PM reasoning is logged with every decision.") def load_rebalance(): tok = os.environ.get("HF_TOKEN") if not tok: return "" try: log = json.load(open(hf_hub_download("s-ttp/marketfm-panel", "deepquant_log.json", repo_type="dataset", token=tok, force_download=True))) if not log: return "" e = log[-1] if e.get("type") == "recalibration": head = f"### 🔁 Strategy recalibrated — {e.get('date','')}\n{e.get('summary','')}\n\n" if e.get("narration"): return head + f"> 💬 *{e['narration']}*\n\n— {e.get('narrated_by','MarketGuruLLM')}" return head mode = "🟢 OFFENSE" if e.get("mode") == "OFFENSE" else "🛡️ DEFENSE" head = (f"### 🗓️ Latest rebalance — {e.get('date','')} · {mode}\n" f"{e.get('buys',0)} buys · {e.get('sells',0)} sells · {e.get('turnover_pct',0)}% turnover · " f"{e.get('n_positions','—')} holdings\n\n") if e.get("narration"): return head + f"> 💬 *{e['narration']}*\n\n— {e.get('narrated_by','MarketGuruLLM')}" return head + f"{e.get('summary','')}" except Exception: return "" def rebalance_preview(): tok = os.environ.get("HF_TOKEN") if not tok: return "_Set the `HF_TOKEN` secret so DeepQuant can read the MarketFM target._", pd.DataFrame(), pd.DataFrame() try: tgt = eng.get_target(tok) acct = ac.get_account() eq = float(acct["equity"]) positions = {p["symbol"]: float(p["market_value"]) for p in ac.get_positions()} orders = eng.compute_orders(tgt["weights"], positions, eq, force_sells=float(acct.get("cash", 0)) < 0) except Exception as e: return f"### ⚠️ Could not build preview\n`{type(e).__name__}: {str(e)[:180]}`", pd.DataFrame(), pd.DataFrame() reg = tgt["regime"] mode = "🟢 OFFENSE" if reg["offense"] else "🛡️ DEFENSE" sma = (f"SPY 10-wk {reg['sma10']:,.0f} vs 40-wk {reg['sma40']:,.0f}" if reg.get("sma10") else reg.get("warn", "")) mix = "≈60 AI-selected stocks · 100% equity" if reg["offense"] else "60% stocks + 20% AGG + 20% GLD (crisis defense)" nb = sum(1 for o in orders if o["side"] == "BUY") ns = sum(1 for o in orders if o["side"] == "SELL") traded = sum(abs(o["delta"]) for o in orders) summ = (f"**{len(orders)} orders** — {nb} buys, {ns} sells · gross traded **${traded:,.0f}** " f"({traded / eq * 100:.0f}% turnover) · no-trade band skips deltas < ${0.005 * eq:,.0f}" if orders else "**No trades needed** — the account already matches the target within the no-trade band.") banner = (f"## {mode}\n**Regime:** {sma} · equity **${eq:,.0f}** · target: {mix}\n\n{summ}\n\n" f"Preview only — **no orders are placed**. This is exactly what the agent would submit at the next " f"Monday-after-open rebalance (notional market orders, sells before buys).") import collections as _c secagg = _c.defaultdict(float) for r in tgt["rows"]: secagg[r["sector"]] += r["weight"] tdf = pd.DataFrame([{"Sector": k, "Target %": f"{v*100:.1f}%", "Names": sum(1 for r in tgt["rows"] if r["sector"] == k)} for k, v in sorted(secagg.items(), key=lambda x: -x[1])]) if orders: buys = sum(o["delta"] for o in orders if o["side"] == "BUY") sells = sum(-o["delta"] for o in orders if o["side"] == "SELL") odf = pd.DataFrame([{"Side": "🟢 BUY", "Orders": sum(1 for o in orders if o["side"] == "BUY"), "Total": f"${buys:,.0f}"}, {"Side": "🔻 SELL", "Orders": sum(1 for o in orders if o["side"] == "SELL"), "Total": f"${sells:,.0f}"}]) else: odf = pd.DataFrame([{"Side": "— already at target —", "Orders": 0, "Total": "$0"}]) return banner, tdf, odf with gr.Blocks(title="DeepQuant — live paper monitor", theme=gr.themes.Soft()) as demo: gr.Markdown( "# 🤖 DeepQuant\n" "### The AI-managed fund — researched by AI, run by AI, governed by AI\n" "DeepQuant is managed end-to-end by artificial intelligence — **no human in the loop**. Its strategy was not " "designed by a portfolio manager: it was **discovered by AI research agents** that stress-tested more than **150 " "strategy configurations across 21 years of survivorship-free market data** — every candidate walk-forward " "validated, net of costs, across five market eras — before converging on the recipe running today.\n\n" "**The secret recipe:** the exact selection signal is proprietary. What we disclose: the fund holds **~60 U.S. " "large caps chosen by an AI-researched quality signal**, refreshed monthly — and a **crisis-only defense**: in " "confirmed severe bears (and only then) it shifts 40% into bonds and gold. No reaction to noise, corrections, " "or headlines. Every trade and every result is published here, live.\n\n" "**The AI stack:**\n" "- 🧠 **[MarketFM](https://huggingface.co/spaces/s-ttp/marketfm-ranker)** — the AI research platform: ≈11,800 US " "stocks, 4.1M stock-weeks, 21 point-in-time factors — the laboratory where the recipe was found and is re-verified\n" "- 🤝 **An AI investment committee** (Claude Opus 5) — every week an **Analyst** reviews the fund against its own " "20-year statistical envelope, an adversarial **Critic** attacks, and a **PM** rules: hold, adopt a better-proven " "variant, or pause — every action gated by a **code validator** (walk-forward proof required, rate-limited)\n" "- ⚙️ **Deterministic execution** — orders, risk rails (long-only, 10% cap, no leverage), market-hours gates, " "self-reconciliation: the parts where correctness must be provable are code, not judgment\n" "- 🩺 **AI self-diagnosis** — daily health checks published openly; deviation from the strategy's own history is " "flagged before anyone asks\n" "- 💬 **[MarketGuruLLM](https://huggingface.co/s-ttp/qwen25-14b-fin-lora)** — a fine-tuned analyst model explains " "every move in plain English\n\n" "**Simulated record of the recipe (2005–2026, walk-forward, net of costs):** ≈14%/yr vs the S&P 500's ≈11% · " "beat the index in **14 of 22 years** and **≈69% of all rolling 3-year windows** · 2008 cushioned to −29% · " "verified across 4 of 5 market eras.\n" "Fully autonomous, paper trading, read-only page. Strategy v2, live since September 2026; the v1 record is " "archived and available. Simulated results — past performance ≠ future. Not investment advice.") with gr.Tabs(): with gr.Tab("📊 Live account"): stats = gr.Markdown() health = gr.Markdown() rebal = gr.Markdown() gr.Markdown("### 📈 DeepQuant fund vs S&P 500") plot = gr.LinePlot(x="date", y="value", color="series", height=320, y_title="Account value ($)", x_title="") note = gr.Markdown(visible=False) gr.Markdown("### 📋 Top 10 holdings\nTop 10 by value. The full ~60-name book is not disclosed — " "the selection signal is the fund's proprietary, AI-researched recipe.") tbl = gr.Dataframe(wrap=True, interactive=False) gov = gr.Markdown() with gr.Row(): updated = gr.Markdown("_loading…_") btn = gr.Button("↻ Refresh now", scale=0) with gr.Tab("🎯 Objectives & record"): gr.Markdown( "## What this fund is built to do\n" "1. **Beat the S&P 500 over the holding periods real investors actually have.** The design objective is " "the rolling **3-year window**, not the calendar quarter: in the 21-year simulation the recipe beat the " "index in **≈69% of all rolling 3-year windows** and **16 of 22 calendar years**.\n" "2. **Deliver equity-like growth** — ≈14%/yr simulated, net of costs, vs the index's ≈11%.\n" "3. **Keep the journey survivable.** A crisis-only defense de-risks 40% into bonds and gold **only in " "confirmed severe bears** — it ignores ordinary corrections entirely. Simulated 2008: **−29%** while the " "index and quality peers took −33% to −37%; worst-case drawdown **−44%** vs the index's −55%.\n" "4. **Never chase noise.** Monthly discipline; changes only on walk-forward proof via the AI committee's " "code validator. Reacting to short-term underperformance was tested — it destroys ≈11%/yr — so the fund " "is built to refuse it.\n\n" "## Simulated record — the recipe, 2005–2026 (walk-forward, net of costs)\n") gr.Image("v2_backtest_chart.png", show_label=False, container=False, show_download_button=False, show_fullscreen_button=False) gr.Markdown( "| | DeepQuant (recipe) | S&P 500 |\n|---|---|---|\n" "| CAGR | **13.99%** | 10.86% |\n| Sharpe | **0.87** | 0.68 |\n" "| Max drawdown | **−44%** | −55% |\n| 2008 | **−29.0%** | −32.6% |\n" "| Calendar years won | **16 / 22** | — |\n| Rolling 3-yr windows won | **≈69%** | — |\n\n" "### Year-by-year (simulated, net)\n" "| Year | Fund | S&P 500 | | Year | Fund | S&P 500 |\n|---|---|---|---|---|---|---|\n" "| 2005 | +12.2 | +4.8 | | 2016 | +6.8 | +12.0 |\n" "| 2006 | +11.3 | +15.8 | | 2017 | **+34.5** | +21.7 |\n" "| 2007 | **+21.8** | +1.6 | | 2018 | −3.3 | −3.6 |\n" "| 2008 | **−29.0** | −32.6 | | 2019 | **+37.6** | +30.2 |\n" "| 2009 | **+33.6** | +22.7 | | 2020 | +21.0 | +18.2 |\n" "| 2010 | +15.3 | +15.1 | | 2021 | +31.6 | +28.7 |\n" "| 2011 | +5.2 | +1.9 | | 2022 | −24.6 | −18.2 |\n" "| 2012 | +16.1 | +19.2 | | 2023 | **+40.1** | +26.2 |\n" "| 2013 | +14.3 | +27.5 | | 2024 | **+32.3** | +26.1 |\n" "| 2014 | +13.7 | +14.5 | | 2025 | **+29.2** | +16.8 |\n" "| 2015 | +1.8 | +1.3 | | 2026* | +16.6 | +12.7 |\n\n" "*2026 through mid-June. **How to read this honestly:** every number above is a walk-forward " "simulation over a single historical realization — survivorship-free data, point-in-time fundamentals, " "net of modeled costs, the selection verified out-of-sample across 4 of 5 market eras — but simulated " "nonetheless, and simulations are typically upward-biased. The live record on the first tab, which began " "September 2026 at $100,000, is the only evidence that ultimately counts. The fund will trail the index " "in some years (see 2013, 2022 above) — by design it accepts scattered shallow losses to win the " "windows that matter. Not investment advice.") with gr.Tab("🔄 Rebalance preview"): gr.Markdown("What the deterministic engine **would** trade right now — the live target portfolio from the " "current (versioned) strategy config, diffed against the account. Display only: orders are placed " "solely by the scheduled Monday agent, inside its guardrails.") pv_banner = gr.Markdown() pbtn = gr.Button("⟳ Recompute preview", scale=0) with gr.Row(): with gr.Column(): gr.Markdown("**Target allocation by sector** (name-level book undisclosed)") tgt_tbl = gr.Dataframe(interactive=False, wrap=True) with gr.Column(): gr.Markdown("**Proposed orders** — aggregate (sells execute first)") ord_tbl = gr.Dataframe(interactive=False, wrap=True) with gr.Accordion("🧬 Why hybrid? Who decides what — and why", open=False): gr.Markdown( "The lesson from building this system: **neither pure determinism nor pure agency is enough.** Rules can't " "weigh ambiguous evidence; models can't be allowed to improvise with money. So each job goes to the framework " "that has *earned* it:\n\n" "| Responsibility | Framework | Why |\n|---|---|---|\n" "| Stock ranking & target weights | **Deterministic** (MarketFM factors + fixed rules) | Validated on a 20-year " "walk-forward, survivorship-free, net of costs — and reproducible to the penny |\n" "| Order execution & risk rails | **Deterministic** | Execution is arithmetic — the last place you want a model " "hallucinating. The rails (long-only, caps, no leverage) are code no one can override |\n" "| Daily monitoring | **Deterministic** | Statistical checks against the strategy's own history — e.g. \"is this " "drawdown inside the envelope of 280 historical 8-week windows?\" |\n" "| Weekly assessment & judgment | **Agentic** — a role-separated crew (Analyst → adversarial Critic → PM) on " "Claude Opus 5 | Weighing noisy, conflicting evidence is judgment; separating the roles makes each argument " "survive an adversarial challenge before any decision |\n" "| Strategy changes | **Hybrid** | The crew may adopt *only* variants that beat the incumbent across a bounded " "menu (selection signal × regime rule × defense sleeve × cadence) on the full 20-year walk-forward, net of cost — " "re-checked by a code validator; max one change per 90 days. Trigger on recent data, validate on all data |\n" "| Emergency brake | **Hybrid** | The crew can pause execution up to 2 weeks on operational anomalies; holding " "the validated book is always the safe default — and any AI failure automatically resolves to HOLD |\n" "| Explanations | **Agentic** (MarketGuruLLM) | Language is what language models are for |\n\n" "Every weekly decision is logged in full — the Analyst's assessment, the Critic's objections, the PM's ruling " "and the evidence they cite — and the current strategy configuration is versioned, so the fund's entire " "decision history is auditable. **AI proposes and judges; validated evidence admits; code enforces.**") timer = gr.Timer(1800) acct_outs = [stats, tbl, plot, note, updated] demo.load(refresh, None, acct_outs) btn.click(refresh, None, acct_outs) timer.tick(refresh, None, acct_outs) demo.load(load_rebalance, None, rebal) btn.click(load_rebalance, None, rebal) timer.tick(load_rebalance, None, rebal) demo.load(load_health, None, health) btn.click(load_health, None, health) timer.tick(load_health, None, health) demo.load(load_governance, None, gov) btn.click(load_governance, None, gov) timer.tick(load_governance, None, gov) pv_outs = [pv_banner, tgt_tbl, ord_tbl] demo.load(rebalance_preview, None, pv_outs) pbtn.click(rebalance_preview, None, pv_outs) if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False)