"""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)