The unofficial python interface for the WeBull API
Specialized options trading capabilities including options chain retrieval, expiration dates, strike price filtering, and options-specific order placement and management.
Options trading requires:
get_trade_token()Retrieve complete options chains with call and put contracts for any underlying security.
def get_options(self, stock=None, count=-1, includeWeekly=1, direction='all', expireDate=None, queryAll=0):
"""
Get options chain for a stock.
Parameters:
- stock (str, optional): Stock symbol (e.g., 'AAPL')
- count (int): Number of strike prices to retrieve (-1 for all)
- includeWeekly (int): Include weekly options (0=no, 1=yes)
- direction (str): Filter by option type - 'all', 'call', 'put'
- expireDate (str, optional): Specific expiration date (YYYY-MM-DD)
- queryAll (int): Query all available data (0=no, 1=yes)
Returns:
list: List of options contracts containing:
- derivativeId: Unique options contract ID
- symbol: Options symbol
- strikePrice: Strike price
- expireDate: Expiration date
- direction: 'call' or 'put'
- lastPrice: Last traded price
- bid: Current bid price
- ask: Current ask price
- volume: Trading volume
- openInterest: Open interest
- impliedVolatility: Implied volatility
- delta: Options delta
- gamma: Options gamma
- theta: Options theta
- vega: Options vega
"""
def get_options_by_strike_and_expire_date(self, stock=None, expireDate=None, strike=None, direction='all'):
"""
Get specific options by strike price and expiration date.
Parameters:
- stock (str, optional): Stock symbol
- expireDate (str): Expiration date (YYYY-MM-DD)
- strike (float): Strike price
- direction (str): 'all', 'call', or 'put'
Returns:
list: Filtered options contracts matching criteria
"""Usage examples:
# Get full options chain for Apple
options_chain = wb.get_options(stock='AAPL', includeWeekly=1)
print(f"Found {len(options_chain)} options contracts")
# Filter for calls only
calls = wb.get_options(stock='AAPL', direction='call')
# Get options for specific expiration
jan_options = wb.get_options(
stock='AAPL',
expireDate='2024-01-19',
direction='all'
)
# Get specific strike and expiration
specific_option = wb.get_options_by_strike_and_expire_date(
stock='AAPL',
expireDate='2024-01-19',
strike=150.0,
direction='call'
)Get available expiration dates for options trading.
def get_options_expiration_dates(self, stock=None, count=-1):
"""
Get available options expiration dates for a stock.
Parameters:
- stock (str, optional): Stock symbol
- count (int): Number of expiration dates to retrieve (-1 for all)
Returns:
list: List of expiration dates in YYYY-MM-DD format, sorted chronologically
"""Usage example:
# Get all expiration dates for Apple options
exp_dates = wb.get_options_expiration_dates(stock='AAPL')
print("Available expiration dates:")
for date in exp_dates[:10]: # Show first 10
print(f" {date}")
# Get next 5 expiration dates
next_expirations = wb.get_options_expiration_dates(stock='AAPL', count=5)Get real-time quotes and pricing for specific options contracts.
def get_option_quote(self, stock=None, tId=None, optionId=None):
"""
Get real-time quote for an options contract.
Parameters:
- stock (str, optional): Underlying stock symbol
- tId (int, optional): Underlying ticker ID
- optionId (int): Options contract derivative ID
Returns:
dict: Options quote containing:
- lastPrice: Last traded price
- bid: Current bid price
- ask: Current ask price
- bidSize: Bid size
- askSize: Ask size
- volume: Daily volume
- openInterest: Open interest
- impliedVolatility: Implied volatility
- delta: Delta value
- gamma: Gamma value
- theta: Theta value
- vega: Vega value
- change: Price change
- changeRatio: Percentage change
"""Usage example:
# First get options to find derivative ID
options = wb.get_options(stock='AAPL', direction='call', count=5)
option_id = options[0]['derivativeId']
# Get real-time quote for the option
quote = wb.get_option_quote(optionId=option_id)
print(f"Option Quote:")
print(f"Last Price: ${quote['lastPrice']}")
print(f"Bid/Ask: ${quote['bid']} / ${quote['ask']}")
print(f"Volume: {quote['volume']}")
print(f"Open Interest: {quote['openInterest']}")
print(f"IV: {quote['impliedVolatility']:.2f}%")
print(f"Delta: {quote['delta']:.3f}")Place buy and sell orders for options contracts.
def place_order_option(self, optionId=None, lmtPrice=None, stpPrice=None, action=None, orderType='LMT', enforce='DAY', quant=0):
"""
Place an options order.
Parameters:
- optionId (int): Options contract derivative ID
- lmtPrice (float, optional): Limit price for limit orders
- stpPrice (float, optional): Stop price for stop orders
- action (str): 'BUY' or 'SELL'
- orderType (str): Order type - 'LMT', 'MKT', 'STP', 'STP_LMT'
- enforce (str): Time in force - 'DAY', 'GTC', 'IOC', 'FOK'
- quant (int): Number of option contracts
Returns:
dict: Order placement result with order ID and status
Raises:
ValueError: If required parameters missing or invalid
"""Usage examples:
# Get options and select one to trade
options = wb.get_options(stock='AAPL', direction='call')
call_option = options[0] # First call option
# Buy call option with limit order
buy_result = wb.place_order_option(
optionId=call_option['derivativeId'],
lmtPrice=5.50,
action='BUY',
orderType='LMT',
enforce='DAY',
quant=1
)
print(f"Buy order placed: {buy_result['orderId']}")
# Sell put option
put_options = wb.get_options(stock='AAPL', direction='put')
put_option = put_options[0]
sell_result = wb.place_order_option(
optionId=put_option['derivativeId'],
lmtPrice=3.25,
action='SELL',
orderType='LMT',
quant=2
)Modify existing options orders.
def modify_order_option(self, order=None, lmtPrice=None, stpPrice=None, enforce=None, quant=0):
"""
Modify an existing options order.
Parameters:
- order (dict): Existing options order object to modify
- lmtPrice (float, optional): New limit price
- stpPrice (float, optional): New stop price
- enforce (str, optional): New time in force
- quant (int): New quantity
Returns:
dict: Modification result
"""Usage example:
# Get current options orders
current_orders = wb.get_current_orders()
options_orders = [o for o in current_orders if o.get('optionId')]
if options_orders:
# Modify first options order
order_to_modify = options_orders[0]
modify_result = wb.modify_order_option(
order=order_to_modify,
lmtPrice=6.00, # New limit price
quant=2 # New quantity
)
print(f"Order modified: {modify_result}")Get historical price data for options contracts.
def get_options_bars(self, derivativeId=None, interval='1m', count=1, direction=1, timeStamp=None):
"""
Get historical price bars for options contracts.
Parameters:
- derivativeId (int): Options contract derivative ID
- interval (str): Time interval - '1m', '5m', '15m', '30m', '1h', '1d'
- count (int): Number of bars to retrieve
- direction (int): Direction flag (1 for ascending, -1 for descending)
- timeStamp (int, optional): Start timestamp for historical data
Returns:
list: Options price bars containing:
- open: Opening price
- high: High price
- low: Low price
- close: Closing price
- volume: Volume
- timestamp: Bar timestamp
"""Usage example:
# Get options historical data
options = wb.get_options(stock='AAPL', direction='call', count=1)
option_id = options[0]['derivativeId']
# Get daily bars for last 30 days
option_bars = wb.get_options_bars(
derivativeId=option_id,
interval='1d',
count=30
)
print(f"Options price history ({len(option_bars)} days):")
for bar in option_bars[-5:]: # Last 5 days
print(f" {bar['timestamp']}: ${bar['close']}")def covered_call_strategy(wb, symbol, strike_price):
"""
Implement a covered call strategy.
"""
# Check current stock position
positions = wb.get_positions()
stock_position = None
for pos in positions:
if pos['ticker']['symbol'] == symbol:
stock_position = pos
break
if not stock_position or stock_position['position'] < 100:
print(f"Need at least 100 shares of {symbol} for covered call")
return
# Get call options above current price
options = wb.get_options(stock=symbol, direction='call')
# Filter for desired strike price
suitable_calls = [
opt for opt in options
if opt['strikePrice'] >= strike_price
]
if not suitable_calls:
print(f"No suitable call options found at ${strike_price}")
return
# Select the first suitable call
call_to_sell = suitable_calls[0]
# Sell covered call
result = wb.place_order_option(
optionId=call_to_sell['derivativeId'],
lmtPrice=call_to_sell['ask'] * 0.95, # Slightly below ask
action='SELL',
orderType='LMT',
enforce='DAY',
quant=1
)
print(f"Covered call placed: {result}")
return result
# Usage
covered_call_strategy(wb, 'AAPL', 160.0)def scan_high_iv_options(wb, symbols, min_iv=30):
"""
Scan for high implied volatility options.
"""
high_iv_options = []
for symbol in symbols:
try:
options = wb.get_options(stock=symbol, direction='all')
for option in options:
iv = option.get('impliedVolatility', 0)
if iv >= min_iv:
high_iv_options.append({
'symbol': symbol,
'strike': option['strikePrice'],
'expiry': option['expireDate'],
'type': option['direction'],
'iv': iv,
'lastPrice': option['lastPrice']
})
except Exception as e:
print(f"Error scanning {symbol}: {e}")
# Sort by IV descending
high_iv_options.sort(key=lambda x: x['iv'], reverse=True)
print(f"High IV Options (IV >= {min_iv}%):")
for opt in high_iv_options[:10]: # Top 10
print(f"{opt['symbol']} {opt['strike']} {opt['type']} {opt['expiry']}: IV={opt['iv']:.1f}%, Price=${opt['lastPrice']}")
return high_iv_options
# Usage
symbols = ['AAPL', 'TSLA', 'MSFT', 'NVDA', 'AMD']
high_iv = scan_high_iv_options(wb, symbols, min_iv=40)from webull import webull
from datetime import datetime, timedelta
wb = webull()
wb.login('your_email@example.com', 'your_password')
wb.get_trade_token('your_trading_password')
symbol = 'AAPL'
try:
# Get options expiration dates
exp_dates = wb.get_options_expiration_dates(stock=symbol)
next_expiry = exp_dates[1] # Skip current week, use next
print(f"Analyzing {symbol} options expiring {next_expiry}")
# Get options chain for next expiration
options = wb.get_options(
stock=symbol,
expireDate=next_expiry,
direction='all'
)
# Get current stock price for reference
quote = wb.get_quote(stock=symbol)
current_price = float(quote['close'])
print(f"Current {symbol} price: ${current_price}")
# Analyze call options
calls = [opt for opt in options if opt['direction'] == 'call']
puts = [opt for opt in options if opt['direction'] == 'put']
print(f"\nCall Options (Strike >= ${current_price}):")
otm_calls = [c for c in calls if c['strikePrice'] >= current_price][:5]
for call in otm_calls:
strike = call['strikePrice']
price = call['lastPrice']
iv = call.get('impliedVolatility', 0)
delta = call.get('delta', 0)
print(f" ${strike} Call: ${price} (IV: {iv:.1f}%, Delta: {delta:.3f})")
print(f"\nPut Options (Strike <= ${current_price}):")
otm_puts = [p for p in puts if p['strikePrice'] <= current_price][:5]
for put in otm_puts:
strike = put['strikePrice']
price = put['lastPrice']
iv = put.get('impliedVolatility', 0)
delta = put.get('delta', 0)
print(f" ${strike} Put: ${price} (IV: {iv:.1f}%, Delta: {delta:.3f})")
# Example: Buy a slightly out-of-the-money call
if otm_calls:
target_call = otm_calls[0] # First OTM call
print(f"\nPlacing order for ${target_call['strikePrice']} call...")
order_result = wb.place_order_option(
optionId=target_call['derivativeId'],
lmtPrice=target_call['ask'] * 0.98, # Slightly below ask
action='BUY',
orderType='LMT',
enforce='DAY',
quant=1
)
print(f"Order placed: {order_result}")
except ValueError as e:
print(f"Options trading error: {e}")Key considerations for options trading:
def analyze_options_risk(option_data, position_size=1):
"""
Analyze risk metrics for an options position.
"""
strike = option_data['strikePrice']
premium = option_data['lastPrice']
option_type = option_data['direction']
# Calculate maximum risk/reward
if option_type == 'call':
max_loss = premium * position_size * 100 # Premium paid
max_gain = "Unlimited"
breakeven = strike + premium
else: # put
max_loss = premium * position_size * 100 # Premium paid
max_gain = (strike - premium) * position_size * 100
breakeven = strike - premium
print(f"Options Risk Analysis:")
print(f"Maximum Loss: ${max_loss}")
print(f"Maximum Gain: {max_gain}")
print(f"Breakeven Price: ${breakeven}")
# Time decay analysis
theta = option_data.get('theta', 0)
if theta:
daily_decay = abs(theta) * position_size * 100
print(f"Daily Time Decay: ${daily_decay:.2f}")
# Usage with options data
option = wb.get_options(stock='AAPL', direction='call')[0]
analyze_options_risk(option, position_size=2)Install with Tessl CLI
npx tessl i tessl/pypi-webull