Metadata-Version: 2.5
Name: luxalgo-broker-sdk
Version: 0.2.0
Summary: Open-source broker connectivity for Python. 22 brokers, one normalized schema, zero dependencies. Your keys never leave your machine.
Project-URL: Homepage, https://github.com/LuxAlgo/broker-py
Project-URL: Repository, https://github.com/LuxAlgo/broker-py
Project-URL: Issues, https://github.com/LuxAlgo/broker-py/issues
Project-URL: TypeScript SDK, https://github.com/LuxAlgo/broker-sdk
Author: LuxAlgo Global, LLC
License-Expression: MIT
License-File: LICENSE
Keywords: alpaca,binance,broker,brokerage,kraken,portfolio,sdk,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/LuxAlgo/broker-py/main/docs/assets/hero.svg" alt="Broker SDK for Python. Every broker. One schema. Your keys never leave your machine." width="100%"/>
</p>

<p align="center">
  <a href="https://pypi.org/project/luxalgo-broker-sdk/"><img src="https://img.shields.io/pypi/v/luxalgo-broker-sdk?color=000000&labelColor=000000" alt="PyPI version"/></a>
  <a href="https://github.com/LuxAlgo/broker-py/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/LuxAlgo/broker-py/ci.yml?label=ci&labelColor=000000" alt="CI"/></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-000000?labelColor=000000&color=555555" alt="MIT license"/></a>
</p>

<p align="center">
  <a href="https://github.com/LuxAlgo/broker-sdk"><b>TypeScript SDK</b></a>
  &nbsp;·&nbsp;
  <a href="https://github.com/LuxAlgo/broker-sdk/blob/main/docs/SCHEMA.md"><b>Schema</b></a>
  &nbsp;·&nbsp;
  <a href="https://pypi.org/project/luxalgo-broker-sdk/"><b>PyPI</b></a>
  &nbsp;·&nbsp;
  <a href="https://github.com/LuxAlgo/luxalgo-mcp-server"><b>MCP server</b></a>
</p>

<p align="center"><sub>Broker SDK is a <a href="https://www.luxalgo.com">LuxAlgo</a> open-source project. Official repository: <a href="https://github.com/LuxAlgo/broker-py">github.com/LuxAlgo/broker-py</a></sub></p>

**Connect Python to real brokerage and exchange accounts.** The same normalized schema, the same 22 brokers, and the same golden conformance vectors as the [TypeScript SDK](https://github.com/LuxAlgo/broker-sdk), so the two SDKs are provably identical in behavior. Point it at Charles Schwab, Alpaca, Robinhood Crypto, Binance, Kraken, Interactive Brokers and more. Get back the same clean picture from every one of them: accounts, balances, positions, trade history, and computed performance stats.

It runs where your code runs: no hosted service, no telemetry, and zero dependencies (the standard library is the whole toolbox).

```bash
pip install luxalgo-broker-sdk
```

## Your portfolio in five lines

```python
from broker_sdk import connect

kraken = connect("kraken", {"apiKey": api_key, "apiSecret": api_secret})
snapshot = kraken.fetch_snapshot()
print(snapshot.accounts)  # normalized: equity, positions, trades
```

Every broker returns the same shape. Learn it once:

```python
@dataclass
class Account:
    id: str                   # broker-side stable id, safe as an upsert key
    name: str
    currency: str             # ISO 4217
    equity: float             # total account value
    cash: float | None        # when the broker reports it separately
    environment: str | None   # "live" or "paper"
    positions: list[Position] # symbol, quantity (negative = short), market_value, ...
    trades: list[Trade]       # symbol, side, quantity, price, fee, executed_at
```

`Account.to_dict()` emits the canonical camelCase JSON shape shared with the TypeScript SDK, omitting unset fields. A missing value is more honest than a guessed one.

## Your whole portfolio, every broker at once

```python
from broker_sdk import create_portfolio
from broker_sdk.stats import compute_stats, stats_accounts

portfolio = create_portfolio()
portfolio.add("alpaca", {"apiKey": key, "apiSecret": secret})
portfolio.add("binance", {"apiKey": key2, "apiSecret": secret2})
portfolio.add("hyperliquid", {"walletAddress": address})

result = portfolio.fetch_all()
stats = compute_stats(stats_accounts(result.snapshots))
print(stats.total_equity, stats.trades.win_rate, stats.top_positions)
```

One broker failing never takes down the sweep: `result.failures` comes back alongside the snapshots that succeeded. The stats engine does FIFO round-trip matching, win rate, average win and loss, and per-symbol activity. A sell with no recorded buy is ignored, never guessed at.

## Import any broker statement

No API? Any account at any institution is importable from a trade-history CSV. The parser is tolerant on headers (brokers disagree on column names) and strict on rows (anything unreadable is skipped and counted, never guessed):

```python
from broker_sdk.statement_csv import parse_statement_csv, positions_from_trades

parsed = parse_statement_csv(csv_text)
print(len(parsed.trades), "trades,", parsed.skipped_rows, "rows skipped")
print(positions_from_trades(parsed.trades))  # net open positions
```

## Supported brokers

The same 22 as the TypeScript SDK: Alpaca, Binance, Bybit, Charles Schwab, Coinbase, Crypto.com Exchange, E\*TRADE, Gemini, Hyperliquid, Interactive Brokers (Flex), Kraken, KuCoin, OKX, Public.com, Questrade, Robinhood Crypto, tastytrade, Topstep (ProjectX), TradeStation, Tradier, Trading212, Webull (OpenAPI), plus any broker via CSV import. The full credentials table lives in the [broker-sdk README](https://github.com/LuxAlgo/broker-sdk#supported-brokers).

`list_brokers()` returns every adapter with its exact credential fields and a one-line guide to creating the key with **read-only scope**, which is all this SDK ever needs.

**Sanctioned APIs only.** If a broker does not officially support programmatic access for its users, it is not in this repo: no scraping, no reverse-engineered private APIs, ever. OAuth brokers where you register your own free developer app (Charles Schwab, TradeStation, E\*TRADE, Coinbase) are supported bring-your-own-app style.

## Read-only, local-only, by design

- **Your keys stay yours.** The SDK runs where your code runs. There is no LuxAlgo server in the path, no telemetry, no phoning home.
- **Read-only.** The Python SDK reads accounts, balances, positions, and history. It has no order placement at all (the TypeScript SDK's experimental write layer has no Python counterpart yet).
- **Credential rotation is first-class.** Brokers with single-use tokens (Questrade) hand the rotated credentials back through `on_credentials_rotated` so you can persist them before the old ones die.
- **Fail-soft, never fabricate.** A position the broker can't price has no `market_value` rather than a made-up one. A history row that can't be read is skipped and counted, not guessed.

## The conformance kit

The vectors in [`conformance/vectors/`](conformance/vectors) are copied verbatim from the [TypeScript SDK](https://github.com/LuxAlgo/broker-sdk): one per adapter, pairing a raw provider payload with the exact normalized output. Every adapter splits into an IO-only `fetch_raw` and a pure `normalize`, and CI asserts `normalize` reproduces every vector byte-for-byte. That is what "the same SDK in two languages" means here: not a similar API, the same proven mapping.

## Runtime

Python 3.10+. Zero runtime dependencies (`urllib` for HTTP, `hmac`/`hashlib` for request signing, and a pure-Python RFC 8032 Ed25519 signer for Robinhood Crypto). Fully typed (`py.typed`). Synchronous API; `Portfolio.fetch_all()` sweeps connections concurrently with a thread pool. Bring your own persistence: `to_dict()` makes every snapshot plain JSON.

## The suite

| Package | What it is |
| --- | --- |
| [`@luxalgo/broker-sdk`](https://github.com/LuxAlgo/broker-sdk) | The TypeScript SDK and reference implementation |
| [`luxalgo-broker-sdk`](https://github.com/LuxAlgo/broker-py) (this repo) | The Python SDK, gated by the same conformance vectors |
| [`@luxalgo/mcp`](https://github.com/LuxAlgo/luxalgo-mcp-server) | The LuxAlgo MCP server; its local `broker_*` tools give AI agents read-only portfolio access |

## Contributing

New adapters land in the [TypeScript SDK](https://github.com/LuxAlgo/broker-sdk) first (that repo owns the schema and the vectors), then port here against the same vector. See [CONTRIBUTING.md](CONTRIBUTING.md). Sign your commits with `git commit -s`.

## Disclaimer

This software reports what your broker reports. It is not investment advice, and nothing in it recommends any trade. Use at your own risk; verify important numbers against your broker's own statements.

## License

[MIT](LICENSE) © LuxAlgo Global, LLC. The "Broker SDK" and "LuxAlgo" names and the LuxAlgo logo are trademarks of LuxAlgo Global, LLC; see [TRADEMARKS.md](TRADEMARKS.md). Security reports: [SECURITY.md](SECURITY.md).
