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

Parallax Portfolio Builder

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

Build a portfolio from a natural language investment thesis. Constructs universe, scores, checks redundancy, and outputs allocation-ready list via Parallax MCP tools. Supports `--augment-silent` mode to fill active house view gaps from Parallax data for the current portfolio (saved view never mutates). Trigger for that mode: 'fill house view gaps from Parallax data for this portfolio'. NOT for an…

No reviews yet
0 installs
0 views
view→install

Install

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

✓ 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-portfolio-builder)

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 Portfolio Builder? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Portfolio Builder

When not to use

  • Analyzing existing portfolio → use /parallax-client-review
  • Screening without allocation → use /parallax-thematic-screen
  • Single stock analysis → use /parallax-should-i-buy
  • Rebalancing existing portfolio → use /parallax-rebalance

Gotchas

  • JIT-load _parallax/parallax-conventions.md for RIC resolution, parallel execution, and fallback patterns
  • JIT-load _parallax/house-view/loader.md FIRST; if active view present, follow §2 (validation), §3 (multipliers), §4 (conflict resolution), §5 (output rendering), §6 (audit)
  • When active view is present, use the view-aware disclaimer per loader.md §5; otherwise use the standard disclaimer
  • buildstockuniverse returns relevance-ranked results — re-rank by factor scores for quality
  • Run redundancy check BEFORE finalizing allocation to avoid sector concentration
  • analyze_portfolio responses often exceed 180K chars. Use streaming JSON extraction (Step 6) instead of waiting for full response; stream validation results progressively to user as they arrive.
  • Weights should sum to ~1.0 in final output
  • Include both the allocation table AND the factor rationale for each pick
  • The saved house view never carries Parallax-derived overlays. When the active view is silent on a dimension this portfolio decision needs, EITHER (a) treat as neutral [default — non-blocking, RM-fan-out-safe] OR (b) JIT-augment via --augment-silent flag with provenance tagged per holding [auditable]. Never fold augmentation back into the saved view.
  • View-status banner is REQUIRED first thing in output when active view exists — never bury after the holdings table. If execution gets compressed, this is the section that must NOT be dropped. RM uses the banner as the primary signal that the view is active and what's being applied.
  • Phase A Parallelization: View load and universe build run in parallel (view load is fast; universe build is the latency bottleneck). Both complete before Phase B begins.
  • 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.
  • Optional audience= argument: client_safe | internal_analyst; precedence follows parallax-conventions.md §13.1.

Construct a portfolio from a plain-English investment thesis using Parallax MCP tools.

Usage

/parallax-portfolio-builder "defensive dividend-focused Asian equities under $10B market cap"
/parallax-portfolio-builder "US tech companies with strong quality and momentum scores" top_n=10
/parallax-portfolio-builder "ESG leaders in European industrials"
/parallax-portfolio-builder "EM-tilt balanced" --augment-silent   # JIT-augment dimensions the active view is silent on (default: off)
/parallax-portfolio-builder "defensive dividend-focused Asian equities" audience=client_safe

Workflow

Call ToolSearch with query "+Parallax" to load the deferred MCP tool schemas before the first mcp__claude_ai_Parallax__* call. Execute using mcp__claude_ai_Parallax__* tools. JIT-load _parallax/parallax-conventions.md for execution mode and fallback patterns. JIT-load _parallax/house-view/loader.md for active-view validation, tilt application, and conflict-resolution rules.

Pre-flight: house-view drift check

JIT-load _parallax/house-view/auto-on-load-judge-pattern.md and follow its protocol. If the protocol surfaces a banner, render it before proceeding to this skill's main workflow.

Skip this pre-flight if invoked with --skip-drift-check or if no active house view exists.

Phase A — Parallel Initialization & Scoring

Execute Steps 0–2 in parallel. All three must complete before Phase B begins. Best-effort error handling: if any step fails (timeout, validation error), flag it, continue with fallback, and proceed to Phase B.

Step 0: Load Active House View (parallel with Step 1 & 2)

  • Per loader.md §1-§2: read view if present, validate hash and expiry, capture tilt vector + excludes + extraction-confidence warnings. If validation fails, run without view per loader.md §2 "Failure handling." If no view present, proceed normally.
  • Fallback on timeout (rare): log warning, continue with empty view. Non-blocking.

Step 1: Build Universe (parallel with Step 0 & 2)

  • Resolve user thesis vs. view per loader.md §4. If view present, prepend tilt context to the query (e.g., "exclude tech, overweight defensive sectors"). Call build_stock_universe. Force-include any sectors/themes with view tilt = +2 if absent from initial candidates.
  • Step 1a: Divergence assertion (per loader.md §5 rule 4) — if the tilt-prepended query named N≥2 sectors/themes, compute max_sector_share / total in returned candidates. If > 0.6, emit fail-loud warning: "universe collapsed to single sector despite multi-sector request." Do NOT proceed with a collapsed universe. Default action (per loader.md §5 rule 4 post-2026-04-24): re-issue as N parallel per-sector build_stock_universe calls and merge/dedupe by symbol (keep highest-rank hit on collisions). Fall back to refusing to render only if the per-sector re-issue is itself skewed (e.g., some requested sectors return zero results). Known upstream limitation on the single-call path.
  • Fallback on timeout: retry once with narrower query (e.g., single sector from thesis). If still times out, set universe = [] and universe_status = "unavailable", continue to Phase B with the empty candidate list, and flag the unavailable state in output under "Universe Built". Do NOT call check_portfolio_redundancy as a placeholder — it requires a holdings parameter and will fail or return nonsense without one.
  • Step 1b: JIT augmentation gate (opt-in) — After universe is built, identify dimensions the THESIS depends on but the active view is silent on. Default behavior (non-blocking, RM-fan-out-safe): treat silent dimensions as neutral, render a one-line note in output: Active view is silent on ; using neutral. Run with --augment-silent to fill from Parallax data for THIS portfolio. Opt-in --augment-silent: JIT-load _parallax/house-view/gap_detect + gap_suggest. Construct a synthetic "draft view" from the active view but with the THESIS-relevant silent dimensions explicitly enumerated. Call gap_detect.detect_gaps() scoped to those dimensions. Call gap_suggest.plan_calls(gaps, available_markets=mcp__claude_ai_Parallax__list_macro_countries()["markets"]). Fire the planned MCP calls in parallel. gap_suggest.fold_responses() → list of Suggestions. Apply each Suggestion as a tilt only for THIS portfolio decision — do NOT write back to ~/.parallax/active-house-view/. Tag each augmented dimension with [parallax_jit, []@] for the output table's "Tilt Source" column.
  • Step 1b-bis: Augmentation-not-used invitation — If the user did NOT pass --augment-silent AND Step 1b's gap detection found ≥1 thesis-relevant silent dimension, render this single line in output (between the universe-built section and the Selected Holdings table): ℹ Active view is silent on (relevant to your thesis). Re-run with --augment-silent to fill these from current Parallax data for THIS portfolio (saved view never mutates). Single line, no AskUserQuestion (RM-fan-out-safe — does not block invocation). Skip if no silent dims found OR if --augment-silent was already passed.

Step 2: Score Top Picks (parallel with Step 0 & 1)

  • For top N (default 10), fire all N get_peer_snapshot calls AND all N get_company_info calls in a single tool-call turn — 2N calls dispatching simultaneously. Do NOT iterate one-at-a-time; that is the dominant latency leak in this skill. Both tools are independent per _parallax/parallax-conventions.md §3.
  • Prefer per-holding get_peer_snapshot aggregation over batch quick_portfolio_scores for portfolio factor profile — the batch tool has a symbol-mapping bug (see parallax-conventions.md §2) that mis-attributes scores to the wrong company for most non-US tickers. Only use quick_portfolio_scores after every returned company_name has been cross-validated against get_company_info.
  • Fallback on timeout: if N > 5, retry with top 5 only and flag in output. If single-call timeouts persist, degrade to quickportfolioscores with name validation.

Phase B — Sequential Selection, Validation & Optimization

Begin only after Phase A completes. Steps 3–6 have tight dependencies; execute sequentially.

Empty-universe gate (REQUIRED FIRST CHECK): If universe_status = "unavailable" from Phase A Step 1 (Build Universe), skip Steps 3-6 entirely. Render Output Format with Universe Built flagged as "unavailable" and no Selected Holdings table. Append an audit log entry per loader.md §6 noting the abort. Do NOT call check_portfolio_redundancy, analyze_portfolio, or quick_portfolio_scores — these tools require holdings input and the universe failure means no holdings exist to validate.

Step 3: Rank & Select

  • If view present, re-rank by composite × multiplier(holding's sector/region/theme) per loader.md §3 multiplier tables. Apply factor tilt re-weighting per loader.md §3 "Factor tilts." Drop candidates that match tilts.excludes (surface block message per loader.md §4 exception). Select top holdings (default 5-8).

Step 4: Redundancy Check

  • Call check_portfolio_redundancy with proposed equal-weight allocation. Sanity-check the response: if the portfolio has >60% concentration in a single sector but sector_concentration: {} is empty and "well-diversified" is returned, the tool's concentration detection has silently failed — compute concentration client-side from per-holding sectors and flag the tool bug in output.

Step 5: Optimize Weights

  • Adjust weights based on scores, redundancy flags, sector balance, AND tilt multipliers. Cap any single sector at 2× its neutral exposure when view is +2 (loader.md §3 cap rule). For factor profile verification, aggregate per-holding get_peer_snapshot scores weighted by portfolio weight (do NOT rely on quick_portfolio_scores unless all company names validated).

Step 6: Validate (streaming)

  • Call analyze_portfolio on the final allocation with stream=true to enable streaming JSON extraction. Fallback for large responses: use streaming; if streaming unavailable or times out, fall back to check_portfolio_redundancy + quick_portfolio_scores for light validation.
  • Sanity-check check_portfolio_redundancy response in this fallback path (mirrors Step 4): if the portfolio has >60% concentration in a single sector but sector_concentration: {} is empty and "well-diversified" is returned, the tool's concentration detection has silently failed — compute concentration client-side from per-holding sectors and flag the tool bug in output. The Step 4 sanity-check gate must fire on the fallback path as well, not only on the primary call.
  • Scope of this fallback: check_portfolio_redundancy + quick_portfolio_scores covers redundancy and basic factor coverage only. analyze_portfolio fields that are NOT recoverable from the fallback — rolling metrics, drawdown analysis, contribution attribution, performance time series — must be flagged as "unavailable in fallback path" in output. Do not silently omit them; the operator must know what wasn't validated.
  • Symbol-mapping caveat (mirrors parallax-conventions.md §2): quick_portfolio_scores on this fallback path is subject to the same symbol-mapping bug — non-US ticker scores may be mis-attributed. Cross-validate every company_name returned by quickportfolioscores against get_company_info before treating any score as authoritative. Mismatches flagged ⚠ MISMATCH and excluded from validation output per Step 2 / loader.md §5 rule 3.
  • When --augment-silent was applied: the audit entry MUST carry augmented_dimensions: [{path, source_tool, source_call_args, data_as_of}] so the per-portfolio JIT augmentation provenance is on the audit chain and recoverable for compliance review. When --augment-silent was NOT applied but silent dimensions existed, log silent_dimensions_skipped: [...] so the auditor can see what wasn't filled.
  • Append audit log entry per loader.md §6.

Pre-Render — Load white-label branding

Load _parallax/white-label/integration-pattern.md §2 and compute white_label_active + client_name per that section. Apply §5 (Branding Header) and §7 (About This Report) when composing the Output Format. The loader returns exactly seven keys; any other access (e.g. branding["voice"]) raises KeyError — structurally enforced by loader.py.

Render — deterministic gate (LAST step, mandatory)

Compose the complete report per Output Format below, then run it through the shared render gate in one Bash step before replying. Use a private mktemp file (never a fixed/predictable path — /tmp symlink hazard). The shared gate is _parallax/render_gate.py, a sibling of the directory you loaded this SKILL.md from; pass this skill's key (use the loaded directory's absolute path as ``):

DRAFT="$(mktemp "${TMPDIR:-/tmp}/builder.XXXXXX")"
cat > "$DRAFT" 
REPORT
python3 "/../_parallax/render_gate.py" --skill portfolio-builder `. If `--augment-silent` was used, append `JIT-augmented: `. This preamble is the user's primary signal that the view is active and what it's doing. If execution gets token-compressed, KEEP this section — drop other sections first if needed.
- **Branding Header** (only if `white_label_active` AND `client_name != ""`) — single line immediately below the House View Preamble (or at the very top if no view): `**** portfolio construction`. 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.
- **Investment Thesis** (restate and refine the user's intent; note any view-vs-thesis conflicts inline per loader.md §4)
- **Universe Built** (how many candidates, key sectors; note force-includes from +2 tilts and excludes applied; surface divergence-assertion result per loader.md §5 rule 4)
- **Why These Holdings**: 2-3 plain-language sentences summarizing why the selected names fit the stated thesis; no factor jargon without the §13.3 gloss. Rendered in both audience modes.
- **Selected Holdings** (table: `input_ticker`, `returned_name` (from scoring-tool response), `expected_name` (from get_company_info), sector, total score, weight, key factor strengths; if view active, include a "Tilt Effect" column showing the multiplier applied to each holding AND a "Tilt Source" column tagging the dimension's source. Under `audience=client_safe`, move the `Tilt Effect` / `Tilt Source` columns out of the primary table into a trailing **Methodology appendix (internal)** section that reproduces the full row × dimension tag map. **Tilt Source enforcement (compliance contract):** EVERY row × dimension cell MUST carry a non-empty tag in `{[house_view: =], [parallax_jit, []@], [neutral, ]}`. If any cell would be empty, that's a runtime bug — emit `⚠ Tilt Source missing for  × ; verify before relying on this output` and refuse to claim the output is compliance-ready. This compliance contract applies to the appendix identically — relocation never deletes or weakens it. **Flag any row where `returned_name ≠ expected_name` after normalizing both per conventions §2 step 2 with ⚠ MISMATCH and do not treat that row's scores as authoritative** — per loader.md §5 rule 3. `⚠ MISMATCH` flags stay in the primary table in both modes because data-integrity warnings are non-suppressible per §13.2.)
- **View-Effect Summary** (only when view active AND ≥1 holding's ranking shifted vs raw-score order) — One paragraph: `Without the active view, the top-N ranking wo

…

## 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.