Install
$ agentstack add skill-bencharoenwong-parallax-workflows-parallax-rebalance ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
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 →About
Portfolio Rebalance
When not to use
- Building a new portfolio from scratch → use /parallax-portfolio-builder
- Diagnostic review without trade recommendations → use /parallax-client-review
- Single stock analysis → use /parallax-should-i-buy
Gotchas
- JIT-load _parallax/parallax-conventions.md for fallback patterns and parallel execution
- 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). Tilts in the view become trade-direction signals: rebalancing should move portfolio toward view-tilted weights.
- When active view is present, use the view-aware disclaimer per loader.md §5 rule 5; otherwise use the standard disclaimer
- JIT-load ../parallax-client-review/references/recommendation-matrix.md for priority classification. If missing, use inline fallback: High=3+ flags (trim/exit), Medium=2 flags (investigate/trim), Low=1 flag (monitor/hold)
- Health flags feed directly into trade action determination — High priority = strong trim/exit
- Call
analyze_portfolioat most once. Build its request from the discovered live schema and request only compact current-state/concentration blocks; never request rolling, drawdown, return-period, benchmark-price, or other daily time-series blocks in the normal rebalance path. If the capability is absent, the request cannot be mapped unambiguously, the response is oversized/truncated, or schema/field validation fails, do not retry it with a guessed shape — use discovered concentration/scoring fallbacks. - buildstockuniverse can find replacement candidates for positions being trimmed
- Output must include specific candidate weight changes, framed per conventions §12 (analysis, not instructions), not just vague suggestions
- For portfolios with 10+ holdings, prioritize score trend scans for top/bottom 5 by weight to manage latency
- When
policy=is supplied, JIT-load_parallax/client-policy/policy-loader.mdand run Batch C2. The S3 solver (_parallax/client-policy/reconcile.py) needs scipy and fails closed without it —solver_unavailablerenders UNVERIFIED per conventions §4.0, never a partial trade list. Deterministic math lives in the helper; never reproduce the LP in prose. - JIT-load
_parallax/white-label/integration-pattern.mdbefore the Pre-Render step. Loader call isload_visual_branding()(7-key visual subset; voice structurally excluded —branding["voice"]raisesKeyError). Apply §5 (Branding Header) and §7 (About This Report) in Output Format. Audience mode resolution (§13.1) is a separate seam call, not a dict read ofbranding["render"]: this skill does not use the RM seam (rm_consumer.py::load_rm_branding_context) for branding, but it DOES call that module'sresolve_audience()function directly, via the one Bashpython3 -cstep documented under Pre-Render — never re-derive the §13.1 precedence in prose.
Generate prioritized trade recommendations using health flags, macro context, and Parallax scores.
Usage
/parallax-rebalance [{"symbol":"AAPL.O","weight":0.30},{"symbol":"MSFT.O","weight":0.25},{"symbol":"XOM.N","weight":0.20},{"symbol":"JNJ.N","weight":0.25}]
/parallax-rebalance [holdings] target="reduce concentration, improve quality score"
/parallax-rebalance [holdings] constraints="max 25% per position, no energy sector"
/parallax-rebalance [holdings] policy=path/to/client-policy.yaml
/parallax-rebalance [holdings] audience=client_safe
policy= accepts the same client-policy artifact parallax-client-review consumes (inline YAML/JSON or a file path; schema in _parallax/client-policy/schema.yaml). When supplied, Batch C2 runs the S3 reconciliation optimizer and its targets replace the multiplier-derived ones.
Optional audience= argument: client_safe | internal_analyst; precedence follows parallax-conventions.md §13.1.
Workflow
Execute with the exact Parallax callables and input schemas exposed by live capability discovery in the current runtime. Logical tool names below describe intent; they are not a fixed MCP namespace or permission to use a stale request shape. JIT-load _parallax/parallax-conventions.md for discovery, execution mode, fallback patterns, and macro reasoning. JIT-load _parallax/house-view/loader.md for active-view validation and tilt application. JIT-load ../parallax-client-review/references/recommendation-matrix.md for the priority system.
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.
Batch 0 — Live Capability Discovery & Active House View
Use the host's live discovery surface per conventions §0.1 (ToolSearch with "+Parallax" in Claude Code). Build a session-local map from each logical capability used below to the exact callable name and live input schema returned now. Live discovery overrides every namespace, parameter, and schema example in this file. Do not synthesize missing callables from a remembered server alias.
Classify failures before any retry: a transient transport/cancellation/empty-success may retry only the affected call once; tool-not-found, schema-validation, or response invalid_fields failures do not permit a same-payload or guessed-shape retry. Use a discovered fallback and record the affected coverage instead.
Per loader.md §1-§2: read view if present, validate hash and expiry. If view present, capture tilt vector + excludes. The view's tilts define direction of rebalance — current weights that diverge from view-tilted weights become rebalance candidates beyond the standard health-flag triggers. If validation fails or no view present, run rebalance using only health flags + macro context.
Batch A — Current state (parallel, best-effort)
The parameter column states the semantic intent. Construct every payload from that callable's discovered live schema, using only advertised keys and types. If the schema cannot represent the intent unambiguously, treat that logical capability as unavailable and follow its fallback without probing guessed variants.
| Tool | Parameters | Notes | |---|---|---| | analyze_portfolio | Map the supplied symbol/weight holdings into the live schema. If fields is advertised, request the compact intersection of portfolio_summary, concentration_metrics, sector_allocation, and company_contribution; omit time-series blocks. | Exactly one call maximum. Supply a date per holding only when the discovered live schema requires one. The date is an as-of date over a price history, not a snapshot key: a deployed connector may need a date early enough that each holding has sufficient prior price history, so today's date can return empty or fail validation. Read the live schema's own description first. When the schema gives no guidance, date every holding at the most recent completed trading day at least 5 calendar days in the past, one date for all holdings, and state the date used in the report — live schema still wins over this default. Skip after 30s, oversized/truncated output, schema validation, or any non-empty result._meta.invalid_fields; do not retry this capability. Use discovered check_portfolio_redundancy for overlap/concentration and per-holding score aggregation for factor context. | | get_peer_snapshot | per holding | Primary scoring source for PARALLAX_LOADER_V2=1. Timeout handling: fire in parallel; if N≥2 calls timeout, mark those holdings as "scores unavailable" and continue with health-flags-only scoring. Collect successful scores only. Aggregate client-side per loader.md §3b. For 10+ holdings: prioritize top/bottom 5 by weight; timeout on remaining holdings is acceptable — fall back to health flags for those positions. Distinguish a timeout from an empty response: a timeout leaves the holding unscored and health-flag-driven per the handling above. A successful call that carries no data for the listing is a coverage gap, not a timeout — fall back to get_company_info plus get_score_analysis for that holding, label every figure derived this way a profile-derived score, and name every profile-derived holding in the report. See the Batch C2 coefficient bullet for the same-scale guard required before a profile-derived score enters the solver. | | get_company_info | per holding | Ground-truth check oracle per loader.md §5 rule 3 — records expected_name for mismatch check against get_peer_snapshot.target_company. Timeout handling: if timeout, mark holding as "name verification unavailable" and flag ⚠ UNVERIFIED. | | get_score_analysis | per holding | Score trend (improving/stable/declining) for the Score Momentum table and the Exit classification. Input is symbol + weeks only — no Batch A dependency, so it fires here in parallel. For 10+ holdings: prioritize top/bottom 5 by weight. Timeout handling: mark the holding's trend "unavailable" and continue. | | check_portfolio_redundancy | Map the normalized holdings into the live schema. | Overlap detection and the compact fallback when analyze_portfolio is unavailable. Timeout fallback: if exceeds 20s, flag "redundancy check skipped" and continue. When analyze_portfolio.sector_allocation also came back, cross-check the two sector breakdowns per "After Batch A" item 4 before rendering either. | | list_macro_countries | — | Check market coverage. Timeout fallback: skip if exceeds 5s. | | quick_portfolio_scores| Map the normalized holdings into the live schema. | Discovered Legacy/V1 fallback only. Do NOT use if PARALLAX_LOADER_V2=1 and view active. Timeout fallback: if exceeds 10s, degrade to health-flags-only scoring. A successful call with no data for a listing (distinct from a timeout) is the same coverage-gap case as the get_peer_snapshot row above — fall back to get_company_info plus get_score_analysis for that holding and label it a profile-derived score. |
After Batch A (best-effort completion):
- Cross-check returned names against
get_company_inforesults per loader.md §5 rule 3. ForPARALLAX_LOADER_V2=1, any mismatch inget_peer_snapshotis flagged ⚠ MISMATCH and excluded from aggregate calculations. Unverified holdings (name check timeout) are flagged ⚠ UNVERIFIED. - For holdings with no scores (timeouts), scoring is determined by health flags only — these holdings cannot be ranked by factor scores and must be evaluated by "High/Medium/Low priority" categories based on flags alone.
- Summary output: "Batch A completed: N/M holdings scored (M-N unavailable or timed out). Portfolio snapshot: available/fallback/unavailable. Rebalance will proceed with health-flag-driven recommendations for scoring-unavailable holdings." Keep this execution receipt inside the rendered report only where the Output Format calls for the information; never leak it as pre-report scaffold. Under
audience=client_safe, this receipt is ops apparatus per conventions §13.2 — relocate the receipt line to the Methodology appendix (internal) defined in Output Format, and keep in the body only a plain-language note naming the holdings whose scores were unavailable. - Redundancy coverage cross-check (only when both
analyze_portfolio.sector_allocationandcheck_portfolio_redundancysector weights came back): write each sector-weights payload to a private mktemp JSON file, then one Bash step —python3 "/../_parallax/coverage_check.py" --portfolio-sectors "$PORTFOLIO_SECTORS" --redundancy-sectors "$REDUNDANCY_SECTORS" --holdings "$HOLDINGS"— and render from its JSON verdict. Tag every--holdingsentry with itssectorfrom theanalyze_portfoliosector mapping (per-holding backstop as usual): the live redundancy payload is aggregate-only, and without sector tags the helper cannot infer absent holdings and resolvesabsent_holdings_basistonot_computable. Cite the operator-agnostic-helper rationale by reference to_parallax/house-view/loader.md§2 ("Why the helper, not inline math") — the same argument applies here: the coverage arithmetic must be identical across operator LLMs, so it is never reproduced in prose. Oncoverage_limited, label the redundancy output coverage-limited in Current Portfolio Assessment, name thediverging_sectorsand anyabsent_holdings, and prefer theanalyze_portfoliosector weights for every rendered concentration figure.absent_holdingsis basis-qualified viaabsent_holdings_basis: when it issector_inference, note that the absent-holdings list is inferred from diverging sectors (the redundancy payload carried no per-holding data) rather than confirmed directly; when it isnot_computable, render nothing about absent holdings at all — do not claim absence and do not claim confirmed coverage. Onconsistent, render normally.
Batch B — Macro (after Batch A)
- Call the discovered
macro_analystcapability for each unique covered market (cap 3), using the live schema's tactical-component value when advertised — fire all calls in one parallel batch. (Score trends moved into Batch A:get_score_analysishas no Batch A dependency, so it no longer waits behind the portfolio snapshot.)
Batch C — Health flags + trade decisions
- Parse mandate parameters (if
constraints=and/ortarget=were passed):
constraints=: split on commas; match each clause against two recognized patterns — "max N% per position" (a per-position weight cap, applied to Target Weight in step 5) and "no " (a sector/name exclusion, applied to Replacement Candidates in step 6 exactly liketilts.excludes).target=: match against recognized phrases — "reduce concentration" (prioritize Reweight/Trim of concentration-flagged holdings in step 5) and "improve quality score" (rank Replacement Candidates by quality sub-score in step 6). Any other phrase is unrecognized.- Fail-loud rule: any
constraints=clause that matches neither recognized pattern is never silently dropped — it renders "constraint not recognized — not applied" in the Mandate Constraints Applied output block. Any unrecognizedtarget=phrase is echoed verbatim there with a statement of how the standard recommendations already address it.
- Evaluate the 5 health flags per holding — binding flag conditions in
../parallax-client-review/references/recommendation-matrix.md(same taxonomy and threshold values asparallax-portfolio-checkup/references/health-flags.md, whose canonical portfolio-level weighted-average definitions apply to portfolio-checkup, not here): Low Score (holding total score ≤5.0), Concentration (holding weight >15%, or holding among the top-3 when their combined weight >45%), Redundancy (holding is part of a redundant pair), Value Trap (holding value score ≤3.0), Macro Misalignment (holding's sector has a negative tactical outlook). Per-holding flag counts drive priority assignment. - House-view alignment check (if view active): for each holding, compute view-tilted target weight using loader.md §3 multipliers; flag holdings >25% off target as "View Misalignment." For holdings on
tilts.excludes, flag as "View Excluded — must trim." The multiplier-derived target is benchmark-free — it tilts current weights, not a policy. When a client policy is supplied, Batch C2's optimizer targets (computed against the policy benchmark) supersede it in Trade Recommendations; the multiplier target then serves only this flag check. - Assign priority per recommendation-matrix.md (count View Misalignment / View Excluded as flags):
- High (3+ flags or View Excluded): Strong trim/exit candidate
- Medium (2 flags): Investigate + potential trim
- Low (1 flag): Monitor, hold unless constraints vi
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: bencharoenwong
- Source: bencharoenwong/parallax-workflows
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.