Chat
Show my 10 worst drawdown days over the last 6 months and what drove each.
    code
    import pandas as pd
    from arcana import sdk
    
    pf = sdk.portfolio("Global Alpha Fund")
    
    # 1 — Daily portfolio returns, trailing 6 months
    returns = pf.returns(start="2025-12-12", end="2026-06-12", freq="D")
    
    # 2 — The 10 worst drawdown days in the window
    worst = returns.sort_values("return_bps").head(10)
    
    # 3 — Position-level contributions on those dates
    contrib = pf.contributions(dates=worst.index)
    
    # 4 — Reconcile: contributions must sum back to the portfolio return.
    #     Tolerance: max(5 bps, 2% of |portfolio return|)  — hybrid rule
    check = contrib.groupby("date")["contribution_bps"].sum().to_frame("sum_bps")
    check["portfolio_bps"] = worst["return_bps"]
    check["residual_bps"] = (check["sum_bps"] - check["portfolio_bps"]).abs()
    check["tolerance_bps"] = pd.concat([
        pd.Series(5.0, index=check.index),
        0.02 * check["portfolio_bps"].abs(),
    ], axis=1).max(axis=1)
    check["reconciled"] = check["residual_bps"] <= check["tolerance_bps"]
    
    # 5 — Top 3 contributors per drawdown date
    top3 = (contrib.sort_values(["date", "contribution_bps"])
                   .groupby("date").head(3))
    
    print(worst.join(check[["residual_bps", "reconciled"]]))
    print(top3)
    output
    
                    
    No native widget answers this directly. Worst-day identification lives in performance; per-date position attribution lives in contribution analysis — no single surface joins them and reconciles the two. Code Mode ran the join deterministically rather than have the model estimate it. A native answer wasn't available for this question.
    Validation for Run 1 · original
    These checks reflect Run 1. You've edited the code — rerun to revalidate against your changes.
    Data
    Daily portfolio returns — Global Alpha Fund · 12 Dec 2025 → 12 Jun 2026
    Position-level daily contributions · 10 dates · Arcana performance store (as of 12 Jun 2026, 06:00 ET)
    Universe
    Positions held on each drawdown date (87–94 names)
    Method
    Identified the 10 lowest daily portfolio returns in the trailing 6 months, pulled position-level contributions for each date, and reconciled contributions against the portfolio return.
    Validation checks
    Residual
    Reconciled when |Σ position contributions − portfolio return| ≤ max(5 bps, 2% × |portfolio return|). Hybrid tolerance applied internally; constants owned by analytics. Residuals surface above; the formula stays in this disclosure (PRD §8).
    Showing the original run. You've edited the code — rerun to update this answer and its validation.
    What changed from Run 1
    You widened the reconciliation tolerance from 5 bps to 10 bps. The 2 dates previously outside tolerance — 07 Apr and 12 Mar — now reconcile, so the caveat is cleared and all 4 checks pass. Worst-day ranking and top contributors are unchanged.

    Three episodes account for 8 of your 10 worst days: the early-March semis selloff (4 days, NVDA the largest detractor on each), the mid-April financials drawdown (3 days, JPM-led), and the mid-February mega-cap pullback. NVDA appears among the top contributors on 5 of the 10 dates — your single largest drawdown driver this half.

    DatePortfolio returnTop contributors (bps)
    04 Mar 2026−212 bpsNVDA −58 · MSFT −41 · AVGO −33
    05 Mar 2026−187 bpsNVDA −49 · TSM −38 · AMD −27
    17 Apr 2026−166 bpsJPM −44 · GS −31 · MS −24
    13 Feb 2026−158 bpsAAPL −39 · AMZN −33 · META −29
    03 Mar 2026−141 bpsNVDA −36 · MSFT −30 · GOOGL −22
    16 Apr 2026−129 bpsJPM −33 · BAC −26 · C −19
    12 Feb 2026−117 bpsAMZN −31 · META −25 · NFLX −18
    07 Apr 2026−104 bpsXOM −28 · CVX −22 · COP −17
    21 Jan 2026−98 bpsLLY −26 · UNH −21 · JNJ −15
    12 Mar 2026−91 bpsNVDA −24 · AVGO −19 · QCOM −14
    Caveat: Position-level contributions did not fully reconcile with portfolio-level returns for 2 of the 10 drawdown dates, so those rows should be treated as directional. Affected dates are flagged in the table (07 Apr · 12 Mar).
    I couldn't complete this computation. Portfolio returns came back fine and the 10 worst days were identified, but the position-contribution request returned no data for 04–05 Mar 2026 even after retries — so the drawdowns can't be attributed reliably. No partial numbers; you can retry now, or rephrase to run without attribution.
    Prototype · Code Mode v2
    Run 1 — validation outcome
    Edit & rerun → live validation
    Expand thinking for the step timeline + retries · click the chip for the run-bound receipt · Edit code → type → Rerun shows divergence · keys 1–4 states
    Analytics events (live)
    Interact with the prototype — events stream here.