Skip to content

Commit

Permalink
sessions & oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
Graeme22 committed Jan 14, 2025
1 parent 582be34 commit 904a334
Show file tree
Hide file tree
Showing 9 changed files with 684 additions and 6 deletions.
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,44 @@
[![Docs](https://readthedocs.org/projects/tradestation/badge/?version=latest)](https://tradestation.readthedocs.io/en/latest/?badge=latest)
[![PyPI](https://img.shields.io/pypi/v/tradestation)](https://pypi.org/project/tradestation)
[![Downloads](https://static.pepy.tech/badge/tradestation)](https://pepy.tech/project/tradestation)
[![Release)](https://img.shields.io/github/v/release/tastyware/tradestation?label=release%20notes)](https://github.com/tastyware/tradestation/releases)

# tradestation
An unofficial Python SDK for Tradestation!
A simple, unofficial, sync/async SDK for Tradestation built on their public API. This will allow you to create trading algorithms for whatever strategies you may have quickly and painlessly in Python.

## Features

- Up to 10x less code than using the API directly
- Sync/async functions for all endpoints
- Powerful websocket implementation for account alerts and data streaming, with support for auto-reconnection and reconnection callbacks
- 100% typed, with Pydantic models for all JSON responses from the API
- 95%+ unit test coverage
- Comprehensive documentation
- Utility functions for timezone calculations, futures monthly expiration dates, and more

## Installation

```console
$ pip install tradestation
```

## Initial setup

Tradestation uses OAuth for secure authentication to the API. In order to obtain access tokens, you need to authenticate with OAuth 2's authorization code flow, which requires a local HTTP server running to handle the callback. Fortunately, the SDK makes doing this easy:

```python
from tradestation.oauth import login
login()
```

This will let you authenticate in your local browser. Fortunately, this only needs to be done once, as afterwards you can use the refresh token to obtain new access tokens indefinitely.

## Creating a session

A session object is required to authenticate your requests to the Tradestation API.
You can create a simulation session by passing `is_test=True`.

```python
from tradestation import Session
session = Session('api_key', 'secret_key', 'refresh_token')
```
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ authors = [
dependencies = [
"httpx>=0.27.2",
"pydantic>=2.9.2",
"pyjwt>=2.10.1",
]

[project.urls]
Expand Down
13 changes: 10 additions & 3 deletions tests/test_session.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import os

from tradestation.session import Session


def test_session():
session = Session()
assert session is not None

api_key = os.getenv("TS_API_KEY")
secret_key = os.getenv("TS_SECRET_KEY")
refresh_token = os.getenv("TS_REFRESH")
assert api_key is not None
assert secret_key is not None
assert refresh_token is not None
session = Session(api_key, secret_key, refresh_token)
assert session.user_info != {}
24 changes: 23 additions & 1 deletion tradestation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,35 @@
API_URL_V3 = "https://api.tradestation.com/v3"
API_URL_V2 = "https://api.tradestation.com/v2"
API_URL_SIM = "https://sim-api.tradestation.com/v3"
OAUTH_SCOPES = [
# Requests access to lookup or stream Market Data.
"MarketData",
# Requests access to view Brokerage Accounts belonging to the current user.
"ReadAccount",
# Requests access to execute orders on behalf of the current user's account(s).
"Trade",
# Request access to execute options related endpoints.
"OptionSpreads",
# Request access to execute market depth related endpoints.
"Matrix",
# Returns the sub claim, which uniquely identifies the user. In an ID Token, iss, aud, exp, iat, and at_hash claims will also be present.
"openid",
# Allows for use of Refresh Tokens.
"offline_access",
# Returns claims in the ID Token that represent basic profile information, including name, family_name, given_name, middle_name, nickname, picture, and updated_at.
"profile",
# Returns the email claim in the ID Token, which contains the user's email address, and email_verified, which is a boolean indicating whether the email address was verified by the user.
"email",
]
OAUTH_URL = "https://signin.tradestation.com"
VERSION = "0.2"

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# ruff: noqa: E402

from .account import Account
from .session import Session

__all__ = ["Session"]
__all__ = ["Account", "Session"]
22 changes: 22 additions & 0 deletions tradestation/account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pydantic import Field

from tradestation.utils import TradestationModel


class AccountDetail(TradestationModel):
day_trading_qualified: bool
enrolled_in_reg_t_program: bool
is_stock_locate_eligible: bool
option_approval_level: int
pattern_day_trader: bool
requires_buying_power_warning: bool


class Account(TradestationModel):
account_detail: AccountDetail | None = None
account_id: str = Field(alias="AccountID")
account_type: str
alias: str | None = None
alt_id: str | None = Field(default=None, alias="AltID")
currency: str
status: str
Loading

0 comments on commit 904a334

Please sign in to comment.