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

# Closed-position stats for a wallet

> Aggregate over the wallet's CLOSED position lifecycles: count, average/min/max hold time, total and average realized PnL, win/loss counts, win rate, and the first/last close time (RFC 3339). Source: the latest 10,000 eligible rows for the wallet in position_lifecycles_full — closed perps only, excluding censored lifecycles that opened before the table's start. There is no time cutoff. The 10,000-position cap bounds work for very active wallets; totalPositions is therefore at most 10,000. losingPositions counts realized_pnl <= 0 (flat closes included), so winningPositions + losingPositions = totalPositions. winRate = winningPositions / totalPositions x 100. Coverage: this route previously aggregated the legacy closed_positions table, whose history reaches further back than the lifecycle table (which begins on 2026-08-31) but whose PnL was the unrealized snapshot at close rather than realized PnL, and whose exact per-position resolution could not complete within the request budget for wallets with tens of thousands of closed positions. totalPositions and firstClose can therefore be lower/later than before because lifecycle history is shorter and the newest 10,000-position cap may apply; PnL figures are now realized. Wallets with no eligible closed lifecycle return zero counts and omit firstClose/lastClose.



## OpenAPI

````yaml /api-reference/openapi.json get /api/public/v1/pulse/trader/{address}/closed-positions/stats
openapi: 3.1.0
info:
  title: coinversa-api
  version: 0.1.0
servers:
  - url: https://api.coinversa.ai
    description: Production
security: []
paths:
  /api/public/v1/pulse/trader/{address}/closed-positions/stats:
    get:
      tags:
        - Pulse
      summary: Closed-position stats for a wallet
      description: >-
        Aggregate over the wallet's CLOSED position lifecycles: count,
        average/min/max hold time, total and average realized PnL, win/loss
        counts, win rate, and the first/last close time (RFC 3339). Source: the
        latest 10,000 eligible rows for the wallet in position_lifecycles_full —
        closed perps only, excluding censored lifecycles that opened before the
        table's start. There is no time cutoff. The 10,000-position cap bounds
        work for very active wallets; totalPositions is therefore at most
        10,000. losingPositions counts realized_pnl <= 0 (flat closes included),
        so winningPositions + losingPositions = totalPositions. winRate =
        winningPositions / totalPositions x 100. Coverage: this route previously
        aggregated the legacy closed_positions table, whose history reaches
        further back than the lifecycle table (which begins on 2026-08-31) but
        whose PnL was the unrealized snapshot at close rather than realized PnL,
        and whose exact per-position resolution could not complete within the
        request budget for wallets with tens of thousands of closed positions.
        totalPositions and firstClose can therefore be lower/later than before
        because lifecycle history is shorter and the newest 10,000-position cap
        may apply; PnL figures are now realized. Wallets with no eligible closed
        lifecycle return zero counts and omit firstClose/lastClose.
      operationId: get-api-public-v1-pulse-trader-by-address-closed-positions-stats
      parameters:
        - description: >-
            Wallet address to inspect (0x followed by 40 hexadecimal
            characters). An unindexed address returns 404.
          in: path
          name: address
          required: true
          schema:
            description: >-
              Wallet address to inspect (0x followed by 40 hexadecimal
              characters). An unindexed address returns 404.
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClosedPositionStatsBody'
          description: OK
          headers:
            X-Billing-Grace-Expires:
              $ref: '#/components/headers/X-Billing-Grace-Expires'
            X-Billing-State:
              $ref: '#/components/headers/X-Billing-State'
            X-RateLimit-Daily:
              $ref: '#/components/headers/X-RateLimit-Daily'
            X-RateLimit-Daily-Reset:
              $ref: '#/components/headers/X-RateLimit-Daily-Reset'
            X-RateLimit-Monthly:
              $ref: '#/components/headers/X-RateLimit-Monthly'
            X-RateLimit-Monthly-Reset:
              $ref: '#/components/headers/X-RateLimit-Monthly-Reset'
            X-RateLimit-Next:
              $ref: '#/components/headers/X-RateLimit-Next'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Route:
              $ref: '#/components/headers/X-RateLimit-Route'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-RateLimit-Tier:
              $ref: '#/components/headers/X-RateLimit-Tier'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Bad Request
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '403':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Forbidden
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '404':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Not Found
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '422':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Unprocessable Entity
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '429':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Too Many Requests
          headers:
            Retry-After:
              $ref: '#/components/headers/Retry-After'
            X-Billing-Grace-Expires:
              $ref: '#/components/headers/X-Billing-Grace-Expires'
            X-Billing-State:
              $ref: '#/components/headers/X-Billing-State'
            X-RateLimit-Daily:
              $ref: '#/components/headers/X-RateLimit-Daily'
            X-RateLimit-Daily-Reset:
              $ref: '#/components/headers/X-RateLimit-Daily-Reset'
            X-RateLimit-Monthly:
              $ref: '#/components/headers/X-RateLimit-Monthly'
            X-RateLimit-Monthly-Reset:
              $ref: '#/components/headers/X-RateLimit-Monthly-Reset'
            X-RateLimit-Next:
              $ref: '#/components/headers/X-RateLimit-Next'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Route:
              $ref: '#/components/headers/X-RateLimit-Route'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-RateLimit-Tier:
              $ref: '#/components/headers/X-RateLimit-Tier'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Internal Server Error
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '504':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/APIError'
          description: Gateway Timeout
          headers:
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
      security:
        - apiKey: []
components:
  schemas:
    ClosedPositionStatsBody:
      additionalProperties: false
      properties:
        $schema:
          description: A URL to the JSON Schema for this object.
          examples:
            - https://api.coinversa.ai/schemas/ClosedPositionStatsBody.json
          format: uri
          readOnly: true
          type: string
        avgDurationMs:
          format: double
          type: number
        avgPnl:
          format: double
          type: number
        firstClose:
          type: string
        lastClose:
          type: string
        losingPositions:
          format: int64
          type: integer
        maxDurationMs:
          format: double
          type: number
        minDurationMs:
          format: double
          type: number
        totalPnl:
          format: double
          type: number
        totalPositions:
          format: int64
          type: integer
        winRate:
          format: double
          type: number
        winningPositions:
          format: int64
          type: integer
      required:
        - totalPositions
        - avgDurationMs
        - totalPnl
        - avgPnl
        - winningPositions
        - losingPositions
        - winRate
      type: object
    APIError:
      additionalProperties: false
      properties:
        $schema:
          description: A URL to the JSON Schema for this object.
          examples:
            - https://api.coinversa.ai/schemas/APIError.json
          format: uri
          readOnly: true
          type: string
        code:
          description: Machine-readable error code; retained for compatibility.
          type: string
        current_tier:
          description: Caller's effective tier
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        reason:
          description: >-
            More specific recovery reason when available: missing_api_key,
            invalid_api_key, insufficient_tier, or invalid_parameters. HTTP
            statuses and legacy code values remain unchanged.
          type: string
        required_tier:
          description: Minimum tier for this operation
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
        upgrade_url:
          description: Where to upgrade
          type: string
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
  headers:
    X-Billing-Grace-Expires:
      description: RFC3339 time when billing grace expires, when applicable.
      schema:
        type: string
    X-Billing-State:
      description: Billing grace state, when applicable.
      schema:
        type: string
    X-RateLimit-Daily:
      description: >-
        Daily account allowance reported by the existing counter check, clamped
        at zero. Best-effort; present only for a capped tier that reaches the
        quota check.
      schema:
        type: string
    X-RateLimit-Daily-Reset:
      description: >-
        Unix seconds (UTC) after the selected daily quota bucket expires. Not a
        source-data timestamp.
      schema:
        type: string
    X-RateLimit-Monthly:
      description: >-
        Monthly account allowance reported by the existing counter check,
        clamped at zero. Best-effort; present only for a capped tier that
        reaches the quota check.
      schema:
        type: string
    X-RateLimit-Monthly-Reset:
      description: >-
        Unix seconds (UTC) after the selected monthly quota bucket expires.
        Follows the existing billing anchor.
      schema:
        type: string
    X-RateLimit-Next:
      description: >-
        Legacy Go duration string until the next token is available across the
        checked buckets; not the daily/monthly reset.
      schema:
        type: string
    X-RateLimit-Remaining:
      description: >-
        Minimum remaining tokens across the checked minute and per-route token
        buckets (account for keys, IP for anonymous requests). Not a
        fixed-window request allowance.
      schema:
        type: string
    X-RateLimit-Reset:
      description: >-
        Unix seconds (UTC), rounded up, when the checked token buckets next
        permit a request, assuming no competing traffic. Not a full bucket
        refill.
      schema:
        type: string
    X-RateLimit-Route:
      description: Remaining tokens in the account's per-route token bucket.
      schema:
        type: string
    X-RateLimit-Scope:
      description: >-
        account for authenticated requests (shared across keys); ip for
        anonymous requests. Describes the limiter scope, not the key's resolved
        tier.
      schema:
        type: string
    X-RateLimit-Tier:
      description: Effective tier for this request; only present after access checks pass.
      schema:
        type: string
    X-Request-ID:
      description: >-
        Server-generated correlation ID. Include it in a support report; not a
        guarantee that an unauthenticated request appears in account usage logs.
      schema:
        type: string
    Retry-After:
      description: >-
        On HTTP 429, whole seconds to wait before retrying, rounded up. Other
        traffic may still consume the available allowance.
      schema:
        type: string
  securitySchemes:
    apiKey:
      description: >-
        Create an API key at https://developers.coinversa.ai/keys. REST limits
        are shared across keys by account; access uses the effective tier of the
        presented key.
      in: header
      name: X-API-Key
      type: apiKey

````