Portfolios
Independent margin units for risk isolation and capital management
A portfolio is an independent margin unit that holds positions and collateral. Each user can have multiple portfolios, enabling risk isolation between different trading strategies. Cross-margin applies within each portfolio only—each portfolio is an independent liquidation unit.
Four Instruments in a Portfolio
Each portfolio holds positions organized by series. Each position stores two signed balances that encode the four-instrument model:
Position Structure (Per Series)
Position {
optionBalance: int256 // positive = Long, negative = Short
premiumBalance: int256 // positive = Receiver, negative = Payer
lastUpdated: uint256
}Critical clarification: The four instruments are NOT four separate positions. A single position entry (per series) uses two signed integers to represent all four instrument types:
| Balance Field | Positive Value | Negative Value |
|---|---|---|
optionBalance | Option Long — receives intrinsic | Option Short — pays intrinsic |
premiumBalance | Premium Receiver — receives premium | Premium Payer — pays premium |
Storage vs. Update Flexibility:
- Storage: Option and premium balances are stored together in one entry per (portfolioId, seriesId)
- Updates: Operators can update option and premium balances independently (e.g., settlement adjustments)
Typical Combinations
| Actor | optionBalance | premiumBalance | Meaning |
|---|---|---|---|
| Buyer | +10 | -$1,500 | Long 10 options, owes $1,500 premium |
| Seller | -10 | +$1,500 | Short 10 options, owed $1,500 premium |
Position Count
- The 16-position limit counts series entries, not individual instruments
- A portfolio with 3 series has 3 positions (each tracking both balances)
- Cross-margin efficiency: longs offset shorts, receivables offset payables
Portfolio Structure
Each portfolio contains:
| Component | Description |
|---|---|
| Portfolio ID | Sequential integer (0, 1, 2...) unique per user |
| Positions | Up to 16 series entries, each with option + premium |
| Collateral | USDC deposit (6 decimals) |
Why 16 Positions?
The 16-position limit ensures gas-bounded liquidation. When liquidating a portfolio, the protocol must iterate through all positions to calculate margin and transfer positions. Bounding this to 16 ensures liquidation transactions fit within block gas limits.
Position Storage
Positions are stored per-series within each portfolio:
User → Portfolio ID → Series ID → {optionBalance, premiumBalance, lastUpdated}Each series in a portfolio tracks its own option and premium balances independently.
Portfolio Equity
Portfolio equity determines health status and withdrawal limits:
Components
| Component | Formula | Effect on Equity |
|---|---|---|
| Deposit | Raw USDC in vault | Always positive |
| Option Value | Positive if net long, negative if net short | |
| Premium Balance | Positive if receivable, negative if payable |
See also: Margin System for detailed equity calculations and stress testing.
Portfolio Lifecycle
Creating a Portfolio
Portfolios are created automatically when needed:
- On first deposit: When a user deposits to a non-existent portfolio ID
- Via PortfolioManager: Users can explicitly create portfolios via
createPortfolio
Portfolio IDs are assigned sequentially (0, 1, 2...) for each user.
Deleting a Portfolio
A portfolio can only be deleted when completely empty:
- No positions: All series entries must have zero option and premium balances
- No collateral: Deposit must be withdrawn first
deletePortfolio(user, portfolioId)
├── Check: positionCount == 0
├── Check: deposit == 0
└── Remove from user's portfolio listCollateral Management
Deposit
Deposits add USDC to a specific portfolio:
depositToPortfolio(portfolioId, amount)
├── No margin check required (deposits always allowed)
├── Portfolio must exist
└── Updates: portfolioDeposits[user][portfolioId] += amountWithdraw
Withdrawals require post-withdrawal equity to exceed Initial Margin:
withdrawFromPortfolio(portfolioId, amount)
├── Check: amount <= maxWithdrawable
├── Check: post-withdrawal equity >= IM
└── Transfer USDC to userMax Withdrawable:
Transfer Between Portfolios
Operators can transfer collateral between a user's portfolios:
transferCollateralBetweenPortfolios(user, fromPortfolioId, toPortfolioId, amount)
├── Check: amount <= fromPortfolio deposit
├── Move collateral between portfolios
└── Verify: source portfolio remains healthy after transferOperations Comparison
| Operation | Margin Check | Who Can Call | Effect |
|---|---|---|---|
| Deposit | None | User | Increases deposit |
| Withdraw | Post-withdrawal ≥ IM | User | Decreases deposit, transfers out |
| Transfer | Source healthy | Operator | Moves between portfolios |
| Debit | None | Operator | Settlement/liquidation use |
| Credit | None | Operator | Settlement/liquidation use |
Position Transfers
Positions can be transferred between portfolios owned by the same user:
transferPosition(user, fromPortfolioId, toPortfolioId, seriesId, amount)Premium Transfer in transferPosition
When using transferPosition to move positions between your own portfolios, premium transfers proportionally with the option balance:
Note: This proportional transfer applies only to
transferPositionbetween a user's own portfolios. Other operations handle premium differently:
- Trades (RFQ/OrderBook): Premium is explicitly agreed between parties
- Liquidation: Option balance transfers to liquidator, premium stays with original user and settles at expiry
- Settlement adjustments: Premium can be modified independently via
updatePositionInPortfolio
Validation Checks
| Check | Description |
|---|---|
| Source balance sufficient | Cannot transfer more than source optionBalance |
| Destination capacity | Destination must have room (< 16 positions) |
| Source health | Source portfolio must remain healthy after transfer |
| Destination health | Destination portfolio must remain healthy after transfer |
Margin Independence
Cross-Margin Within Portfolio
Within a single portfolio, the four instruments offset each other during margin calculation:
- Option Long offsets Option Short risk (across different series)
- Premium Receiver offsets Premium Payer obligations
- Example: Long call + Short put can have lower combined margin than the short put alone
Isolation Between Portfolios
Each portfolio is margined independently:
User
├── Portfolio 0 (USDC: $10,000)
│ ├── Position A: optionBalance = +50, premiumBalance = -$2,500
│ └── Health: Equity $12,000 vs MM $8,000 ✓
│
├── Portfolio 1 (USDC: $5,000)
│ ├── Position B: optionBalance = -30, premiumBalance = +$1,800
│ └── Health: Equity $4,200 vs MM $3,500 ✓
│
└── Portfolio 2 (USDC: $3,000)
├── Position C: optionBalance = +20, premiumBalance = -$1,000
└── Health: Equity $3,500 vs MM $2,000 ✓Key property: If Portfolio 1 becomes liquidatable, Portfolios 0 and 2 are unaffected. Risk is isolated.
Use Cases
Single Portfolio (Simple User)
Most users need only one portfolio:
- All positions in Portfolio 0
- All collateral in one place
- Full cross-margin benefit across positions
Multi-Portfolio Risk Isolation
Advanced users may want separate portfolios:
| Portfolio | Strategy | Rationale |
|---|---|---|
| 0 | Conservative | Blue-chip options, low risk |
| 1 | Speculative | High-risk plays, isolated from main funds |
| 2 | Hedging | Protective positions for external holdings |
If the speculative portfolio gets liquidated, conservative and hedging portfolios remain intact.
MMM Single-Position Pattern
The Main Market Maker uses single-position portfolios for operational simplicity:
- Portfolio 0: Liquidation receiving only
- Portfolio 1, 2, 3...: Each holds exactly one series
See also: MMM Operations for detailed market maker portfolio patterns.
Worked Examples
Example A: Position After Trade
Alice buys 10 ETH-3500-CALL options at $150 each from Bob.
Alice's position (buyer):
| Field | Value | Meaning |
|---|---|---|
optionBalance | +10 | Long 10 options |
premiumBalance | -$1,500 | Owes $1,500 at settlement |
Bob's position (seller):
| Field | Value | Meaning |
|---|---|---|
optionBalance | -10 | Short 10 options |
premiumBalance | +$1,500 | Owed $1,500 at settlement |
Key insight: Each party has ONE position (one series entry) with two balances, not four separate positions.
Example B: Portfolio Equity Calculation
Charlie has Portfolio 0 with:
- Deposit: $5,000 USDC
- Position 1 (ETH-3500-CALL): optionBalance = +20, premiumBalance = -$2,000
- Position 2 (ETH-3200-PUT): optionBalance = -10, premiumBalance = +$800
Current marks: Call = $120, Put = $95
Calculation:
Option Value:
Premium Balance:
Portfolio Equity:
Example C: Cross-Margin Benefit
Compare two scenarios for holding a short put:
Scenario 1: Short put alone
| Position | optionBalance | Mark | Stress Loss (spot -30%) |
|---|---|---|---|
| ETH-2800-PUT | -10 | $80 | $6,300 |
| Total IM | ~$7,000 |
Scenario 2: Short put + Short call (short strangle)
| Position | optionBalance | Mark | Stress Loss (spot -30%) |
|---|---|---|---|
| ETH-2800-PUT | -10 | $80 | $6,300 |
| ETH-3500-CALL | -10 | $100 | -$950 (gain) |
| Net Loss | $5,350 | ||
| Total IM | ~$6,000 |
The short call gains value when spot drops (call becomes worthless, releasing its liability), partially offsetting the short put loss and reducing margin by ~$1,000.
Example D: Collateral Transfer
Dana has two portfolios:
- Portfolio 0: $10,000 deposit, no positions (Equity = $10,000, IM = $0)
- Portfolio 1: $2,000 deposit, short puts (Equity = $1,800, IM = $1,500)
Dana wants to move $5,000 from Portfolio 0 to Portfolio 1.
Transfer check:
- Portfolio 0 post-transfer: $5,000 deposit, IM = $0 → Healthy ✓
- Portfolio 1 post-transfer: $7,000 deposit, IM = $1,500 → Healthy ✓
Transfer succeeds. Portfolio 1 now has more buffer against liquidation.
Example E: Position Transfer with Premium
Eve wants to transfer 5 long calls from Portfolio 0 to Portfolio 1.
Portfolio 0 before:
- optionBalance = +20
- premiumBalance = -$3,000
Proportional premium calculation:
Portfolio 0 after:
- optionBalance = +15
- premiumBalance = -$2,250
Portfolio 1 after:
- optionBalance = +5
- premiumBalance = -$750
In transferPosition, the premium obligation transfers proportionally with the option balance.
Smart Contract API
DiffusalPortfolioManager
| Function | Description |
|---|---|
createPortfolio | Create a new portfolio for a user |
deletePortfolio | Delete an empty portfolio |
transferPosition | Move position between portfolios |
getUserPortfolios | Get all portfolio IDs for a user |
portfolioExists | Check if a portfolio exists |
getPortfolioCount | Get number of portfolios for a user |
DiffusalCollateralVault
| Function | Description |
|---|---|
depositToPortfolio | Deposit USDC to a specific portfolio |
withdrawFromPortfolio | Withdraw USDC from a portfolio |
transferCollateralBetweenPortfolios | Move collateral between portfolios |
getPortfolioDeposit | Get deposit amount for a portfolio |
DiffusalOptionsPositionManager
| Function | Description |
|---|---|
getPortfolioPositionInfo | Get position details for a series |
getPortfolioSeriesIds | Get all series IDs in a portfolio |
getPortfolioPositionCount | Get number of positions in a portfolio |
updatePositionInPortfolio | Update option/premium balances (operator only) |
DiffusalMarginCalculator
| Function | Description |
|---|---|
getPortfolioEquity | Calculate current portfolio equity |
getPortfolioMargin | Calculate initial and maintenance margin |
getPortfolioMaxWithdraw | Calculate maximum withdrawable amount |
isPortfolioHealthy | Check if portfolio equity >= maintenance margin |
isLiquidatable | Check if portfolio can be liquidated |
Related
Protocol Documentation
- Protocol Design — Four-instrument model and core architecture
- Margin System — Equity calculation and stress testing
- Liquidation — What happens when equity falls below MM
- MMM Operations — Market maker portfolio patterns
Contract Documentation
- DiffusalPortfolioManager — Portfolio lifecycle management
- DiffusalCollateralVault — Collateral deposits and withdrawals
- DiffusalOptionsPositionManager — Position tracking