Skip to main content

Cliente ligero para API de Schwab: OAuth, REST y Streaming WebSocket

Project description

Schwab SDK (Python)

Lightweight client for the Schwab API: OAuth, REST (Trader/Market Data), and WebSocket Streaming.

  • Focus: thin wrappers, no heavy validation; robust token handling, refresh, and retries.
  • Coverage: Accounts, Orders, Market Data, and Streaming (Level One, Book, Chart, Screener, Account Activity).

Installation

Unofficial PyPI package (distribution name):

pip install schwab_sdk_unofficial

Import in code (module):

from schwab_sdk import Client

Note: The package name on PyPI is schwab_sdk_unofficial, but the import remains schwab_sdk for a clean API.

Table of Contents

Requirements

  • Python 3.9+
  • Dependencies (installed automatically with pip install schwab_sdk_unofficial):
Package Purpose
httpx HTTP client (REST + OAuth)
fastapi OAuth callback server
uvicorn ASGI server for callback
cryptography Adhoc TLS certs & token encryption
python-multipart Form POST parsing in callback
websocket-client Streaming WebSocket
websockets Async streaming

Configuration

Create .env (or export environment variables):

SCHWAB_CLIENT_ID=your_client_id
SCHWAB_CLIENT_SECRET=your_client_secret
SCHWAB_REDIRECT_URI=https://127.0.0.1:8080/callback

Tokens are saved in schwab_tokens.json by default and rotate automatically (access ~29 min; re-login notice when refresh expires ~7 d). Set persist=False to keep tokens only in memory (useful for DB-backed storage).

Quick Start

from schwab_sdk import Client
import os

client = Client(
    os.environ['SCHWAB_CLIENT_ID'],
    os.environ['SCHWAB_CLIENT_SECRET'],
    os.environ.get('SCHWAB_REDIRECT_URI', 'https://127.0.0.1:8080/callback'),
    token_path='my_tokens.json',  # Optional: custom token file path
    persist=True,                 # Optional: False to keep tokens only in memory
)

# First use: OAuth login (opens the browser)
client.login()

# REST
quotes = client.market.get_quotes(["AAPL", "MSFT"])  # Market Data
accounts = client.account.get_accounts()               # Accounts

# Streaming (Level One equities)
ws = client.streaming
ws.on_data(lambda f: print("DATA", f))
ws.connect(); ws.login()
ws.equities_subscribe(["AAPL"])

Authentication (OAuth)

  • client.login(timeout=300, auto_open_browser=True, callback_port=None)
  • Handy: client.has_valid_token(), client.refresh_token_now(), client.logout()
  • Manual flow: client.get_auth_url() + client.exchange_code(code) (sync) or await client.exchange_code(code) (AsyncClient)
  • Internals: adhoc HTTPS callback server (FastAPI + uvicorn), code-for-token exchange, auto-refresh and notice when refresh expires.

Token storage options

By default tokens are persisted to a JSON file (schwab_tokens.json). You can customize this:

# Custom file path
client = Client(client_id, client_secret, redirect_uri, token_path="tokens/my_tokens.json")

# Encrypted at rest (AES-256-GCM)
client = Client(client_id, client_secret, redirect_uri, encryption_key="my-secret")

# In-memory only (no file written) — useful for DB-backed storage
client = Client(client_id, client_secret, redirect_uri, persist=False)

# After login, read tokens to store in your DB:
handler = client.token_handler
db.save(
    access_token=handler.access_token,
    refresh_token=handler.refresh_token,
    access_expires=handler.access_token_expires_at,
    refresh_expires=handler.refresh_token_expires_at,
)

Client constructor parameters

Parameter Type Default Description
client_id str required Schwab application Client ID
client_secret str required Schwab application Client Secret
redirect_uri str https://localhost:8080/callback OAuth redirect URI
token_path str | None "schwab_tokens.json" Path to token file
encryption_key str | None None Passphrase for AES-256-GCM token encryption
persist bool True False to keep tokens only in memory

Request & Error Handling (REST)

All REST calls go through Client._request() which provides automatic error recovery:

  • Authorization: Bearer token header injected automatically.
  • 401 Unauthorized: refreshes the access token once and retries immediately.
  • 429 / 5xx: retries up to 3 times with exponential backoff (0.5 * 2^attempt seconds).
  • Network errors (httpx.RequestError): same retry logic as 429/5xx.

Exception hierarchy

HTTP errors raise a subclass of SchwabAPIError. Each exception carries:

Attribute Type Description
status_code int HTTP status code
message str Human-readable error from response body
correl_id str | None Schwab-Client-CorrelId header (for Schwab support)
errors list[dict] Raw error dicts from the response body
response httpx.Response | None Raw response for advanced inspection
Exception HTTP Status When
SchwabValidationError 400 Invalid parameters or malformed request body
SchwabAuthenticationError 401 Access token missing, invalid, or expired
SchwabForbiddenError 403 Valid credentials but insufficient permissions
SchwabNotFoundError 404 Requested resource does not exist
SchwabRateLimitError 429 API rate limit exceeded (after retries)
SchwabServerError 500/502/503/504 Schwab-side failure (after retries)
SchwabTokenExpiredError (subclass of 401) Refresh token expired; full re-login required
SchwabParameterError (client-side) ValueError subclass for parameter validation

Error handling example

from schwab_sdk import (
    Client,
    SchwabAPIError,
    SchwabNotFoundError,
    SchwabRateLimitError,
    SchwabAuthenticationError,
)

try:
    account = client.account.get_account_by_id("invalid-hash")
except SchwabNotFoundError as e:
    print(f"Not found: {e.message}")
    print(f"Correlation ID: {e.correl_id}")  # for Schwab support
except SchwabRateLimitError as e:
    print(f"Rate limited after retries: {e.message}")
except SchwabAuthenticationError as e:
    print("Token expired, re-login needed")
    client.login()
except SchwabAPIError as e:
    print(f"API error {e.status_code}: {e.message}")

Schwab error response format

{
  "errors": [
    {
      "id": "uuid",
      "status": "400",
      "title": "Bad Request",
      "detail": "Missing header",
      "source": {"header": "Authorization"}
    }
  ]
}

The SDK extracts detail, title, or message from each error and joins them into e.message. The Schwab-Client-CorrelId response header is captured in e.correl_id.

Factory function

raise_for_schwab_status(response) inspects an httpx.Response and raises the appropriate exception for non-2xx status codes. Used internally by each endpoint module (accounts, orders, market) after calling _request(), and also available for custom flows:

from schwab_sdk import raise_for_schwab_status
raise_for_schwab_status(response)  # raises SchwabValidationError, SchwabNotFoundError, etc.

Accounts (accounts.py)

Possible exceptions: SchwabAuthenticationError (401), SchwabForbiddenError (403), SchwabNotFoundError (404), SchwabServerError (5xx)

Related enums: AccountField, TransactionType, AccountInstrumentType, TransactionStatus

get_account_numbers() -> list[dict]

  • GET /accounts/accountNumbers
  • Returns accountNumber and hashValue pairs.
  • Example response:
[
  {"accountNumber":"12345678","hashValue":"827C...AC12"}
]

get_accounts(fields=None, params=None) -> dict

  • GET /accounts

  • Parameters:

    • fields (optional): List[str] — use ["positions"] or [AccountField.POSITIONS] to include positions.
    • params (optional): additional query parameters.

get_account_by_id(account_hash, fields=None, params=None) -> dict

  • GET /accounts/{accountNumber}

  • account_hash: encrypted account identifier (hashValue).

  • Raises SchwabNotFoundError if account_hash is invalid.

  • Parameters:

    • fields (optional): List[str]["positions"] or [AccountField.POSITIONS] to include positions.
    • params (optional): additional query parameters.

find_account(last_4_digits: str) -> dict|None

  • Helper that uses get_account_numbers() and filters by the last 4 digits, then calls get_account_by_id.

get_transactions(account_hash, from_date=None, to_date=None, transaction_types=None, symbol=None, filters=None) -> dict

  • GET /accounts/{accountHash}/transactions

  • At least one date recommended: you may pass only from_date or only to_date. If you pass a single date, the SDK fills in the other for the same day. If both are omitted, the API may return an error or empty results:

    • Short format YYYY-MM-DD: start → YYYY-MM-DDT00:00:00.000Z, end → YYYY-MM-DDT23:59:59.000Z
    • Full ISO UTC YYYY-MM-DDTHH:MM:SS.ffffffZ: used as-is; if the other date is missing, it is derived with 00:00:00.000Z or 23:59:59.000Z of the same day.
  • Parameters:

    • account_hash (required): encrypted account identifier (hashValue)
    • from_date (optional): start date — YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.ffffffZ
    • to_date (optional): end date — YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.ffffffZ
    • transaction_types (optional): List[str] of TransactionType values: TRADE, RECEIVE_AND_DELIVER, DIVIDEND_OR_INTEREST, ACH_RECEIPT, ACH_DISBURSEMENT, CASH_RECEIPT, CASH_DISBURSEMENT, ELECTRONIC_FUND, WIRE_OUT, WIRE_IN, JOURNAL, MEMORANDUM, MARGIN_CALL, MONEY_MARKET, SMA_ADJUSTMENT
    • symbol (optional): filter by specific symbol
    • filters (optional): additional query parameters dict

Correct example:

from datetime import datetime, timezone, timedelta

# Get hashValue
hash_value = client.account.get_account_numbers()[0]['hashValue']

# Create UTC dates
start = datetime.now(timezone.utc) - timedelta(days=7)
start = start.replace(hour=0, minute=0, second=0, microsecond=0)
end = datetime.now(timezone.utc).replace(hour=23, minute=59, second=59, microsecond=999999)

# Proper call
transactions = client.account.get_transactions(
    account_hash=hash_value,  # Use hashValue!
    from_date=start.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
    to_date=end.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
    transaction_types=["TRADE", "DIVIDEND_OR_INTEREST"],  # Optional
)

get_transaction(account_hash: str, transaction_id: str) -> dict

  • GET /accounts/{accountHash}/transactions/{transactionId}

  • Path parameters:

    • account_hash (required)
    • transaction_id (required): numeric transaction ID
  • Returns details of a specific transaction.

get_user_preferences() -> dict

  • GET /userPreference

  • Returns user preferences and, when applicable, streamer information needed for WebSocket:

    • streamerSocketUrl
    • schwabClientCustomerId
    • schwabClientCorrelId
    • SchwabClientChannel
    • SchwabClientFunctionId
  • Useful to initialize client.streaming (LOGIN and subscriptions).


Orders (orders.py)

Possible exceptions: SchwabValidationError (400), SchwabAuthenticationError (401), SchwabForbiddenError (403), SchwabNotFoundError (404), SchwabServerError (5xx)

Related enums: OrderType, Duration, Session, OrderStatus, EquityInstruction, OptionInstruction, AssetType, OrderStrategyType, ComplexOrderStrategyType, SpecialInstruction, RequestedDestination, PriceLinkBasis, PriceLinkType, StopType, TaxLotMethod, PositionEffect, QuantityType

All responses include HTTP metadata and the native data:

{
  "status_code": 200,
  "success": true,
  "headers": {"...": "..."},
  "url": "https://...",
  "elapsed_seconds": 0.42,
  "method": "GET|POST|PUT|DELETE",
  "params": {"...": "..."},
  "data": {},
  "order_id": "..."
}

get_orders(account_hash, from_entered_time=None, to_entered_time=None, status=None, max_results=None) -> dict

  • GET /accounts/{accountNumber}/orders
  • API requirements: fromEnteredTime and toEnteredTime are mandatory (ISO-8601). The SDK defaults them to "last 60 days" if you omit them.
  • status (case-insensitive): OrderStatus enum — normalized to uppercase. See OrderStatus for all values.
  • maxResults (optional): record limit (API default 3000).
  • Datetime format: ISO-8601 YYYY-MM-DDTHH:MM:SS.000Z.

get_all_orders(from_entered_time=None, to_entered_time=None, status=None, max_results=None) -> dict

  • GET /orders
  • API requirements: fromEnteredTime and toEnteredTime are mandatory (ISO-8601). If you omit them, the SDK uses "last 60 days".
  • Filters identical to get_orders (including status normalization).
  • maxResults (optional): record limit (API default 3000).

place_order(account_hash: str, order_data: dict) -> dict

  • POST /accounts/{accountNumber}/orders
  • Extracts order_id from the Location header when present.

get_order(account_hash: str, order_id: str) -> dict

  • GET /accounts/{accountNumber}/orders/{orderId}

cancel_order(account_hash: str, order_id: str) -> dict

  • DELETE /accounts/{accountNumber}/orders/{orderId}
  • The order_id you pass is included in the result dict as order_id.

replace_order(account_hash: str, order_id: str, new_order_data: dict) -> dict

  • PUT /accounts/{accountNumber}/orders/{orderId}
  • Returns original_order_id (the id you passed) and new order_id (from Location header) when the server provides it.

preview_order(account_hash: str, order_data: dict) -> dict

  • POST /accounts/{accountNumber}/previewOrder
  • Returns preview data; no order is placed.

Payload helpers

  • build_limit_order(symbol, quantity, price, instruction="BUY")
  • build_market_order(symbol, quantity, instruction="BUY")
  • build_bracket_order(symbol, quantity, entry_price, take_profit_price, stop_loss_price)

Example (preview):

acc = client.account.get_account_numbers()[0]['hashValue']
order = client.orders.build_limit_order("AAPL", 1, 100.00)
preview = client.orders.preview_order(acc, order)

Market Data (market.py)

Possible exceptions: SchwabValidationError (400), SchwabAuthenticationError (401), SchwabNotFoundError (404), SchwabServerError (5xx)

Related enums: ContractType, Strategy, StrikeRange, ExpirationMonth, OptionType, Entitlement, PeriodType, FrequencyType, QuoteField, MoverIndex, MoverSort, MoverFrequency, MarketID, Projection

Response enums: AssetMainType, AssetSubType, SecurityStatus, Exchange, MICId, ExchangeName, QuoteType

get_quotes(symbols, fields=None, indicative=None, params=None) -> dict

  • GET /quotes?symbols=...

  • Parameters:

    • symbols (required): str or List[str]. E.g.: "AAPL" or ["AAPL", "AMZN", "$DJI"].
    • fields (optional): str or List[str]QuoteField values: quote, fundamental, extended, reference, regular, all. Default: all.
    • indicative (optional): bool — include indicative symbol quotes for ETFs.
    • params (optional): additional query parameters.

get_quote(symbol, fields=None, indicative=None, params=None) -> dict

  • GET /{symbol}/quotes

  • Raises SchwabNotFoundError if the symbol does not exist.

  • Parameters:

    • symbol (required): single symbol (e.g., "TSLA").
    • fields (optional): str or List[str] — same QuoteField values as get_quotes.
    • indicative (optional): bool — include indicative symbol quotes for ETFs.
    • params (optional): additional query parameters.

get_option_chain(symbol: str, contract_type: str|None=None, strike_count: int|None=None, include_underlying_quote: bool|None=None, strategy: str|None=None, interval: float|None=None, strike: float|None=None, range_type: str|None=None, from_date: str|None=None, to_date: str|None=None, volatility: float|None=None, underlying_price: float|None=None, interest_rate: float|None=None, days_to_expiration: int|None=None, exp_month: str|None=None, option_type: str|None=None, entitlement: str|None=None, params: dict|None=None) -> dict

  • GET /chains

  • Parameters:

    • symbol (required): Underlying asset symbol
    • contract_type (optional): ContractTypeCALL, PUT, ALL
    • strike_count (optional): Number of strikes above/below ATM
    • include_underlying_quote (optional): Include underlying quotes (boolean)
    • strategy (optional): StrategySINGLE (default), ANALYTICAL, COVERED, VERTICAL, CALENDAR, STRANGLE, STRADDLE, BUTTERFLY, CONDOR, DIAGONAL, COLLAR, ROLL
    • interval (optional): Strike interval for spread strategy chains
    • strike (optional): Strike Price
    • range_type (optional): StrikeRangeITM, NTM, OTM, SAK, SBK, SNK, ALL
    • from_date (optional): From date (yyyy-MM-dd)
    • to_date (optional): To date (yyyy-MM-dd)
    • volatility (optional): Volatility (ANALYTICAL strategy only)
    • underlying_price (optional): Underlying price (ANALYTICAL strategy only)
    • interest_rate (optional): Interest rate (ANALYTICAL strategy only)
    • days_to_expiration (optional): Days to expiration (ANALYTICAL strategy only)
    • exp_month (optional): ExpirationMonthJAN..DEC, ALL
    • option_type (optional): OptionTypeSTANDARD, NON_STANDARD, ALL
    • entitlement (optional): EntitlementPN (NonPayingPro), NP (NonPro), PP (PayingPro)
    • params (optional): Additional query parameters

get_expiration_chain(symbol: str, params: dict|None=None) -> dict

  • GET /expirationchain

  • Parameters:

    • symbol (required): Underlying asset symbol
    • params (optional): Additional query parameters
  • Returns: JSON response with option expiration dates for the symbol

get_price_history(symbol, periodType="month", period=1, frequencyType="daily", frequency=1, startDate=None, endDate=None, need_extended_hours_data=None, need_previous_close=None, params=None) -> dict

  • GET /pricehistory

  • Parameters:

    • symbol (required): instrument symbol
    • periodType: PeriodTypeday, month, year, ytd
    • period: int — number of periods
    • frequencyType: FrequencyTypeminute, daily, weekly, monthly
    • frequency: int — specific frequency
    • startDate / endDate: epoch millis (int), datetime, date, or "YYYY-MM-DD" string
    • need_extended_hours_data (optional): bool — include extended hours data (default: True)
    • need_previous_close (optional): bool — include previous close price/date
    • params (optional): additional query parameters

get_movers(symbol_id: str, sort: str|None=None, frequency: int|None=None, params: dict|None=None) -> dict

  • GET /movers/{symbol_id} (e.g., $DJI, $SPX, NASDAQ)

  • Parameters:

    • symbol_id (required): MoverIndex$DJI, $COMPX, $SPX, NYSE, NASDAQ, OTCBB, INDEX_ALL, EQUITY_ALL, OPTION_ALL, OPTION_PUT, OPTION_CALL
    • sort (optional): MoverSortVOLUME, TRADES, PERCENT_CHANGE_UP, PERCENT_CHANGE_DOWN
    • frequency (optional): MoverFrequency0, 1, 5, 10, 30, 60 (minutes). Default 0
    • params (optional): Additional query parameters

get_markets(markets=None, date=None, params=None) -> dict

  • GET /markets

  • Parameters:

    • markets (optional): List[str] of MarketID values — equity, option, bond, future, forex. If None, returns all markets.
    • date (optional): YYYY-MM-DD (if you send ISO, the SDK trims to date-only)
    • params (optional): additional query parameters

get_market_hours(market_id, date=None, params=None) -> dict

  • GET /markets/{market_id}MarketID: equity, option, bond, future, forex

  • Parameters:

    • market_id (required): validated against MarketID enum
    • date (optional): YYYY-MM-DD (if you send ISO, the SDK trims to date-only)
    • params (optional): additional query parameters

get_instruments(symbols, projection="symbol-search", extra_params=None) -> dict

  • GET /instruments

  • Parameters:

    • symbols (required): str or List[str] — single symbol or list of symbols
    • projection (optional): Projectionsymbol-search (default), symbol-regex, desc-search, desc-regex, search, fundamental
    • extra_params (optional): additional query parameters

get_instrument_by_cusip(cusip_id, params=None) -> dict

  • GET /instruments/{cusip_id}

  • Parameters:

    • cusip_id (required): instrument CUSIP identifier
    • params (optional): additional query parameters

WebSocket Streaming (streaming.py)

Related enums: StreamService, StreamCommand, StreamResponseCode

Callbacks

  • on_data(fn) (data frames)
  • on_response(fn) (command confirmations/errors)
  • on_notify(fn) (heartbeats/notices)

Basic flow

ws = client.streaming
ws.on_data(lambda f: print("DATA", f))
ws.on_response(lambda f: print("RESP", f))
ws.on_notify(lambda f: print("NOTIFY", f))
ws.connect(); ws.login()  # Authorization = access token without "Bearer"
ws.equities_subscribe(["AAPL","MSFT"])             # LEVELONE_EQUITIES
ws.options_subscribe(["AAPL  250926C00257500"])      # LEVELONE_OPTIONS
ws.nasdaq_book(["MSFT"])                             # NASDAQ_BOOK
ws.chart_equity(["AAPL"])                            # CHART_EQUITY
ws.screener_equity(["NYSE_VOLUME_5"])                # SCREENER_EQUITY

Key Formats (quick table)

Type Format Example Notes
Equities Ticker AAPL, MSFT Uppercase
Options RRRRRRYYMMDDsWWWWWddd AAPL 251219C00200000 6-char symbol, YYMMDD, C/P, 5+3 strike
Futures /<root><month><yy> /ESZ25 Root/month/year in uppercase
FuturesOptions ./<root><month><year><C/P><strike> ./OZCZ23C565 Depends on the feed
Forex PAIR EUR/USD, USD/JPY / separator
Screener PREFIX_SORTFIELD_FREQUENCY NYSE_VOLUME_5 Prefix/criterion/frequency

Service-by-Service Examples

Level One Options

ws.options_subscribe(["AAPL  250926C00257500"])  # standard option string
# Default fields: 0,2,3,4,8,16,17,18,20,28,29,30,31,37,44

Level One Futures

ws.futures_subscribe(["/ESZ25"])  # E-mini S&P 500 Dec 2025
# Default fields: 0,1,2,3,4,5,8,12,13,18,19,20,24,33

Level One Futures Options

ws.futures_options_subscribe(["./OZCZ23C565"])
# Default fields: 0,1,2,3,4,5,8,12,13,17,18,19,23,24,25,29

Level One Forex

ws.forex_subscribe(["EUR/USD","USD/JPY"])
# Default fields: 0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,20,21,27,28,29

Book (Level II)

ws.nasdaq_book(["MSFT"])  # Also: ws.nyse_book, ws.options_book
# Default fields: 0 (Symbol), 1 (BookTime), 2 (Bids), 3 (Asks)

Chart (Series)

ws.chart_equity(["AAPL"])      # 0..7: key, open, high, low, close, volume, sequence, chartTime
ws.chart_futures(["/ESZ25"])   # 0..6

Screener

ws.screener_equity(["NYSE_VOLUME_5"])
ws.screener_options(["CBOE_VOLUME_5"])

Account Activity

ws.account_activity()  # Gets accountHash and subscribes

Utilities

  • connect() — open the WebSocket connection
  • wait_until_connected(timeout=10.0) — block until the connection is ready
  • login(...) — authenticate the stream (sends ADMIN LOGIN)
  • logout() — send ADMIN LOGOUT
  • disconnect() — close the WebSocket connection (AsyncStreaming only)
  • subscribe(service, keys, fields=None) — generic SUBS
  • add(service, keys) — generic ADD
  • unsubscribe(service, keys) / unsubscribe_service(service, keys) — generic UNSUBS
  • view(service, fields) — generic VIEW

AsyncStreaming: AsyncClient.streaming returns an AsyncStreaming instance. It mirrors all Streaming methods as async/await, adds disconnect(), and is safe for use in async frameworks (FastAPI, etc.).

Option Symbol Helper

  • create_option_symbol(symbol, expiration, option_type, strike_price) - Creates Schwab option symbol from components

Example:

# Create option symbol from components
option_symbol = ws.create_option_symbol("AAPL", "2025-12-19", "C", 200.0)
# Returns: "AAPL  251219C00200000"

# Use in subscription
ws.options_subscribe([option_symbol])

Parameters:

  • symbol: Underlying symbol (e.g., "AAPL")
  • expiration: Expiration date in "YYYY-MM-DD" format (e.g., "2025-10-03")
  • option_type: "C" for Call or "P" for Put
  • strike_price: Strike price (e.g., 257.5)

Recommended Fields

  • LEVELONE_EQUITIES: 0,1,2,3,4,5,8,10,18,42,33,34,35
  • LEVELONE_OPTIONS: 0,2,3,4,8,16,17,18,20,28,29,30,31,37,44
  • LEVELONE_FUTURES: 0,1,2,3,4,5,8,12,13,18,19,20,24,33
  • CHART_EQUITY: 0,1,2,3,4,5,6,7

Quick fields table (copy/paste)

Service Fields CSV
LEVELONE_EQUITIES 0,1,2,3,4,5,8,10,18,42,33,34,35
LEVELONE_OPTIONS 0,2,3,4,8,16,17,18,20,28,29,30,31,37,44
LEVELONE_FUTURES 0,1,2,3,4,5,8,12,13,18,19,20,24,33
LEVELONE_FUTURES_OPTIONS 0,1,2,3,4,5,8,12,13,17,18,19,23,24,25,29
LEVELONE_FOREX 0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,20,21,27,28,29
NASDAQ_BOOK 0,1,2,3
NYSE_BOOK 0,1,2,3
OPTIONS_BOOK 0,1,2,3
CHART_EQUITY 0,1,2,3,4,5,6,7
CHART_FUTURES 0,1,2,3,4,5,6
SCREENER_EQUITY 0,1,2,3,4
SCREENER_OPTION 0,1,2,3,4
ACCT_ACTIVITY 0,1,2,3

SUBS / ADD / VIEW / UNSUBS examples by service

ws = client.streaming
ws.on_data(lambda f: print("DATA", f))
ws.on_response(lambda f: print("RESP", f))
ws.connect(); ws.login()

# LEVELONE_EQUITIES
ws.equities_subscribe(["AAPL","TSLA"], fields=[0,1,2,3,4,5,8,10,18,42,33,34,35])
ws.equities_add(["MSFT"])                          # adds without replacing
ws.equities_view([0,1,2,3,5,8,18])                  # changes fields
ws.equities_unsubscribe(["TSLA"])                  # removes symbols

# LEVELONE_OPTIONS
ws.options_subscribe(["AAPL  250926C00257500"], fields=[0,2,3,4,8,16,17,18,20,28,29,30,31,37,44])
ws.options_add(["AAPL  250926P00257500"])
ws.options_view([0,2,3,4,8,16,17,20,28,29,30,31,37,44])
ws.options_unsubscribe(["AAPL  250926C00257500"])

# LEVELONE_FUTURES
ws.futures_subscribe(["/ESZ25"], fields=[0,1,2,3,4,5,8,12,13,18,19,20,24,33])
ws.futures_add(["/NQZ25"])
ws.futures_view([0,1,2,3,4,5,8,12,13,18,19,20,24,33])
ws.futures_unsubscribe(["/ESZ25"])

# LEVELONE_FUTURES_OPTIONS
ws.futures_options_subscribe(["./OZCZ23C565"], fields=[0,1,2,3,4,5,8,12,13,17,18,19,23,24,25,29])
ws.futures_options_add(["./OZCZ23P565"])
ws.futures_options_view([0,1,2,3,4,5,8,12,13,17,18,19,23,24,25,29])
ws.futures_options_unsubscribe(["./OZCZ23C565"])

# LEVELONE_FOREX
ws.forex_subscribe(["EUR/USD","USD/JPY"], fields=[0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,20,21,27,28,29])
ws.forex_add(["GBP/USD"])
ws.forex_view([0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,20,21,27,28,29])
ws.forex_unsubscribe(["USD/JPY"])

# BOOK (Level II)
ws.nasdaq_book(["MSFT"], fields=[0,1,2,3])
ws.add("NASDAQ_BOOK", ["AAPL"])                    # generic ADD
ws.view("NASDAQ_BOOK", [0,1,2,3])                   # generic VIEW
ws.unsubscribe_service("NASDAQ_BOOK", ["MSFT"])    # generic UNSUBS

# CHART (Series)
ws.chart_equity(["AAPL"], fields=[0,1,2,3,4,5,6,7])
ws.add("CHART_EQUITY", ["MSFT"])                  # generic ADD
ws.view("CHART_EQUITY", [0,1,2,3,4,5,6,7])          # generic VIEW
ws.unsubscribe("CHART_EQUITY", ["AAPL"])           # generic UNSUBS

# SCREENER
ws.screener_equity(["EQUITY_ALL_VOLUME_5"], fields=[0,1,2,3,4])
ws.add("SCREENER_EQUITY", ["NYSE_TRADES_1"])
ws.view("SCREENER_EQUITY", [0,1,2,3,4])
ws.unsubscribe("SCREENER_EQUITY", ["EQUITY_ALL_VOLUME_5"])

# ACCT_ACTIVITY
ws.account_activity(fields=[0,1,2,3])                  # subscribe account activity
# For UNSUBS you need the same key used in SUBS (account_hash)
account_hash = getattr(client, "_account_hash", None)
if account_hash:
    ws.unsubscribe_service("ACCT_ACTIVITY", [account_hash])

Quick Field Guide (IDs → meaning)

Note: exact mappings may vary depending on entitlements/version. Below are practical equivalences observed in frames.

LEVELONE_EQUITIES

ID Field
0 symbol/key
1 bidPrice
2 askPrice
3 lastPrice
4 bidSize
5 askSize
8 totalVolume
10 referencePrice (open/mark)
18 netChange
42 percentChange

LEVELONE_OPTIONS

ID Field
0 symbol/key
2 bidPrice
3 askPrice
4 lastPrice
8 totalVolume
16 openInterest
17 daysToExpiration
20 strikePrice
28 delta
29 gamma
30 theta
31 vega
44 impliedVolatility (if provided)

LEVELONE_FUTURES

ID Field
0 symbol/key
1 bidPrice
2 askPrice
3 lastPrice
4 bidSize
5 askSize
8 totalVolume
12 openInterest
13 contractDepth/series info (per feed)
18 netChange
19 sessionChange (or days/indicator per feed)
20 percentChange/ratio (per feed)
24 lastSettlement/mark
33 priorSettle

Frame Structure

  • Confirmations (response): { "response": [ { "service":"ADMIN","command":"LOGIN","content":{"code":0,"msg":"..."}} ] }
  • Data (data): { "service":"LEVELONE_EQUITIES","timestamp":...,"command":"SUBS","content":[{"key":"AAPL",...}] }
  • Notifications (notify): { "notify": [ { "heartbeat": "..." } ] }

Streamer API Cheat Sheet (parameters and commands)

  1. Connection and prerequisites
  • Auth: use the Access Token from the OAuth flow.
  • Session IDs (from GET /userPreference): schwabClientCustomerId, schwabClientCorrelId, SchwabClientChannel, SchwabClientFunctionId.
  • Transport: JSON WebSocket. One stream per user (if you open more: code 12 CLOSE_CONNECTION).
  1. Envelope of each command
  • Common fields:

    • service (req.): ADMIN, LEVELONE_EQUITIES, LEVELONE_OPTIONS, LEVELONE_FUTURES, LEVELONE_FUTURES_OPTIONS, LEVELONE_FOREX, NYSE_BOOK, NASDAQ_BOOK, OPTIONS_BOOK, CHART_EQUITY, CHART_FUTURES, SCREENER_EQUITY, SCREENER_OPTION, ACCT_ACTIVITY.
    • command (req.): LOGIN, SUBS, ADD, UNSUBS, VIEW, LOGOUT.
    • requestid (req.): unique request identifier.
    • SchwabClientCustomerId and SchwabClientCorrelId (recommended): from userPreference.
    • parameters (optional): depends on service/command.
  • Notes: SUBS overwrites list; ADD appends; UNSUBS removes; VIEW changes fields.

  1. ADMIN (session)
  • LOGIN (service=ADMIN, command=LOGIN)

    • parameters: Authorization (token without "Bearer"), SchwabClientChannel, SchwabClientFunctionId.
  • LOGOUT (service=ADMIN, command=LOGOUT)

    • parameters: empty.
  1. LEVEL ONE (L1 quotes)
  • Common parameters: keys (req., CSV list), fields (optional, indexes).
  • LEVELONE_EQUITIES: keys uppercase tickers (e.g., AAPL,TSLA).
  • LEVELONE_OPTIONS: keys Schwab option format RRRRRR YYMMDD[C/P]STRIKE.
  • LEVELONE_FUTURES: keys /<root><monthCode><yearCode> (month codes: F,G,H,J,K,M,N,Q,U,V,X,Z; year two digits), e.g., /ESZ25.
  • LEVELONE_FUTURES_OPTIONS: keys ./<root><month><yy><C|P><strike>, e.g., ./OZCZ23C565.
  • LEVELONE_FOREX: keys BASE/QUOTE pairs CSV (e.g., EUR/USD,USD/JPY).
  1. BOOK (Level II)
  • Services: NYSE_BOOK, NASDAQ_BOOK, OPTIONS_BOOK.
  • Parameters: keys (req., tickers), fields (optional, level indexes).
  1. CHART (streaming series)
  • CHART_EQUITY: keys equities; fields indexes (OHLCV, time, seq).
  • CHART_FUTURES: keys futures (same format as L1 futures); fields indexes.
  1. SCREENER (gainers/losers/actives)
  • Services: SCREENER_EQUITY, SCREENER_OPTION.

  • keys pattern PREFIX_SORTFIELD_FREQUENCY, e.g., EQUITY_ALL_VOLUME_5.

    • PREFIX examples: $COMPX, $DJI, $SPX, INDEX_ALL, NYSE, NASDAQ, OTCBB, EQUITY_ALL, OPTION_PUT, OPTION_CALL, OPTION_ALL.
    • SORTFIELD: VOLUME, TRADES, PERCENT_CHANGE_UP, PERCENT_CHANGE_DOWN, AVERAGE_PERCENT_VOLUME.
    • FREQUENCY: 0,1,5,10,30,60 (min; 0 = full day).
  • fields (optional): screener field indexes.

  1. ACCOUNT (account activity)
  • Service: ACCT_ACTIVITY (SUBS/UNSUBS).
  • keys (req.): arbitrary identifier for your sub; if you send multiple, the first is used.
  • fields (recommended): 0 (or 0,1,2,3 per example/need).
  1. Server responses (StreamResponseCode)
  • Types: response (to your requests), notify (heartbeats), data (market flow).
Code Name Meaning
0 SUCCESS Command succeeded
3 LOGIN_DENIED Invalid or expired token
9 UNKNOWN_FAILURE Unspecified server error
11 SERVICE_NOT_AVAILABLE Service unavailable for your entitlement
12 CLOSE_CONNECTION Only one stream per user allowed
19 REACHED_SYMBOL_LIMIT Too many symbols subscribed
20 STREAM_CONN_NOT_FOUND Stream connection not found
21 BAD_COMMAND_FORMAT Malformed command (check Auth format, keys)
22 FAILED_COMMAND_SUBS SUBS command failed
23 FAILED_COMMAND_UNSUBS UNSUBS command failed
24 FAILED_COMMAND_ADD ADD command failed
25 FAILED_COMMAND_VIEW VIEW command failed
26 SUCCEEDED_COMMAND_SUBS SUBS succeeded
27 SUCCEEDED_COMMAND_UNSUBS UNSUBS succeeded
28 SUCCEEDED_COMMAND_ADD ADD succeeded
29 SUCCEEDED_COMMAND_VIEW VIEW succeeded
30 STOP_STREAMING Server stopped streaming
  1. Delivery Types
  • All Sequence: everything with sequence number.
  • Change: only changed fields (conflated).
  • Whole: full messages with throttling.
  1. Best practices
  • Do LOGIN and wait for code=0 before SUBS/ADD.
  • To add symbols without losing existing ones, use ADD (not SUBS).
  • Change fields with VIEW for performance.
  • Handle notify (heartbeats) and reconnect if they are lost.
  • Reuse your SchwabClientCorrelId during the session.
  • If you see 19 (symbol limit), shard loads by service/session.

Enums Reference (enums.py)

All enums are StrEnum (or IntEnum) subclasses, so they can be passed directly where a str is expected. Import from the top-level package:

from schwab_sdk import ContractType, OrderType, StreamService

Market Data — Request Parameter Enums

ContractType

Option chain contract type filter.

Value Description
CALL Call contracts only
PUT Put contracts only
ALL Both calls and puts

Strategy

Option chain strategy.

Value
SINGLE, ANALYTICAL, COVERED, VERTICAL, CALENDAR, STRANGLE, STRADDLE, BUTTERFLY, CONDOR, DIAGONAL, COLLAR, ROLL

StrikeRange

Option chain strike range filter.

Value API Code Description
IN_THE_MONEY ITM In the money
NEAR_THE_MONEY NTM Near the money
OUT_OF_THE_MONEY OTM Out of the money
STRIKES_ABOVE_MARKET SAK Strikes above market
STRIKES_BELOW_MARKET SBK Strikes below market
STRIKES_NEAR_MARKET SNK Strikes near market
ALL ALL All strikes

ExpirationMonth

Option chain expiration month filter.

JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC, ALL

OptionType

Option type filter for chains.

Value Description
STANDARD Standard contracts
NON_STANDARD Non-standard (adjusted) contracts
ALL Both

Entitlement

Retail token entitlement level.

Value Description
PN NonPayingPro
NP NonPro
PP PayingPro

PeriodType

Price history period type.

day, month, year, ytd

FrequencyType

Price history frequency type.

minute, daily, weekly, monthly

QuoteField

Quote field groups for GET /quotes.

quote, fundamental, extended, reference, regular, all

MoverIndex

Index symbols for GET /movers.

$DJI, $COMPX, $SPX, NYSE, NASDAQ, OTCBB, INDEX_ALL, EQUITY_ALL, OPTION_ALL, OPTION_PUT, OPTION_CALL

MoverSort

Movers sort attribute.

VOLUME, TRADES, PERCENT_CHANGE_UP, PERCENT_CHANGE_DOWN, AVERAGE_PERCENT_VOLUME

MoverFrequency (IntEnum)

Movers frequency in minutes. 0 = real-time snapshot.

0, 1, 5, 10, 30, 60

MarketID

Market IDs for market hours endpoints.

equity, option, bond, future, forex

Projection

Instrument search projection type.

symbol-search, symbol-regex, desc-search, desc-regex, search, fundamental

Market Data — Response Enums

AssetMainType

Primary asset type returned in responses and streaming data.

BOND, EQUITY, ETF, EXTENDED, FOREX, FUTURE, FUTURE_OPTION, FUNDAMENTAL, INDEX, INDICATOR, MUTUAL_FUND, OPTION, UNKNOWN

AssetSubType

Asset sub-type in responses.

Value Description
ADR American Depositary Receipt
CEF Closed-End Fund
COE Common Equity
ETF Exchange-Traded Fund
ETN Exchange-Traded Note
GDR Global Depositary Receipt
OEF Open-End Fund
PRF Preferred Stock
RGT Right
UIT Unit Investment Trust
WAR Warrant

SecurityStatus

Security status in quote responses.

Normal, Unknown, Halted, Closed

Exchange

Exchange single-character codes (reference.exchange, streaming field 13).

Value Code Exchange
AMEX A NYSE American (AMEX)
NASDAQ Q NASDAQ
NYSE N NYSE
NYSE_ARCA P NYSE Arca (Pacific)
OPR o Options
OTC_MARKETS 9 Pink Sheets
INDEX 0 Index
XCME @ CME Futures
GFT T Forex
MUTUAL_FUND 3 Mutual Fund
NASDAQ_OTCBB U OTCBB
INDICATOR : Indicator (realtime)

MICId

Market Identifier Codes (ISO 10383) in quote data (askMICId, bidMICId, lastMICId).

XNYS, XNAS, ARCX, XADF, MEMX, IEGX, EDGX, BATS, IEXG, EPRL

ExchangeName

Human-readable exchange names (reference.exchangeName).

NASDAQ, NYSE, NYSE Arca, OPR, OTC Markets, Index, XCME, GFT, Mutual Fund, Nasdaq OTCBB

OtcMarketTier

Value Code Description
OTCQX QX Best Market
OTCQB QB Venture Market
PINK_CURRENT PC Pink Current Information
EXPERT_MARKET EM Expert Market

Other Response Enums

Enum Values Context
QuoteType NBBO Quote type in equity/ETF quotes
OptionContractChar C, P Contract type in option reference
OptionSettlementType P (PM), A (AM) Settlement type
OptionExpirationType S (Standard), W (Weekly), Q (Quarterly), M (Mini), R (Reduced Value) UV expiration type
DividendFrequency 0 (None), 1 (Annual), 2 (Semi-Annual), 4 (Quarterly), 12 (Monthly) divFreq in fundamentals
FundStrategy A (Active), P (Passive) ETF fund strategy
MoverDirection up, down Direction in movers response

Orders — Enums

OrderType

Order type for placing and querying orders.

MARKET, LIMIT, STOP, STOP_LIMIT, TRAILING_STOP, CABINET, NON_MARKETABLE, MARKET_ON_CLOSE, EXERCISE, TRAILING_STOP_LIMIT, NET_DEBIT, NET_CREDIT, NET_ZERO, LIMIT_ON_CLOSE

Duration

Order duration / time-in-force.

Value Description
DAY Day order
GOOD_TILL_CANCEL GTC
FILL_OR_KILL FOK
IMMEDIATE_OR_CANCEL IOC
END_OF_WEEK End of week
END_OF_MONTH End of month
NEXT_END_OF_MONTH Next end of month

Session

Trading session for orders.

Value Description
NORMAL Regular trading hours
AM Pre-market
PM After-hours
SEAMLESS Extended hours (all sessions)

OrderStatus

Order status values for filtering and responses.

AWAITING_PARENT_ORDER, AWAITING_CONDITION, AWAITING_STOP_CONDITION, AWAITING_MANUAL_REVIEW, ACCEPTED, AWAITING_UR_OUT, PENDING_ACTIVATION, QUEUED, WORKING, REJECTED, PENDING_CANCEL, CANCELED, PENDING_REPLACE, REPLACED, FILLED, EXPIRED, NEW, AWAITING_RELEASE_TIME, PENDING_ACKNOWLEDGEMENT, PENDING_RECALL, UNKNOWN

EquityInstruction

Instruction for equity order legs.

Value Description
BUY Buy long
SELL Sell long position
SELL_SHORT Short sell
BUY_TO_COVER Cover short position

OptionInstruction

Instruction for option order legs.

Value Description
BUY_TO_OPEN Open new long position
SELL_TO_CLOSE Close existing long position
SELL_TO_OPEN Open new short position
BUY_TO_CLOSE Close existing short position

AssetType

Asset type for order placement (instrument.assetType).

EQUITY, OPTION

OrderStrategyType

Order strategy type.

Value Description
SINGLE Single order
OCO One-cancels-other
TRIGGER Triggered (bracket) order
CANCEL Cancel order
RECALL Recall order
PAIR Pair trade
FLATTEN Flatten position
TWO_DAY_SWAP Two-day swap
BLAST_ALL Blast all

ComplexOrderStrategyType

Complex strategy type for multi-leg orders.

NONE, COVERED, VERTICAL, BACK_RATIO, CALENDAR, DIAGONAL, STRADDLE, STRANGLE, COLLAR_SYNTHETIC, BUTTERFLY, CONDOR, IRON_CONDOR, VERTICAL_ROLL, COLLAR_WITH_STOCK, DOUBLE_DIAGONAL, UNBALANCED_BUTTERFLY, UNBALANCED_VERTICAL_ROLL, UNBALANCED_CONDOR, CUSTOM

Other Order Enums

Enum Values Context
SpecialInstruction ALL_OR_NONE, DO_NOT_REDUCE, ALL_OR_NONE_DO_NOT_REDUCE Special order instructions
RequestedDestination INET, ECN_ARCA, CBOE, AMEX, PHLX, ISE, BOX, NASDAQ, BATS, C2, AUTO Order routing
PriceLinkBasis MANUAL, BASE, TRIGGER, LAST, BID, ASK, ASK_BID, MARK, AVERAGE Stop/limit price basis
PriceLinkType VALUE, PERCENT, TICK Trailing stop type
StopType STANDARD, BID, ASK, LAST, MARK Stop price type
TaxLotMethod FIFO, LIFO, HIGH_COST, LOW_COST, AVERAGE_COST, SPECIFIC_LOT, LOSS_HARVESTER Tax lot selection
OrderLegType EQUITY, OPTION, INDEX, MUTUAL_FUND, CASH_EQUIVALENT, FIXED_INCOME, CURRENCY Leg asset type
PositionEffect OPENING, CLOSING, AUTOMATIC Option position effect
QuantityType ALL_SHARES, DOLLARS, SHARES Quantity type
DivCapGains REINVEST, PAYOUT Dividend reinvestment
ActivityType EXECUTION, ORDER_ACTION Order activity type
ExecutionType FILL Execution type
AdvancedOrderType NONE Preview orders
SettlementInstruction REGULAR Settlement type
OrderValidationSeverity ACCEPT Validation severity
CommissionFeeType COMMISSION Commission/fee type

Accounts — Enums

AccountField

Additional fields for account queries.

Value Description
POSITIONS "positions" — include positions in response

TransactionType

Transaction types for filtering.

TRADE, RECEIVE_AND_DELIVER, DIVIDEND_OR_INTEREST, ACH_RECEIPT, ACH_DISBURSEMENT, CASH_RECEIPT, CASH_DISBURSEMENT, ELECTRONIC_FUND, WIRE_OUT, WIRE_IN, JOURNAL, MEMORANDUM, MARGIN_CALL, MONEY_MARKET, SMA_ADJUSTMENT

AccountInstrumentType

Instrument type in account position responses.

SWEEP_VEHICLE, CASH_EQUIVALENT, EQUITY, OPTION, MUTUAL_FUND, FIXED_INCOME, INDEX, CURRENCY, COLLECTIVE_INVESTMENT

Other Account Enums

Enum Values Context
TransactionStatus VALID Transaction status
TransactionSubAccount CASH Sub-account type
TransactionActivityType ACTIVITY_CORRECTION Transaction activity type
UserType ADVISOR_USER User type in transactions

Streaming — Enums

StreamService

WebSocket streaming service names.

ADMIN, LEVELONE_EQUITIES, LEVELONE_OPTIONS, LEVELONE_FUTURES, LEVELONE_FUTURES_OPTIONS, LEVELONE_FOREX, NASDAQ_BOOK, NYSE_BOOK, OPTIONS_BOOK, CHART_EQUITY, CHART_FUTURES, SCREENER_EQUITY, SCREENER_OPTION, ACCT_ACTIVITY

StreamCommand

WebSocket streaming commands.

Value Description
LOGIN Authenticate the stream
LOGOUT Close the stream session
SUBS Subscribe (replaces existing keys)
UNSUBS Unsubscribe keys
ADD Add keys (appends to existing)
VIEW Change fields for a service

StreamResponseCode (IntEnum)

See the full response code table in the Streaming section above.


Advanced Troubleshooting

  • notify.code=12 (Only one connection): close other active WebSocket sessions.
  • response.content.code=3 (Login denied): invalid/expired token → client.login().
  • response.content.code=21 (Bad command formatting): check Authorization format (without Bearer) and keys (spacing for options, uppercase).
  • Persistent REST 401: delete schwab_tokens.json (or clear your DB tokens if using persist=False) and re-run client.login().
  • High latency/lost frames: avoid parallel reconnects; use the SDK's auto-resubscription.

Contributions

Your contributions are welcome! Ideas, issues, and PRs help improve the SDK:

  • Open an issue with clear details (environment, steps, expected/actual error).
  • Propose endpoint coverage improvements and examples.
  • Follow a clear style and add tests or minimal examples when possible.

If you want to hold working sessions or discuss the roadmap, open an issue labeled discussion.

Disclaimer

This project is unofficial and is not affiliated with, sponsored by, or endorsed by Charles Schwab & Co., Inc. "Schwab" and other trademarks are the property of their respective owners. Use of this SDK is subject to the terms and conditions of Schwab APIs and applicable regulations. Use at your own discretion and responsibility.


License

MIT (LICENSE)

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

schwab_sdk_unofficial-0.3.2.tar.gz (120.6 kB view details)

Uploaded Source

Built Distribution

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

schwab_sdk_unofficial-0.3.2-py3-none-any.whl (82.0 kB view details)

Uploaded Python 3

File details

Details for the file schwab_sdk_unofficial-0.3.2.tar.gz.

File metadata

  • Download URL: schwab_sdk_unofficial-0.3.2.tar.gz
  • Upload date:
  • Size: 120.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for schwab_sdk_unofficial-0.3.2.tar.gz
Algorithm Hash digest
SHA256 f3e5fec9eb0e54ede566531f6ed80b507931943cc2dfe831f83343ee552cfa5f
MD5 24c25660493314932fd3cc2fce0b14d9
BLAKE2b-256 85bf44d3dec798550c238799762335a7474ed9788fdd25a66f3962866c2f4bf4

See more details on using hashes here.

File details

Details for the file schwab_sdk_unofficial-0.3.2-py3-none-any.whl.

File metadata

File hashes

Hashes for schwab_sdk_unofficial-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2b196bc060aa02bf8e70f284f372e232751af88d9a4774a3c78905faad17be9c
MD5 e251f919e504d5b18fb6122895d38be3
BLAKE2b-256 1f446f8c3b51d4a48d2996ed8f98fd53a32f8c7256346998a1802e0714173eb3

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