Order Templates
schwab-py
strives to be easy to use. This means making it easy to do simple
things, while making it possible to do complicated things. Order construction is
a major challenge to this mission: both simple and complicated orders use the
same format, meaning simple orders require a surprising amount of sophistication
to place.
We get around this by providing templates that make it easy to place common orders, while allowing advanced users to modify the orders returned from the templates to create more complex ones. Very advanced users can even create their own orders from scratch. This page describes the simple templates, while the OrderBuilder Reference page documents the order builder in all its complexity.
Using These Templates
These templates serve two purposes. First, they are designed to choose defaults so you can immediately place them. These defaults are:
All orders execute during the current normal trading session. If placed outside of trading hours, the execute during the next normal trading session.
Time-in-force is set to
DAY
.All other fields (such as requested destination, etc.) are left unset, meaning they receive default treatment from Schwab. Note this treatment depends on Schwab’s implementation, and may change without warning.
Secondly, they serve as starting points for building more complex order types.
All templates return a pre-populated OrderBuilder
object, meaning complex
functionality can be specified by modifying the returned object. For example,
here is how you would place an order to buy GOOG
for no more than $1250 at
any time in the next six months:
from schwab.orders.equities import equity_buy_limit
from schwab.orders.common import Duration, Session
client = ... # See "Authentication and Client Creation"
client.place_order(
1000, # account_id
equity_buy_limit('GOOG', 1, 1250.0)
.set_duration(Duration.GOOD_TILL_CANCEL)
.set_session(Session.SEAMLESS)
.build())
You can find a full reference for all supported fields in OrderBuilder Reference.
Equity Templates
Buy orders
- schwab.orders.equities.equity_buy_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for an equity buy market order.
- schwab.orders.equities.equity_buy_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for an equity buy limit order.
Sell orders
- schwab.orders.equities.equity_sell_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for an equity sell market order.
- schwab.orders.equities.equity_sell_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for an equity sell limit order.
Sell short orders
- schwab.orders.equities.equity_sell_short_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for an equity short sell market order.
- schwab.orders.equities.equity_sell_short_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for an equity short sell limit order.
Buy to cover orders
- schwab.orders.equities.equity_buy_to_cover_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for an equity buy-to-cover market order.
- schwab.orders.equities.equity_buy_to_cover_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for an equity buy-to-cover limit order.
Options Templates
Schwab supports over a dozen options strategies, each of which involve a precise
structure in the order builder. schwab-py
is slowly gaining support for
these strategies, and they are documented here as they become ready for use. As
time goes on, more templates will be added here.
In the meantime, you can construct all supported options orders using the OrderBuilder, although you will have to construct them yourself.
Note orders placed using these templates may be rejected, depending on the user’s options trading authorization.
Building Options Symbols
All templates require option symbols, which are somewhat more involved than equity symbols. They encode the underlying, the expiration date, option type (put or call) and the strike price. They are especially tricky to extract because both the Schwab UI and the thinkorswim UI don’t reveal the symbol in the option chain view.
Real trading symbols can be found by requesting the Option Chains. They
can also be built using the OptionSymbol
helper, which provides utilities
for creating options symbols. Note it only emits syntactically correct symbols
and does not validate whether the symbol actually represents a traded option:
from schwab.orders.options import OptionSymbol
symbol = OptionSymbol(
'TSLA', datetime.date(year=2020, month=11, day=20), 'P', '1360').build()
- class schwab.orders.options.OptionSymbol(underlying_symbol, expiration_date, contract_type, strike_price_as_string)
Construct an option symbol from its constituent parts.
- Parameters:
underlying_symbol – Symbol of the underlying. Not validated.
expiration_date – Expiration date. Accepts
datetime.date
,datetime.datetime
, or strings with the format[Two digit year][Two digit month][Two digit day]
.contract_type –
P
orPUT
for put andC
orCALL
for call.strike_price_as_string – Strike price represented as a decimal string.
Note while each of the individual parts is validated by itself, the option symbol itself may not represent a traded option:
Some underlyings do not support options.
Not all dates have valid option expiration dates.
Not all strike prices are valid options strikes.
You can use
get_option_chain()
to obtain real option symbols for an underlying, as well as extensive data in pricing, bid/ask spread, volume, etc.For those interested in the details, options symbols have the following format:
[Underlying left justified with spaces to 6 positions] [Two digit year][Two digit month][Two digit day]['P' or 'C'][Strike price]
- The format of the strike price is modified based on its amount:
If less than 1000, Strike Price is multiple by 1000 and pre-pended with two zeroes
If greater than 1000, it’s prepended with one zero.
- Examples include:
QQQ 240420P00500000
: QQQ Apr 20, 2024 500 Put (note the two zeroes in front because strike is less than 1000)SPXW 240420C05040000
: SPX Weekly Apr 20, 2024 5040 Call (note the one zero in front because strike is greater than 1000)
- OptionSymbol.build()
Returns the option symbol represented by this builder.
Single Options
Buy and sell single options.
- schwab.orders.options.option_buy_to_open_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for a buy-to-open market order.
- schwab.orders.options.option_buy_to_open_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for a buy-to-open limit order.
- schwab.orders.options.option_sell_to_open_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for a sell-to-open market order.
- schwab.orders.options.option_sell_to_open_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for a sell-to-open limit order.
- schwab.orders.options.option_buy_to_close_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for a buy-to-close market order.
- schwab.orders.options.option_buy_to_close_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for a buy-to-close limit order.
- schwab.orders.options.option_sell_to_close_market(symbol, quantity)
Returns a pre-filled
OrderBuilder
for a sell-to-close market order.
- schwab.orders.options.option_sell_to_close_limit(symbol, quantity, price)
Returns a pre-filled
OrderBuilder
for a sell-to-close limit order.
Vertical Spreads
Vertical spreads are a complex option strategy that provides both limited upside and limited downside. They are constructed by buying an option at one strike while simultaneously selling another option with the same underlying and expiration date, except with a different strike, and they can be constructed using either puts or call. You can find more information about this strategy on Investopedia
schwab-py
provides utilities for opening and closing vertical spreads in
various ways. It follows the standard (bull/bear) (put/call)
naming
convention, where the name specifies the market attitude and the option type
used in construction.
For consistency’s sake, the option with the smaller strike price is always passed first, followed by the higher strike option. You can find the option symbols by consulting the return value of the Option Chains client call.
Call Verticals
- schwab.orders.options.bull_call_vertical_open(long_call_symbol, short_call_symbol, quantity, net_debit)
Returns a pre-filled
OrderBuilder
that opens a bull call vertical position. See Vertical Spreads for details.
- schwab.orders.options.bull_call_vertical_close(long_call_symbol, short_call_symbol, quantity, net_credit)
Returns a pre-filled
OrderBuilder
that closes a bull call vertical position. See Vertical Spreads for details.
- schwab.orders.options.bear_call_vertical_open(short_call_symbol, long_call_symbol, quantity, net_credit)
Returns a pre-filled
OrderBuilder
that opens a bear call vertical position. See Vertical Spreads for details.
- schwab.orders.options.bear_call_vertical_close(short_call_symbol, long_call_symbol, quantity, net_debit)
Returns a pre-filled
OrderBuilder
that closes a bear call vertical position. See Vertical Spreads for details.
Put Verticals
- schwab.orders.options.bull_put_vertical_open(long_put_symbol, short_put_symbol, quantity, net_credit)
Returns a pre-filled
OrderBuilder
that opens a bull put vertical position. See Vertical Spreads for details.
- schwab.orders.options.bull_put_vertical_close(long_put_symbol, short_put_symbol, quantity, net_debit)
Returns a pre-filled
OrderBuilder
that closes a bull put vertical position. See Vertical Spreads for details.
- schwab.orders.options.bear_put_vertical_open(short_put_symbol, long_put_symbol, quantity, net_debit)
Returns a pre-filled
OrderBuilder
that opens a bear put vertical position. See Vertical Spreads for details.
- schwab.orders.options.bear_put_vertical_close(short_put_symbol, long_put_symbol, quantity, net_credit)
Returns a pre-filled
OrderBuilder
that closes a bear put vertical position. See Vertical Spreads for details.
Utility Methods
These methods return orders that represent complex multi-order strategies,
namely “one cancels other” and “first triggers second” strategies. Note they
expect all their parameters to be of type OrderBuilder
. You can construct
these orders using the templates above or by
creating them from scratch.
Note that you do not construct composite orders by placing the constituent orders and then passing the results to the utility methods:
order_one = c.place_order(config.account_id,
option_buy_to_open_limit(trade_symbol, contracts, safety_ask)
.set_duration(Duration.GOOD_TILL_CANCEL)
.set_session(Session.NORMAL)
.build())
order_two = c.place_order(config.account_id,
option_sell_to_close_limit(trade_symbol, half, double)
.set_duration(Duration.GOOD_TILL_CANCEL)
.set_session(Session.NORMAL)
.build())
# THIS IS BAD, DO NOT DO THIS
exec_trade = c.place_order(config.account_id, first_triggers_second(order_one, order_two))
What’s happening here is both constituent orders are being executed, and then
place_order
will fail. Creating an OrderBuilder
defers their execution,
subject to your composite order rules.
- schwab.orders.common.one_cancels_other(order1, order2)
If one of the orders is executed, immediately cancel the other.
- schwab.orders.common.first_triggers_second(first_order, second_order)
If
first_order
is executed, immediately placesecond_order
.