get_positions() is the py_clob_client method that retrieves all your open positions on Polymarket. Each position represents your holdings of a specific outcome token — how many shares you hold and at what average price. This page covers the method signature, response fields, P&L calculation, the public Data API alternative, and common patterns for position management.

For the complete py_clob_client method reference covering all methods, see the py_clob_client Reference. For Kalshi’s equivalent positions endpoint, see the Prediction Market API Reference.


Method Signature

client.get_positions() -> list

Parameters

None required. The method fetches all positions for the authenticated user.

Return Type

A list of position dictionaries, each containing:

FieldTypeDescription
assetdictToken details: token_id (str), condition_id (str)
sizestrNumber of shares held
avgPricestrAverage entry price per share (0.00–1.00)
sidestrSide of the position

Authentication required: Yes. You must call set_api_creds() before using this method.


Basic Example

List all your open positions:

from py_clob_client.client import ClobClient

client = ClobClient(
    "https://clob.polymarket.com",
    key="<your-private-key>",
    chain_id=137
)
client.set_api_creds(client.create_or_derive_api_creds())

positions = client.get_positions()

if not positions:
    print("No open positions")
else:
    for pos in positions:
        token_id = pos["asset"]["token_id"]
        size = float(pos["size"])
        avg_price = float(pos["avgPrice"])
        cost_basis = size * avg_price

        print(f"Token:      {token_id[:20]}...")
        print(f"Shares:     {size:.2f}")
        print(f"Avg Price:  ${avg_price:.4f}")
        print(f"Cost Basis: ${cost_basis:.2f}")
        print("---")

Calculate Unrealized P&L

Combine positions with current prices to calculate unrealized profit or loss:

from py_clob_client.client import ClobClient

client = ClobClient(
    "https://clob.polymarket.com",
    key="<your-private-key>",
    chain_id=137
)
client.set_api_creds(client.create_or_derive_api_creds())

positions = client.get_positions()
total_pnl = 0.0
total_cost = 0.0

for pos in positions:
    token_id = pos["asset"]["token_id"]
    size = float(pos["size"])
    avg_price = float(pos["avgPrice"])

    # Get current market price
    current_price = float(client.get_midpoint(token_id=token_id))

    cost_basis = size * avg_price
    current_value = size * current_price
    unrealized_pnl = current_value - cost_basis
    pnl_pct = (unrealized_pnl / cost_basis * 100) if cost_basis > 0 else 0

    total_pnl += unrealized_pnl
    total_cost += cost_basis

    print(f"Token: {token_id[:20]}...")
    print(f"  Entry: ${avg_price:.4f} → Current: ${current_price:.4f}")
    print(f"  P&L:   ${unrealized_pnl:+.2f} ({pnl_pct:+.1f}%)")

print(f"\nTotal Cost Basis: ${total_cost:.2f}")
print(f"Total Unrealized P&L: ${total_pnl:+.2f}")

Check for Existing Position Before Trading

Prevent accidentally doubling your exposure when a bot runs repeatedly:

def has_position(client, target_token_id):
    """Check if we already hold a position in this outcome."""
    positions = client.get_positions()
    for pos in positions:
        if pos["asset"]["token_id"] == target_token_id:
            return float(pos["size"]) > 0
    return False

def get_position_size(client, target_token_id):
    """Get current position size for a token, or 0 if no position."""
    positions = client.get_positions()
    for pos in positions:
        if pos["asset"]["token_id"] == target_token_id:
            return float(pos["size"])
    return 0.0

# Example: Only buy if we don't already have a position
token_id = "<token-id>"
if not has_position(client, token_id):
    order = OrderArgs(
        token_id=token_id,
        price=0.50,
        size=10.0,
        side=BUY
    )
    signed = client.create_order(order)
    client.post_order(signed, OrderType.GTC)
    print("Order placed")
else:
    current_size = get_position_size(client, token_id)
    print(f"Already holding {current_size:.2f} shares — skipping")

Position Sizing Based on Current Holdings

Scale orders based on your existing exposure:

def calculate_order_size(client, token_id, max_position=1000, target_price=0.50):
    """Calculate order size respecting a maximum position limit."""
    current_size = get_position_size(client, token_id)
    remaining_capacity = max_position - current_size

    if remaining_capacity <= 0:
        print(f"Position limit reached: {current_size:.0f}/{max_position} shares")
        return 0

    # Check available balance
    balance_wei = client.get_balance()
    balance_usdc = int(balance_wei) / 1e6
    max_affordable = balance_usdc / target_price

    order_size = min(remaining_capacity, max_affordable)
    print(f"Current: {current_size:.0f} | Capacity: {remaining_capacity:.0f} | "
          f"Affordable: {max_affordable:.0f} | Order: {order_size:.0f}")

    return order_size

Public Data API Alternative

The Polymarket Data API provides position data without authentication — you only need a wallet address. This is useful for monitoring positions for any address or building dashboards.

REST Endpoint

curl "https://data-api.polymarket.com/positions?user=YOUR_WALLET_ADDRESS"

Python Example

import requests

address = "0xYOUR_WALLET_ADDRESS"
url = f"https://data-api.polymarket.com/positions?user={address}"

response = requests.get(url)
positions = response.json()

for pos in positions:
    print(f"Market: {pos.get('title', 'Unknown')}")
    print(f"Token:  {pos['token_id'][:20]}...")
    print(f"Size:   {pos['size']}")
    print("---")

CLI Equivalent

# Via Polymarket CLI
polymarket data positions YOUR_WALLET_ADDRESS

# JSON output
polymarket -o json data positions YOUR_WALLET_ADDRESS

When to Use Data API vs get_positions()

ScenarioUseWhy
Your bot’s own positionsget_positions()Already authenticated, no extra HTTP call
Monitor any wallet’s positionsData APIPublic, no auth needed
Building a dashboardData APICan query multiple addresses
Pre-trade validation in a botget_positions()Part of the authenticated trading flow

Common Errors

ErrorCauseFix
UNAUTHORIZED or 403API credentials not setCall client.set_api_creds(client.create_or_derive_api_creds()) first
Empty list returnedNo open positions, or wrong walletVerify your wallet address and that you have active positions
Wrong positions shownUsing EOA wallet but funds are on proxySet signature_type=1 and funder="<proxy-address>" for Magic wallets
ConnectionErrorAPI unreachableRetry with exponential backoff
Stale position dataPositions may lag recent fills by secondsFor real-time fills, use the WebSocket user channel

See Also


{{ partial “marketplace-cta.html” . }}


This reference is maintained by AgentBets.ai. Found an error or SDK change we missed? Let us know on Twitter.

Not financial advice. Built for builders.