> ## Documentation Index
> Fetch the complete documentation index at: https://docs.compasslabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Rebalance a position

> Move a position to a new range, in one transaction.

**`NOOP` is a real answer and often the right one.** Rebalancing realizes
the impermanent loss the position has taken so far, pays gas twice and a
swap, and puts the position back at risk from a new price. If the position
is already centred at the requested width, that is what you will get.

When there is something to do, the transaction unwinds the old position,
sweeps it together with the fees, opens the new range and burns the empty
NFT. Every leg is sized from the **floor** the previous one guarantees
rather than from its quote — they execute in the same transaction, and a
mint sized from a quote reverts when the decrease comes back a wei short,
leaving the owner having paid gas to dismantle a position. `estimated_dust`
is what that safety costs.

The default `vol_scaled` strategy sizes the new range from the pair's own
measured volatility: two standard deviations over the horizon. A range
narrower than the asset's ordinary movement spends most of its life out of
range earning nothing, which is the most common way to lose money doing
this on purpose.



## OpenAPI

````yaml /v2/combined_spec.json post /v2/risk_yield/rebalance
openapi: 3.1.0
info:
  title: Compass API
  description: Compass Labs DeFi API
  version: 0.0.1
servers:
  - url: https://api.compasslabs.ai
    description: Production server
security:
  - ApiKeyAuth: []
paths:
  /v2/risk_yield/rebalance:
    post:
      tags:
        - Risk Yield
      summary: Rebalance a position
      description: >-
        Move a position to a new range, in one transaction.


        **`NOOP` is a real answer and often the right one.** Rebalancing
        realizes

        the impermanent loss the position has taken so far, pays gas twice and a

        swap, and puts the position back at risk from a new price. If the
        position

        is already centred at the requested width, that is what you will get.


        When there is something to do, the transaction unwinds the old position,

        sweeps it together with the fees, opens the new range and burns the
        empty

        NFT. Every leg is sized from the **floor** the previous one guarantees

        rather than from its quote — they execute in the same transaction, and a

        mint sized from a quote reverts when the decrease comes back a wei
        short,

        leaving the owner having paid gas to dismantle a position.
        `estimated_dust`

        is what that safety costs.


        The default `vol_scaled` strategy sizes the new range from the pair's
        own

        measured volatility: two standard deviations over the horizon. A range

        narrower than the asset's ordinary movement spends most of its life out
        of

        range earning nothing, which is the most common way to lose money doing

        this on purpose.
      operationId: v2_risk_yield_rebalance
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RiskYieldRebalanceRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RiskYieldRebalanceResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      x-codeSamples:
        - lang: python
          label: Python (SDK)
          source: |-
            from compass_api_sdk import CompassAPI, models


            with CompassAPI(
                api_key_auth="<YOUR_API_KEY_HERE>",
            ) as compass_api:

                res = compass_api.risk_yield.risk_yield_rebalance(owner="0x06A9aF046187895AcFc7258450B15397CAc67400", position_id=1076416, chain=models.RiskYieldRebalanceRequestChain.ROBINHOOD, gas_sponsorship=False, preview=False, slippage_pct="0.5", deadline_seconds=300, strategy=models.RebalanceStrategy.VOL_SCALED, horizon_days=7, burn_old=True)

                # Handle response
                print(res)
        - lang: typescript
          label: Typescript (SDK)
          source: |-
            import { CompassApiSDK } from "@compass-labs/api-sdk";

            const compassApiSDK = new CompassApiSDK({
              apiKeyAuth: "<YOUR_API_KEY_HERE>",
            });

            async function run() {
              const result = await compassApiSDK.riskYield.riskYieldRebalance({
                owner: "0x06A9aF046187895AcFc7258450B15397CAc67400",
                chain: "robinhood",
                positionId: 1076416,
                strategy: "vol_scaled",
                horizonDays: 7,
              });

              console.log(result);
            }

            run();
components:
  schemas:
    RiskYieldRebalanceRequest:
      properties:
        owner:
          type: string
          title: Owner
          description: The wallet that owns the Risk Yield Account.
          default: '0x06A9aF046187895AcFc7258450B15397CAc67400'
          examples:
            - '0x06A9aF046187895AcFc7258450B15397CAc67400'
        chain:
          type: string
          enum:
            - robinhood
          title: Chain
          description: Risk Yield is available on Robinhood Chain only.
          default: robinhood
          examples:
            - robinhood
        gas_sponsorship:
          type: boolean
          title: Gas Sponsorship
          description: >-
            Return EIP-712 typed data for the owner to sign instead of a
            transaction, so a sponsor can broadcast it.
          default: false
        preview:
          type: boolean
          title: Preview
          description: >-
            Return the plan and its simulation without building a transaction.
            Nothing is signed and nothing can be broadcast.
          default: false
        slippage_pct:
          anyOf:
            - type: number
              maximum: 10
              exclusiveMinimum: 0
            - type: string
              pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Slippage Pct
          description: >-
            How far the executed amounts may fall short of the quote before the
            transaction reverts. Memecoin pools move between the quote and the
            block that includes the transaction.
          default: '0.5'
        deadline_seconds:
          type: integer
          maximum: 3600
          minimum: 30
          title: Deadline Seconds
          description: How long the transaction stays valid once built.
          default: 300
        position_id:
          type: integer
          title: Position Id
          default: 1076416
          examples:
            - 1076416
        dex_version:
          $ref: '#/components/schemas/DexVersion'
          default: V3
        strategy:
          $ref: '#/components/schemas/RebalanceStrategy'
          default: vol_scaled
          examples:
            - vol_scaled
        width_pct:
          anyOf:
            - type: number
              maximum: 1000
              exclusiveMinimum: 0
            - type: string
              pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
            - type: 'null'
          title: Width Pct
          description: Required for `recenter_symmetric_pct`.
        horizon_days:
          type: integer
          maximum: 365
          minimum: 1
          title: Horizon Days
          description: >-
            For `vol_scaled`: how long the range should survive an ordinary
            move. A range narrower than the asset's usual movement spends most
            of its life out of range earning nothing.
          default: 7
          examples:
            - 7
        tick_lower:
          anyOf:
            - type: integer
            - type: 'null'
          title: Tick Lower
          description: For `manual`.
        tick_upper:
          anyOf:
            - type: integer
            - type: 'null'
          title: Tick Upper
          description: For `manual`.
        burn_old:
          type: boolean
          title: Burn Old
          description: Destroy the emptied NFT once it is unwound.
          default: true
      type: object
      required:
        - owner
        - position_id
      title: RiskYieldRebalanceRequest
      description: >-
        Move a position to a new range.


        Rebalancing is not free: it realizes the impermanent loss taken so far,
        pays

        gas twice and a swap, and puts the position back at risk from a new
        price.

        The API will answer `NOOP` when it thinks the move is not worth making.
      default:
        owner: '0x06A9aF046187895AcFc7258450B15397CAc67400'
        chain: robinhood
        position_id: 1076416
        strategy: vol_scaled
        horizon_days: 7
    RiskYieldRebalanceResponse:
      properties:
        action:
          type: string
          title: Action
          description: >-
            `NOOP`, `COLLECT_ONLY` or `RECENTER`. `NOOP` is a real answer and
            often the right one — moving a position realizes its loss and pays
            for a swap.
        reason:
          type: string
          title: Reason
        transaction:
          anyOf:
            - $ref: '#/components/schemas/UnsignedTransaction'
            - type: 'null'
        old_position_id:
          anyOf:
            - type: integer
            - type: 'null'
          title: Old Position Id
        old_range:
          anyOf:
            - $ref: '#/components/schemas/ResolvedRange'
            - type: 'null'
        new_range:
          anyOf:
            - $ref: '#/components/schemas/ResolvedRange'
            - type: 'null'
        liquidity_removed:
          anyOf:
            - type: string
            - type: 'null'
          title: Liquidity Removed
        amount0_floor:
          anyOf:
            - type: string
            - type: 'null'
          title: Amount0 Floor
          description: >-
            What the unwind is guaranteed to return. The new position is sized
            from this rather than from the quote, because every leg executes in
            the same transaction and a mint sized from a quote reverts when the
            decrease comes back a wei short.
        amount1_floor:
          anyOf:
            - type: string
            - type: 'null'
          title: Amount1 Floor
        expected_liquidity_floor:
          anyOf:
            - type: string
            - type: 'null'
          title: Expected Liquidity Floor
        estimated_dust0:
          anyOf:
            - type: string
            - type: 'null'
          title: Estimated Dust0
        estimated_dust1:
          anyOf:
            - type: string
            - type: 'null'
          title: Estimated Dust1
        phases:
          items:
            $ref: '#/components/schemas/RebalancePhase'
          type: array
          title: Phases
        simulation:
          anyOf:
            - $ref: '#/components/schemas/Simulation'
            - type: 'null'
        warnings:
          items:
            type: string
          type: array
          title: Warnings
      type: object
      required:
        - action
        - reason
      title: RiskYieldRebalanceResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    DexVersion:
      type: string
      enum:
        - V3
        - V4
      title: DexVersion
      description: >-
        Which Uniswap deployment a pool belongs to.


        v3 pools hold their own tokens and pay LPs the fee tier. v4 pools live
        in a

        shared PoolManager and may route the fee through a hook, which is where
        the

        launchpad pools' zero LP yield comes from.
    RebalanceStrategy:
      type: string
      enum:
        - recenter_symmetric_pct
        - vol_scaled
        - manual
      title: RebalanceStrategy
      description: How to choose the new range.
    UnsignedTransaction:
      properties:
        chainId:
          type: string
          title: Chainid
          description: The chain id of the transaction
        data:
          type: string
          title: Data
          description: The data of the transaction
        from:
          type: string
          title: From
          description: The sender of the transaction
        gas:
          anyOf:
            - type: string
            - type: 'null'
          title: Gas
          description: The gas of the transaction
        to:
          type: string
          title: To
          description: The recipient of the transaction
        value:
          type: string
          title: Value
          description: The value of the transaction
        nonce:
          type: string
          title: Nonce
          description: The nonce of the address
        maxFeePerGas:
          type: string
          title: Maxfeepergas
          description: The max fee per gas of the transaction
        maxPriorityFeePerGas:
          type: string
          title: Maxpriorityfeepergas
          description: The max priority fee per gas of the transaction
      type: object
      required:
        - chainId
        - data
        - from
        - gas
        - to
        - value
        - nonce
        - maxFeePerGas
        - maxPriorityFeePerGas
      title: UnsignedTransaction
      example:
        chainId: '0x2105'
        data: >-
          0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000675f4a3d
        from: '0x4A83b4413CF41C3244027e1590E35a0F48403F0c'
        gas: '0x7a120'
        maxFeePerGas: '0x59682f00'
        maxPriorityFeePerGas: '0x3b9aca00'
        nonce: '0x5'
        to: '0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67'
        value: '0x0'
    ResolvedRange:
      properties:
        tick_lower:
          type: integer
          title: Tick Lower
        tick_upper:
          type: integer
          title: Tick Upper
        price_lower:
          type: string
          title: Price Lower
        price_upper:
          type: string
          title: Price Upper
        width_lower_pct:
          type: string
          title: Width Lower Pct
          description: How far below the current price the lower bound sits.
        width_upper_pct:
          type: string
          title: Width Upper Pct
        is_full_range:
          type: boolean
          title: Is Full Range
      type: object
      required:
        - tick_lower
        - tick_upper
        - price_lower
        - price_upper
        - width_lower_pct
        - width_upper_pct
        - is_full_range
      title: ResolvedRange
      description: >-
        A range after the API has snapped it to the pool's tick spacing.


        Returned because the range you asked for is rarely the range you get:
        ticks

        are discrete, and a 30% band becomes whichever usable ticks bracket it.
    RebalancePhase:
      properties:
        name:
          type: string
          title: Name
        description:
          type: string
          title: Description
        steps:
          items:
            $ref: '#/components/schemas/PlanStep'
          type: array
          title: Steps
      type: object
      required:
        - name
        - description
      title: RebalancePhase
      description: One stage of the plan, with the legs it contributes.
    Simulation:
      properties:
        ok:
          type: boolean
          title: Ok
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
        gas_used:
          anyOf:
            - type: integer
            - type: 'null'
          title: Gas Used
      type: object
      required:
        - ok
      title: Simulation
      description: >-
        The result of executing the transaction against current state.


        Meme tokens on this chain carry transfer taxes, blacklists and pause

        switches, none of which are visible from a pool's parameters. Simulating
        is

        the only way to find out before the owner signs.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    PlanStep:
      properties:
        kind:
          $ref: '#/components/schemas/PlanStepKind'
        description:
          type: string
          title: Description
        contract:
          anyOf:
            - type: string
            - type: 'null'
          title: Contract
        token:
          anyOf:
            - type: string
            - type: 'null'
          title: Token
        amount:
          anyOf:
            - type: string
            - type: 'null'
          title: Amount
      type: object
      required:
        - kind
        - description
      title: PlanStep
      description: >-
        One leg of a bundled transaction, in the order it executes.


        Every transact endpoint returns a single transaction; this is what is
        inside

        it, so a caller can show a person what they are about to sign.
    PlanStepKind:
      type: string
      enum:
        - APPROVE
        - PERMIT2_APPROVE
        - SWAP
        - MINT
        - INCREASE
        - DECREASE
        - COLLECT
        - BURN
        - TRANSFER
      title: PlanStepKind
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your Compass API Key. Get your key
        [here](https://www.compasslabs.ai/dashboard).

````