A production-ready Python SDK for the TradeZero REST API.
Project description
tradezero-sdk
<<<<<<< HEAD
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 support —
TradeZeroClientfor scripts,AsyncTradeZeroClientfor 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:
Binance Pay — UID: 751730419
Your support helps maintain the library, add new endpoints, and test against the live API.
Contact & Contributing
- Email: ShadyEmadContact@gmail.com
- Issues & feature requests: GitHub Issues
- Pull requests: Read CONTRIBUTING.md first
Contributions are welcome:
- Fork the repository and create a feature branch from
main - Make your change and add tests
- Run
pytest -m "not live",ruff check ., andmypy tradezero— all must pass - 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e9feb82af2130d4236ad98ae547da3cc90fa59ab7172879e9c95209fb3a96d8
|
|
| MD5 |
7af2cb9544b22f50629ef751edfda434
|
|
| BLAKE2b-256 |
682efb8f03e4dd0b98a3cbe51d447837f03765e2e8cb923365a9aab85c16a5e1
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53a834888bb9a2aa4170d2fb5f4688184935244a4cc9a31730e68dc1747a419d
|
|
| MD5 |
58939e88673da77b6c50699035e7af37
|
|
| BLAKE2b-256 |
8651dba439c18d4f33ec6ad3c9b9714bb025098e3df283576c684032dadd1d44
|