Position Groups
A position group is a named strategy assembled from individual positions. A leveraged loop spread across a collateral position and a borrow, or a cash-and-carry split between spot and a perp, is one strategy to an investor and several rows to a ledger. Groups are the mapping between the two. They matter for reporting because an LP report’s strategies can be backed by groups: the strategy’s NAV, returns and allocation slice then come from the group’s legs rather than from a single share token.A group is a view, never a ledger write. Every endpoint here reads positions the reconciliation already produced; grouping them changes presentation, not accounting.
Base path
/portfolio-management on it.
Every endpoint requires the admin, trader, or pms_user role plus access to the portfolio.
Response envelope
Success responses return the payload under a named key (groups, group, legs, membership) with no wrapper. Errors use the platform-wide shape:
details object explaining what failed validation.
Reading groups
GET /strategy-types
The closed vocabulary forstrategy_type. No portfolio needed.
GET /position-groups
string
required
The portfolio whose groups to list.
{ "groups": [ ... ] }, each group carrying group_id, portfolio_id, name, strategy_type, legs, mandate, notes and creation metadata.
GET /position-groups/{group_id}
One group.404 when the id doesn’t belong to that portfolio.
GET /position-groups/legs
The leg catalog: every groupable position in the portfolio, each annotated with the group that already owns it (group, or null when unassigned). Sorted by absolute USD value, largest first. This is what a “group these positions” picker reads.
A leg is identified by leg_uid, derived from account_id, chain and key, where key is a contract address, native, or a synthetic id such as a Morpho market.
GET /position-groups/membership
The same relationship inverted:leg_uid -> group summary, so a positions table can badge each row with the strategy that claims it without walking every group.
Writing groups
POST /position-groups
string
required
Also required in the body, see the warning above.
string
required
The portfolio this group belongs to.
string
required
Display name, and the name the LP report’s strategy will carry.
string
required
One of the ids from
/strategy-types.array
required
The member positions, each
{ account_id, chain, key }. leg_uid is derived server-side.string
Free text describing what the strategy is for. Carried through to the LP report.
string
Internal note, not rendered on statements.
201 with the created group.
The “Unreconciled (capital basis incomplete)” row cannot be grouped. It’s a disclosure that the books don’t fully close, not a position, and attempting to include it is rejected.
PUT /position-groups/{group_id}
Update name, type, legs, mandate or notes.portfolio_id on the query string.
DELETE /position-groups/{group_id}
Removes the group. The positions are untouched; they simply become ungrouped again.Derived values
Everything below is computed from ledger rows the reconciliation already produced. None of it writes.GET /position-groups/aggregate
Every group’s combined value, cost, P&L and return, plus the ungrouped remainder, so the caller sees the whole portfolio partitioned rather than just the parts someone remembered to group.ungrouped block is the honest half of this endpoint. A dashboard that charts only groups will silently understate the portfolio by whatever hasn’t been assigned yet.
GET /position-groups/{group_id}/history
The group’s daily value curve, summed from its legs’ existing series. No backfill: days a leg has no data for are days the curve doesn’t claim a value, rather than being interpolated into one.GET /position-groups/foot-check
Asserts that portfolio NAV equals the sum of groups plus ungrouped legs, and reports the residual with the reason when it doesn’t.How groups reach an LP report
A report strategy backed by a group carries these fields in/config under strategies[]:
The strategy’s returns, allocation slice and per-strategy detail on the statement then derive from the group’s legs.

