Streaming Client
A wrapper around the Schwab streaming data API. This API is a websockets-based streaming API that provides to up-to-the-second data on market activity. Most impressively, it provides realtime data, including Level Two and time of sale data for major equities, options, and futures exchanges.
Here’s an example of how you can receive book snapshots of GOOG (note if you
run this outside regular trading hours you may not see anything):
from schwab.auth import easy_client
from schwab.client import Client
from schwab.streaming import StreamClient
import asyncio
import json
# Assumes you've already created a token. See the authentication page for more
# information.
client = easy_client(
api_key='YOUR_API_KEY',
app_secret='YOUR_APP_SECRET',
callback_url='https://127.0.0.1',
token_path='/path/to/token.json')
stream_client = StreamClient(client, account_id=1234567890)
async def read_stream():
await stream_client.login()
def print_message(message):
print(json.dumps(message, indent=4))
# Always add handlers before subscribing because many streams start sending
# data immediately after success, and messages with no handlers are dropped.
stream_client.add_nasdaq_book_handler(print_message)
await stream_client.nasdaq_book_subs(['GOOG'])
while True:
await stream_client.handle_message()
asyncio.run(read_stream())
Use Overview
The example above demonstrates the end-to-end workflow for using schwab.stream.
There’s more in there than meets the eye, so let’s dive into the details.
Logging In
Before we can perform any stream operations, the client must be logged in to the stream. Unlike the HTTP client, in which every request is authenticated using a token, this client sends unauthenticated requests and instead authenticates the entire stream. As a result, this login process is distinct from the token generation step that’s used in the HTTP client.
Stream login is accomplished simply by calling StreamClient.login(). Once
this happens successfully, all stream operations can be performed. Attemping to
perform operations that require login before this function is called raises an
exception.
- async StreamClient.login(websocket_connect_args=None)
-
- Performs initial stream setup:
Fetches streaming information from the HTTP client’s
get_user_principals()methodInitializes the socket
Builds and sends and authentication request
Waits for response indicating login success
All stream operations are available after this method completes.
- Parameters:
websocket_connect_args –
dictof additional arguments to pass to the websocketconnectcall. Useful for setting timeouts and other connection parameters. See the official documentation for details.
Logging Out
For a clean exit, it’s recommended to log out of the stream when you’re done.
Subscribing to Streams
These functions have names that follow the pattern SERVICE_NAME_subs. These
functions send a request to enable streaming data for a particular data stream.
They are not thread safe, so they should only be called in series.
When subscriptions are called multiple times on the same stream, the results vary. What’s more, these results aren’t documented in the official documentation. As a result, it’s recommended not to call a subscription function more than once for any given stream.
Some services, notably Equity Charts and Futures Charts,
offer SERVICE_NAME_add functions which can be used to add symbols to the
stream after the subscription has been created. For others, calling the
subscription methods again seems to clear the old subscription and create a new
one. Note this behavior is not officially documented, so this interpretation may
be incorrect.
Add symbols to Streams
These functions have names that follow the pattern SERVICE_NAME_add.
These functions send a request to add to the list of subscribed symbols for a
particular data stream.
Un-Subscribing to Streams
These functions have names that follow the pattern SERVICE_NAME_unsubs.
These functions send a request to disable the symbols of a streaming data for a
particular data stream. They are not thread safe, so they should only be
called in series. When unsubscribing to services with symbols, symbols which
were not explicitly unsubscribed remain subscribed.
Registering Handlers
By themselves, the subscription functions outlined above do nothing except cause
messages to be sent to the client. The add_SERVICE_NAME_handler functions
register functions that will receive these messages when they arrive. When
messages arrive, these handlers will be called serially. There is no limit to
the number of handlers that can be registered to a service.
Handling Messages
Once the stream client is properly logged in, subscribed to streams, and has
handlers registered, we can start handling messages. This is done simply by
awaiting on the handle_message() function. This function reads a single
message and dispatches it to the appropriate handler or handlers.
If a message is received for which no handler is registered, that message is ignored.
Handlers should take a single argument representing the stream message received:
import json
def sample_handler(msg):
print(json.dumps(msg, indent=4))
Data Field Relabeling
Under the hood, this API returns JSON objects with numerical key representing labels:
{
"service": "CHART_EQUITY",
"timestamp": 1715908546054,
"command": "SUBS",
"content": [{
"seq": 0,
"key": "MSFT",
"1": 779,
"2": 421.65,
"3": 421.79,
"4": 421.65,
"5": 421.755,
"6": 26.0,
"7": 1715903940000,
"8": 19859
}]
}
These labels are tricky to decode, and require a knowledge of the documentation
to decode properly. schwab-api makes your life easier by doing this decoding
for you, replacing numerical labels with strings proposed by the community For
instance, the message above would be relabeled as:
{
"service": "CHART_EQUITY",
"timestamp": 1715908546054,
"command": "SUBS",
"content": [{
"seq": 0,
"key": "MSFT",
"SEQUENCE": 779,
"OPEN_PRICE": 421.65,
"HIGH_PRICE": 421.79,
"LOW_PRICE": 421.65,
"CLOSE_PRICE": 421.755,
"VOLUME": 26.0,
"CHART_TIME_MILLIS": 1715903940000,
"CHART_DAY": 19859
}]
}
This documentation describes the various fields and their numerical values. You
can find them by investigating the various enum classes ending in ***Fields.
Some streams, such as the ones described in Level One Quotes, allow you to
specify a subset of fields to be returned. Subscription handlers for these
services take a list of the appropriate field enums the extra fields
parameter. If nothing is passed to this parameter, all supported fields are
requested.
Stream Statuses
Schwab’s streaming functionality is very similar to that of the former TDAmeritrade. So similar, in fact, that this module is largely a direct adaptation of the implementation developed for the older tda-api library.
As a result of this nearly direct copy-pasting, some streams may have been
carried over which don’t actually work. What’s more, some streams never
worked, even in tda-api, but were only implemented because some old,
now-defunct documentation referred to them.
The community is in the process of making sense of this new world. You are encouraged to try and use this streaming library and report what you find back to our Discord server. We’ll be updating this page as we discover new things.
- The following streams are confirmed working:
OHLCV Charts
These streams summarize trading activity on a minute-by-minute basis for equities and futures, providing OHLCV (Open/High/Low/Close/Volume) data.
Equity Charts
Minute-by-minute OHLCV data for equities.
- async StreamClient.chart_equity_subs(symbols)
-
Subscribe to equity charts. Behavior is undefined if called multiple times.
- Parameters:
symbols – Equity symbols to subscribe to.
- async StreamClient.chart_equity_unsubs(symbols)
-
Un-Subscribe to equity charts. Behavior is undefined if called multiple times.
- Parameters:
symbols – Equity symbols to subscribe to.
- async StreamClient.chart_equity_add(symbols)
-
Add a symbol to the equity charts subscription. Behavior is undefined if called before
chart_equity_subs().- Parameters:
symbols – Equity symbols to add to the subscription.
- StreamClient.add_chart_equity_handler(handler)
Adds a handler to the equity chart subscription. See Handling Messages for details.
- class StreamClient.ChartEquityFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
Data fields for equity OHLCV data. Primarily an implementation detail and not used in client code. Provided here as documentation for key values stored returned in the stream messages.
- SYMBOL = 0
Ticker symbol
- SEQUENCE = 1
Sequence number
- OPEN_PRICE = 2
Today’s open price
- HIGH_PRICE = 3
Today’s high price
- LOW_PRICE = 4
Today’s low price
- CLOSE_PRICE = 5
Previous day’s close price
- VOLUME = 6
Today’s trading volume
- CHART_TIME_MILLIS = 7
Chart timestamp
- CHART_DAY = 8
Chart day
Futures Charts
Minute-by-minute OHLCV data for futures.
- async StreamClient.chart_futures_subs(symbols)
-
Subscribe to futures charts. Behavior is undefined if called multiple times.
- Parameters:
symbols – Futures symbols to subscribe to.
- async StreamClient.chart_futures_unsubs(symbols)
-
Un-Subscribe to futures charts. Behavior is undefined if called multiple times.
- Parameters:
symbols – Futures symbols to subscribe to.
- async StreamClient.chart_futures_add(symbols)
-
Add a symbol to the futures chart subscription. Behavior is undefined if called before
chart_futures_subs().- Parameters:
symbols – Futures symbols to add to the subscription.
- StreamClient.add_chart_futures_handler(handler)
Adds a handler to the futures chart subscription. See Handling Messages for details.
- class StreamClient.ChartFuturesFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
Data fields for equity OHLCV data. Primarily an implementation detail and not used in client code. Provided here as documentation for key values stored returned in the stream messages.
- SYMBOL = 0
Ticker symbol in upper case.
- CHART_TIME_MILLIS = 1
Milliseconds since Epoch
- OPEN_PRICE = 2
Opening price for the minute
- HIGH_PRICE = 3
Highest price for the minute
- LOW_PRICE = 4
Chart’s lowest price for the minute
- CLOSE_PRICE = 5
Closing price for the minute
- VOLUME = 6
Total volume for the minute
Level One Quotes
Level one quotes provide an up-to-date view of bid/ask/volume data. In particular they list the best available bid and ask prices, together with the requested volume of each. They are updated live as market conditions change.
Equities Quotes
Level one quotes for equities traded on NYSE, AMEX, and PACIFIC.
- async StreamClient.level_one_equity_subs(symbols, *, fields=None)
-
Subscribe to level one equity quote data.
- Parameters:
symbols – Equity symbols to receive quotes for
fields – Iterable of
LevelOneEquityFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- async StreamClient.level_one_equity_unsubs(symbols)
-
Un-Subscribe to level one equity quote data.
- Parameters:
symbols – Equity symbols to receive quotes for
- async StreamClient.level_one_equity_add(symbols, *, fields=None)
-
Add symbols to the list to receive quotes for.
- Parameters:
symbols – Equity symbols to receive quotes for
fields – Iterable of
LevelOneEquityFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- StreamClient.add_level_one_equity_handler(handler)
Register a function to handle level one equity quotes as they are sent. See Handling Messages for details.
- class StreamClient.LevelOneEquityFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
Fields for equity quotes.
- SYMBOL = 0
Ticker symbol
- BID_PRICE = 1
Bid price
- ASK_PRICE = 2
Ask price
- LAST_PRICE = 3
Last trade price
- BID_SIZE = 4
Size of the highest bid
- ASK_SIZE = 5
Size of the lowest ask
- ASK_ID = 6
Exchange ID of the lowest ask
- BID_ID = 7
Exchange ID of the highest bid
- TOTAL_VOLUME = 8
Total volume trade to date
- LAST_SIZE = 9
Size of the last trade
- HIGH_PRICE = 10
Daily high price
- LOW_PRICE = 11
Daily low price
- CLOSE_PRICE = 12
Previous close price
- EXCHANGE_ID = 13
Exchange ID
- MARGINABLE = 14
Is this equity marginable?
- DESCRIPTION = 15
Description
- LAST_ID = 16
Exchange ID of the last trade
- OPEN_PRICE = 17
Today’s open price
- NET_CHANGE = 18
Net change
- HIGH_PRICE_52_WEEK = 19
52 week high price
- LOW_PRICE_52_WEEK = 20
52 week low price
- PE_RATIO = 21
P/E ratio
- DIVIDEND_AMOUNT = 22
Dividend amount
- DIVIDEND_YIELD = 23
Dividend yield
- NAV = 24
ETF net asset value
- EXCHANGE_NAME = 25
Exchange name
- DIVIDEND_DATE = 26
Dividend date
- REGULAR_MARKET_QUOTE = 27
Is this a regular market quote?
- REGULAR_MARKET_TRADE = 28
Is this a regular market trade?
- REGULAR_MARKET_LAST_PRICE = 29
Regular market last price
- REGULAR_MARKET_LAST_SIZE = 30
Regular market last size
- REGULAR_MARKET_NET_CHANGE = 31
Regular market net change
- SECURITY_STATUS = 32
Security status
- MARK = 33
Mark
- QUOTE_TIME_MILLIS = 34
Quote time in milliseconds
- TRADE_TIME_MILLIS = 35
Last trade time in milliseconds
- REGULAR_MARKET_TRADE_MILLIS = 36
Regular market trade time in milliseconds
- BID_TIME_MILLIS = 37
Bid time in millis
- ASK_TIME_MILLIS = 38
Ask time in millis
- ASK_MIC_ID = 39
Ask MIC ID
- BID_MIC_ID = 40
Bid MIC ID
- LAST_MIC_ID = 41
Last trade MIC ID
- NET_CHANGE_PERCENT = 42
Net change in percent
- REGULAR_MARKET_CHANGE_PERCENT = 43
Regular market change in percent
- MARK_CHANGE = 44
Mark change
- MARK_CHANGE_PERCENT = 45
Mark change in percent
- HTB_QUANTITY = 46
HTB quantity
- HTB_RATE = 47
HTB rate
- HARD_TO_BORROW = 48
Is this equity hard to borrow?
- IS_SHORTABLE = 49
Is this equity shortable
- POST_MARKET_NET_CHANGE = 50
Post market net change
- POST_MARKET_NET_CHANGE_PERCENT = 51
Post market net change percent
Options Quotes
Level one quotes for options. Note you can use
Client.get_option_chain() to fetch
available option symbols.
- async StreamClient.level_one_option_subs(symbols, *, fields=None)
-
Subscribe to level one option quote data.
- Parameters:
symbols – Option symbols to receive quotes for
fields – Iterable of
LevelOneOptionFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- async StreamClient.level_one_option_unsubs(symbols)
-
Un-Subscribe to level one option quote data.
- Parameters:
symbols – Option symbols to receive quotes for
- async StreamClient.level_one_option_add(symbols, *, fields=None)
-
Add symbols to the list to receive quotes for.
- Parameters:
symbols – Option symbols to add to list to receive quotes for
fields – Iterable of
LevelOneOptionFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- StreamClient.add_level_one_option_handler(handler)
Register a function to handle level one options quotes as they are sent. See Handling Messages for details.
- class StreamClient.LevelOneOptionFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
- SYMBOL = 0
Option symbol
- DESCRIPTION = 1
Description
- BID_PRICE = 2
Highest bid price
- ASK_PRICE = 3
Lowest ask price
- LAST_PRICE = 4
Last trade price
- HIGH_PRICE = 5
Today’s high price
- LOW_PRICE = 6
Today’s low price
- CLOSE_PRICE = 7
Last close price
- TOTAL_VOLUME = 8
Today’s total volume
- OPEN_INTEREST = 9
Open interest
- VOLATILITY = 10
Volatility
- MONEY_INTRINSIC_VALUE = 11
Money intrinsic value
- EXPIRATION_YEAR = 12
Expiration year
- MULTIPLIER = 13
Multiplier
- DIGITS = 14
Digits
- OPEN_PRICE = 15
Open price
- BID_SIZE = 16
Highest bid size
- ASK_SIZE = 17
Lowest ask size
- LAST_SIZE = 18
Last trade size
- NET_CHANGE = 19
Net change
- STRIKE_TYPE = 20
Strike type
- CONTRACT_TYPE = 21
Contract type
- UNDERLYING = 22
Underlying symbol
- EXPIRATION_MONTH = 23
Expiration month
- DELIVERABLES = 24
Deliverables
- TIME_VALUE = 25
Time value
- EXPIRATION_DAY = 26
Expiration day
- DAYS_TO_EXPIRATION = 27
Days to expiration
- DELTA = 28
Delta
- GAMMA = 29
Gamma
- THETA = 30
Theta
- VEGA = 31
Vega
- RHO = 32
Rho
- SECURITY_STATUS = 33
Security status
- THEORETICAL_OPTION_VALUE = 34
Theoretical option value
- UNDERLYING_PRICE = 35
Underlying price
- UV_EXPIRATION_TYPE = 36
UV expiration type
- MARK = 37
Mark
- QUOTE_TIME_MILLIS = 38
Quote time in millis
- TRADE_TIME_MILLIS = 39
Last trade time in millis
- EXCHANGE_ID = 40
Exchange ID
- EXCHANGE_NAME = 41
Exchange name
- LAST_TRADING_DAY = 42
Last trading day
- SETTLEMENT_TYPE = 43
Settlement type
- NET_PERCENT_CHANGE = 44
Net percent change
- MARK_CHANGE = 45
Mark change
- MARK_CHANGE_PERCENT = 46
Mark change in percent
- IMPLIED_YIELD = 47
Implied yield
- IS_PENNY = 48
Is penny stock?
- OPTION_ROOT = 49
Option root
- HIGH_PRICE_52_WEEK = 50
52 week high price
- LOW_PRICE_52_WEEK = 51
52 week low price
- INDICATIVE_ASKING_PRICE = 52
Indicative asking price
- INDICATIVE_BID_PRICE = 53
Indicative bid price
- INDICATIVE_QUOTE_TIME = 54
Indicative quote time
- EXERCISE_TYPE = 55
Exercise type
Futures Quotes
Level one quotes for futures.
- async StreamClient.level_one_futures_subs(symbols, *, fields=None)
-
Subscribe to level one futures quote data.
- Parameters:
symbols – Futures symbols to receive quotes for
fields – Iterable of
LevelOneFuturesFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- async StreamClient.level_one_futures_unsubs(symbols)
-
Un-Subscribe to level one futures quote data.
- Parameters:
symbols – Futures symbols to receive quotes for
- async StreamClient.level_one_futures_add(symbols, *, fields=None)
-
Add symbols to the list to receive quotes for.
- Parameters:
symbols – Futures symbols to add to the list to receive quotes for
fields – Iterable of
LevelOneFuturesFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- StreamClient.add_level_one_futures_handler(handler)
Register a function to handle level one futures quotes as they are sent. See Handling Messages for details.
- class StreamClient.LevelOneFuturesFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
- SYMBOL = 0
Ticker symbol in upper case.
- BID_PRICE = 1
Current Best Bid Price
- ASK_PRICE = 2
Current Best Ask Price
- LAST_PRICE = 3
Price at which the last trade was matched
- BID_SIZE = 4
Number of contracts for bid
- ASK_SIZE = 5
Number of contracts for ask
- BID_ID = 6
Exchange with the best bid
- ASK_ID = 7
Exchange with the best ask
- TOTAL_VOLUME = 8
Aggregated contracts traded throughout the day, including pre/post market hours.
- LAST_SIZE = 9
Number of contracts traded with last trade
- QUOTE_TIME_MILLIS = 10
Time of the last quote in milliseconds since epoch
- TRADE_TIME_MILLIS = 11
Time of the last trade in milliseconds since epoch
- HIGH_PRICE = 12
Day’s high trade price
- LOW_PRICE = 13
Day’s low trade price
- CLOSE_PRICE = 14
Previous day’s closing price
- EXCHANGE_ID = 15
Primary “listing” Exchange
- DESCRIPTION = 16
Description of the product
- LAST_ID = 17
Exchange where last trade was executed
- OPEN_PRICE = 18
Day’s Open Price
- NET_CHANGE = 19
Current Last-Prev Close
- FUTURE_CHANGE_PERCENT = 20
Current percent change
- EXCHANGE_NAME = 21
Name of exchange
- SECURITY_STATUS = 22
Trading status of the symbol
- OPEN_INTEREST = 23
The total number of futures contracts that are not closed or delivered on a particular day
- MARK = 24
Mark-to-Market value is calculated daily using current prices to determine profit/loss
- TICK = 25
Minimum price movement
- TICK_AMOUNT = 26
Minimum amount that the price of the market can change
- PRODUCT = 27
Futures product
- FUTURE_PRICE_FORMAT = 28
Display in fraction or decimal format.
- FUTURE_TRADING_HOURS = 29
Trading hours
- FUTURE_IS_TRADABLE = 30
Flag to indicate if this future contract is tradable
- FUTURE_MULTIPLIER = 31
Point value
- FUTURE_IS_ACTIVE = 32
Indicates if this contract is active
- FUTURE_SETTLEMENT_PRICE = 33
Closing price
- FUTURE_ACTIVE_SYMBOL = 34
Symbol of the active contract
- FUTURE_EXPIRATION_DATE = 35
Expiration date of this contract
- EXPIRATION_STYLE = 36
Expiration Style
- ASK_TIME_MILLIS = 37
Time of the last ask-side quote in milliseconds since epoch
- BID_TIME_MILLIS = 38
Time of the last bid-side quote in milliseconds since epoch
- QUOTED_IN_SESSION = 39
Indicates if this contract has quoted during the active session
- SETTLEMENT_DATE = 40
Expiration date of this contract
Futures Options Quotes
Level one quotes for futures options.
- async StreamClient.level_one_futures_options_subs(symbols, *, fields=None)
-
Subscribe to level one futures options quote data.
- Parameters:
symbols – Futures options symbols to receive quotes for
fields – Iterable of
LevelOneFuturesOptionsFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- async StreamClient.level_one_futures_options_unsubs(symbols)
-
Un-Subscribe to level one futures options quote data.
- Parameters:
symbols – Futures options symbols to receive quotes for
- async StreamClient.level_one_futures_options_add(symbols, *, fields=None)
-
Add symbols to the list to receive quotes for.
- Parameters:
symbols – Futures options symbols add to list to receive quotes for
fields – Iterable of
LevelOneFuturesOptionsFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- StreamClient.add_level_one_futures_options_handler(handler)
Register a function to handle level one futures options quotes as they are sent. See Handling Messages for details.
- class StreamClient.LevelOneFuturesOptionsFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
- SYMBOL = 0
Ticker symbol in upper case.
- BID_PRICE = 1
Current Bid Price
- ASK_PRICE = 2
Current Ask Price
- LAST_PRICE = 3
Price at which the last trade was matched
- BID_SIZE = 4
Number of contracts for bid
- ASK_SIZE = 5
Number of contracts for ask
- BID_ID = 6
Exchange with the bid
- ASK_ID = 7
Exchange with the ask
- TOTAL_VOLUME = 8
Aggregated contracts traded throughout the day, including pre/post market hours.
- LAST_SIZE = 9
Number of contracts traded with last trade
- QUOTE_TIME_MILLIS = 10
Trade time of the last quote in milliseconds since epoch
- TRADE_TIME_MILLIS = 11
Trade time of the last trade in milliseconds since epoch
- HIGH_PRICE = 12
Day’s high trade price
- LOW_PRICE = 13
Day’s low trade price
- CLOSE_PRICE = 14
Previous day’s closing price
- LAST_ID = 15
Exchange where last trade was executed
- DESCRIPTION = 16
Description of the product
- OPEN_PRICE = 17
Day’s Open Price
- OPEN_INTEREST = 18
Open Interest
- MARK = 19
Mark-to-Market value is calculated daily using current prices to determine profit/loss
- TICK = 20
Minimum price movement
- TICK_AMOUNT = 21
Minimum amount that the price of the market can change
- FUTURE_MULTIPLIER = 22
Point value
- FUTURE_SETTLEMENT_PRICE = 23
Closing price
- UNDERLYING_SYMBOL = 24
Underlying symbol
- STRIKE_PRICE = 25
Strike Price
- FUTURE_EXPIRATION_DATE = 26
Expiration date of this contract
- EXPIRATION_STYLE = 27
Expiration Style
- CONTRACT_TYPE = 28
Contract Type
- SECURITY_STATUS = 29
Security Status
- EXCHANGE_ID = 30
Exchange character
- EXCHANGE_NAME = 31
Display name of exchange
Forex Quotes
Level one quotes for foreign exchange pairs.
- async StreamClient.level_one_forex_subs(symbols, *, fields=None)
-
Subscribe to level one forex quote data.
- Parameters:
symbols – Forex symbols to receive quotes for
fields – Iterable of
LevelOneForexFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- async StreamClient.level_one_forex_unsubs(symbols)
-
Un-Subscribe to level one forex quote data.
- Parameters:
symbols – Forex symbols to receive quotes for
- async StreamClient.level_one_forex_add(symbols, *, fields=None)
-
Add symbols to the list to receive quotes for.
- Parameters:
symbols – Forex symbols to add to list to receive quotes for
fields – Iterable of
LevelOneForexFieldsrepresenting the fields to return in streaming entries. If unset, all fields will be requested.
- StreamClient.add_level_one_forex_handler(handler)
Register a function to handle level one forex quotes as they are sent. See Handling Messages for details.
- class StreamClient.LevelOneForexFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
- SYMBOL = 0
Ticker symbol in upper case.
- BID_PRICE = 1
Current Bid Price
- ASK_PRICE = 2
Current Ask Price
- LAST_PRICE = 3
Price at which the last trade was matched
- BID_SIZE = 4
Number of currency pairs for bid
- ASK_SIZE = 5
Number of currency pairs for ask
- TOTAL_VOLUME = 6
Aggregated currency pairs traded throughout the day, including pre/post market hours.
- LAST_SIZE = 7
Number of currency pairs traded with last trade
- QUOTE_TIME_MILLIS = 8
Trade time of the last quote in milliseconds since epoch
- TRADE_TIME_MILLIS = 9
Trade time of the last trade in milliseconds since epoch
- HIGH_PRICE = 10
Day’s high trade price
- LOW_PRICE = 11
Day’s low trade price
- CLOSE_PRICE = 12
Previous day’s closing price
- EXCHANGE_ID = 13
Exchange Id
- DESCRIPTION = 14
Description of the product
- OPEN_PRICE = 15
Day’s Open Price
- NET_CHANGE = 16
Current Last-Prev Close
- CHANGE_PERCENT = 17
Current percent change
- EXCHANGE_NAME = 18
Name of exchange
- DIGITS = 19
Valid decimal points
- SECURITY_STATUS = 20
Trading status of the symbol
- TICK = 21
Minimum price movement
- TICK_AMOUNT = 22
Minimum amount that the price of the market can change
- PRODUCT = 23
Product name
- TRADING_HOURS = 24
Trading hours
- IS_TRADABLE = 25
Flag to indicate if this forex is tradable
- MARKET_MAKER = 26
Market Maker
- HIGH_PRICE_52_WEEK = 27
Highest price traded in the past 12 months, or 52 weeks
- LOW_PRICE_52_WEEK = 28
Lowest price traded in the past 12 months, or 52 weeks
- MARK = 29
Mark-to-Market value is calculated daily using current prices to determine profit/loss
Level Two Order Book
Level two streams provide a view on continuous order books of various securities. The level two order book describes the current bids and asks on the market, and these streams provide snapshots of that state.
Due to the lack of official documentation, these streams are largely reverse engineered. While the labeled data represents a best effort attempt to interpret stream fields, it’s possible that something is wrong or incorrectly labeled.
The documentation lists more book types than are implemented here. In
particular, it also lists FOREX_BOOK, FUTURES_BOOK, and
FUTURES_OPTIONS_BOOK as accessible streams. All experimentation has resulted
in these streams refusing to connect, typically returning errors about
unavailable services. Due to this behavior and the lack of official
documentation for book streams generally, schwab-api assumes these streams are not
actually implemented, and so excludes them. If you have any insight into using
them, please let us know.
Equities Order Books: NYSE and NASDAQ
schwab-api supports level two data for NYSE and NASDAQ, which are the two major
exchanges dealing in equities, ETFs, etc. Stocks are typically listed on one or
the other, and it is useful to learn about the differences between them:
You can identify on which exchange a symbol is listed by using
Client.search_instruments():
r = c.search_instruments(['GOOG'], projection=c.Instrument.Projection.FUNDAMENTAL)
assert r.status_code == httpx.codes.OK, r.raise_for_status()
print(r.json()['GOOG']['exchange']) # Outputs NASDAQ
However, many symbols have order books available on these streams even though this API call returns neither NYSE nor NASDAQ. The only sure-fire way to find out whether the order book is available is to attempt to subscribe and see what happens.
Note to preserve equivalence with what little documentation there is, the NYSE book is called “listed.” Testing indicates this stream corresponds to the NYSE book, but if you find any behavior that suggests otherwise please let us know.
- async StreamClient.nyse_book_subs(symbols)
Subscribe to the NYSE level two order book.
- Parameters:
symbols – NYSE symbols to subscribe to.
- async StreamClient.nyse_book_unsubs(symbols)
Un-Subscribe to the NYSE level two order book.
- Parameters:
symbols – NYSE symbols to unsubscribe from.
- async StreamClient.nyse_book_add(symbols)
Add to the NYSE level two order book.
- Parameters:
symbols – NYSE symbols to add to the subscription.
- StreamClient.add_nyse_book_handler(handler)
Register a function to handle level two NYSE book data as it is updated See Handling Messages for details.
- async StreamClient.nasdaq_book_subs(symbols)
Subscribe to the NASDAQ level two order book.
- Parameters:
symbols – NASDAQ symbols to subscribe to.
- async StreamClient.nasdaq_book_unsubs(symbols)
Un-Subscribe to the NASDAQ level two order book.
- Parameters:
symbols – NASDAQ symbols to unsubscribe from.
- async StreamClient.nasdaq_book_add(symbols)
Add to the NASDAQ level two order book.
- Parameters:
symbols – NASDAQ symbols to add to the subscription.
- StreamClient.add_nasdaq_book_handler(handler)
Register a function to handle level two NASDAQ book data as it is updated See Handling Messages for details.
Options Order Book
This stream provides the order book for options. It’s not entirely clear what exchange it aggregates from, but it’s been tested to work and deliver data. The leading hypothesis is that it is the order book for the Chicago Board of Exchange options exchanges, although this is an admittedly an uneducated guess.
- async StreamClient.options_book_subs(symbols)
Subscribe to the level two order book for options.
- Parameters:
symbols – Option symbols to subscribe to.
- async StreamClient.options_book_unsubs(symbols)
Un-Subscribe to the level two order book for options.
- Parameters:
symbols – Option symbols to unsubscribe from.
- async StreamClient.options_book_add(symbols)
Add to the level two order book for options.
- Parameters:
symbols – Option symbols to add to the subscription.
- StreamClient.add_options_book_handler(handler)
Register a function to handle level two options book data as it is updated See Handling Messages for details.
Screener
Top 10 advances and decliners by volume, trades, percent change and average percent volume.
Symbols in upper case and separated by commas.
- (PREFIX)_(SORTFIELD)_(FREQUENCY) where PREFIX is:
Indices: $COMPX $DJI, $SPX.X, INDEX_ALL
Exchanges: NYSE, NASDAQ, OTCBB, EQUITY_ALL
Option: OPTION_PUT, OPTION_CALL, OPTION_ALL
- and sortField is:
VOLUME, TRADES, PERCENT_CHANGE_UP, PERCENT_CHANGE_DOWN, AVERAGE_PERCENT_VOLUME
- and frequency is:
0, 1, 5, 10, 30 60 minutes (0 is for all day)
Both the equity and option screener streams use a common set of fields:
- class StreamClient.ScreenerFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
- SYMBOL = 0
The symbol used to look up either actives, gainers or losers
- TIMESTAMP = 1
Market snapshot timestamp in milliseconds since Epoch
- SORT_FIELD = 2
Field to sort on
- FREQUENCY = 3
Frequency of data to sort
- ITEMS = 4
Array of fields
Screener Equity
- async StreamClient.screener_equity_subs(symbols)
Subscribe to Screener Equity.
- Parameters:
symbols – Equity symbols to subscribe to.
- async StreamClient.screener_equity_unsubs(symbols)
Un-Subscribe to Screener Equity.
- Parameters:
symbols – Equity symbols to unsubscribe from.
- async StreamClient.screener_equity_add(symbols)
Add symbols to the Screener Equity list.
- Parameters:
symbols – Equity symbols to add to the subscription.
- StreamClient.add_screener_equity_handler(handler)
Register a function to handle Screener Equity data as it is updated See Handling Messages for details.
Screener Option
- async StreamClient.screener_option_subs(symbols)
Subscribe to Screener Option.
- Parameters:
symbols – Option symbols to subscribe to.
- async StreamClient.screener_option_unsubs(symbols)
Un-Subscribe to Screener Option.
- Parameters:
symbols – Option symbols to unsubscribe from.
- async StreamClient.screener_option_add(symbols)
Add symbols to the Screener Option list.
- Parameters:
symbols – Option symbols to add to the subscription.
- StreamClient.add_screener_option_handler(handler)
Register a function to handle Screener Option data as it is updated See Handling Messages for details.
Account Activity
- async StreamClient.account_activity_sub()
-
Subscribe to account activity for the account id associated with this streaming client. See
AccountActivityFieldsfor more info.
- async StreamClient.account_activity_unsubs()
-
Un-Subscribe to account activity for the account id associated with this streaming client. See
AccountActivityFieldsfor more info.
- StreamClient.add_account_activity_handler(handler)
Adds a handler to the account activity subscription. See Handling Messages for details.
- class StreamClient.AccountActivityFields(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
-
Data fields for equity account activity. Primarily an implementation detail and not used in client code. Provided here as documentation for key values stored returned in the stream messages.
- SUBSCRIPTION_KEY = 0
Passed back to the client from the request to identify a subscription this response belongs to.
- ACCOUNT = 1
Account Number that the activity occurred on.
- MESSAGE_TYPE = 2
Message Type that dictates the format of the Message Data field.
- MESSAGE_DATA = 3
The core data for the message. Either JSON-formatted data describing the update, NULL in some cases, or plain text in case of ERROR.