This API documentation is provided for informational purposes only. Before using this library, please read and understand our full disclaimer. By using this library, you acknowledge that trading involves substantial risk and that you are solely responsible for verifying and validating all trading operations.
- Installation
- Authentication
- Client Initialization
- Account Management
- Order Creation
- Order Management
- Order Monitoring
- Market Data
- Portfolio Management
- Paper Trading
- Streaming Data
- Batch Operations
- Error Handling
- Async Support
pip install schwab-tradergit clone https://github.com/ibouazizi/schwab-trader.git
cd schwab-trader
pip install -e .from schwab.auth import SchwabAuth
# Initialize auth handler
auth = SchwabAuth(
client_id="your_client_id",
client_secret="your_client_secret",
redirect_uri="https://localhost:8080/callback"
)
# Get authorization URL
auth_url = auth.get_authorization_url()
print(f"Please authorize at: {auth_url}")
# After user authorizes, exchange code for tokens
auth_code = "code_from_callback"
tokens = auth.exchange_code_for_tokens(auth_code)
# Tokens are automatically managed and refreshedfrom schwab import SchwabClient
# Initialize with auth object
client = SchwabClient(auth=auth)
# Or initialize with existing tokens
client = SchwabClient(
client_id="your_client_id",
client_secret="your_client_secret",
access_token="your_access_token",
refresh_token="your_refresh_token"
)from schwab import AsyncSchwabClient
# Initialize async client
async_client = AsyncSchwabClient(auth=auth)
# Use as context manager
async with async_client as client:
accounts = await client.get_account_numbers()accounts = client.get_account_numbers()# Get all accounts without positions
accounts = client.get_accounts()
# Get all accounts with positions
accounts = client.get_accounts(include_positions=True)account = client.get_account(
account_number="encrypted_account_number",
include_positions=True
)order = client.create_market_order(
symbol="AAPL",
quantity=100,
instruction=OrderInstruction.BUY,
description="APPLE INC"
)order = client.create_limit_order(
symbol="AAPL",
quantity=100,
limit_price=150.00,
instruction=OrderInstruction.BUY,
description="APPLE INC"
)order = client.create_stop_order(
symbol="AAPL",
quantity=100,
stop_price=140.00,
instruction=OrderInstruction.SELL,
description="APPLE INC"
)order = client.create_stop_limit_order(
symbol="AAPL",
quantity=100,
stop_price=140.00,
limit_price=138.00,
instruction=OrderInstruction.SELL,
description="APPLE INC"
)client.place_order(account_number="encrypted_account_number", order=order)order = client.get_order(
account_number="encrypted_account_number",
order_id=12345
)from datetime import datetime, timedelta
orders = client.get_orders(
account_number="encrypted_account_number",
from_date=datetime.now() - timedelta(days=7),
to_date=datetime.now(),
status="WORKING" # Optional status filter
)modified_order = client.modify_order_price(
account_number="encrypted_account_number",
order_id=12345,
new_price=155.00
)modified_order = client.modify_order_quantity(
account_number="encrypted_account_number",
order_id=12345,
new_quantity=200
)client.cancel_order(
account_number="encrypted_account_number",
order_id=12345
)from schwab.order_monitor import OrderMonitor
# Initialize order monitor
monitor = OrderMonitor(client)
# Define callbacks
def on_status_change(order, old_status, new_status):
print(f"Order {order.order_id}: {old_status} -> {new_status}")
def on_execution(order, execution):
print(f"Order {order.order_id} executed: {execution.quantity} @ ${execution.price}")
# Start monitoring
monitor.start_monitoring(
account_number="encrypted_account_number",
order_ids=[12345, 12346],
on_status_change=on_status_change,
on_execution=on_execution,
interval=1.0 # Poll every second
)
# Stop monitoring
monitor.stop_monitoring()# Single quote
quote = client.get_quote("AAPL")
# Multiple quotes
quotes = client.get_quotes(["AAPL", "MSFT", "GOOGL"])
# Access quote data
print(f"AAPL Price: ${quotes['AAPL'].quote.lastPrice}")
print(f"AAPL Volume: {quotes['AAPL'].quote.totalVolume}")options_chain = client.get_options_chain(
symbol="AAPL",
contract_type="ALL", # CALL, PUT, or ALL
strike_count=10,
include_quotes=True,
strategy="SINGLE",
interval=5.0,
strike=150.0,
range="ITM" # ITM, OTM, or ALL
)from schwab.portfolio import PortfolioManager
# Create portfolio manager
portfolio = PortfolioManager(client)
# Add accounts to track
portfolio.add_account("account1")
portfolio.add_account("account2")
# Refresh all positions
portfolio.refresh_positions()
# Get portfolio summary
summary = portfolio.get_portfolio_summary()
print(f"Total Value: ${summary['total_value']:,.2f}")
print(f"Total P&L: ${summary['total_pnl']:,.2f}")
# Get aggregated position
aapl_position = portfolio.get_position("AAPL")
if aapl_position:
print(f"Total AAPL shares: {aapl_position['total_quantity']}")
print(f"Average cost: ${aapl_position['average_cost']:,.2f}")
# Monitor portfolio orders
def on_portfolio_update(event_type, data):
print(f"Portfolio event: {event_type}")
portfolio.monitor_orders(callback=on_portfolio_update)# Save portfolio state
portfolio.save_state("portfolio_backup.json")
# Load portfolio state
portfolio.load_state("portfolio_backup.json")from schwab.paper_trading import PaperTradingClient
# Initialize paper trading client
paper_client = PaperTradingClient(auth=auth)
# Client automatically detects paper vs real accounts
# Visual indicators show when in paper trading mode
# Place a paper trade
order = paper_client.create_market_order(
symbol="AAPL",
quantity=100,
instruction="BUY"
)
result = paper_client.place_order("paper_account_id", order)
# Shows visual indicator: "[PAPER TRADING] Order placed..."from schwab.paper_trading.indicators import RSI, MovingAverage, MACD
# Calculate RSI
rsi = RSI(period=14)
rsi_values = rsi.calculate(price_data)
# Calculate Moving Average
ma = MovingAverage(period=20, ma_type="EMA")
ma_values = ma.calculate(price_data)
# Calculate MACD
macd = MACD(fast_period=12, slow_period=26, signal_period=9)
macd_line, signal_line, histogram = macd.calculate(price_data)from schwab.streaming import SchwabStreamer
# Initialize streamer
streamer = SchwabStreamer(client)
# Define callback for quote updates
def on_quote_update(data):
print(f"Quote update: {data}")
# Subscribe to real-time quotes
streamer.subscribe_quotes(
symbols=["AAPL", "MSFT"],
callback=on_quote_update
)
# Start streaming
streamer.start()
# Stop streaming
streamer.stop()# Subscribe to level 1 data
streamer.subscribe_level_one_equity(
symbols=["AAPL"],
fields=["BID_PRICE", "ASK_PRICE", "LAST_PRICE", "TOTAL_VOLUME"]
)
# Subscribe to options
streamer.subscribe_level_one_option(
symbols=["AAPL_012025C150"],
fields=["BID_PRICE", "ASK_PRICE", "IMPLIED_VOLATILITY"]
)
# Quality of Service
streamer.set_quality_of_service("EXPRESS") # REAL_TIME, FAST, MODERATE, EXPRESSresults = client.batch_cancel_orders(
account_number="encrypted_account_number",
order_ids=[12345, 12346, 12347]
)
# results is a dict mapping order_ids to success statusmodifications = [
{"order_id": 12345, "price": 155.00},
{"order_id": 12346, "quantity": 200},
{"order_id": 12347, "price": 160.00, "quantity": 150}
]
results = client.batch_modify_orders(
account_number="encrypted_account_number",
modifications=modifications
)
# results is a dict mapping order_ids to modified orders or exceptionsfrom schwab.models.order_validation import OrderValidationError
try:
modified_order = client.modify_order_price(
account_number="encrypted_account_number",
order_id=12345,
new_price=155.00
)
except OrderValidationError as e:
print(f"Order modification failed: {str(e)}")
print(f"Validation details: {e.validation_errors}")import requests
try:
order = client.get_order(
account_number="encrypted_account_number",
order_id=12345
)
except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e.response.status_code} - {e.response.text}")
except requests.exceptions.RequestException as e:
print(f"API request failed: {str(e)}")from schwab.auth import AuthenticationError
try:
tokens = auth.exchange_code_for_tokens(auth_code)
except AuthenticationError as e:
print(f"Authentication failed: {str(e)}")import asyncio
from schwab import AsyncSchwabClient
async def main():
async with AsyncSchwabClient(auth=auth) as client:
# Concurrent operations
accounts, quotes = await asyncio.gather(
client.get_accounts(include_positions=True),
client.get_quotes(["AAPL", "MSFT", "GOOGL"])
)
# Place order
order = client.create_limit_order(
symbol="AAPL",
quantity=100,
limit_price=150.00,
instruction="BUY"
)
result = await client.place_order(accounts[0].account_number, order)
print(f"Order placed: {result}")
# Run async function
asyncio.run(main())from schwab.paper_trading import AsyncPaperTradingClient
async def paper_trade():
async with AsyncPaperTradingClient(auth=auth) as client:
# All operations are async
accounts = await client.get_account_numbers()
# Paper trading with async support
order = client.create_market_order(
symbol="TSLA",
quantity=50,
instruction="BUY"
)
await client.place_order(accounts[0], order)WORKING: Order is active and workingPENDING_ACTIVATION: Order is pending activationPENDING_CANCEL: Order cancellation is pendingPENDING_REPLACE: Order replacement is pendingQUEUED: Order is queued for submissionREJECTED: Order was rejectedCANCELED: Order was cancelledFILLED: Order was completely filledEXPIRED: Order has expiredREPLACED: Order was replacedPARTIALLY_FILLED: Order was partially filledACCEPTED: Order was acceptedAWAITING_MANUAL_REVIEW: Order awaiting manual reviewAWAITING_UR_OUT: Order awaiting UR out
BUY: Buy to open positionSELL: Sell to close positionBUY_TO_COVER: Buy to cover short positionSELL_SHORT: Sell shortBUY_TO_CLOSE: Buy to close (options)SELL_TO_CLOSE: Sell to close (options)BUY_TO_OPEN: Buy to open (options)SELL_TO_OPEN: Sell to open (options)
MARKET: Market orderLIMIT: Limit orderSTOP: Stop orderSTOP_LIMIT: Stop-limit orderTRAILING_STOP: Trailing stop orderMARKET_ON_CLOSE: Market-on-close orderLIMIT_ON_CLOSE: Limit-on-close orderCABINET: Cabinet order (options)NON_MARKETABLE: Non-marketable limit orderNET_DEBIT: Net debit (multi-leg)NET_CREDIT: Net credit (multi-leg)NET_ZERO: Net zero (multi-leg)
DAY: Day orderGOOD_TILL_CANCEL: Good-till-cancel orderFILL_OR_KILL: Fill-or-kill orderIMMEDIATE_OR_CANCEL: Immediate-or-cancel orderWEEK: Week orderMONTH: Month orderEND_OF_WEEK: End of week orderEND_OF_MONTH: End of month orderNEXT_END_OF_MONTH: Next end of month orderUNKNOWN: Unknown duration
SINGLE: Single leg orderCOVERED: Covered call/putVERTICAL: Vertical spreadBACK_RATIO: Back ratio spreadCALENDAR: Calendar spreadDIAGONAL: Diagonal spreadSTRADDLE: StraddleSTRANGLE: StrangleCOLLAR_SYNTHETIC: Collar syntheticBUTTERFLY: Butterfly spreadCONDOR: Condor spreadIRON_CONDOR: Iron condorVERTICAL_ROLL: Vertical rollCOLLAR_WITH_STOCK: Collar with stockDOUBLE_DIAGONAL: Double diagonalUNBALANCED_BUTTERFLY: Unbalanced butterflyUNBALANCED_CONDOR: Unbalanced condorUNBALANCED_IRON_CONDOR: Unbalanced iron condorUNBALANCED_VERTICAL_ROLL: Unbalanced vertical rollCUSTOM: Custom strategy
EQUITY: Stock/ETFOPTION: Option contractMUTUAL_FUND: Mutual fundFIXED_INCOME: Fixed incomeINDEX: IndexCASH_EQUIVALENT: Cash equivalentCURRENCY: CurrencyCOLLECTIVE_INVESTMENT: Collective investment
ALL_OR_NONE: All-or-none orderDO_NOT_REDUCE: Do not reduce orderALL_OR_NONE_DO_NOT_REDUCE: All-or-none and do not reduce
- API Reference - Detailed method documentation
- Order Types Tutorial - Comprehensive order type guide
- Order Strategies - Complex order strategies explained
- Paper Trading Guide - Safe testing environment setup
- Asset Types - Supported asset types and examples
- Migration Guide - Upgrading from previous versions