def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib): super().tickPrice(reqId, tickType, price, attrib) ticker_str = self.market_data_ReqId_dictionary[reqId] if tickType == 1: self.bid_price_dictionary[ticker_str] = price if ticker_str in self.nonfinished_bid_price_list: self.nonfinished_bid_price_list.remove(ticker_str) elif tickType == 2: self.ask_price_dictionary[ticker_str] = price if ticker_str in self.nonfinished_ask_price_list: self.nonfinished_ask_price_list.remove(ticker_str) if (tickType == 1) or (tickType == 2): self.fair_price_dictionary[ticker_str] = self.calculate_mid_price( ticker_str) if (len(self.nonfinished_bid_price_list)==0)&(len(self.nonfinished_ask_price_list)==0)&\ (len(self.nonfinished_bid_quantity_list)==0)&(len(self.nonfinished_ask_quantity_list)==0)&(~self.option_model_call_initiated_q): fair_price_dictionary = self.fair_price_dictionary print(self.bid_price_dictionary) underlying_ticker_list = [] mid_price_list = [] for key in fair_price_dictionary: selection_indx = self.contract_frame['ticker'] == key self.contract_frame['mid_price'].loc[ selection_indx] = fair_price_dictionary[key] self.contract_frame['bid_p'].loc[ selection_indx] = self.bid_price_dictionary[key] self.contract_frame['ask_p'].loc[ selection_indx] = self.ask_price_dictionary[key] self.contract_frame['bid_q'].loc[ selection_indx] = self.bid_quantity_dictionary[key] self.contract_frame['ask_q'].loc[ selection_indx] = self.ask_quantity_dictionary[key] #self.contract_frame['underlying_ticker'] = self.contract_frame['ticker'] self.contract_frame['spread_cost'] = self.contract_frame[ 'contract_multiplier'] * (self.contract_frame['ask_p'] - self.contract_frame['bid_p']) self.contract_frame['urgency_aux'] = self.contract_frame[ 'risk'] / self.contract_frame['spread_cost'] self.contract_frame['urgency'] = 0 self.contract_frame['urgency'].loc[ self.contract_frame['urgency_aux'] > 5] = 100 self.contract_frame.rename(columns={'ticker': 'underlying_ticker'}, inplace=True) self.option_model_call_initiated_q = True #print(self.contract_frame) tsh.strategy_hedge_report(intraday_price_frame=self.contract_frame, delta_alias=self.delta_alias, con=self.con) position_frame = tas.get_net_position_4strategy_alias( alias=self.delta_alias, as_of_date=self.current_date, con=self.con) print(position_frame) hedge_frame = tsh.get_hedge_frame(con=self.con) hedge_aux = self.contract_frame hedge_aux.rename(columns={'underlying_ticker': 'ticker'}, inplace=True) hedge_aux = hedge_aux[['ticker', 'urgency']] hedge_frame = pd.merge(hedge_frame, hedge_aux, how='inner', on='ticker') unique_ticker_head_list = hedge_frame['ticker_head'].unique() for i in range(len(unique_ticker_head_list)): hedge_frame_ticker_head = hedge_frame[ hedge_frame['ticker_head'] == unique_ticker_head_list[i]] for j in range(len(hedge_frame_ticker_head.index)): self.log.info( str(hedge_frame_ticker_head['hedge'].iloc[j]) + ' ' + hedge_frame_ticker_head['ticker'].iloc[j] + ' with urgency ' + '% 4.1f' % hedge_frame_ticker_head['urgency'].iloc[j]) continue_q = 'n' if len(hedge_frame.index) == 0: self.log.info('No hedging needed today') else: continue_q = input('Do you agree? (y/n): ') if continue_q == 'y': self.log.info('Hedging now') for i in range(len(hedge_frame.index)): ticker_i = hedge_frame['ticker'].iloc[i] split_output = ticker_i.split('-') contract_specs_output = cmi.get_contract_specs( split_output[0]) tick_size = cmi.tick_size[ contract_specs_output['ticker_head']] action_str = '' trade_quantity = abs(hedge_frame['hedge'].iloc[i]) if hedge_frame['hedge'].iloc[i] > 0: if hedge_frame['urgency'].iloc[i] == 100: limit_price = self.ask_price_dictionary[ticker_i] else: limit_price = m.ceil( self.fair_price_dictionary[ticker_i] / tick_size) * tick_size action_str = 'BUY' else: if hedge_frame['urgency'].iloc[i] == 100: limit_price = self.bid_price_dictionary[ticker_i] else: limit_price = m.floor( self.fair_price_dictionary[ticker_i] / tick_size) * tick_size action_str = 'SELL' if hedge_frame['is_spread_q'].iloc[i]: contract_i = self.spread_contract_dictionary[ticker_i] order = ib_api_trade.ComboLimitOrder( action_str, trade_quantity, limit_price, False) else: contract_i = self.outright_contract_dictionary[ ticker_i] order = ib_api_trade.LimitOrder( action_str, trade_quantity, limit_price) self.order_ticker_dictionary[self.next_val_id] = ticker_i self.order_urgency_dictionary[ self.next_val_id] = hedge_frame['urgency'].iloc[i] self.placeOrder(self.next_valid_id(), contract_i, order)
def periodic_call(self): overnight_calendars = self.overnight_calendars self.period_call_initiated_q = True datetime_now = dt.datetime.now() self.log.info(datetime_now.strftime('%Y-%m-%d %H:%M:%S')) self.log.info('total volume traded so far: ' + str(self.total_volume_traded)) for i in range(len(overnight_calendars.index)): front_spread_ticker = overnight_calendars.loc[i, 'front_spread_ticker'] back_spread_ticker = overnight_calendars.loc[i, 'back_spread_ticker'] mid_ticker = overnight_calendars.loc[i, 'ticker1'] if (self.bid_quantity_dictionary[front_spread_ticker]==0) or \ (self.ask_quantity_dictionary[front_spread_ticker]==0)or \ (self.bid_quantity_dictionary[back_spread_ticker]==0) or \ (self.ask_quantity_dictionary[back_spread_ticker]==0) or \ (self.bid_quantity_dictionary[mid_ticker]==0) or \ (self.ask_quantity_dictionary[mid_ticker]==0): continue overnight_calendars.loc[i, 'front_spread_price'] = (self.bid_price_dictionary[front_spread_ticker]*self.bid_quantity_dictionary[front_spread_ticker] + self.ask_price_dictionary[front_spread_ticker]*self.ask_quantity_dictionary[front_spread_ticker])\ /(self.bid_quantity_dictionary[front_spread_ticker]+self.ask_quantity_dictionary[front_spread_ticker]) overnight_calendars.loc[i, 'back_spread_price'] = (self.bid_price_dictionary[back_spread_ticker]*self.bid_quantity_dictionary[back_spread_ticker] + self.ask_price_dictionary[back_spread_ticker]*self.ask_quantity_dictionary[back_spread_ticker]) \ /(self.bid_quantity_dictionary[back_spread_ticker]+self.ask_quantity_dictionary[back_spread_ticker]) overnight_calendars.loc[i, 'mid_ticker_price'] = (self.bid_price_dictionary[mid_ticker]*self.bid_quantity_dictionary[mid_ticker] + self.ask_price_dictionary[mid_ticker]*self.ask_quantity_dictionary[mid_ticker]) \ /(self.bid_quantity_dictionary[mid_ticker]+self.ask_quantity_dictionary[mid_ticker]) overnight_calendars.loc[i,'normalized_butterfly_price'] = 100 * (overnight_calendars.loc[i,'front_spread_price'] - overnight_calendars.loc[i,'back_spread_price']) / overnight_calendars.loc[i,'mid_ticker_price'] overnight_calendars.loc[i, 'normalized_butterfly_price_b'] = 100 * (overnight_calendars.loc[i, 'front_spread_price'] - self.bid_price_dictionary[back_spread_ticker]) /overnight_calendars.loc[i, 'mid_ticker_price'] overnight_calendars.loc[i, 'normalized_butterfly_price_a'] = 100 * (overnight_calendars.loc[i, 'front_spread_price'] - self.ask_price_dictionary[back_spread_ticker]) / overnight_calendars.loc[i, 'mid_ticker_price'] overnight_calendars.loc[i,'butterfly_z_current'] = (overnight_calendars.loc[i,'normalized_butterfly_price'] -overnight_calendars.loc[i,'butterflyMean']) / overnight_calendars.loc[i,'butterflyNoise'] overnight_calendars.loc[i, 'butterfly_z_current_b'] = (overnight_calendars.loc[i, 'normalized_butterfly_price_b'] -overnight_calendars.loc[i, 'butterflyMean']) / overnight_calendars.loc[i, 'butterflyNoise'] overnight_calendars.loc[i, 'butterfly_z_current_a'] = (overnight_calendars.loc[i, 'normalized_butterfly_price_a'] -overnight_calendars.loc[i, 'butterflyMean']) / overnight_calendars.loc[i, 'butterflyNoise'] ticker_head = overnight_calendars['tickerHead'].loc[i] ticker_class = overnight_calendars['tickerClass'].loc[i] ticker1 = overnight_calendars['ticker1'].loc[i] ticker2 = overnight_calendars['ticker2'].loc[i] trDte1 = overnight_calendars['trDte1'].loc[i] spread_contract = self.spread_contract_dictionary[back_spread_ticker] spread_price = overnight_calendars.loc[i,'back_spread_price'] bid_price = self.bid_price_dictionary[back_spread_ticker] ask_price = self.ask_price_dictionary[back_spread_ticker] bid_quantity = self.bid_quantity_dictionary[back_spread_ticker] ask_quantity = self.ask_quantity_dictionary[back_spread_ticker] tick_size = cmi.tick_size[ticker_head] bid_ask_in_ticks = (self.ask_price_dictionary[back_spread_ticker] - self.bid_price_dictionary[back_spread_ticker]) / tick_size butterfly_price = overnight_calendars.loc[i,'front_spread_price'] - overnight_calendars.loc[i,'back_spread_price'] normalized_butterfly_price = overnight_calendars.loc[i,'normalized_butterfly_price'] normalized_butterfly_price_b = overnight_calendars.loc[i, 'normalized_butterfly_price_b'] normalized_butterfly_price_a = overnight_calendars.loc[i, 'normalized_butterfly_price_a'] butterfly_q25 = overnight_calendars.loc[i,'butterfly_q25'] butterfly_q75 = overnight_calendars.loc[i,'butterfly_q75'] min_avg_volume = overnight_calendars.loc[i,'min_avg_volume'] z_score = overnight_calendars.loc[i,'butterfly_z_current'] z_score_b = overnight_calendars.loc[i, 'butterfly_z_current_b'] z_score_a = overnight_calendars.loc[i, 'butterfly_z_current_a'] z_score_s = overnight_calendars.loc[i, 'butterflyZ'] qCarry = overnight_calendars.loc[i, 'qCarry'] target_quantity = overnight_calendars.loc[i,'target_quantity'] dollar_noise100 = overnight_calendars.loc[i,'dollarNoise100'] holding_period = overnight_calendars.loc[i, 'holding_period'] continue_q = 'n' pnl_frame = self.pnl_frame position_select = pnl_frame['alias'] == overnight_calendars.loc[i, 'alias'] if sum(position_select) ==0: realized_pnl = 0 else: realized_pnl = pnl_frame['total_pnl'].loc[position_select].values[0] total_position_long = self.ocs_portfolio.position_with_all_orders[ticker_head + '_long'] working_position_long = self.ocs_portfolio.position_with_working_orders[ticker_head + '_long'] filled_position_long = self.ocs_portfolio.position_with_filled_orders[ticker_head + '_long'] total_position_short = self.ocs_portfolio.position_with_all_orders[ticker_head + '_short'] working_position_short = self.ocs_portfolio.position_with_working_orders[ticker_head + '_short'] filled_position_short = self.ocs_portfolio.position_with_filled_orders[ticker_head + '_short'] total_alias_long = self.ocs_alias_portfolio.position_with_all_orders[back_spread_ticker + '_long'] working_alias_long = self.ocs_alias_portfolio.position_with_working_orders[back_spread_ticker + '_long'] filled_alias_long = self.ocs_alias_portfolio.position_with_filled_orders[back_spread_ticker + '_long'] total_alias_short = self.ocs_alias_portfolio.position_with_all_orders[back_spread_ticker + '_short'] working_alias_short = self.ocs_alias_portfolio.position_with_working_orders[back_spread_ticker + '_short'] filled_alias_short = self.ocs_alias_portfolio.position_with_filled_orders[back_spread_ticker + '_short'] total_risk_long = self.ocs_risk_portfolio.position_with_all_orders[ticker_head + '_long'] working_risk_long = self.ocs_risk_portfolio.position_with_working_orders[ticker_head + '_long'] filled_risk_long = self.ocs_risk_portfolio.position_with_filled_orders[ticker_head + '_long'] total_risk_short = self.ocs_risk_portfolio.position_with_all_orders[ticker_head + '_short'] working_risk_short = self.ocs_risk_portfolio.position_with_working_orders[ticker_head + '_short'] filled_risk_short = self.ocs_risk_portfolio.position_with_filled_orders[ticker_head + '_short'] if self.total_traded_volume_since_last_confirmation+target_quantity>self.total_traded_volume_max_before_user_confirmation: self.log.info('total volume traded since last user approval is: ' + str(self.total_traded_volume_since_last_confirmation)) self.log.info('new target quantity:' + str(target_quantity)) continue_q = input('Continue? (y/n): ') if continue_q == 'y': self.total_traded_volume_since_last_confirmation = 0 else: continue # new sell entry orders if (z_score < -1) and (z_score<=z_score_s) and (qCarry<=-9) and (normalized_butterfly_price<butterfly_q25) and (min_avg_volume>=self.min_avg_volume_limit) and (total_position_short <= 0) and (working_position_short == 0) and ( self.num_bets < self.max_num_bets): if self.total_traded_volume_since_last_confirmation+target_quantity < self.total_traded_volume_max_before_user_confirmation: self.ocs_portfolio.order_send(ticker=ticker_head + '_short', qty=target_quantity) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_short', qty=target_quantity) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_short', qty=target_quantity*dollar_noise100) self.log.info('real order!! id:' + str(self.next_val_id)) self.log.info('total_position_short:' + str(total_position_short) + ', working_position_short: ' + str(working_position_short)) overnight_calendars.loc[i, 'working_order_id'] = self.next_val_id self.order_filled_dictionary[self.next_val_id] = 0 if (z_score_b<-1) and (z_score_b<=z_score_s) and (normalized_butterfly_price_b<butterfly_q25) and (bid_quantity<(ask_quantity/2)) and (bid_ask_in_ticks<1.1): self.placeOrder(self.next_valid_id(), spread_contract, ib_api_trade.ComboLimitOrder('SELL', target_quantity, bid_price, False)) else: self.placeOrder(self.next_valid_id(), spread_contract,ib_api_trade.ComboLimitOrder('SELL', target_quantity, ask_price, False)) self.total_volume_traded += target_quantity self.total_traded_volume_since_last_confirmation += target_quantity self.num_bets += 1 self.log.info(back_spread_ticker + ' is a sell, Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score + ', z_score_b: %.2f' % z_score_b) # new buy entry orders if (z_score > 1) and (z_score>=z_score_s) and (qCarry>=19) and (normalized_butterfly_price>butterfly_q75) and (min_avg_volume>=self.min_avg_volume_limit) and (ticker_head not in ['CL', 'HO', 'NG']) and (total_position_long <= 0) and (working_position_long == 0) and (self.num_bets < self.max_num_bets): if self.total_traded_volume_since_last_confirmation+target_quantity < self.total_traded_volume_max_before_user_confirmation: self.ocs_portfolio.order_send(ticker=ticker_head + '_long', qty=target_quantity) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_long', qty=target_quantity) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_long',qty=target_quantity * dollar_noise100) self.log.info('real order!! id:' + str(self.next_val_id)) self.log.info('total_position_long:' + str(total_position_long) + ', working_position_long: ' + str(working_position_long)) overnight_calendars.loc[i, 'working_order_id'] = self.next_val_id self.order_filled_dictionary[self.next_val_id] = 0 if (z_score_a>1) and (z_score_a>=z_score_s) and (normalized_butterfly_price_a>butterfly_q75) and (ask_quantity<(bid_quantity/2)) and (bid_ask_in_ticks<1.1): self.placeOrder(self.next_valid_id(), spread_contract, ib_api_trade.ComboLimitOrder('BUY', target_quantity, ask_price, False)) else: self.placeOrder(self.next_valid_id(), spread_contract, ib_api_trade.ComboLimitOrder('BUY', target_quantity, bid_price, False)) self.total_volume_traded += target_quantity self.total_traded_volume_since_last_confirmation += target_quantity self.num_bets += 1 self.log.info(back_spread_ticker + ' is a buy, Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score + ', z_score_a: %.2f' % z_score_a) # cancel working short entry orders before exiting filled position to ensure correct acconting if (working_alias_short>0) and (total_alias_short>0): self.log.info('Monitor Existing Short Entry Orders: ' + back_spread_ticker + ', Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score) if (z_score>=-0.5) or (mth.isnan(z_score)): self.cancelOrder(int(overnight_calendars.loc[i, 'working_order_id'])) self.log.info(back_spread_ticker + ' normalized, cancelled entry orders with id ' + str(overnight_calendars.loc[i, 'working_order_id'])) overnight_calendars.loc[i, 'working_order_id'] = np.nan self.ocs_portfolio.order_send(ticker=ticker_head + '_short', qty=-working_alias_short) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_short', qty=-working_alias_short) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_short',qty=-working_alias_short * dollar_noise100) # cancel working long entry orders before exiting filled position to ensure correct acconting if (working_alias_long > 0) and (total_alias_long > 0): self.log.info('Monitor Existing Long Entry Orders: ' + back_spread_ticker + ', Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score) if (z_score <= 0.5) or (mth.isnan(z_score)): self.cancelOrder(int(overnight_calendars.loc[i, 'working_order_id'])) self.log.info(back_spread_ticker + ' normalized, cancelled entry orders with id ' + str(overnight_calendars.loc[i, 'working_order_id'])) overnight_calendars.loc[i, 'working_order_id'] = np.nan self.ocs_portfolio.order_send(ticker=ticker_head + '_long', qty=-working_alias_long) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_long',qty=-working_alias_long) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_long',qty=-working_alias_long * dollar_noise100) # before closing a short position, make sure there's actaully a position on the books, the first condition ensures that we avoid sending close orders repeatedly if (filled_alias_short>0) and (total_alias_short>0): self.log.info('Monitor Existing Short Position: ' + back_spread_ticker + ', Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score) # Livestock original holdings time: 14 # Ag, Energy original holding time: 28 if ((z_score > 0) and (z_score>=z_score_s) and ((qCarry>-4) or (trDte1<20))) or \ ((ticker_class=='Livestock') and (holding_period>=14) and (z_score > 0) and (z_score>=z_score_s) and (realized_pnl>0)) or \ ((ticker_class in ['Ag','Energy']) and (holding_period>=28) and (z_score > 0) and (z_score>=z_score_s) and (realized_pnl>0)) or \ (trDte1<15) or (mth.isnan(z_score)): self.log.info(back_spread_ticker + ' normalized, closing position') overnight_calendars.loc[i, 'working_order_id'] = self.next_val_id self.order_filled_dictionary[self.next_val_id] = 0 self.placeOrder(self.next_valid_id(), spread_contract,ib_api_trade.ComboLimitOrder('BUY', filled_alias_short, bid_price, False)) self.total_volume_traded += filled_alias_short self.total_traded_volume_since_last_confirmation += filled_alias_short self.ocs_portfolio.order_send(ticker=ticker_head + '_short', qty=-filled_alias_short) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_short', qty=-filled_alias_short) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_short',qty=-filled_alias_short * dollar_noise100) # before closing a long position, make sure there's actaully a position on the books, the first condition ensures that we avoid sending close orders repeatedly if (filled_alias_long > 0) and (total_alias_long > 0): self.log.info('Monitor Existing Long Position: ' + back_spread_ticker + ', Spread Price: %.4f' % spread_price + ', Butterfly Price: %.4f' % butterfly_price + ', z_score: %.2f' % z_score) if ((z_score < 0) and (z_score<=z_score_s) and ((qCarry<9) or (trDte1<20))) or \ ((ticker_class == 'Livestock') and (holding_period >= 14) and (z_score < 0) and (z_score<=z_score_s) and (realized_pnl>0)) or \ ((ticker_class in ['Ag', 'Energy']) and (holding_period >= 28) and (z_score < 0) and (z_score<=z_score_s) and (realized_pnl>0)) or \ (trDte1 < 15) or (mth.isnan(z_score)): self.log.info(back_spread_ticker + ' normalized, closing position') overnight_calendars.loc[i, 'working_order_id'] = self.next_val_id self.order_filled_dictionary[self.next_val_id] = 0 self.placeOrder(self.next_valid_id(), spread_contract,ib_api_trade.ComboLimitOrder('SELL', filled_alias_long, bid_price, False)) self.total_volume_traded += filled_alias_long self.total_traded_volume_since_last_confirmation += filled_alias_long self.ocs_portfolio.order_send(ticker=ticker_head + '_long', qty=-filled_alias_long) self.ocs_alias_portfolio.order_send(ticker=back_spread_ticker + '_long',qty=-filled_alias_long) self.ocs_risk_portfolio.order_send(ticker=ticker_head + '_long',qty=-filled_alias_long * dollar_noise100) self.overnight_calendars = overnight_calendars thr.Timer(10, self.periodic_call).start()
def prepare_orders(self): vcs_pairs = self.vcs_pairs for i in range(len(vcs_pairs.index)): if vcs_pairs.loc[i, 'validQ']: if (vcs_pairs.loc[i, 'QC'] <= 30) and (vcs_pairs.loc[i, 'Q'] <= 30): trade_decision = 'SELL' quantity = round(vcs_pairs.loc[i, 'long_quantity'] / 2) elif (vcs_pairs.loc[i, 'QC'] >= 70) and (vcs_pairs.loc[i, 'Q'] >= 70): trade_decision = 'BUY' quantity = round(vcs_pairs.loc[i, 'short_quantity'] / 2) else: continue exchange = cmi.get_ib_exchange_name( vcs_pairs.loc[i, 'tickerHead']) option_tick_size = cmi.option_tick_size[vcs_pairs.loc[ i, 'tickerHead']] ib_ticker_head = su.get_key_in_dictionary( dictionary_input=tfl.conversion_from_tt_ticker_head, value=vcs_pairs.loc[i, 'tickerHead']) ib_underlying_multiplier = ib_contract.ib_underlying_multiplier_dictionary.get( vcs_pairs.loc[i, 'tickerHead'], 1) spread_contract = Contract() spread_contract.symbol = ib_ticker_head spread_contract.secType = "BAG" spread_contract.currency = "USD" spread_contract.exchange = exchange spread_contract.comboLegs = [] action_dict = {1: 'SELL', 2: 'BUY'} for j in [1, 2]: call_option_ticker_string = vcs_pairs.loc[ i, 'ticker' + str(j)] + '_C_' + str( vcs_pairs.loc[i, 'current_strike' + str(j)]) put_option_ticker_string = vcs_pairs.loc[ i, 'ticker' + str(j)] + '_P_' + str( vcs_pairs.loc[i, 'current_strike' + str(j)]) leg1 = ComboLeg() leg1.conId = self.contractIDDictionary[ call_option_ticker_string] leg1.ratio = 1 leg1.action = action_dict[j] leg1.exchange = exchange leg2 = ComboLeg() leg2.conId = self.contractIDDictionary[ put_option_ticker_string] leg2.ratio = 1 leg2.action = action_dict[j] leg2.exchange = exchange spread_contract.comboLegs.append(leg1) spread_contract.comboLegs.append(leg2) mid_price_db_raw = vcs_pairs.loc[ i, 'call_mid_price2'] + vcs_pairs.loc[ i, 'put_mid_price2'] - vcs_pairs.loc[ i, 'call_mid_price1'] - vcs_pairs.loc[ i, 'put_mid_price1'] print('mid_price_db_raw: ' + str(mid_price_db_raw)) mid_price_db_raw_ticks = mid_price_db_raw / option_tick_size print('mid_price_db_raw_ticks: ' + str(mid_price_db_raw_ticks)) if trade_decision == 'BUY': order_price = ib_underlying_multiplier * m.floor( mid_price_db_raw_ticks) * option_tick_size elif trade_decision == 'SELL': order_price = ib_underlying_multiplier * m.ceil( mid_price_db_raw_ticks) * option_tick_size print(vcs_pairs.loc[i, 'ticker1'] + '_' + vcs_pairs.loc[i, 'ticker2'] + '_' + str(vcs_pairs.loc[i, 'current_strike1']) + '_' + str(vcs_pairs.loc[i, 'current_strike2'])) print(trade_decision + ', quantity: ' + str(quantity) + ', price: ' + str(order_price)) continue_q = 'n' continue_q = input('Continue? (y/n): ') if continue_q == 'y': self.order_alias_dictionary[ self.next_val_id] = vcs_pairs.loc[i, 'alias'] self.placeOrder( self.next_valid_id(), spread_contract, ib_api_trade.ComboLimitOrder(trade_decision, quantity, order_price, False))