tradestation-api 0.1.0

Complete TradeStation REST API v3 wrapper for Rust
Documentation
# tradestation-api

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Crates.io](https://img.shields.io/crates/v/tradestation-api.svg)](https://crates.io/crates/tradestation-api)
[![docs.rs](https://docs.rs/tradestation-api/badge.svg)](https://docs.rs/tradestation-api)

Complete, typed TradeStation REST API v3 wrapper for Rust.

Provides async access to all TradeStation v3 endpoints with automatic OAuth2 token management, typed request/response models, and HTTP chunked-transfer streaming.

## Installation

```sh
cargo add tradestation-api
```

## Quick Start

```rust
use tradestation_rs::{Client, Credentials, Scope};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let creds = Credentials::new("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

    // 1. Direct user to authorization URL
    let url = creds.authorization_url(&Scope::defaults());
    println!("Visit: {url}");

    // 2. Exchange the callback code for tokens
    let mut client = Client::new(creds);
    client.authenticate("AUTH_CODE_FROM_CALLBACK").await?;

    // 3. Fetch data
    let quotes = client.get_quotes(&["AAPL", "MSFT"]).await?;
    for q in &quotes {
        println!("{}: last={}", q.symbol, q.last);
    }

    Ok(())
}
```

## Features

- **OAuth2 Authorization Code** flow with automatic token refresh
- **Market Data**: Historical bars (OHLCV), quotes, symbol info, crypto pairs, options data
- **Brokerage**: Accounts, balances, BOD balances, positions, orders, historical orders, wallets
- **Execution**: Place, replace, cancel orders; OCO/bracket groups; order preview; activation triggers; routes
- **Streaming**: HTTP chunked-transfer for live quotes, bars, market depth, option chains, orders, positions
- **Simulation**: Built-in support for TradeStation's sim API via `Client::with_sim()`
- **Typed models**: All API responses are strongly typed with serde deserialization
- **Convenience parsers**: `Bar::ohlcv()` and `Bar::timestamp()` for numeric/datetime conversion

## Endpoint Coverage

| Category    | Endpoint                                           | Method   | Function                           |
|-------------|-----------------------------------------------------|----------|------------------------------------|
| **Auth**    | `/oauth/token` (authorization code)                 | POST     | `auth::exchange_code`              |
|             | `/oauth/token` (refresh)                            | POST     | `auth::refresh_token`              |
|             | `/oauth/token` (revoke)                             | POST     | `auth::revoke_token`               |
| **Market Data** | `/v3/marketdata/barcharts/{symbol}`             | GET      | `Client::get_bars`                 |
|             | `/v3/marketdata/quotes/{symbols}`                   | GET      | `Client::get_quotes`               |
|             | `/v3/marketdata/symbols/{symbols}`                  | GET      | `Client::get_symbol_info`          |
|             | `/v3/marketdata/symbollists/cryptopairs/symbolnames` | GET     | `Client::get_crypto_pairs`         |
|             | `/v3/marketdata/options/expirations/{underlying}`   | GET      | `Client::get_option_expirations`   |
|             | `/v3/marketdata/options/strikes/{underlying}`       | GET      | `Client::get_option_strikes`       |
|             | `/v3/marketdata/options/spreadtypes`                | GET      | `Client::get_option_spread_types`  |
|             | `/v3/marketdata/options/riskreward`                 | POST     | `Client::get_option_risk_reward`   |
| **Brokerage** | `/v3/brokerage/accounts`                          | GET      | `Client::get_accounts`             |
|             | `/v3/brokerage/accounts/{id}/balances`              | GET      | `Client::get_balances`             |
|             | `/v3/brokerage/accounts/{id}/bodbalances`           | GET      | `Client::get_bod_balances`         |
|             | `/v3/brokerage/accounts/{id}/positions`             | GET      | `Client::get_positions`            |
|             | `/v3/brokerage/accounts/{id}/orders`                | GET      | `Client::get_orders`               |
|             | `/v3/brokerage/accounts/{id}/orders/{orderId}`      | GET      | `Client::get_orders_by_id`         |
|             | `/v3/brokerage/accounts/{id}/historicalorders`      | GET      | `Client::get_historical_orders`    |
|             | `/v3/brokerage/accounts/{id}/historicalorders/{orderId}` | GET | `Client::get_historical_orders_by_id` |
|             | `/v3/brokerage/accounts/{id}/wallets`               | GET      | `Client::get_wallets`              |
| **Execution** | `/v3/orderexecution/orders`                       | POST     | `Client::place_order`              |
|             | `/v3/orderexecution/orders/{id}`                    | PUT      | `Client::replace_order`            |
|             | `/v3/orderexecution/orders/{id}`                    | DELETE   | `Client::cancel_order`             |
|             | `/v3/orderexecution/orderconfirm`                   | POST     | `Client::confirm_order`            |
|             | `/v3/orderexecution/ordergroups`                    | POST     | `Client::place_order_group`        |
|             | `/v3/orderexecution/ordergroupconfirm`              | POST     | `Client::confirm_order_group`      |
|             | `/v3/orderexecution/activationtriggers`             | GET      | `Client::get_activation_triggers`  |
|             | `/v3/orderexecution/routes`                         | GET      | `Client::get_routes`               |
| **Streaming** | `/v3/marketdata/stream/quotes/{symbols}`          | GET      | `Client::stream_quotes`            |
|             | `/v3/marketdata/stream/barcharts/{symbol}`          | GET      | `Client::stream_bars`              |
|             | `/v3/marketdata/stream/marketdepth/quotes/{symbol}` | GET     | `Client::stream_market_depth_quotes` |
|             | `/v3/marketdata/stream/marketdepth/aggregates/{symbol}` | GET | `Client::stream_market_depth_aggregates` |
|             | `/v3/marketdata/stream/options/chains/{underlying}` | GET     | `Client::stream_option_chains`     |
|             | `/v3/marketdata/stream/options/quotes/{legs}`       | GET      | `Client::stream_option_quotes`     |
|             | `/v3/brokerage/stream/accounts/{id}/orders`         | GET      | `Client::stream_orders`            |
|             | `/v3/brokerage/stream/accounts/{id}/orders/{orderId}` | GET   | `Client::stream_orders_by_id`      |
|             | `/v3/brokerage/stream/accounts/{id}/positions`      | GET      | `Client::stream_positions`         |

**Total: 38 endpoints**

## Relationship to Other Crates

This is a **new, independent crate** -- not a fork of any existing TradeStation library. It was built from scratch against the [TradeStation v3 OpenAPI spec](https://api.tradestation.com/docs/) with a focus on:

- Complete endpoint coverage (all 38 v3 endpoints)
- Idiomatic async Rust with `tokio` and `futures`
- Typed streaming via HTTP chunked transfer (not WebSocket)
- Zero external runtime dependencies beyond `tokio` + `reqwest`

## Examples

See the [`examples/`](examples/) directory:

- [`quickstart.rs`]examples/quickstart.rs -- OAuth2 flow and fetching quotes
- [`stream_quotes.rs`]examples/stream_quotes.rs -- Real-time quote streaming
- [`place_order.rs`]examples/place_order.rs -- Order placement (use sim API!)

## License

MIT -- see [LICENSE](LICENSE).