tradezero-sdk 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shady Emad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,441 @@
1
+ Metadata-Version: 2.4
2
+ Name: tradezero-sdk
3
+ Version: 1.0.0
4
+ Summary: A production-ready Python SDK for the TradeZero REST API.
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: tradezero,trading,sdk,api,finance,stocks
8
+ Author: Shady Emad
9
+ Author-email: ShadyEmadContact@gmail.com
10
+ Requires-Python: >=3.11,<4.0
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Classifier: Typing :: Typed
21
+ Requires-Dist: httpx (>=0.27)
22
+ Requires-Dist: pydantic (>=2.7,<3.0)
23
+ Requires-Dist: tenacity (>=8.3,<9.0)
24
+ Project-URL: Homepage, https://github.com/shadyemad/tradezero-sdk
25
+ Project-URL: Repository, https://github.com/shadyemad/tradezero-sdk
26
+ Description-Content-Type: text/markdown
27
+
28
+ # tradezero-sdk
29
+ <<<<<<< HEAD
30
+
31
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
32
+ [![PyPI](https://img.shields.io/pypi/v/tradezero-sdk.svg)](https://pypi.org/project/tradezero-sdk/)
33
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
34
+ [![CI](https://github.com/shadyemad/tradezero-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/shadyemad/tradezero-sdk/actions/workflows/ci.yml)
35
+ [![codecov](https://codecov.io/gh/shadyemad/tradezero-sdk/branch/main/graph/badge.svg)](https://codecov.io/gh/shadyemad/tradezero-sdk)
36
+
37
+ An unofficial, production-ready Python SDK for the [TradeZero](https://www.tradezero.com/) REST API.
38
+
39
+ 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.
40
+
41
+ > **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.
42
+
43
+ ---
44
+
45
+ ## Documentation & Links
46
+
47
+ | Resource | Description |
48
+ |----------|-------------|
49
+ | [DOCUMENTATION.md](DOCUMENTATION.md) | **Complete reference** — every class, method, model, enum, and exception explained in full |
50
+ | [CHANGELOG.md](CHANGELOG.md) | Full version history and breaking-change notes |
51
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | How to set up a dev environment and submit pull requests |
52
+ | [SECURITY.md](SECURITY.md) | Vulnerability reporting policy and credential safety |
53
+ | [examples/basic_sync.py](examples/basic_sync.py) | Runnable synchronous usage example |
54
+ | [examples/basic_async.py](examples/basic_async.py) | Runnable asynchronous usage example |
55
+
56
+ ---
57
+
58
+ ## Features
59
+
60
+ - **Dual sync/async support** — `TradeZeroClient` for scripts, `AsyncTradeZeroClient` for async frameworks
61
+ - **Full Pydantic v2 validation** — all API responses parsed into typed Python models
62
+ - **Automatic retries with exponential backoff** — 429 and 5xx errors retried up to 3 times automatically
63
+ - **Rich exception hierarchy** — catch `AuthenticationError`, `RateLimitError`, `NotFoundError`, `ServerError`, and more
64
+ - **Environment variable support** — inject credentials via `TZ_API_KEY` / `TZ_API_SECRET`
65
+ - **Context-manager lifecycle** — connections released automatically via `with` / `async with`
66
+ - **Typed models for all resources** — accounts, P&L, positions, orders, trade history, and locates
67
+
68
+ ---
69
+
70
+ ## Installation
71
+
72
+ ### From PyPI
73
+
74
+ ```bash
75
+ pip install tradezero-sdk
76
+ ```
77
+
78
+ ### From Source
79
+
80
+ ```bash
81
+ git clone https://github.com/shadyemad/tradezero-sdk.git
82
+ cd tradezero-sdk
83
+ pip install poetry
84
+ poetry install
85
+ ```
86
+
87
+ Requires **Python 3.11+**.
88
+
89
+ ---
90
+
91
+ ## Quick Start
92
+
93
+ ### Synchronous
94
+
95
+ ```python
96
+ from tradezero import TradeZeroClient
97
+
98
+ with TradeZeroClient(api_key="YOUR_KEY", api_secret="YOUR_SECRET") as client:
99
+ # List all accounts
100
+ accounts = client.accounts.list_accounts()
101
+ account_id = accounts[0].account
102
+ print(f"Account: {account_id}, Equity: {accounts[0].equity:,.2f}")
103
+
104
+ # Get day P&L
105
+ pnl = client.accounts.get_account_pnl(account_id)
106
+ print(f"Day P&L: {pnl.day_pnl:+,.2f}, Realized: {pnl.day_realized:+,.2f}")
107
+
108
+ # Open positions with computed unrealized P&L
109
+ positions = client.positions.get_positions(account_id)
110
+ for pos in positions:
111
+ print(f"{pos.symbol} {pos.side}: unrealized = {pos.unrealized_pnl:+,.2f}")
112
+
113
+ # Place a limit buy order
114
+ resp = client.trading.create_order(
115
+ account_id=account_id,
116
+ symbol="AAPL",
117
+ quantity=100,
118
+ side="Buy",
119
+ order_type="Limit",
120
+ time_in_force="Day",
121
+ limit_price=185.0,
122
+ )
123
+ print(f"Order status: {resp.order_status}")
124
+
125
+ # Check short-sell borrow availability
126
+ etb = client.trading.is_easy_to_borrow(account_id, "AAPL")
127
+ print(f"AAPL easy to borrow: {etb}")
128
+
129
+ # Cancel all open orders
130
+ client.trading.cancel_all_orders(account_id)
131
+ ```
132
+
133
+ ### Asynchronous
134
+
135
+ ```python
136
+ import asyncio
137
+ from tradezero import AsyncTradeZeroClient
138
+
139
+ async def main():
140
+ async with AsyncTradeZeroClient(api_key="YOUR_KEY", api_secret="YOUR_SECRET") as client:
141
+ accounts = await client.accounts.list_accounts()
142
+ account_id = accounts[0].account
143
+
144
+ pnl = await client.accounts.get_account_pnl(account_id)
145
+ print(f"Day P&L: {pnl.day_pnl:+,.2f}")
146
+
147
+ positions = await client.positions.get_positions(account_id)
148
+ for pos in positions:
149
+ print(f"{pos.symbol}: {pos.unrealized_pnl:+,.2f}")
150
+
151
+ resp = await client.trading.create_order(
152
+ account_id=account_id,
153
+ symbol="TSLA",
154
+ quantity=50,
155
+ side="Sell",
156
+ order_type="Market",
157
+ time_in_force="Day",
158
+ )
159
+ print(f"Order: {resp.order_status}")
160
+
161
+ asyncio.run(main())
162
+ ```
163
+
164
+ More complete examples are in the [`examples/`](examples/) directory.
165
+
166
+ ---
167
+
168
+ ## Configuration
169
+
170
+ Credentials can be passed explicitly or loaded from environment variables:
171
+
172
+ | Environment Variable | Description | Default |
173
+ |----------------------|---------------------------|---------------------------------------|
174
+ | `TZ_API_KEY` | TradeZero API key ID | — |
175
+ | `TZ_API_SECRET` | TradeZero API secret key | — |
176
+ | `TZ_BASE_URL` | Override the API base URL | `https://webapi.tradezero.com/v1/api` |
177
+
178
+ ```bash
179
+ export TZ_API_KEY="your-key"
180
+ export TZ_API_SECRET="your-secret"
181
+ ```
182
+
183
+ ```python
184
+ # Credentials resolved automatically from environment
185
+ client = TradeZeroClient()
186
+ ```
187
+
188
+ Additional constructor options:
189
+
190
+ ```python
191
+ client = TradeZeroClient(
192
+ api_key="...",
193
+ api_secret="...",
194
+ timeout=60.0, # per-request timeout in seconds (default: 30)
195
+ )
196
+ ```
197
+
198
+ ---
199
+
200
+ ## API Reference
201
+
202
+ > For full method signatures, parameter descriptions, return types, and code examples for every endpoint, see [DOCUMENTATION.md](DOCUMENTATION.md).
203
+
204
+ ### `client.accounts`
205
+
206
+ | Method | Returns | Description |
207
+ |--------|---------|-------------|
208
+ | `list_accounts()` | `list[Account]` | All accounts for your API credentials |
209
+ | `get_account_details(account_id)` | `Account` | Full account details including all financial fields |
210
+ | `get_account_pnl(account_id)` | `AccountPnL` | Daily P&L, exposure, and balance metrics |
211
+
212
+ ### `client.positions`
213
+
214
+ | Method | Returns | Description |
215
+ |--------|---------|-------------|
216
+ | `get_positions(account_id)` | `list[Position]` | All open positions with computed `unrealized_pnl` |
217
+
218
+ ### `client.trading`
219
+
220
+ | Method | Returns | Description |
221
+ |--------|---------|-------------|
222
+ | `create_order(account_id, symbol, quantity, side, order_type, time_in_force, ...)` | `OrderResponse` | Place a new order |
223
+ | `list_orders(account_id)` | `list[Order]` | Current-day orders (all statuses) |
224
+ | `list_historical_orders(account_id, start_date)` | `list[TradeRecord]` | Trade records up to one week back |
225
+ | `cancel_order(account_id, client_order_id)` | `None` | Cancel a specific open order |
226
+ | `cancel_all_orders(account_id, *, symbol=None)` | `dict \| None` | Cancel all open orders, optionally filtered by symbol |
227
+ | `is_easy_to_borrow(account_id, symbol)` | `bool` | Check short-sell borrow availability |
228
+ | `get_routes(account_id)` | `list[dict]` | Available trading routes |
229
+
230
+ ### `client.locates`
231
+
232
+ | Method | Returns | Description |
233
+ |--------|---------|-------------|
234
+ | `request_quote(account, symbol, quantity, quote_req_id)` | `dict` | Submit a short-sell locate quote request |
235
+ | `get_history(account_id)` | `list[LocateHistoryItem]` | Poll locate request history and status |
236
+ | `get_inventory(account_id)` | `list[LocateInventoryItem]` | Active locate inventory |
237
+ | `accept_quote(account_id, quote_req_id)` | `dict` | Accept an offered locate quote |
238
+ | `sell_locate(account, symbol, quote_req_id, quantity, locate_type)` | `dict` | Sell locate back for credit |
239
+ | `cancel_locate(account_id, quote_req_id)` | `None` | Cancel a pending locate quote |
240
+
241
+ ---
242
+
243
+ ## Enum Values
244
+
245
+ All enum values match the TradeZero API wire format exactly. String literals are accepted wherever enum members are — the SDK coerces them automatically:
246
+
247
+ ```python
248
+ # These are equivalent:
249
+ client.trading.create_order(..., side="Buy", order_type="Limit", time_in_force="Day")
250
+ client.trading.create_order(..., side=OrderSide.BUY, order_type=OrderType.LIMIT, time_in_force=TimeInForce.DAY)
251
+ ```
252
+
253
+ | Enum | Members |
254
+ |------|---------|
255
+ | `OrderSide` | `BUY="Buy"`, `SELL="Sell"` |
256
+ | `OrderType` | `MARKET="Market"`, `LIMIT="Limit"`, `STOP="Stop"`, `STOP_LIMIT="StopLimit"` |
257
+ | `TimeInForce` | `DAY="Day"`, `GTC="GoodTillCancel"`, `IOC="ImmediateOrCancel"`, `FOK="FillOrKill"`, `AT_THE_OPENING`, `GOOD_TILL_CROSSING`, `DAY_PLUS`, `GTC_PLUS` |
258
+ | `SecurityType` | `STOCK="Stock"`, `OPTION="Option"` |
259
+ | `LocateStatus` | `NEW=48`, `FILLED=50`, `CANCELED=52`, `PENDING=54`, `REJECTED=56`, `OFFERED=65`, `EXPIRED=67`, `QUOTING=81` |
260
+ | `LocateTypeStr` | `LOCATE="Locate"`, `INTRADAY="IntraDay"`, `PRE_BORROW="PreBorrow"`, `SINGLE_USE="SingleUse"` |
261
+
262
+ See [DOCUMENTATION.md § Enumerations](DOCUMENTATION.md#10-enumerations) for full descriptions of every member.
263
+
264
+ ---
265
+
266
+ ## Exception Handling
267
+
268
+ ```python
269
+ from tradezero import (
270
+ TradeZeroSDKError, # Base class for all SDK errors
271
+ TradeZeroAPIError, # Non-2xx API response (.status_code, .response_body)
272
+ AuthenticationError, # 401 — invalid credentials
273
+ ForbiddenError, # 403 — insufficient permissions
274
+ NotFoundError, # 404 — resource not found
275
+ RateLimitError, # 429 — too many requests (auto-retried)
276
+ APIValidationError, # 422 — request validation failed
277
+ InsufficientFundsError, # insufficient buying power
278
+ ServerError, # 5xx — server error (auto-retried)
279
+ )
280
+
281
+ try:
282
+ resp = client.trading.create_order(...)
283
+ except RateLimitError:
284
+ print("Still rate limited after 3 automatic retries")
285
+ except AuthenticationError:
286
+ print("Check your API credentials")
287
+ except InsufficientFundsError:
288
+ print("Not enough buying power for this order")
289
+ except TradeZeroAPIError as e:
290
+ print(f"API error {e.status_code}: {e}")
291
+ print(f"Response body: {e.response_body}")
292
+ ```
293
+
294
+ ### Retry Behaviour
295
+
296
+ | Condition | Behaviour |
297
+ |-----------|-----------|
298
+ | `RateLimitError` (HTTP 429) | Retried up to 3 times |
299
+ | `ServerError` (HTTP 5xx) | Retried up to 3 times |
300
+ | `httpx.TransportError` (network) | Retried up to 3 times |
301
+ | All other errors | Raised immediately, no retry |
302
+
303
+ Backoff: 1 s → 2 s → 4 s, capped at 60 s.
304
+
305
+ ---
306
+
307
+ ## Package Structure
308
+
309
+ ```
310
+ tradezero-sdk/
311
+
312
+ ├── tradezero/ # Main installable package
313
+ │ ├── __init__.py # Public API surface & __version__
314
+ │ ├── config.py # Constants and env-var helpers
315
+ │ ├── enums.py # All API enumerations
316
+ │ ├── exceptions.py # Exception hierarchy
317
+ │ ├── client/
318
+ │ │ ├── sync_client.py # TradeZeroClient (synchronous)
319
+ │ │ └── async_client.py # AsyncTradeZeroClient (asynchronous)
320
+ │ ├── http/
321
+ │ │ ├── _base.py # Auth headers, utility functions
322
+ │ │ ├── _retry.py # Tenacity retry decorator
323
+ │ │ ├── sync_http.py # SyncHTTPClient
324
+ │ │ └── async_http.py # AsyncHTTPClient
325
+ │ ├── models/
326
+ │ │ ├── accounts.py # Account, AccountPnL
327
+ │ │ ├── orders.py # CreateOrderRequest, OrderResponse,
328
+ │ │ │ # Order, TradeRecord
329
+ │ │ ├── positions.py # Position (with computed unrealized_pnl)
330
+ │ │ └── locates.py # All locate request/response models
331
+ │ └── modules/
332
+ │ ├── accounts.py # AccountsModule + AsyncAccountsModule
333
+ │ ├── trading.py # TradingModule + AsyncTradingModule
334
+ │ ├── positions.py # PositionsModule + AsyncPositionsModule
335
+ │ └── locates.py # LocatesModule + AsyncLocatesModule
336
+
337
+ ├── tests/
338
+ │ ├── conftest.py # Shared pytest fixtures
339
+ │ ├── test_accounts.py # 7 unit tests
340
+ │ ├── test_trading.py # 14 unit tests
341
+ │ ├── test_positions.py # 5 unit tests
342
+ │ ├── test_locates.py # 8 unit tests
343
+ │ ├── test_async.py # 11 unit tests
344
+ │ ├── test_exceptions.py # 3 unit tests
345
+ │ ├── test_retry.py # 6 unit tests
346
+ │ └── live/ # Live integration tests (real API, opt-in)
347
+ │ ├── conftest.py # Reads TZ_API_KEY / TZ_API_SECRET from env
348
+ │ ├── test_accounts.py
349
+ │ ├── test_trading.py
350
+ │ ├── test_positions.py
351
+ │ ├── test_locates.py
352
+ │ └── test_errors.py
353
+
354
+ ├── examples/
355
+ │ ├── basic_sync.py # Synchronous usage example
356
+ │ └── basic_async.py # Asynchronous usage example
357
+
358
+ ├── .github/
359
+ │ ├── ISSUE_TEMPLATE/
360
+ │ │ ├── bug_report.md
361
+ │ │ └── feature_request.md
362
+ │ └── workflows/ci.yml # CI pipeline (Python 3.11 + 3.12)
363
+
364
+ ├── README.md # This file
365
+ ├── DOCUMENTATION.md # Complete reference documentation
366
+ ├── CONTRIBUTING.md # Contributor guide
367
+ ├── CHANGELOG.md # Version history
368
+ ├── SECURITY.md # Security and vulnerability policy
369
+ ├── LICENSE # MIT License
370
+ ├── pyproject.toml # Package metadata, deps, tool config
371
+ └── pytest.ini # Pytest settings
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Development
377
+
378
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contributor guide.
379
+
380
+ ```bash
381
+ # Install all dependencies including dev tools
382
+ poetry install
383
+
384
+ # Run unit tests (no API credentials required)
385
+ poetry run pytest -m "not live" --cov=tradezero -v
386
+
387
+ # Lint with ruff
388
+ poetry run ruff check .
389
+
390
+ # Type-check with mypy
391
+ poetry run mypy tradezero
392
+ ```
393
+
394
+ Live integration tests (require real credentials):
395
+
396
+ ```bash
397
+ export TZ_API_KEY="your-key"
398
+ export TZ_API_SECRET="your-secret"
399
+ poetry run pytest tests/live/ -m live -v
400
+ ```
401
+
402
+ ---
403
+
404
+ ## Sponsorship
405
+
406
+ If this SDK saves you time or money, consider sponsoring the project:
407
+
408
+ [![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-00457C.svg?logo=paypal)](https://www.paypal.me/shaadyemad)
409
+
410
+ **Binance Pay** — UID: `751730419`
411
+
412
+ Your support helps maintain the library, add new endpoints, and test against the live API.
413
+
414
+ ---
415
+
416
+ ## Contact & Contributing
417
+
418
+ - **Email:** [ShadyEmadContact@gmail.com](mailto:ShadyEmadContact@gmail.com)
419
+ - **Issues & feature requests:** [GitHub Issues](https://github.com/shadyemad/tradezero-sdk/issues)
420
+ - **Pull requests:** Read [CONTRIBUTING.md](CONTRIBUTING.md) first
421
+
422
+ Contributions are welcome:
423
+
424
+ 1. Fork the repository and create a feature branch from `main`
425
+ 2. Make your change and add tests
426
+ 3. Run `pytest -m "not live"`, `ruff check .`, and `mypy tradezero` — all must pass
427
+ 4. Open a pull request with a clear description
428
+
429
+ ---
430
+
431
+ ## License
432
+
433
+ [MIT](LICENSE) — Copyright (c) 2026 Shady Emad
434
+
435
+ ---
436
+
437
+ > **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.
438
+ =======
439
+ 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.
440
+ >>>>>>> 324b053fbd7afd9dfb3780b8a59ea558bc113754
441
+