예제 #1
0
    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)
예제 #2
0
    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()
예제 #3
0
    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))