fix: gross_exposure() uses abs(asset_value) for grouped portfolios#837
Merged
polakowo merged 1 commit intopolakowo:masterfrom Mar 26, 2026
Merged
Conversation
…with short positions gross_exposure() was computing net signed exposure instead of gross exposure for grouped portfolios. For short-only positions, it returned negative values; for mixed long/short, it could return wildly inflated values (e.g. 6000%+ when actual gross exposure was ~50%). Root cause: when group_by is active, asset_value is the net sum of per-column values (longs - shorts). For gross exposure, we need the sum of absolute per-column values. The fix computes abs(per-column asset values) before group aggregation. The existing net_exposure() method is unaffected — it correctly computes long_exposure - short_exposure from direction-filtered gross_exposure calls. Fixes polakowo#836. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes Portfolio.gross_exposure() so grouped portfolios compute true gross exposure (sum of absolute per-column position values) rather than netting longs and shorts within each group, which previously produced negative and/or extreme values for mixed long/short groupings.
Changes:
- Updated
Portfolio.gross_exposure()to aggregateabs(asset_value)at the per-column level before grouping. - Updated
test_gross_exposureexpected outputs to ensure gross exposure is non-negative and matches the corrected computation. - Updated
test_statshardcodedMax Gross Exposure [%]values to reflect the corrected metric.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
vectorbt/portfolio/base.py |
Fixes grouped gross exposure by summing per-column absolute asset values before group aggregation. |
tests/test_portfolio.py |
Updates expected outputs for gross exposure and derived stats to match corrected behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
polakowo
approved these changes
Mar 26, 2026
Contributor
Author
|
Great job, AIs! 👏🏻 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
gross_exposure()was computing net signed exposure instead of gross exposure for grouped portfolios with short positionsasset_valueis the net sum across columns (longs - shorts), but gross exposure requiressum(abs(per_column_values))Fix
In
Portfolio.gross_exposure(), whengroup_byis active, computeabs()on per-column asset values before group aggregation, rather than using the net grouped asset value.Test plan
test_gross_exposure— all gross exposure values are now non-negativetest_stats— hardcodedMax Gross Exposure [%]values correctedtest_net_exposurepasses unchanged —net_exposure()correctly computeslong_exposure - short_exposureFixes #836.
🤖 Generated with Claude Code