Skip to main content

Lightweight async Python client for the TopstepX / ProjectX Gateway API

Project description

topstep-client-py

CI PyPI - Version PyPI - Downloads Python Version License Async

Lightweight async Python client for the TopstepX / ProjectX Gateway API.

Disclaimer

This project is an independent community-built library. It is not officially affiliated with, endorsed by, maintained by, or otherwise directly associated with Topstep, TopstepX, or ProjectX.

The goal of this package is to provide a clean and practical Python client for the public API and realtime interfaces. It is maintained on a best-effort basis and will be kept up to date as quickly as reasonably possible when the upstream API changes.

This repository only provides the API client layer. It does not include trading strategies, alpha generation, signal logic, backtesting frameworks, portfolio tooling, or other trader-specific systems. Those decisions and tools are intentionally left to each user and their own workflow.

  • Async-first (built on httpx)
  • Fully typed responses with Pydantic models
  • All 16 REST endpoints covered
  • Real-time market & user data via SignalR WebSocket
  • Retry with backoff + rate limit handling
  • Clean exception hierarchy

Installation

pip install topstep-client-py

Quick Start

import asyncio
from datetime import datetime, timedelta, timezone
from topstep import TopstepClient, BarUnit

async def main():
    async with await TopstepClient.create(
        username="you@email.com",
        api_key="your-api-key",
    ) as client:

        # Search accounts
        accounts = await client.accounts.search()
        account = accounts[0]
        print(f"Account: {account.name} | Balance: {account.balance}")

        # Find a contract
        contracts = await client.contracts.search("Micro E-mini Nasdaq")
        contract = contracts[0]
        print(f"Contract: {contract.description} | Tick: {contract.tick_size}")

        # Get historical bars
        end = datetime.now(timezone.utc)
        start = end - timedelta(hours=1)
        bars = await client.history.retrieve_bars(
            contract_id=contract.id,
            start=start,
            end=end,
            unit=BarUnit.MINUTE,
            unit_number=5,
        )
        for bar in bars[-3:]:
            print(f"  {bar.timestamp} O:{bar.open} H:{bar.high} L:{bar.low} C:{bar.close}")

asyncio.run(main())

Placing Orders

from topstep import PlaceOrderRequest, OrderType, OrderSide, Bracket

order_id = await client.orders.place(PlaceOrderRequest(
    account_id=account.id,
    contract_id=contract.id,
    type=OrderType.STOP,
    side=OrderSide.BUY,
    size=2,
    stop_price=21500.0,
    stop_loss_bracket=Bracket(ticks=-20, type=4),
    take_profit_bracket=Bracket(ticks=40, type=1),
))
print(f"Order placed: {order_id}")

# Check open orders
open_orders = await client.orders.search_open(account.id)

# Cancel an order
await client.orders.cancel(account.id, order_id)

Positions

# Get open positions
positions = await client.positions.search_open(account.id)

# Close all positions for a contract
await client.positions.close(account.id, contract.id)

# Partial close
await client.positions.partial_close(account.id, contract.id, size=1)

Trade History

from datetime import datetime, timezone

trades = await client.trades.search(
    account_id=account.id,
    start=datetime(2026, 3, 1, tzinfo=timezone.utc),
)
for trade in trades:
    print(f"  {trade.price} | P&L: {trade.profit_and_loss} | Fees: {trade.fees}")

Real-Time Market Data (WebSocket)

import asyncio
from topstep import TopstepClient

async def main():
    async with await TopstepClient.create(
        username="you@email.com",
        api_key="your-api-key",
    ) as client:

        # Register callbacks
        client.market.on_quote(lambda *args: print("QUOTE:", args))
        client.market.on_trade(lambda *args: print("TRADE:", args))
        client.market.on_depth(lambda *args: print("DEPTH:", args))

        # Connect and subscribe
        await client.market.connect()
        await client.market.subscribe_all("CON.F.US.ENQ.H26")

        # Keep alive
        try:
            while True:
                await asyncio.sleep(1)
        except KeyboardInterrupt:
            await client.market.stop()

asyncio.run(main())

Real-Time User Data (WebSocket)

async with await TopstepClient.create(...) as client:

    client.user.on_order(lambda *args: print("ORDER:", args))
    client.user.on_position(lambda *args: print("POSITION:", args))
    client.user.on_trade(lambda *args: print("TRADE:", args))
    client.user.on_account(lambda *args: print("ACCOUNT:", args))

    await client.user.connect()
    await client.user.subscribe_all(account_id=account.id)

    # ...

Token Refresh

Tokens expire after 24 hours. Refresh manually:

await client.refresh_token()

Error Handling

from topstep import TopstepError, AuthenticationError, APIError, RateLimitError

try:
    accounts = await client.accounts.search()
except AuthenticationError:
    # Invalid credentials or expired token
    await client.refresh_token()
except RateLimitError:
    # HTTP 429 — too many requests (auto-retried 3 times before raising)
    pass
except APIError as e:
    # API returned success=False
    print(f"API error [{e.error_code}]: {e}")
except TopstepError:
    # Any other client error
    pass

Rate Limits

The API enforces these limits (handled automatically with retry + backoff):

  • History/retrieveBars: 50 requests per 30 seconds
  • All other endpoints: 200 requests per 60 seconds

Development

git clone https://github.com/YOUR_USER/topstep-client-py.git
cd topstep-client-py
pip install -e ".[dev]"
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

topstep_client_py-0.1.1.tar.gz (19.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

topstep_client_py-0.1.1-py3-none-any.whl (22.4 kB view details)

Uploaded Python 3

File details

Details for the file topstep_client_py-0.1.1.tar.gz.

File metadata

  • Download URL: topstep_client_py-0.1.1.tar.gz
  • Upload date:
  • Size: 19.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for topstep_client_py-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a68ada515fc46eb4053e2a1e2253fa983f28d2b82e40bf85cc53c2da7da9c163
MD5 f392a29962d923c0f90f0c761ffb1e32
BLAKE2b-256 9ba6b92c06767e0c49bd228e6396428b10ff47c517b2f8a6e6376b4eb5acc266

See more details on using hashes here.

Provenance

The following attestation bundles were made for topstep_client_py-0.1.1.tar.gz:

Publisher: publish.yml on icarus-research/topstep-client-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file topstep_client_py-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for topstep_client_py-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 52d99b38d0b7d88bc9db744bb293bd82185f1dfa98e8ec74d5188ac1115ee0e5
MD5 55222086e5aaf94760e9a728593b28ba
BLAKE2b-256 be169bfec5f5c78349d45f9c93e813d9a350c2d16fd088dc86cec63123bf95db

See more details on using hashes here.

Provenance

The following attestation bundles were made for topstep_client_py-0.1.1-py3-none-any.whl:

Publisher: publish.yml on icarus-research/topstep-client-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page