AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Parallax Explain Portfolio

skill-bencharoenwong-parallax-workflows-parallax-explain-portfolio · by bencharoenwong

Reactive portfolio performance attribution: decompose a drawdown into market/regime, factor/thematic, and stock-specific components. Also called 'drawdown attribution' or 'performance attribution' in PM/RIA vocabulary. Uses score-vs-price divergence to determine if the loss is fundamental or transient, then gives conditional advice. Triggered when a client asks 'why am I down X%?'. Holdings as [{…

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add skill-bencharoenwong-parallax-workflows-parallax-explain-portfolio

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bencharoenwong-parallax-workflows-parallax-explain-portfolio)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
yesterday

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Parallax Explain Portfolio? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Explain Portfolio

When not to use

  • Proactive portfolio health check → use /parallax-portfolio-checkup
  • Scheduled client meeting prep → use /parallax-client-review
  • Hypothetical scenario / news event → use /parallax-scenario-analysis
  • Rebalancing trade recommendations → use /parallax-rebalance
  • Single stock analysis → use /parallax-should-i-buy

Gotchas

  • JIT-load _parallax/parallax-conventions.md for RIC resolution, parallel execution, fallbacks
  • JIT-load _parallax/house-view/loader.md FIRST; if active view present, follow §2 (validation), §5 (output rendering), §6 (audit). For attribution, the view provides additional context: a drawdown in a view-tilted-overweight sector is "expected pain from view exposure"; a drawdown in a view-tilted-underweight sector raises "why was this still held?" — surface in the verdict.
  • When active view is present, use the view-aware disclaimer per loader.md §5 rule 5; otherwise use the standard disclaimer
  • Holdings must be in RIC format with weights summing to ~1.0
  • exportpriceseries returns daily OHLCV — use close prices for return calculation
  • gettelemetry regimetag and mechanism fields are the key attribution inputs
  • Score-vs-price divergence is the core insight — scores stable + price down = transient; scores falling + price down = fundamental
  • Score data is weekly (getscoreanalysis) vs daily price data — there may be a ~7 day lag. Acknowledge this gap in the divergence analysis, especially if major news broke after the last score data point.
  • The client said a number ("down 4%") — verify it against actual computed returns before attributing
  • Cap news calls at top 3 detractors to manage token cost
  • quickportfolioscores may fail for concentrated/niche portfolios — fall back to getscoreanalysis (Step 3) as the primary factor source
  • getpeersnapshot may return a different company as target (see Convention #2) — extract the queried stock's scores from the peer list, not from the target_company field
  • JIT-load _parallax/white-label/integration-pattern.md before the Pre-Render step. Loader call is load_visual_branding() (7-key visual subset; voice structurally excluded — branding["voice"] raises KeyError). Apply §5 (Branding Header) and §7 (About This Report) in Output Format.

Reactive performance attribution when a client asks "why am I down?" Decomposes the loss into market/regime, factor/thematic, and stock-specific layers, then determines if the drawdown is fundamental or noise.

Usage

/parallax-explain-portfolio [{"symbol":"AAPL.O","weight":0.25},{"symbol":"JPM.N","weight":0.20},{"symbol":"MSFT.O","weight":0.30},{"symbol":"JNJ.N","weight":0.25}] "I'm down about 4% this month"

The second argument is the client's stated concern — used to anchor the lookback period and validate against actual returns.

Workflow

Execute using mcp__claude_ai_Parallax__* tools. JIT-load _parallax/parallax-conventions.md for execution mode, fallback patterns, and macro reasoning. JIT-load _parallax/house-view/loader.md for active-view validation and output rendering.

Step 0 — Tool Loading & Active House View

Call ToolSearch with query "+Parallax" to load the deferred MCP tool schemas before the first mcp__claude_ai_Parallax__* call.

Per loader.md §1-§2. If view present, capture tilt vector. The view does NOT change attribution math (Steps 1-5) — it shapes the Step 6 verdict and the framing of Step 4 stock-specific findings. Specifically: when a top detractor is in a view-OW sector, the loss is "expected from view exposure"; when in a view-UW sector that wasn't trimmed, the loss raises a portfolio-management question.

Step 1 — Measure actual performance

Infer lookback period from the client's statement ("this month" → ~21 trading days, "this week" → 5 days, "this quarter" → ~63 days). Default to 21 days if ambiguous.

Step 1a — Asset-class pre-classification (parallel, MANDATORY)

export_price_series is the equity-only price endpoint; ETFs (SPY, QQQ, IEFA, EWJ, etc.) silently return empty from it and would otherwise be dropped from portfolio-return attribution — a HIGH-IMPACT bias. Before pulling price history, classify each holding:

  • For each holding, call etf_profile() in parallel.
  • If response is {"error": "No profile data found", ...} → treat as equity, route through export_price_series.
  • If response returns an ETF profile (non-error) → treat as ETF, route through etf_daily_price.

This adds N calls at 1 token each (one per holding) — see _parallax/token-costs.md.

Step 1b — Pull price history (parallel, split by asset class)

Fire ALL of the following in a single tool-call turn:

  • For each EQUITY holding → export_price_series(symbol=, days=, format="json")
  • For each ETF holding → etf_daily_price(symbol=, start_date=, end_date=)
Step 1c — Compute attribution + halt rule

Compute:

  • Per-holding return over the period (close-to-close)
  • Weighted contribution to portfolio return: holding return × weight
  • Total portfolio return (sum of weighted contributions)
  • Rank holdings by contribution (biggest detractors first)

Halt rule (no silent drops): if any holding returns empty/error from BOTH etf_profile AND its routed endpoint, the skill MUST surface this explicitly:

> ⚠ Cannot compute return for ` — neither exportpriceseries nor etfdailyprice returned data. This holding is **not** included in the attribution below; the reported portfolio return is computed on the remaining %` of weight. Operator decision required: supply prices externally, or remove from the portfolio for this analysis.

Render this banner above the attribution table — never silently zero or skip a holding.

Compare computed return against the client's stated figure. If they diverge significantly (>1%), note the discrepancy.

Step 2 — Attribution layer 1: Market and regime (parallel)

| Tool | Parameters | Purpose | |---|---|---| | get_telemetry | fields: regime_tag, signals, commentary.headline, commentary.mechanism, divergences | Current market regime — is the whole market down? | | list_macro_countries | — | Check coverage for home markets | | get_peer_snapshot | per holding | Primary scoring source for PARALLAX_LOADER_V2=1. Aggregate scores client-side per loader.md §3b. | | get_company_info | per holding (parallel) | Ground-truth oracle per loader.md §5 rule 3 (required universally). Records expected_name for mismatch check. | | quick_portfolio_scores | holdings | Legacy/V1 path only. Do NOT use if PARALLAX_LOADER_V2=1 and view active. |

After Step 2: cross-check returned names against get_company_info names per loader.md §5 rule 3. For PARALLAX_LOADER_V2=1, any mismatch in get_peer_snapshot is flagged ⚠ MISMATCH and excluded from aggregate calculations. For V1, any mismatch in quick_portfolio_scores is re-scored individually.

After Batch: call macro_analyst with component="tactical" for each home market (cap at 2). This establishes the macro backdrop: is this a market-wide drawdown, sector rotation, or idiosyncratic?

If quick_portfolio_scores fails or returns `):

DRAFT="$(mktemp "${TMPDIR:-/tmp}/explain.XXXXXX")"
cat > "$DRAFT" 
REPORT
python3 "/../_parallax/render_gate.py" --skill explain-portfolio ** portfolio attribution`. Logo handling per integration-pattern.md §5: empty path → text only; URL → embed; absolute local (`/` or `~`) → skip embed and append `Logo on file: ` to About This Report.
- **What Happened** (computed portfolio return over the period, compared to client's stated figure; 1-sentence summary of the loss magnitude)
- **Performance Attribution** (table: each holding with return, weighted contribution, and primary driver tag — Market / Factor / Stock-Specific; if view active, add "View Exposure" tag — OW / Neutral / UW per the view)
- **Market & Regime Context** (regime tag, mechanism, 2-3 sentences on what's driving markets; is the broad market down too?)
- **Factor Exposure** (which factor tilts helped/hurt; connection to the current regime; if view active, note whether realized factor exposure matched view's intended tilts)
- **Top Detractors** (for each of top 3: what happened, why, and whether scores agree with the price move; flag whether the holding's view-exposure tag means the loss was expected pain from the view)
- **The Key Question: Noise or Signal?** (score-vs-price divergence summary — portfolio-level verdict with per-holding classification table)
- **What To Do** (conditional advice based on the verdict; if view active, separate "stay-the-course-per-view" actions from "view says trim anyway" actions)
- **About This Report** (always present): one line stating branding state per integration-pattern.md §7 markdown column (render per table; do not collapse). If a logo was skipped per the Branding Header rule, append `Logo on file: ` as a second About This Report line.

Append audit log entry per loader.md §6.

Keep tone calm and explanatory. The client is worried — the output should reduce anxiety with clarity, not amplify it with jargon.

**AI-interaction disclosure (required regardless of view state):** Render `parallax-conventions.md §9.2` immediately above the disclaimer below.

If active view: end with the view-aware disclaimer per loader.md §5 rule 5. Otherwise: render the standard disclaimer verbatim from `parallax-conventions.md` §9.1.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [bencharoenwong](https://github.com/bencharoenwong)
- **Source:** [bencharoenwong/parallax-workflows](https://github.com/bencharoenwong/parallax-workflows)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.