Skip to main content

A production-ready Python SDK for the TradeZero REST API.

Project description

tradezero-sdk

<<<<<<< HEAD

Python PyPI License: MIT CI codecov

An unofficial, production-ready Python SDK for the TradeZero REST API.

TradeZero is an online broker offering direct-access trading for equities. This SDK wraps their REST API with a clean Python interface — no manual HTTP, no raw JSON parsing, no retry boilerplate.

Disclaimer: This is an unofficial, community-maintained library. It is not affiliated with, endorsed by, or supported by TradeZero Global Ltd. Use at your own risk. Always verify order execution through the official TradeZero platform before making financial decisions.


Documentation & Links

Resource Description
DOCUMENTATION.md Complete reference — every class, method, model, enum, and exception explained in full
CHANGELOG.md Full version history and breaking-change notes
CONTRIBUTING.md How to set up a dev environment and submit pull requests
SECURITY.md Vulnerability reporting policy and credential safety
examples/basic_sync.py Runnable synchronous usage example
examples/basic_async.py Runnable asynchronous usage example

Features

  • Dual sync/async supportTradeZeroClient for scripts, AsyncTradeZeroClient for async frameworks
  • Full Pydantic v2 validation — all API responses parsed into typed Python models
  • Automatic retries with exponential backoff — 429 and 5xx errors retried up to 3 times automatically
  • Rich exception hierarchy — catch AuthenticationError, RateLimitError, NotFoundError, ServerError, and more
  • Environment variable support — inject credentials via TZ_API_KEY / TZ_API_SECRET
  • Context-manager lifecycle — connections released automatically via with / async with
  • Typed models for all resources — accounts, P&L, positions, orders, trade history, and locates

Installation

From PyPI

pip install tradezero-sdk

From Source

git clone https://github.com/shadyemad/tradezero-sdk.git
cd tradezero-sdk
pip install poetry
poetry install

Requires Python 3.11+.


Quick Start

Synchronous

from tradezero import TradeZeroClient

with TradeZeroClient(api_key="YOUR_KEY", api_secret="YOUR_SECRET") as client:
    # List all accounts
    accounts = client.accounts.list_accounts()
    account_id = accounts[0].account
    print(f"Account: {account_id}, Equity: {accounts[0].equity:,.2f}")

    # Get day P&L
    pnl = client.accounts.get_account_pnl(account_id)
    print(f"Day P&L: {pnl.day_pnl:+,.2f}, Realized: {pnl.day_realized:+,.2f}")

    # Open positions with computed unrealized P&L
    positions = client.positions.get_positions(account_id)
    for pos in positions:
        print(f"{pos.symbol} {pos.side}: unrealized = {pos.unrealized_pnl:+,.2f}")

    # Place a limit buy order
    resp = client.trading.create_order(
        account_id=account_id,
        symbol="AAPL",
        quantity=100,
        side="Buy",
        order_type="Limit",
        time_in_force="Day",
        limit_price=185.0,
    )
    print(f"Order status: {resp.order_status}")

    # Check short-sell borrow availability
    etb = client.trading.is_easy_to_borrow(account_id, "AAPL")
    print(f"AAPL easy to borrow: {etb}")

    # Cancel all open orders
    client.trading.cancel_all_orders(account_id)

Asynchronous

import asyncio
from tradezero import AsyncTradeZeroClient

async def main():
    async with AsyncTradeZeroClient(api_key="YOUR_KEY", api_secret="YOUR_SECRET") as client:
        accounts = await client.accounts.list_accounts()
        account_id = accounts[0].account

        pnl = await client.accounts.get_account_pnl(account_id)
        print(f"Day P&L: {pnl.day_pnl:+,.2f}")

        positions = await client.positions.get_positions(account_id)
        for pos in positions:
            print(f"{pos.symbol}: {pos.unrealized_pnl:+,.2f}")

        resp = await client.trading.create_order(
            account_id=account_id,
            symbol="TSLA",
            quantity=50,
            side="Sell",
            order_type="Market",
            time_in_force="Day",
        )
        print(f"Order: {resp.order_status}")

asyncio.run(main())

More complete examples are in the examples/ directory.


Configuration

Credentials can be passed explicitly or loaded from environment variables:

Environment Variable Description Default
TZ_API_KEY TradeZero API key ID
TZ_API_SECRET TradeZero API secret key
TZ_BASE_URL Override the API base URL https://webapi.tradezero.com/v1/api
export TZ_API_KEY="your-key"
export TZ_API_SECRET="your-secret"
# Credentials resolved automatically from environment
client = TradeZeroClient()

Additional constructor options:

client = TradeZeroClient(
    api_key="...",
    api_secret="...",
    timeout=60.0,   # per-request timeout in seconds (default: 30)
)

API Reference

For full method signatures, parameter descriptions, return types, and code examples for every endpoint, see DOCUMENTATION.md.

client.accounts

Method Returns Description
list_accounts() list[Account] All accounts for your API credentials
get_account_details(account_id) Account Full account details including all financial fields
get_account_pnl(account_id) AccountPnL Daily P&L, exposure, and balance metrics

client.positions

Method Returns Description
get_positions(account_id) list[Position] All open positions with computed unrealized_pnl

client.trading

Method Returns Description
create_order(account_id, symbol, quantity, side, order_type, time_in_force, ...) OrderResponse Place a new order
list_orders(account_id) list[Order] Current-day orders (all statuses)
list_historical_orders(account_id, start_date) list[TradeRecord] Trade records up to one week back
cancel_order(account_id, client_order_id) None Cancel a specific open order
cancel_all_orders(account_id, *, symbol=None) dict | None Cancel all open orders, optionally filtered by symbol
is_easy_to_borrow(account_id, symbol) bool Check short-sell borrow availability
get_routes(account_id) list[dict] Available trading routes

client.locates

Method Returns Description
request_quote(account, symbol, quantity, quote_req_id) dict Submit a short-sell locate quote request
get_history(account_id) list[LocateHistoryItem] Poll locate request history and status
get_inventory(account_id) list[LocateInventoryItem] Active locate inventory
accept_quote(account_id, quote_req_id) dict Accept an offered locate quote
sell_locate(account, symbol, quote_req_id, quantity, locate_type) dict Sell locate back for credit
cancel_locate(account_id, quote_req_id) None Cancel a pending locate quote

Enum Values

All enum values match the TradeZero API wire format exactly. String literals are accepted wherever enum members are — the SDK coerces them automatically:

# These are equivalent:
client.trading.create_order(..., side="Buy", order_type="Limit", time_in_force="Day")
client.trading.create_order(..., side=OrderSide.BUY, order_type=OrderType.LIMIT, time_in_force=TimeInForce.DAY)
Enum Members
OrderSide BUY="Buy", SELL="Sell"
OrderType MARKET="Market", LIMIT="Limit", STOP="Stop", STOP_LIMIT="StopLimit"
TimeInForce DAY="Day", GTC="GoodTillCancel", IOC="ImmediateOrCancel", FOK="FillOrKill", AT_THE_OPENING, GOOD_TILL_CROSSING, DAY_PLUS, GTC_PLUS
SecurityType STOCK="Stock", OPTION="Option"
LocateStatus NEW=48, FILLED=50, CANCELED=52, PENDING=54, REJECTED=56, OFFERED=65, EXPIRED=67, QUOTING=81
LocateTypeStr LOCATE="Locate", INTRADAY="IntraDay", PRE_BORROW="PreBorrow", SINGLE_USE="SingleUse"

See DOCUMENTATION.md § Enumerations for full descriptions of every member.


Exception Handling

from tradezero import (
    TradeZeroSDKError,       # Base class for all SDK errors
    TradeZeroAPIError,       # Non-2xx API response (.status_code, .response_body)
    AuthenticationError,     # 401 — invalid credentials
    ForbiddenError,          # 403 — insufficient permissions
    NotFoundError,           # 404 — resource not found
    RateLimitError,          # 429 — too many requests (auto-retried)
    APIValidationError,      # 422 — request validation failed
    InsufficientFundsError,  # insufficient buying power
    ServerError,             # 5xx — server error (auto-retried)
)

try:
    resp = client.trading.create_order(...)
except RateLimitError:
    print("Still rate limited after 3 automatic retries")
except AuthenticationError:
    print("Check your API credentials")
except InsufficientFundsError:
    print("Not enough buying power for this order")
except TradeZeroAPIError as e:
    print(f"API error {e.status_code}: {e}")
    print(f"Response body: {e.response_body}")

Retry Behaviour

Condition Behaviour
RateLimitError (HTTP 429) Retried up to 3 times
ServerError (HTTP 5xx) Retried up to 3 times
httpx.TransportError (network) Retried up to 3 times
All other errors Raised immediately, no retry

Backoff: 1 s → 2 s → 4 s, capped at 60 s.


Package Structure

tradezero-sdk/
│
├── tradezero/                          # Main installable package
│   ├── __init__.py                     # Public API surface & __version__
│   ├── config.py                       # Constants and env-var helpers
│   ├── enums.py                        # All API enumerations
│   ├── exceptions.py                   # Exception hierarchy
│   ├── client/
│   │   ├── sync_client.py              # TradeZeroClient (synchronous)
│   │   └── async_client.py             # AsyncTradeZeroClient (asynchronous)
│   ├── http/
│   │   ├── _base.py                    # Auth headers, utility functions
│   │   ├── _retry.py                   # Tenacity retry decorator
│   │   ├── sync_http.py                # SyncHTTPClient
│   │   └── async_http.py               # AsyncHTTPClient
│   ├── models/
│   │   ├── accounts.py                 # Account, AccountPnL
│   │   ├── orders.py                   # CreateOrderRequest, OrderResponse,
│   │   │                               # Order, TradeRecord
│   │   ├── positions.py                # Position (with computed unrealized_pnl)
│   │   └── locates.py                  # All locate request/response models
│   └── modules/
│       ├── accounts.py                 # AccountsModule + AsyncAccountsModule
│       ├── trading.py                  # TradingModule + AsyncTradingModule
│       ├── positions.py                # PositionsModule + AsyncPositionsModule
│       └── locates.py                  # LocatesModule + AsyncLocatesModule
│
├── tests/
│   ├── conftest.py                     # Shared pytest fixtures
│   ├── test_accounts.py                # 7 unit tests
│   ├── test_trading.py                 # 14 unit tests
│   ├── test_positions.py               # 5 unit tests
│   ├── test_locates.py                 # 8 unit tests
│   ├── test_async.py                   # 11 unit tests
│   ├── test_exceptions.py              # 3 unit tests
│   ├── test_retry.py                   # 6 unit tests
│   └── live/                           # Live integration tests (real API, opt-in)
│       ├── conftest.py                 # Reads TZ_API_KEY / TZ_API_SECRET from env
│       ├── test_accounts.py
│       ├── test_trading.py
│       ├── test_positions.py
│       ├── test_locates.py
│       └── test_errors.py
│
├── examples/
│   ├── basic_sync.py                   # Synchronous usage example
│   └── basic_async.py                  # Asynchronous usage example
│
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/ci.yml                # CI pipeline (Python 3.11 + 3.12)
│
├── README.md                           # This file
├── DOCUMENTATION.md                    # Complete reference documentation
├── CONTRIBUTING.md                     # Contributor guide
├── CHANGELOG.md                        # Version history
├── SECURITY.md                         # Security and vulnerability policy
├── LICENSE                             # MIT License
├── pyproject.toml                      # Package metadata, deps, tool config
└── pytest.ini                          # Pytest settings

Development

See CONTRIBUTING.md for the full contributor guide.

# Install all dependencies including dev tools
poetry install

# Run unit tests (no API credentials required)
poetry run pytest -m "not live" --cov=tradezero -v

# Lint with ruff
poetry run ruff check .

# Type-check with mypy
poetry run mypy tradezero

Live integration tests (require real credentials):

export TZ_API_KEY="your-key"
export TZ_API_SECRET="your-secret"
poetry run pytest tests/live/ -m live -v

Sponsorship

If this SDK saves you time or money, consider sponsoring the project:

Donate via PayPal

Binance Pay — UID: 751730419

Your support helps maintain the library, add new endpoints, and test against the live API.


Contact & Contributing

Contributions are welcome:

  1. Fork the repository and create a feature branch from main
  2. Make your change and add tests
  3. Run pytest -m "not live", ruff check ., and mypy tradezero — all must pass
  4. Open a pull request with a clear description

License

MIT — Copyright (c) 2026 Shady Emad


Disclaimer: tradezero-sdk is an unofficial, community-maintained project. It is not affiliated with, endorsed by, or sponsored by TradeZero Global Ltd. The TradeZero name and API are trademarks of TradeZero Global Ltd. The authors accept no responsibility for financial losses resulting from the use of this library. Always verify all trades through the official TradeZero platform. ======= Unofficial TradeZero SDK for Python that provides a clean and structured interface to automate trading, manage orders, and access account data through TradeZero API endpoints. Built for developers and trading bots. Not affiliated with TradeZero.

324b053fbd7afd9dfb3780b8a59ea558bc113754

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

tradezero_sdk-1.0.0.tar.gz (24.4 kB view details)

Uploaded Source

Built Distribution

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

tradezero_sdk-1.0.0-py3-none-any.whl (30.4 kB view details)

Uploaded Python 3

File details

Details for the file tradezero_sdk-1.0.0.tar.gz.

File metadata

  • Download URL: tradezero_sdk-1.0.0.tar.gz
  • Upload date:
  • Size: 24.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for tradezero_sdk-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0e9feb82af2130d4236ad98ae547da3cc90fa59ab7172879e9c95209fb3a96d8
MD5 7af2cb9544b22f50629ef751edfda434
BLAKE2b-256 682efb8f03e4dd0b98a3cbe51d447837f03765e2e8cb923365a9aab85c16a5e1

See more details on using hashes here.

File details

Details for the file tradezero_sdk-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: tradezero_sdk-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 30.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for tradezero_sdk-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 53a834888bb9a2aa4170d2fb5f4688184935244a4cc9a31730e68dc1747a419d
MD5 58939e88673da77b6c50699035e7af37
BLAKE2b-256 8651dba439c18d4f33ec6ad3c9b9714bb025098e3df283576c684032dadd1d44

See more details on using hashes here.

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