from datetime import datetime from dotenv import load_dotenv from ibkr import Client from ibkr.option_type import CALL, PUT from os import getenv from tastytrade import Tastytrade load_dotenv() ibkr_host = getenv('IBKR_HOST') ibkr_port = getenv('IBKR_PORT') ibkr_client = Client(host = ibkr_host, port = ibkr_port) tastytrade_account = getenv('TASTYTRADE_ACCOUNT') tastytrade_username = getenv('TASTYTRADE_USERNAME') tastytrade_password = getenv('TASTYTRADE_PASSWORD') tastytrade_client = Tastytrade(tastytrade_username, tastytrade_password) tastytrade_client.login() underlying_ticker = ibkr_client.get_ticker('SPX', 'CBOE') current_price = underlying_ticker.last # Filtering strikes based on distance from current price speeds up the request. max_strike_distance = 100 def contract_filter(contract): if contract.right == 'C': return contract.strike <= (current_price + max_strike_distance) and contract.strike >= current_price return contract.strike <= current_price and contract.strike >= (current_price - max_strike_distance) # The weekly symbol for SPX (SPXW) is required in order to distinguish from monthly options. option_chain = ibkr_client.get_option_chain('SPX', datetime.now(), sub_symbol = 'SPXW', contract_filter = contract_filter) print(option_chain) target_delta = 0.10 def closest_strike_by_delta(target_delta, option_chain, option_type): options = option_chain[option_chain['Type'] == option_type].copy() options['Delta Distance'] = abs(options['Delta'] - (target_delta * (1 if option_type == CALL else -1))) return options.loc[options['Delta Distance'].idxmin()] # Find the strikes that minimize the distance to the target delta. closest_call_strike = closest_strike_by_delta(target_delta, option_chain, CALL) closest_put_strike = closest_strike_by_delta(target_delta, option_chain, PUT) # Do the same for the long strikes. target_long_call_strike = closest_call_strike['Strike'] + 50 target_long_put_strike = closest_put_strike['Strike'] - 50 def closest_strike_by_strike(target_strike, option_chain, option_type): options = option_chain[option_chain['Type'] == option_type].copy() options['Strike Distance'] = abs(options['Strike'] - target_strike) return options.loc[options['Strike Distance'].idxmin()] closest_long_call_strike = closest_strike_by_strike(target_long_call_strike, option_chain, CALL) closest_long_put_strike = closest_strike_by_strike(target_long_put_strike, option_chain, PUT) # The requested iron condor. print('Short Call Strike:', closest_call_strike['Strike']) print('Long Call Strike:', closest_long_call_strike['Strike']) print("Short Put Strike:", closest_put_strike['Strike']) print('Long Put Strike:', closest_long_put_strike['Strike'])