Skip to main content

Composite Strategies

Composite strategies combine multiple legs with designated risk partners to achieve enhanced capital efficiency. When legs are partnered, the protocol recognizes that their combined risk profile may be less than the sum of individual risks, resulting in reduced collateral requirements.

Risk Partners Overview
​

Each leg in a Panoptic position can designate another leg as its "risk partner" via the riskPartner field in the TokenId. When two legs reference each other as partners and meet specific criteria, they're treated as a composite strategy rather than independent positions.

if (tokenId.riskPartner(index) == index) {
// No partner - compute as standalone leg
return _getRequiredCollateralSingleLegNoPartner(...);
} else {
// Has partner - check for composite strategy
return _getRequiredCollateralSingleLegPartner(...);
}

Strategy Classification Matrix
​

Composite strategies are classified by the attributes of the two partnered legs:

Width AWidth BisLong AisLong BTokenType MatchStrategy
> 0> 000DifferentStrangle
> 0> 00/11/0DifferentSynthetic Stock
> 0> 00/11/0SameSpread
> 00-1SameCredit-Option Composite
> 00-0SameLoan-Option Composite
0001DifferentDelayed Swap

Strangles
​

A strangle consists of two short options with different token types (one call, one put).

Identification
​

if (_tokenType != tokenTypeP) {  // Different token types
if (_isLong == 0 && isLongP == 0) { // Both short
return _computeStrangle(...);
}
}

Collateral Efficiency
​

Strangles receive 50% capital efficiency because only one side can be in-the-money at any given time:

function _computeStrangle(...) internal view returns (uint256 strangleRequired) {
// Negative utilization signals strangle treatment
poolUtilization = -(poolUtilization == 0 ? int16(1) : poolUtilization);

return _getRequiredCollateralSingleLegNoPartner(
tokenId,
index,
positionSize,
atTick,
poolUtilization // Negative triggers 50% discount in _sellCollateralRatio
);
}

How the Discount Works
​

In _sellCollateralRatio:

if (utilization < 0) {
min_sell_ratio /= 2; // 50% of normal base ratio
utilization = -utilization;
}

Example
​

ComponentStandalone RequirementStrangle Requirement
Short Put (20% base)20% of notional10% of notional
Short Call (20% base)20% of notional10% of notional
Total40%20%

Synthetic Stock
​

A synthetic stock combines a long option of one type with a short option of the opposite type.

Identification
​

if (_tokenType != tokenTypeP) {  // Different token types
if (_isLong != isLongP) { // One long, one short
// Synthetic stock
}
}

Collateral Requirement
​

The requirement is the maximum of the two legs' individual requirements:

return index < partnerIndex
? Math.max(
_getRequiredCollateralSingleLegNoPartner(tokenId, index, positionSize, atTick, poolUtilization),
_getRequiredCollateralSingleLegNoPartner(tokenId, partnerIndex, positionSize, atTick, poolUtilization)
)
: 0; // Only compute once

Rationale
​

A synthetic stock (long call + short put, or long put + short call) behaves like holding the underlying asset:

  • If price rises: call profits, put loses
  • If price falls: put profits, call loses

The positions offset each other, so only one needs full collateral.


Spreads
​

A spread combines a long and short option of the same type (both calls or both puts) at different strikes.

Identification
​

if (_tokenType == tokenTypeP) {  // Same token type
if (_isLong != isLongP) { // One long, one short
return _computeSpread(...);
}
}

Types of Spreads
​

Spread TypeLong StrikeShort Strike
Bull CallLowerHigher
Bear CallHigherLower
Bull PutLowerHigher
Bear PutHigherLower

Collateral Calculation
​

The spread requirement is the minimum of:

  1. The sum of individual leg requirements (split requirement)
  2. The defined maximum loss of the spread
function _computeSpread(...) internal view returns (uint256 spreadRequirement) {
spreadRequirement = 1; // Minimum floor

// Option 1: Sum of individual requirements
uint256 splitRequirement = _getRequiredCollateralSingleLegNoPartner(index) +
_getRequiredCollateralSingleLegNoPartner(partnerIndex);

// Option 2: Maximum loss calculation
// ... (detailed below)

spreadRequirement = Math.min(splitRequirement, spreadRequirement);
}

Calendar Spread Adjustment
​

For spreads with different widths (calendar spreads), an additional adjustment accounts for time value differences:

int24 deltaWidth = _tokenId.width(index) - _tokenId.width(partnerIndex);
if (deltaWidth < 0) deltaWidth = -deltaWidth;

// Add width-based adjustment
spreadRequirement += (amountsMoved * uint256(deltaWidth * tickSpacing)) / 80000;

Maximum Loss Calculation
​

Case 1: Asset != TokenType
​

When the position's asset differs from its token type, the max loss is simply the difference in notional values:

if (tokenId.asset(index) != tokenType) {
spreadRequirement += |moved0 - moved0Partner|; // or moved1 for token1
}

Case 2: Asset == TokenType
​

When asset equals token type, the calculation accounts for the ratio of notional to contracts:

spreadRequirement += |notional - notionalP| Γ— contracts / max(notional, notionalP)

Example
​

ComponentStandaloneSpread
Short 100 Call200 USDC-
Long 105 Call100 USDC-
Total300 USDC50 USDC (max loss)

Credit-Option Composites
​

These strategies pair an option with a credit position of the same token type.

Strategies Included
​

Option TypeResult
Long option + CreditPrepaid Long Option
Short option + CreditCash-Secured Option

Identification
​

if (_width != widthP) {  // One option, one credit/loan
if (_tokenType == tokenTypeP) { // Same asset
if (isLongP == 1) { // Partner is credit
return _width ? _computeCreditOptionComposite(...) : 0;
}
}
}

Collateral Calculation
​

function _computeCreditOptionComposite(
TokenId tokenId,
uint128 positionSize,
uint256 index,
int24 atTick
) internal view returns (uint256) {
// Assume 100% utilization for conservative requirement
uint256 _required = _getRequiredCollateralSingleLegNoPartner(
tokenId,
index,
positionSize,
atTick,
MAX_UTILIZATION // 10000
);

return _required;
}

Key Features
​

  1. Uses MAX_UTILIZATION: This means:

    • Short options require 100% collateralization (cash-secured)
    • Long options get enhanced capital efficiency (5% vs 10%)
  2. Credit automatically offsets: The credit amount is added to balance, naturally offsetting the requirement

Prepaid Long Option Example
​

A prepaid long option "pre-pays" for the option cost:

ComponentEffect
Credit (100 USDC)+100 USDC to balance
Long Call (5% requirement at max util)50 USDC requirement
Net Effect+50 USDC excess collateral

Cash-Secured Option Example
​

ComponentEffect
Credit (1000 USDC)+1000 USDC to balance
Short Put (100% at max util)1000 USDC requirement
Net EffectFully cash-secured

Loan-Option Composites
​

These strategies pair an option with a loan position of the same token type.

Strategies Included
​

Option TypeResult
Long option + LoanOption-Protected Loan
Short option + LoanUpfront Short Option

Identification
​

if (_width != widthP) {  // One option, one credit/loan
if (_tokenType == tokenTypeP) { // Same asset
if (isLongP == 0) { // Partner is loan
return _width ? _computeLoanOptionComposite(...) : 0;
}
}
}

Collateral Calculation
​

function _computeLoanOptionComposite(...) internal view returns (uint256) {
uint256 _required = _getRequiredCollateralSingleLegNoPartner(index, ...);
uint256 requiredPartner = _getRequiredCollateralSingleLegNoPartner(partnerIndex, ...);

if (tokenId.isLong(index) == 0) {
// Short option + Loan: sum of both
return _required + requiredPartner;
} else {
// Long option + Loan: max of both
return Math.max(_required, requiredPartner);
}
}

Upfront Short Option
​

The short option premium is received as a loan upfront:

ComponentRequirement
Loan (100 USDC)120 USDC (100% + 20% SCR)
Short Put200 USDC
Total320 USDC (sum)

Option-Protected Loan
​

The long option provides downside protection for the borrowed amount:

ComponentRequirement
Loan (1000 USDC)1200 USDC
Long Put (protection)100 USDC
Total1200 USDC (max, not sum)

The put provides protection, so only the larger requirement applies.


Delayed Swaps
​

A delayed swap pairs a credit in one token with a loan in another, effectively creating a token exchange with delayed settlement.

Identification
​

if (_width == 0 && widthP == 0) {  // Both are credits/loans
if (_tokenType != tokenTypeP) { // Different tokens
if (_isLong != isLongP) { // One credit, one loan
return _isLong == 0 ? _computeDelayedSwap(...) : 0;
}
}
}

Collateral Calculation
​

function _computeDelayedSwap(...) internal view returns (uint256) {
// Loan amount + standard collateral ratio
uint256 loanAmount = ...;
uint256 required = Math.mulDivRoundingUp(
loanAmount,
SELLER_COLLATERAL_RATIO + DECIMALS,
DECIMALS
);

// Credit amount converted to loan token
uint256 creditAmount = ...;
uint256 convertedCredit = PanopticMath.convert0to1(...) or convert1to0(...);

// Requirement is max of loan requirement or converted credit
return required > convertedCredit ? required : convertedCredit;
}

Example
​

Swapping ETH for USDC with delayed settlement:

ComponentTokenAmount
CreditETH1 ETH
LoanUSDC2000 USDC

If ETH = 2000 USDC:

  • Loan requirement: 2000 Γ— 1.2 = 2400 USDC
  • Credit value: 1 ETH = 2000 USDC
  • Final requirement: max(2400, 2000) = 2400 USDC

Strategy Summary
​

StrategyCapital EfficiencyKey Benefit
Strangle50% discountOnly one side can be ITM
Synthetic StockMax of two legsPositions offset
SpreadMax loss cappedDefined risk
Prepaid Long5% at max utilPre-paid premium
Cash-Secured100%Fully collateralized
Option-Protected LoanMax of twoProtection from option
Upfront ShortSum of bothUpfront premium receipt
Delayed SwapMax of convertedToken exchange

Important Notes
​

  1. Partner Validation: Legs must have matching asset and optionRatio to be valid partners
  2. Single Computation: When legs are partnered, requirement is computed once (for the lower index leg)
  3. Fallback: If partnered legs don't match any composite pattern, they're computed as individual positions
  4. Option Ratios Must Match: Partners must have equal option ratios to receive composite treatment