Research

Structured Products for AI Agents: Dual Investment, Principal-Protected Notes, and Barrier Options

Purple Flea Research Team March 6, 2026 22 min read

Structured products — financial instruments that combine fixed-income components with derivative overlays to produce customized risk/return profiles — have historically been the exclusive domain of institutional investors. AI agents operating through programmable financial infrastructure can now construct and trade these instruments synthetically, using DeFi lending yields as the fixed-income leg and perpetual futures as the derivative leg. This guide covers the four most important structured product archetypes for agents: dual investment, principal-protected notes (PPNs), barrier options, and autocallable structures — with complete Python implementations using Purple Flea's trading API.

What Are Structured Products?

A structured product is a pre-packaged investment strategy that combines two or more financial instruments — typically a bond or lending position plus one or more derivatives — to create a return profile that neither component can provide alone. Traditional structured products are issued by banks and sold to retail or institutional investors. For AI agents, the relevant innovation is synthetic replication: constructing the same economic exposure from primitive DeFi building blocks rather than purchasing a pre-packaged instrument.

Why Structured Products for AI Agents?

The DeFi Building Blocks

Synthetic structured product construction requires two primitive categories:

  1. Fixed-income leg: DeFi lending protocols (Aave, Compound, Morpho) provide deterministic interest rates on stablecoin deposits. Rates typically range from 4–18% APY depending on market conditions. This is the "principal protection" mechanism.
  2. Derivative leg: Perpetual futures contracts (available through Purple Flea's Hyperliquid-powered trading API) provide leveraged directional or conditional exposure to crypto assets. Options on some platforms, or delta-hedged perpetual positions, replicate option-like payoffs.

Dual Investment: BTC — Earn More or Buy the Dip

What Is Dual Investment?

Dual Investment is the most popular crypto-native structured product. Offered natively by Binance Earn, OKX, and Bybit, it comes in two variants:

Economically, Dual Investment = Lending position + Short put (Buy Low) or Short call (Sell High). The enhanced yield comes from the option premium earned by selling the optionality.

Buy Low Dual Investment — Payoff at Expiry: Profit | |____________________________ | \ | \ ← Enhanced yield earned if | \ BTC stays above strike | \ | \ --+----------------------------------\-----------> BTC Price at Expiry | Strike \ | \ ← Effective BTC purchase | \ at strike price Outcome A (BTC > Strike): Keep USDC + yield Outcome B (BTC < Strike): Buy BTC at strike (below current market)

Synthetic Replication with Purple Flea

An agent can replicate a Buy Low Dual Investment synthetically:

  1. Deposit USDC to a DeFi lending protocol (earn base yield, e.g., 8% APY)
  2. Sell a short put on BTC at the target strike using the Purple Flea trading API (earn option premium as additional yield)
  3. At expiry: if BTC is below strike, use the USDC to buy BTC (the put is exercised); if above strike, let the put expire and collect full premium + lending yield
"""
Synthetic Dual Investment implementation using Purple Flea trading API.
Replicates a "Buy Low" structure: lend USDC + sell BTC put.

Risk: Must hold sufficient USDC to cover potential BTC purchase at strike.
Return: Base lending yield + put premium.
"""
import asyncio
import httpx
from datetime import date, timedelta
from decimal import Decimal

PF_API = "https://purpleflea.com/api"

@dataclass
class DualInvestmentPosition:
    asset: str                    # "BTC-USDC"
    direction: str                # "buy_low" | "sell_high"
    principal_usdc: Decimal
    strike_price_usd: Decimal
    expiry: date
    lending_apy: Decimal
    premium_collected_usdc: Decimal = Decimal("0")
    status: str = "active"

    @property
    def days_to_expiry(self) -> int:
        return (self.expiry - date.today()).days

    @property
    def annualized_yield(self) -> Decimal:
        # Total yield = lending APY + annualized premium
        premium_apy = (
            self.premium_collected_usdc / self.principal_usdc
        ) * (Decimal("365") / Decimal(str((self.expiry - date.today()).days + 1)))
        return self.lending_apy + premium_apy

class DualInvestmentAgent:
    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.api_key = api_key
        self.client = httpx.AsyncClient(timeout=30)
        self.positions: list[DualInvestmentPosition] = []

    async def open_buy_low(
        self,
        principal_usdc: Decimal,
        strike_pct_below_current: float = 0.10,
        tenor_days: int = 7
    ) -> DualInvestmentPosition:
        """
        Open a Buy Low Dual Investment position.

        Args:
            principal_usdc: USDC to deploy
            strike_pct_below_current: Strike as % below current BTC price (0.10 = 10% OTM)
            tenor_days: Product tenor in days

        Returns:
            Position object with expected yield information
        """
        # Get current BTC price
        btc_price = await self._get_btc_price()
        strike = btc_price * Decimal(str(1 - strike_pct_below_current))
        expiry = date.today() + timedelta(days=tenor_days)

        # Step 1: Deposit USDC to lending protocol via Purple Flea
        lending_resp = await self.client.post(
            f"{PF_API}/wallet/lend",
            json={
                "agent_id": self.agent_id,
                "token": "USDC",
                "amount": str(principal_usdc),
                "protocol": "aave-v3",
            },
            headers={"Authorization": f"Bearer {self.api_key}"}
        )
        lending_data = lending_resp.json()
        lending_apy = Decimal(str(lending_data["current_apy"]))

        # Step 2: Sell a BTC short put at the strike via Purple Flea trading
        # On Hyperliquid: approximate with short perpetual delta position
        # sized to match put delta at the given strike/tenor
        put_delta = self._estimate_put_delta(btc_price, strike, tenor_days)
        perp_size = principal_usdc * Decimal(str(put_delta)) / btc_price

        trading_resp = await self.client.post(
            f"{PF_API}/trading/order",
            json={
                "agent_id": self.agent_id,
                "market": "BTC-PERP",
                "side": "sell",
                "size": str(perp_size),
                "type": "market",
                "reduce_only": False,
            },
            headers={"Authorization": f"Bearer {self.api_key}"}
        )
        trading_data = trading_resp.json()

        # Estimate premium from implied vol pricing
        premium = self._estimate_put_premium(
            btc_price, strike, tenor_days, iv=0.75
        ) * principal_usdc

        position = DualInvestmentPosition(
            asset="BTC-USDC",
            direction="buy_low",
            principal_usdc=principal_usdc,
            strike_price_usd=strike,
            expiry=expiry,
            lending_apy=lending_apy,
            premium_collected_usdc=premium,
        )
        self.positions.append(position)
        return position

    def _estimate_put_delta(self, spot: Decimal, strike: Decimal, days: int) -> float:
        """Black-Scholes delta approximation for short put."""
        import math
        T = days / 365
        iv = 0.75  # BTC 30-day IV (approximate)
        r = 0.05   # Risk-free rate
        S, K = float(spot), float(strike)
        d1 = (math.log(S/K) + (r + 0.5*iv**2)*T) / (iv * math.sqrt(T))
        from scipy.stats import norm
        return norm.cdf(d1) - 1  # Put delta is negative

    def _estimate_put_premium(
        self, spot: Decimal, strike: Decimal, days: int, iv: float
    ) -> Decimal:
        """Black-Scholes put premium as fraction of notional."""
        import math
        from scipy.stats import norm
        S, K, T, r = float(spot), float(strike), days/365, 0.05
        d1 = (math.log(S/K) + (r + 0.5*iv**2)*T) / (iv*math.sqrt(T))
        d2 = d1 - iv*math.sqrt(T)
        put = K*math.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
        return Decimal(str(put / S))  # As fraction of spot

    async def _get_btc_price(self) -> Decimal:
        resp = await self.client.get(
            f"{PF_API}/trading/price/BTC-PERP",
            headers={"Authorization": f"Bearer {self.api_key}"}
        )
        return Decimal(str(resp.json()["mid_price"]))
Dual Investment Yield Enhancement

At 70% BTC implied volatility, a 7-day 10%-OTM Buy Low position generates approximately 18–30% annualized premium on top of the 8–12% base lending yield — for a total annualized yield of 26–42%, while capping maximum downside to buying BTC at a pre-agreed discount price.


Principal-Protected Notes Using DeFi Yields

Structure Overview

A Principal-Protected Note (PPN) guarantees return of the full principal at maturity regardless of underlying asset performance, while providing upside participation if the asset appreciates. The guarantee is funded by the interest earned on the principal during the product's tenor.

Classic PPN structure:

  1. Invest $1,000 in a lending protocol at 10% APY for 1 year → guaranteed to receive $1,100 at maturity
  2. Use the $100 expected interest (discounted to present value) to purchase BTC call options
  3. At maturity: worst case receive exactly $1,000 (principal protected). Best case: $1,000 + BTC upside
"""
Principal-Protected Note (PPN) engine.
Construction: Fixed lending position + Long call options on target asset.
"""
import math
from dataclasses import dataclass
from decimal import Decimal
from scipy.stats import norm

@dataclass
class PPNParameters:
    principal_usd: Decimal
    tenor_days: int
    lending_apy: Decimal        # Expected DeFi lending rate
    underlying_asset: str       # "BTC" | "ETH" | "SOL"
    spot_price: Decimal
    implied_vol: Decimal        # Asset IV (e.g., 0.75 for 75%)
    participation_rate: Decimal = Decimal("1.0")  # % of upside captured

    @property
    def tenor_years(self) -> float:
        return self.tenor_days / 365

    @property
    def interest_earned_usd(self) -> Decimal:
        """Future value of lending yield over tenor."""
        return self.principal_usd * self.lending_apy * Decimal(str(self.tenor_years))

    @property
    def pv_interest_usd(self) -> Decimal:
        """Present value of interest — available to buy options TODAY."""
        rf = Decimal("0.05")
        discount = Decimal("1") + rf * Decimal(str(self.tenor_years))
        return self.interest_earned_usd / discount

def price_atm_call(spot: float, tenor_years: float, iv: float, rf: float = 0.05) -> float:
    """Black-Scholes ATM call price as fraction of spot."""
    K = spot  # ATM strike
    d1 = ((rf + 0.5*iv**2)*tenor_years) / (iv*math.sqrt(tenor_years))
    d2 = d1 - iv*math.sqrt(tenor_years)
    call = spot*norm.cdf(d1) - K*math.exp(-rf*tenor_years)*norm.cdf(d2)
    return call / spot

def design_ppn(params: PPNParameters) -> dict:
    """
    Design a Principal-Protected Note and calculate key metrics.

    Returns structure details including:
    - Call option budget available
    - Number of ATM calls purchasable
    - Effective participation rate
    - Break-even price at maturity
    """
    # Budget available for call purchase (present value of interest)
    call_budget = float(params.pv_interest_usd)

    # Price one ATM call option
    call_price_per_unit = price_atm_call(
        float(params.spot_price),
        params.tenor_years,
        float(params.implied_vol)
    )
    call_price_usd = float(params.spot_price) * call_price_per_unit

    # How many units of the underlying can be covered?
    notional_covered = call_budget / call_price_usd * float(params.spot_price)
    actual_participation = notional_covered / float(params.principal_usd)

    # Breakeven: price must rise enough for call payoff to exceed zero
    # (breakeven = ATM by definition for long call)
    breakeven_price = float(params.spot_price)

    return {
        "principal_usd": float(params.principal_usd),
        "tenor_days": params.tenor_days,
        "lending_apy_pct": float(params.lending_apy * 100),
        "interest_earned_usd": float(params.interest_earned_usd),
        "call_option_budget_usd": round(call_budget, 2),
        "call_price_pct_spot": round(call_price_per_unit * 100, 2),
        "effective_participation_pct": round(actual_participation * 100, 1),
        "breakeven_price_usd": round(breakeven_price, 0),
        "minimum_return_usd": float(params.principal_usd),  # Always 100%
        "structure": "Long lending + Long ATM call",
    }

# Example: 90-day BTC PPN with $100,000 principal
from decimal import Decimal
params = PPNParameters(
    principal_usd=Decimal("100000"),
    tenor_days=90,
    lending_apy=Decimal("0.12"),   # 12% DeFi yield
    underlying_asset="BTC",
    spot_price=Decimal("90000"),
    implied_vol=Decimal("0.75"),   # 75% IV
)
ppn = design_ppn(params)
print(ppn)
# Output:
# {
#   "principal_usd": 100000,
#   "interest_earned_usd": 2958.90,
#   "call_option_budget_usd": 2814.51,
#   "call_price_pct_spot": 8.24,
#   "effective_participation_pct": 34.2,
#   "minimum_return_usd": 100000
# }
PPN Trade-off

A 90-day BTC PPN at 12% DeFi yield captures approximately 34% of BTC upside while guaranteeing 100% principal return. The participation rate increases with higher lending APY and lower implied volatility — high-yield DeFi environments are ideal for PPN construction.


Barrier Options: Conditional Exposure for Agents

What Are Barrier Options?

Barrier options are options that activate or deactivate when the underlying asset reaches a specified price level (the "barrier"). They are significantly cheaper than vanilla options with the same strike and expiry because the buyer accepts additional path-dependency risk.

Type Description Triggered When Agent Use Case
Up-and-In Call Call option activated if price rises above barrier Price crosses barrier upward Cheap upside exposure only if breakout occurs
Down-and-In Put Put option activated if price falls below barrier Price crosses barrier downward Cheap crash insurance
Up-and-Out Call Call option cancelled if price rises above barrier Price crosses barrier upward Capped upside, maximum at barrier
Down-and-Out Put Put option cancelled if price falls below barrier Price crosses barrier downward Hedging that expires in extreme crashes

Synthetic Barrier Option via Perpetuals

Barrier options are not natively available on most crypto venues, but agents can replicate their payoff profile using conditional perpetuals orders on Purple Flea. A Down-and-In Put, for example, is replicated by placing a limit short order at the barrier price level — the position only opens if price reaches the barrier, replicating the knock-in behavior.

"""
Synthetic barrier option replication using Purple Flea perpetuals.
Implements Down-and-In Put via conditional limit order at barrier.
"""
import asyncio
import httpx
from decimal import Decimal

class BarrierOptionAgent:
    """
    Replicates barrier option payoffs using conditional perpetuals positions.

    Down-and-In Put:
    - No position while price > barrier (option inactive)
    - Short perpetual position activated when price <= barrier
    - Position size = notional / barrier_price

    This gives the agent crash insurance that only activates
    if BTC actually breaks a key support level.
    """

    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.api_key = api_key
        self.client = httpx.AsyncClient(timeout=30)
        self.active_barriers: list[dict] = []

    async def place_down_and_in_put(
        self,
        asset: str,
        notional_usd: Decimal,
        barrier_price: Decimal,
        stop_loss_price: Decimal,
        expiry_timestamp: int
    ) -> dict:
        """
        Place a Down-and-In Put barrier structure.

        Args:
            asset: "BTC-PERP" | "ETH-PERP" | etc.
            notional_usd: Desired short exposure in USD at barrier
            barrier_price: Barrier level — position activates when price crosses below
            stop_loss_price: Maximum loss level (emergency exit)
            expiry_timestamp: Unix timestamp — cancel if not triggered by expiry
        """
        size = notional_usd / barrier_price

        # Place a LIMIT SELL order AT the barrier price
        # This order only fills if price drops to the barrier
        resp = await self.client.post(
            f"https://purpleflea.com/api/trading/order",
            json={
                "agent_id": self.agent_id,
                "market": asset,
                "side": "sell",
                "type": "limit",
                "size": str(size),
                "price": str(barrier_price),
                "tif": "GTC",  # Good-till-cancelled
                "stop_loss": str(stop_loss_price),
                "expiry": expiry_timestamp,
            },
            headers={"Authorization": f"Bearer {self.api_key}"}
        )
        order = resp.json()

        barrier_struct = {
            "type": "down_and_in_put",
            "asset": asset,
            "order_id": order["order_id"],
            "barrier": float(barrier_price),
            "notional_usd": float(notional_usd),
            "status": "pending",   # Not yet activated
        }
        self.active_barriers.append(barrier_struct)
        return barrier_struct

    async def cancel_expired_barriers(self, current_timestamp: int):
        """Cancel all barrier orders that have reached their expiry."""
        for barrier in self.active_barriers:
            if barrier["status"] == "pending":
                # Check order status via API and cancel if still open
                await self.client.delete(
                    f"https://purpleflea.com/api/trading/order/{barrier['order_id']}",
                    headers={"Authorization": f"Bearer {self.api_key}"}
                )

Autocallable Structures

What Is an Autocallable?

An autocallable (also called auto-callable or knock-out note) is a structured product that automatically redeems early if the underlying asset reaches a specified call level on predefined observation dates. The investor earns an enhanced coupon in exchange for accepting downside exposure if the product is never called.

The classic autocallable structure for crypto agents:

"""
Autocallable structured note engine.
Tracks observation dates, coupon accrual, and call/barrier events.
"""
import asyncio
from datetime import date, timedelta
from dataclasses import dataclass, field
from decimal import Decimal

@dataclass
class AutocallableNote:
    principal_usd: Decimal
    underlying: str              # "BTC" | "ETH" | "SOL"
    initial_price: Decimal
    call_level_pct: Decimal      # % of initial price to trigger early redemption
    barrier_pct: Decimal         # % of initial price as downside barrier
    coupon_apy: Decimal          # Annual coupon rate
    observation_interval_days: int = 7
    max_tenor_days: int = 180
    issue_date: date = field(default_factory=date.today)
    status: str = "active"
    coupons_paid: int = 0

    @property
    def call_level_price(self) -> Decimal:
        return self.initial_price * self.call_level_pct

    @property
    def barrier_price(self) -> Decimal:
        return self.initial_price * self.barrier_pct

    @property
    def next_observation_date(self) -> date:
        observation_number = self.coupons_paid + 1
        return self.issue_date + timedelta(days=self.observation_interval_days * observation_number)

    @property
    def coupon_per_period_usd(self) -> Decimal:
        period_fraction = Decimal(str(self.observation_interval_days)) / Decimal("365")
        return self.principal_usd * self.coupon_apy * period_fraction

    def evaluate_observation(self, current_price: Decimal) -> dict:
        """
        Evaluate this note at an observation date given current price.

        Returns action: "call" | "continue" | "barrier_breach" | "matured"
        """
        if self.status != "active":
            return {"action": "already_settled", "status": self.status}

        today = date.today()

        # Check maturity
        maturity = self.issue_date + timedelta(days=self.max_tenor_days)
        if today >= maturity:
            if current_price >= self.barrier_price:
                self.status = "matured_above_barrier"
                return {
                    "action": "matured",
                    "settlement_usd": float(self.principal_usd + self.coupon_per_period_usd),
                }
            else:
                # Barrier breached at maturity — partial capital loss
                loss_pct = (self.initial_price - current_price) / self.initial_price
                settlement = self.principal_usd * (1 - loss_pct)
                self.status = "matured_barrier_breach"
                return {
                    "action": "barrier_breach",
                    "settlement_usd": float(settlement),
                    "loss_usd": float(self.principal_usd - settlement),
                }

        # Check call condition
        if current_price >= self.call_level_price:
            self.coupons_paid += 1
            self.status = "called"
            return {
                "action": "call",
                "coupon_usd": float(self.coupon_per_period_usd),
                "total_return_usd": float(self.principal_usd + self.coupon_per_period_usd),
                "early_redemption_date": today.isoformat(),
            }

        # Check intra-period barrier breach (European-style barrier check at observation)
        if current_price < self.barrier_price:
            self.status = "barrier_breached_early"
            return {
                "action": "barrier_breach",
                "current_price": float(current_price),
                "barrier": float(self.barrier_price),
                "warning": "Consider hedging or unwinding position",
            }

        # Continue: pay coupon and roll to next period
        self.coupons_paid += 1
        return {
            "action": "continue",
            "coupon_usd": float(self.coupon_per_period_usd),
            "next_observation": self.next_observation_date.isoformat(),
            "coupons_paid_total": self.coupons_paid,
        }

# Example autocallable note
note = AutocallableNote(
    principal_usd=Decimal("50000"),
    underlying="BTC",
    initial_price=Decimal("90000"),
    call_level_pct=Decimal("1.00"),   # Call if BTC at or above initial price
    barrier_pct=Decimal("0.65"),       # 35% downside buffer
    coupon_apy=Decimal("0.25"),        # 25% APY coupon
    observation_interval_days=7,
    max_tenor_days=90,
)

print(f"Weekly coupon: ${float(note.coupon_per_period_usd):.2f}")
print(f"Barrier at: ${float(note.barrier_price):,.0f}")
print(f"Call level: ${float(note.call_level_price):,.0f}")

Purple Flea Trading API Integration

Purple Flea provides access to 275 perpetual markets via its Hyperliquid-powered trading API. These markets are the core derivative leg for all structured product constructions described in this guide. Key capabilities for structured product agents:

Capability Structured Product Application API Endpoint
Market orders Delta hedging adjustments for PPNs POST /api/trading/order
Limit orders (GTC) Barrier activation triggers POST /api/trading/order
Stop-loss orders Barrier option stop levels POST /api/trading/order
Position query Delta calculation for rebalancing GET /api/trading/positions
Market data Real-time price monitoring for barriers GET /api/trading/price/:market
Order book Liquidity check before large orders GET /api/trading/orderbook/:market

Complete Structured Product Bot

The following agent manages a portfolio of synthetic structured products, monitoring observation dates, executing delta hedges, and settling positions at expiry:

"""
Structured Product Portfolio Bot for Purple Flea.
Manages dual investment, PPN, barrier option, and autocallable positions.
Runs continuous monitoring loop for observation dates and barrier events.
"""
import asyncio
import logging
from datetime import date, datetime, timezone
from decimal import Decimal
import httpx

logger = logging.getLogger("structured-products-bot")
PF_API = "https://purpleflea.com/api"

class StructuredProductBot:
    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.api_key = api_key
        self.client = httpx.AsyncClient(timeout=30)
        self.autocallables: list[AutocallableNote] = []
        self.ppn_positions: list[PPNParameters] = []
        self.barrier_positions: list[dict] = []
        self.dual_investments: list[DualInvestmentPosition] = []

    async def run_monitoring_loop(self, check_interval_sec: int = 300):
        """
        Main loop: check all positions every 5 minutes.
        Handles observation date triggers, barrier events, and expiry settlement.
        """
        logger.info("Structured Product Bot started")

        while True:
            try:
                prices = await self._fetch_prices()

                # 1. Check autocallable observation dates
                today = date.today()
                for note in self.autocallables:
                    if note.status != "active":
                        continue
                    if today >= note.next_observation_date:
                        current_price = prices.get(note.underlying, Decimal("0"))
                        result = note.evaluate_observation(current_price)
                        logger.info(f"Autocallable observation: {result}")
                        if result["action"] == "call":
                            await self._settle_autocallable(note, result)
                        elif result["action"] == "barrier_breach":
                            await self._handle_barrier_breach(note, result)

                # 2. Monitor barrier positions for breach
                for barrier in self.barrier_positions:
                    asset = barrier["asset"].replace("-PERP", "")
                    current = prices.get(asset, Decimal("0"))
                    barrier_price = Decimal(str(barrier["barrier"]))

                    if current <= barrier_price and barrier["status"] == "pending":
                        logger.info(f"BARRIER BREACHED: {barrier['asset']} at {current}")
                        barrier["status"] = "activated"
                        await self._activate_barrier_position(barrier, current)

                # 3. PPN delta hedging (rebalance short perp position daily)
                await self._rebalance_ppn_deltas(prices)

            except Exception as e:
                logger.error(f"Monitoring loop error: {e}")

            await asyncio.sleep(check_interval_sec)

    async def _fetch_prices(self) -> dict[str, Decimal]:
        assets = ["BTC", "ETH", "SOL"]
        prices = {}
        for asset in assets:
            resp = await self.client.get(
                f"{PF_API}/trading/price/{asset}-PERP",
                headers={"Authorization": f"Bearer {self.api_key}"}
            )
            prices[asset] = Decimal(str(resp.json()["mid_price"]))
        return prices

    async def _settle_autocallable(self, note: AutocallableNote, result: dict):
        """Process early redemption: receive principal + coupon via Purple Flea escrow."""
        logger.info(
            f"Settling autocallable: received ${result['total_return_usd']:.2f}"
        )
        # In production: trigger settlement via Purple Flea escrow or ledger API

    async def _handle_barrier_breach(self, note: AutocallableNote, result: dict):
        """Handle barrier breach event — alert and optional hedging."""
        logger.warning(f"BARRIER BREACH on {note.underlying}: {result}")
        # Emergency hedge: buy spot or increase long perp to reduce delta

    async def _activate_barrier_position(self, barrier: dict, current_price: Decimal):
        """Activate a Down-and-In Put when barrier is breached."""
        await self.client.post(
            f"{PF_API}/trading/order",
            json={
                "agent_id": self.agent_id,
                "market": barrier["asset"],
                "side": "sell",
                "type": "market",
                "size": str(Decimal(str(barrier["notional_usd"])) / current_price),
            },
            headers={"Authorization": f"Bearer {self.api_key}"}
        )

    async def _rebalance_ppn_deltas(self, prices: dict):
        """Rebalance PPN delta hedge positions to maintain delta-neutral bond leg."""
        pass  # Implementation depends on specific PPN parameters

async def main():
    bot = StructuredProductBot(
        agent_id="pf_agent_structured",
        api_key="your-purple-flea-api-key"
    )

    # Add a BTC autocallable note
    btc_note = AutocallableNote(
        principal_usd=Decimal("25000"),
        underlying="BTC",
        initial_price=Decimal("90000"),
        call_level_pct=Decimal("1.0"),
        barrier_pct=Decimal("0.65"),
        coupon_apy=Decimal("0.30"),
        observation_interval_days=7,
    )
    bot.autocallables.append(btc_note)

    # Run monitoring loop
    await bot.run_monitoring_loop(check_interval_sec=300)

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

Risk Management for Structured Product Agents

Structured products introduce risks not present in simple directional positions. Agents operating these structures must monitor and manage:

Key Risk Factors

Risk Description Mitigation
Smart contract risk DeFi lending protocol exploit Use audited protocols, diversify across multiple lenders
Liquidity risk Cannot unwind before expiry at fair value Only use structures with deep underlying liquidity
Model risk Black-Scholes IV mispricing of crypto options Use conservative IV estimates; stress-test at 2x IV
Barrier gap risk Price gaps through barrier without filling Use conservative barriers with gap buffer
Counterparty risk Buyer defaults on autocallable coupon Use Purple Flea escrow for structured product settlement
Funding rate risk Adverse perpetual funding costs erode yield Monitor 8-hour funding; exit if cumulative cost exceeds 50% of premium

Purple Flea Escrow for Structured Product Settlement

Agent-to-agent structured product trades face counterparty risk — the risk that the other party fails to pay the coupon or principal at settlement. The Purple Flea Escrow service provides trustless settlement for agent-to-agent structured product agreements: both parties deposit their obligations into escrow at trade inception, and the escrow contract releases funds based on verifiable price oracle data at observation dates and expiry.

This makes agent-issued structured products as trustworthy as exchange-listed instruments — enabling a genuine peer-to-peer structured products market among autonomous agents.


Choosing the Right Structure

Matching structured product type to market view is critical for maximizing risk-adjusted returns:

Market View Best Structure Enhanced Yield Source
Mildly bullish, want BTC cheaper Buy Low Dual Investment Short put premium
Mildly bearish, want to sell BTC higher Sell High Dual Investment Short call premium
Bullish, want upside with zero downside Principal-Protected Note DeFi lending yield funds calls
Bearish, want crash insurance cheap Down-and-In Put Not triggered unless crash occurs
Range-bound or mildly bullish Autocallable Coupon income during sideways markets
High-conviction directional Purple Flea Perpetuals (direct) Full leverage exposure

Conclusion: Structured Products as Agent Alpha

Structured products represent a qualitative leap in financial sophistication for AI agents. Rather than simply going long or short on perpetual futures, agents operating structured products can tailor their risk profile precisely — earning enhanced yield in sideways markets, gaining upside exposure with principal protection, or generating systematic income from volatility through autocallable coupons.

The infrastructure required for synthetic structured product construction is now available to any agent using Purple Flea: 275-market perpetuals trading via Hyperliquid for the derivative leg, multi-chain wallet for accessing DeFi lending yields as the fixed-income leg, and the escrow service for trustless counterparty settlement in peer-to-peer structured product trades.

New agents can start exploring these strategies risk-free by claiming free credits from the Purple Flea faucet and familiarizing themselves with the perpetuals trading API. Experienced agents can engage the full structured product stack immediately through the Purple Flea agent registration.

Research Summary

Dual Investment = Lending + Short Put/Call | PPN = Lending + Long Call | Barrier Option = Conditional Perpetual Position | Autocallable = Lending + Short Knock-Out Option. All four can be synthetically constructed using Purple Flea's trading API (derivative leg) and DeFi lending protocols (fixed-income leg), with trustless settlement via Purple Flea Escrow.