Skip to main content

A Python wrapper for the TradeStation WebAPI, providing easy access to brokerage, order execution, and market data services.

Project description

TradeStation API Python Wrapper ๐Ÿš€

License: MIT PyPI version

Hey there, Trader! ๐Ÿ‘‹ Ready to connect your Python apps to the TradeStation universe? This library makes it easy-peasy.

Think of it as your friendly Pythonic remote control for TradeStation's API. Build trading bots, analyze data, manage your account โ€“ all with clean, asynchronous Python code.

What Can You Do? โœจ

  • Log In Easily: Handles the tricky OAuth 2.0 stuff (including token refreshes) so you don't have to.
  • Market Pulse: Grab real-time quotes, historical price bars, symbol details, and more.
  • Account Access: Check your balances, see your positions, and review order history.
  • Trade Time: Place, change, or cancel orders programmatically.
  • Live Streams: Get data beamed straight to you with WebSocket support.
  • Plays Nicely: Built-in rate limiting helps you avoid getting timed out by the API.

What You'll Need ๐Ÿ“‹

  • Python 3.11 or newer (Gotta have that async power!)
  • A TradeStation Account (Real or Simulated)
  • Your TradeStation API Credentials (Client ID & Refresh Token - get these from the Developer Portal)

Get It Installed! ๐Ÿ’ป

Open your terminal and let's get this library installed.

# Option 1: Install directly from PyPI (Easiest ๐ŸŒŸ)
pip install tradestation-api-python

# Option 2: Clone the project (for developers)
git clone https://github.com/mxcoppell/tradestation-api-python.git
cd tradestation-api-python

# Then install using Poetry (Recommended for development โœจ)
poetry install

# OR: Use pip if you prefer
# pip install -e .

Quick Start: Your First API Call! ๐Ÿš€

Let's fetch a stock quote right now!

  1. Set up your secrets: Copy .env.sample to .env and fill in your CLIENT_ID, REFRESH_TOKEN, and ENVIRONMENT (Live or Simulation).
    cp .env.sample .env
    # Now edit .env with your details!
    
  2. Run this Python code:
import asyncio
import os
from dotenv import load_dotenv
from tradestation import TradeStationClient

async def get_a_quote():
    # Load secrets from .env file
    load_dotenv()
    print(f"Using Environment: {os.getenv('ENVIRONMENT')}")

    # Create the client (it reads your .env automatically!)
    client = TradeStationClient()

    try:
        print("Asking TradeStation for an AAPL quote...")
        # Use the market data service to get a quote snapshot
        quote_response = await client.market_data.get_quote_snapshots("AAPL")

        if quote_response and quote_response.Quotes:
            aapl_price = quote_response.Quotes[0].Last
            print(f"----> Got it! AAPL last price: ${aapl_price}")
        else:
            print("Hmm, couldn't get the quote. Error:", getattr(quote_response, 'Errors', 'Unknown error'))

    except Exception as e:
        print(f"Whoops! Something went wrong: {e}")
    finally:
        print("Closing the connection.")
        # Always close the client when you're finished!
        await client.close()

if __name__ == "__main__":
    asyncio.run(get_a_quote())

Want more? Check out the examples/QuickStart directory for scripts you can run immediately!

Project Peek ๐Ÿ‘€

Curious how it's organized?

.
โ”œโ”€โ”€ docs/                 # You are here! (Hopefully useful docs)
โ”œโ”€โ”€ examples/             # Ready-to-run example scripts!
โ”‚   โ”œโ”€โ”€ QuickStart/       # Start here!
โ”‚   โ”œโ”€โ”€ Brokerage/        # Account & order history examples
โ”‚   โ”œโ”€โ”€ MarketData/       # Price, quote, & symbol examples
โ”‚   โ””โ”€โ”€ OrderExecution/   # Placing & managing orders examples
โ””โ”€โ”€ src/                  # The heart of the library
    โ””โ”€โ”€ tradestation/     # The importable package
        โ”œโ”€โ”€ client/       # The main TradeStationClient
        โ”œโ”€โ”€ services/     # API sections (MarketData, Brokerage, etc.)
        โ”œโ”€โ”€ streaming/    # WebSocket streaming code
        โ”œโ”€โ”€ ts_types/     # Data models (Pydantic types)
        โ””โ”€โ”€ utils/        # Helpers (Auth, Rate Limiting, etc.)

Error Handling ๐Ÿ›ก๏ธ

This library provides a comprehensive exception system to help you handle API errors gracefully:

Exception Hierarchy

TradeStationAPIError (base exception)
โ”œโ”€โ”€ TradeStationAuthError           # Authentication failures (401, 403)
โ”œโ”€โ”€ TradeStationRateLimitError      # Rate limit exceeded (429)
โ”œโ”€โ”€ TradeStationResourceNotFoundError # Resource not found (404)
โ”œโ”€โ”€ TradeStationValidationError     # Invalid request parameters (400)
โ”œโ”€โ”€ TradeStationNetworkError        # Network connectivity issues
โ”œโ”€โ”€ TradeStationServerError         # Server-side errors (5xx)
โ”œโ”€โ”€ TradeStationTimeoutError        # Request timeouts
โ””โ”€โ”€ TradeStationStreamError         # WebSocket streaming issues

Using Exception Handling

from tradestation import TradeStationClient
from tradestation import (
    TradeStationAPIError,
    TradeStationAuthError,
    TradeStationRateLimitError,
    TradeStationValidationError,
    TradeStationNetworkError
)

async def handle_with_care():
    client = TradeStationClient()
    
    try:
        quotes = await client.market_data.get_quotes("AAPL,MSFT")
        print(f"Success! Got quotes for {len(quotes)} symbols")
        
    except TradeStationAuthError as e:
        print(f"Authentication failed: {e}")
        # Handle credential refresh or re-login
        
    except TradeStationRateLimitError as e:
        print(f"Rate limit hit: {e}")
        if hasattr(e, 'retry_after') and e.retry_after:
            print(f"Try again in {e.retry_after} seconds")
            
    except TradeStationValidationError as e:
        print(f"Invalid request: {e}")
        if e.validation_errors:
            print(f"Validation details: {e.validation_errors}")
            
    except TradeStationNetworkError as e:
        print(f"Network issue: {e}")
        # Implement retry with backoff
        
    except TradeStationAPIError as e:
        # Catch-all for any other API errors
        print(f"API error: {e}")
        if e.status_code:
            print(f"Status code: {e.status_code}")
        if e.request_id:
            print(f"Request ID: {e.request_id}")

Implementing Retries

For transient errors like rate limits, network issues, or server errors, you might want to implement retry logic:

import asyncio
import random

async def retry_with_backoff(func, max_attempts=3):
    attempt = 0
    while attempt < max_attempts:
        try:
            return await func()
        except (TradeStationRateLimitError, TradeStationNetworkError, 
                TradeStationServerError, TradeStationTimeoutError) as e:
            attempt += 1
            if attempt >= max_attempts:
                raise  # Re-raise if we've hit max attempts
                
            # Calculate backoff delay (with jitter)
            if isinstance(e, TradeStationRateLimitError) and e.retry_after:
                delay = e.retry_after
            else:
                # Exponential backoff with jitter
                delay = (2 ** attempt) * (0.5 + 0.5 * random.random())
                
            print(f"Retrying in {delay:.2f} seconds...")
            await asyncio.sleep(delay)

For a complete error handling example, check out the examples/QuickStart/error_handling.py file.

Logging In (Authentication) ๐Ÿ”’

The library needs your API keys to talk to TradeStation. The easiest way is the .env file (shown in Quick Start).

Other ways:

  1. Environment Variables: Set CLIENT_ID, REFRESH_TOKEN, ENVIRONMENT directly in your system.
  2. Python Dictionary:
    client = TradeStationClient({
        "client_id": "your_id",
        "refresh_token": "your_token",
        "environment": "Simulation"
    })
    
  3. Direct Parameters:
    client = TradeStationClient(
        refresh_token="your_token",
        environment="Live" # CLIENT_ID still needs to be in env or config
    )
    

See Authentication Guide for the full scoop.

Dive Deeper (Documentation) ๐Ÿ“š

Ready for more details?

Contributing ๐Ÿค

Got ideas or found a bug? Feel free to open an issue or submit a pull request!

License ๐Ÿ“œ

This project is licensed under the MIT License - see the LICENSE file for details.


Happy Trading! ๐ŸŽ‰

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

tradestation_api_python-1.2.1.tar.gz (54.1 kB view details)

Uploaded Source

Built Distribution

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

tradestation_api_python-1.2.1-py3-none-any.whl (61.4 kB view details)

Uploaded Python 3

File details

Details for the file tradestation_api_python-1.2.1.tar.gz.

File metadata

  • Download URL: tradestation_api_python-1.2.1.tar.gz
  • Upload date:
  • Size: 54.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.11.14 Linux/6.11.0-1018-azure

File hashes

Hashes for tradestation_api_python-1.2.1.tar.gz
Algorithm Hash digest
SHA256 6cb1e18f0968b66293bd9fbd5c2b5ea0c84cfca8a9989e239f209d4dedc00966
MD5 4c9fee47dec094154d016dc274676548
BLAKE2b-256 98a9ae42559d5cd07452039147fd249c24985071281606e9949482ce25576131

See more details on using hashes here.

File details

Details for the file tradestation_api_python-1.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for tradestation_api_python-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 038bc2b4bc6ea8743bf03a0d5694950512d5d8d73e35628c7dd40c0e3e748fb2
MD5 132b0112224662ab18107db3425c4486
BLAKE2b-256 4c341f9e539213df5a87195436f0c667c5da57404664f7c1641df46c2e8f5f50

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