diff --git a/backtesting/backtest_iron_condor.py b/backtesting/backtest_iron_condor.py index 88478fe..f5f3761 100644 --- a/backtesting/backtest_iron_condor.py +++ b/backtesting/backtest_iron_condor.py @@ -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: