Refactoring credit and delta targeting strike selection in order to prevent scenarios where an infinite loop is entered and assigning a default value to the current call and put spread prices

This commit is contained in:
moshferatu 2024-01-31 14:51:28 -08:00
parent c56e7bf0bf
commit ea46e6dd13

View File

@ -44,24 +44,16 @@ exit_times = []
def get_spread_history_credit(historical_option_data: pd.DataFrame, option_strat: CreditTargetStrategy) -> pd.DataFrame:
current_date = historical_option_data.iloc[0]['quote_datetime'][:10]
opening_quotes = historical_option_data[(historical_option_data['quote_datetime'] == (current_date + ' ' + option_strat.trade_entry_time))]
opening_quotes = historical_option_data[(historical_option_data['quote_datetime'] == (current_date + ' ' + option_strat.trade_entry_time))].copy()
if opening_quotes.empty:
return None
else:
opening_quotes_by_contract_type = opening_quotes[opening_quotes['option_type'] == option_strat.option_type.value]
short_contract_candidates = opening_quotes_by_contract_type[(opening_quotes_by_contract_type['bid'] >= (option_strat.credit_target - 1.0)) & (opening_quotes_by_contract_type['bid'] < (option_strat.credit_target + 1.0))]
credit_increment = 2.00
while short_contract_candidates.empty:
short_contract_candidates = opening_quotes_by_contract_type[(opening_quotes_by_contract_type['bid'] >= (option_strat.credit_target - credit_increment)) & (opening_quotes_by_contract_type['bid'] < (option_strat.credit_target + credit_increment))]
credit_increment += 1.00
opening_quotes_by_contract_type = opening_quotes[opening_quotes['option_type'] == option_strat.option_type.value].copy()
strike_candidates = {}
for i in range(len(short_contract_candidates)):
candidate = short_contract_candidates.iloc[i]
strike_candidates[candidate['bid']] = candidate['strike']
opening_quotes_by_contract_type['credit_diff'] = (opening_quotes_by_contract_type['bid'] - option_strat.credit_target).abs()
short_contract = opening_quotes_by_contract_type.loc[opening_quotes_by_contract_type['credit_diff'].idxmin()]
closest_bid = min(strike_candidates, key=lambda candidate_bid: abs(option_strat.credit_target - candidate_bid))
short_strike = strike_candidates[closest_bid]
short_strike = short_contract['strike']
logging.info('Short Strike: %s', short_strike)
long_strike = short_strike + (option_strat.spread_width if option_strat.option_type == OptionType.CALL else -option_strat.spread_width)
@ -78,23 +70,16 @@ def get_spread_history_credit(historical_option_data: pd.DataFrame, option_strat
def get_spread_history(historical_option_data: pd.DataFrame, option_strat: DeltaTargetStrategy) -> pd.DataFrame:
current_date = historical_option_data.iloc[0]['quote_datetime'][:10]
opening_quotes = historical_option_data[(historical_option_data['quote_datetime'] == (current_date + ' ' + option_strat.trade_entry_time))]
opening_quotes = historical_option_data[(historical_option_data['quote_datetime'] == (current_date + ' ' + option_strat.trade_entry_time))].copy()
if opening_quotes.empty:
return None
else:
if option_strat.option_type == OptionType.PUT:
short_contract_candidates = opening_quotes[(opening_quotes['delta'] > -option_strat.delta_upper_bound) & (opening_quotes['delta'] <= -option_strat.delta_lower_bound)]
opening_quotes['delta_diff'] = (opening_quotes['delta'] + option_strat.delta_upper_bound).abs()
short_contract = opening_quotes.loc[opening_quotes['delta_diff'].idxmin()]
else:
short_contract_candidates = opening_quotes[(opening_quotes['delta'] < option_strat.delta_upper_bound) & (opening_quotes['delta'] >= option_strat.delta_lower_bound)]
delta_increment = 0.01
while short_contract_candidates.empty:
if option_strat.option_type == OptionType.PUT:
short_contract_candidates = opening_quotes[(opening_quotes['delta'] > (-option_strat.delta_upper_bound - delta_increment)) & (opening_quotes['delta'] <= -option_strat.delta_lower_bound)]
else:
short_contract_candidates = opening_quotes[(opening_quotes['delta'] < (option_strat.delta_upper_bound + delta_increment)) & (opening_quotes['delta'] >= option_strat.delta_lower_bound)]
delta_increment = delta_increment + 0.01
# Might return more than one, take greatest strike
short_contract = short_contract_candidates.iloc[-1]
opening_quotes['delta_diff'] = (opening_quotes['delta'] - option_strat.delta_upper_bound).abs()
short_contract = opening_quotes.loc[opening_quotes['delta_diff'].idxmin()]
short_strike = short_contract['strike']
logging.info('Short Strike: %s', short_strike)
@ -179,6 +164,9 @@ def _backtest_iron_condor(
max_drawdown = 0.0
exit_time = '16:00:00'
current_call_spread_price = original_call_spread_price
current_put_spread_price = original_put_spread_price
for i in range(len(call_spread_history)):
call_spread = call_spread_history.iloc[i]
put_spread = put_spread_history.iloc[i]
@ -258,13 +246,13 @@ def _backtest_iron_condor(
max_profit = current_profit_dollars
if current_profit_dollars < max_drawdown:
max_drawdown = current_profit_dollars
if not call_spread_stopped_out and current_call_spread_price > 0.05:
premium_received -= current_call_spread_price
if not put_spread_stopped_out and current_put_spread_price > 0.05:
premium_received -= current_put_spread_price
number_of_contracts = call_spread_strategy.number_of_contracts
stop_out_fees = 0.0 # It costs money to get stopped out.
if call_spread_stopped_out: