"""DeepQuant — deterministic rebalance engine (Phase 1: compute only, no execution). Reproduces the MarketFM Tactical target portfolio and diffs it against the live account in DOLLARS, trading only the change. No order is placed here — compute_orders returns the list the agent *would* submit. Execution (Phase 2) consumes this same output, guardrailed. """ import json import os import ssl import urllib.request import numpy as np import pandas as pd from huggingface_hub import hf_hub_download try: import certifi _CTX = ssl.create_default_context(cafile=certifi.where()) except Exception: _CTX = ssl.create_default_context() PANEL_REPO = os.environ.get("MARKETFM_REPO", "s-ttp/marketfm-panel") AV = os.environ.get("ALPHAVANTAGE_API_KEY", "") SEG_K, SECTOR_CAP, SIZE, MAX_W = 1000, 5, 50, 0.10 # top-1000 by mktcap, ≤5/sector, 50 names, 10% cap DEF_EQ, DEF_AGG, DEF_GLD = 0.60, 0.20, 0.20 # defense: 60% stocks + 20% bonds + 20% gold ETF = {"AGG": ("iShares Core US Aggregate Bond ETF", "Bonds (ETF)"), "GLD": ("SPDR Gold Shares", "Gold (ETF)")} def cap_weights(w, mw=MAX_W): w = np.asarray(w, float) for _ in range(30): over = w > mw + 1e-9 if not over.any(): break excess = (w[over] - mw).sum() w[over] = mw under = ~over if w[under].sum() <= 0: break w[under] += excess * w[under] / w[under].sum() return w def detect_regime(): try: u = f"https://www.alphavantage.co/query?function=TIME_SERIES_WEEKLY_ADJUSTED&symbol=SPY&apikey={AV}" ts = json.load(urllib.request.urlopen(u, timeout=25, context=_CTX))["Weekly Adjusted Time Series"] s = pd.Series({k: float(v["5. adjusted close"]) for k, v in ts.items()}).sort_index() sma10, sma40 = s.rolling(10).mean().iloc[-1], s.rolling(40).mean().iloc[-1] return {"offense": bool(sma10 >= sma40), "sma10": float(sma10), "sma40": float(sma40), "spy": float(s.iloc[-1])} except Exception as e: return {"offense": True, "sma10": None, "sma40": None, "spy": None, "warn": f"SPY fetch failed ({type(e).__name__}); defaulting to OFFENSE"} def equity_sleeve(token): p = hf_hub_download(PANEL_REPO, "marketfm_snapshot.parquet", repo_type="dataset", token=token) df = pd.read_parquet(p) df = df[df["marketcap"].notna() & (df["marketcap"] > 0)].copy() df = df.sort_values("marketcap", ascending=False).head(SEG_K) df["score"] = df["n_mom_12_1"].fillna(0) + df["n_roe"].fillna(0) df = df.sort_values("score", ascending=False) picked, sec = [], {} for _, r in df.iterrows(): if sec.get(r["sector"], 0) >= SECTOR_CAP: continue sec[r["sector"]] = sec.get(r["sector"], 0) + 1 picked.append(r) if len(picked) >= SIZE: break mc = np.array([r["marketcap"] for r in picked], float) w = cap_weights(mc / mc.sum()) return [{"ticker": r["ticker"], "name": r.get("name"), "sector": r["sector"], "weight": float(wi)} for r, wi in zip(picked, w)] def get_target(token): reg = detect_regime() sleeve = equity_sleeve(token) if reg["offense"]: rows = [dict(x) for x in sleeve] else: rows = [dict(x, weight=DEF_EQ * x["weight"]) for x in sleeve] for sym, (nm, sct) in ETF.items(): rows.append({"ticker": sym, "name": nm, "sector": sct, "weight": DEF_AGG if sym == "AGG" else DEF_GLD}) weights = {r["ticker"]: r["weight"] for r in rows} return {"regime": reg, "weights": weights, "rows": rows} def compute_orders(weights, positions, equity, band_pct=0.005): """positions: {symbol: market_value $}. Returns order list (sells first), trading only the delta.""" band = band_pct * equity orders = [] for sym in set(weights) | set(positions): tw = weights.get(sym, 0.0) tgt = tw * equity cur = positions.get(sym, 0.0) delta = tgt - cur cw = (cur / equity) if equity else 0.0 if tw == 0 and cur > 0: # dropped from basket → full exit (always) orders.append({"symbol": sym, "side": "SELL", "delta": -cur, "cur_w": cw, "tgt_w": 0.0, "exit": True}) elif cur == 0 and tgt > 1.0: # establish a new target position (always; band can't block it) orders.append({"symbol": sym, "side": "BUY", "delta": tgt, "cur_w": 0.0, "tgt_w": tw, "exit": False}) elif abs(delta) < band: # churn guard: skip small adjustments to EXISTING positions continue else: orders.append({"symbol": sym, "side": "BUY" if delta > 0 else "SELL", "delta": delta, "cur_w": cw, "tgt_w": tw, "exit": False}) orders.sort(key=lambda o: (0 if o["side"] == "SELL" else 1, -abs(o["delta"]))) # sells first return orders