Esempio n. 1
0
    def bracketOrder(self, action: str, quantity: float,
            limitPrice:float, takeProfitPrice: float,
            stopLossPrice: float) -> BracketOrder:
        """
        Create a limit order that is bracketed by a take-profit order and
        a stop-loss order. Submit the bracket like:

        .. code-block:: python

            for o in bracket:
                ib.placeOrder(contract, o)

        https://interactivebrokers.github.io/tws-api/bracket_order.html
        """
        assert action in ('BUY', 'SELL')
        reverseAction = 'BUY' if action == 'SELL' else 'SELL'
        parent = LimitOrder(
                action, quantity, limitPrice,
                orderId=self.client.getReqId(),
                transmit=False)
        takeProfit = LimitOrder(
                reverseAction, quantity, takeProfitPrice,
                orderId=self.client.getReqId(),
                transmit=False,
                parentId=parent.orderId)
        stopLoss = StopOrder(
                reverseAction, quantity, stopLossPrice,
                orderId=self.client.getReqId(),
                transmit=True,
                parentId=parent.orderId)
        return BracketOrder(parent, takeProfit, stopLoss)
Esempio n. 2
0
    def exit_positions(self):
        portfolio = self.get_portfolio()
        trades = self.get_trades()
        curr_date, curr_dt = get_datetime_for_logging()
        if self._nope_value > self.config["nope"]["long_exit"]:
            held_calls = self.get_held_contracts(portfolio, 'C')
            existing_call_order_ids = self.get_existing_order_ids(trades, 'C', 'SELL')
            remaining_calls = list(filter(lambda c: c['contract'].conId not in existing_call_order_ids, held_calls))

            if len(remaining_calls) > 0:
                remaining_calls.sort(key=lambda c: c['contract'].conId)
                remaining_call_contracts = [c['contract'] for c in remaining_calls]
                qualified_contracts = self.ib.qualifyContracts(*remaining_call_contracts)
                tickers = self.ib.reqTickers(*qualified_contracts)
                tickers.sort(key=lambda t: t.contract.conId)
                for idx, ticker in enumerate(tickers):
                    price = midpoint_or_market_price(ticker)
                    if not util.isNan(price):
                        quantity = remaining_calls[idx]['position']
                        order = LimitOrder("SELL", quantity, price,
                                           algoStrategy="Adaptive",
                                           algoParams=[TagValue(tag='adaptivePriority', value='Normal')],
                                           tif="DAY")
                        call_contract = ticker.contract
                        self.wait_for_trade_submitted(self.ib.placeOrder(call_contract, order))
                        with open(f"logs/{curr_date}-trade.txt", "a") as f:
                            f.write(f'Sold {quantity} {call_contract.strike}C{call_contract.lastTradeDateOrContractMonth} ({remaining_calls[idx]["avg"]} average) for {price * 100} each, {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(f'Error selling call at {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
        if self._nope_value < self.config["nope"]["short_exit"]:
            held_puts = self.get_held_contracts(portfolio, 'P')
            existing_put_order_ids = self.get_existing_order_ids(trades, 'P', 'SELL')
            remaining_puts = list(filter(lambda c: c['contract'].conId not in existing_put_order_ids, held_puts))

            if len(remaining_puts) > 0:
                remaining_puts.sort(key=lambda c: c['contract'].conId)
                remaining_put_contracts = [c['contract'] for c in remaining_puts]
                qualified_contracts = self.ib.qualifyContracts(*remaining_put_contracts)
                tickers = self.ib.reqTickers(*qualified_contracts)
                tickers.sort(key=lambda t: t.contract.conId)
                for idx, ticker in enumerate(tickers):
                    price = midpoint_or_market_price(ticker)
                    if not util.isNan(price):
                        quantity = remaining_puts[idx]['position']
                        order = LimitOrder("SELL", quantity, price,
                                           algoStrategy="Adaptive",
                                           algoParams=[TagValue(tag='adaptivePriority', value='Normal')],
                                           tif="DAY")
                        put_contract = ticker.contract
                        self.wait_for_trade_submitted(self.ib.placeOrder(put_contract, order))
                        with open(f"logs/{curr_date}-trade.txt", "a") as f:
                            f.write(f'Sold {quantity} {put_contract.strike}P{put_contract.lastTradeDateOrContractMonth} ({remaining_puts[idx]["avg"]} average) for {price * 100} each, {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(f'Error selling put at {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
Esempio n. 3
0
 def enter_positions(self):
     portfolio = self.get_portfolio()
     trades = self.get_trades()
     curr_date, curr_dt = get_datetime_for_logging()
     if self._nope_value < self.config["nope"]["long_enter"]:
         held_calls = self.get_total_position(portfolio, 'C')
         existing_order_quantity = self.get_total_buys(trades, 'C')
         total_buys = held_calls + existing_order_quantity
         if total_buys < self.config["nope"]["call_limit"]:
             contracts = self.find_eligible_contracts(self.SYMBOL, 'C')
             # TODO: Implement contract selection from eligible candidiates
             contract_to_buy = contracts[self.config["nope"]["call_strike_offset"]]
             qualified_contracts = self.ib.qualifyContracts(contract_to_buy)
             tickers = self.ib.reqTickers(*qualified_contracts)
             if len(tickers) > 0:
                 price = midpoint_or_market_price(tickers[0])
                 call_contract = qualified_contracts[0]
                 if not util.isNan(price):
                     quantity = self.config["nope"]["call_quantity"]
                     order = LimitOrder('BUY', quantity, price,
                                        algoStrategy="Adaptive",
                                        algoParams=[TagValue(tag='adaptivePriority', value='Normal')],
                                        tif="DAY")
                     self.wait_for_trade_submitted(self.ib.placeOrder(call_contract, order))
                     with open(f"logs/{curr_date}-trade.txt", "a") as f:
                         f.write(f'Bought {quantity} {call_contract.strike}C{call_contract.lastTradeDateOrContractMonth} for {price * 100} each, {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
                 else:
                     with open("logs/errors.txt", "a") as f:
                         f.write(f'Error buying call at {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
     elif self._nope_value > self.config["nope"]["short_enter"]:
         held_puts = self.get_total_position(portfolio, 'P')
         existing_order_quantity = self.get_total_buys(trades, 'P')
         total_buys = held_puts + existing_order_quantity
         if total_buys < self.config["nope"]["put_limit"]:
             contracts = self.find_eligible_contracts(self.SYMBOL, 'P')
             # TODO: Implement contract selection from eligible candidates
             contract_to_buy = contracts[-self.config["nope"]["put_strike_offset"] - 1]
             qualified_contracts = self.ib.qualifyContracts(contract_to_buy)
             tickers = self.ib.reqTickers(*qualified_contracts)
             if len(tickers) > 0:
                 price = midpoint_or_market_price(tickers[0])
                 put_contract = qualified_contracts[0]
                 if not util.isNan(price):
                     quantity = self.config["nope"]["put_quantity"]
                     order = LimitOrder('BUY', quantity, price,
                                        algoStrategy="Adaptive",
                                        algoParams=[TagValue(tag='adaptivePriority', value='Normal')],
                                        tif="DAY")
                     self.wait_for_trade_submitted(self.ib.placeOrder(put_contract, order))
                     with open(f"logs/{curr_date}-trade.txt", "a") as f:
                         f.write(f'Bought {quantity} {put_contract.strike}P{put_contract.lastTradeDateOrContractMonth} for {price * 100} each, {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
                 else:
                     with open("logs/errors.txt", "a") as f:
                         f.write(f'Error buying put at {self._nope_value} | {self._underlying_price} | {curr_dt}\n')
Esempio n. 4
0
    def write_puts(self, symbol, quantity):
        sell_ticker = self.find_eligible_contracts(symbol, "P")

        if not self.wait_for_midpoint_price(sell_ticker):
            click.secho(
                "Couldn't get midpoint price for contract={sell_ticker}, skipping for now",
                fg="red",
            )
            return

        # Create order
        order = LimitOrder(
            "SELL",
            quantity,
            round(midpoint_or_market_price(sell_ticker), 2),
            algoStrategy="Adaptive",
            algoParams=[TagValue("adaptivePriority", "Patient")],
            tif="DAY",
        )

        # Submit order
        trade = self.wait_for_trade_submitted(
            self.ib.placeOrder(sell_ticker.contract, order))
        click.echo()
        click.secho("Order submitted", fg="green")
        click.secho(f"{trade}", fg="green")
Esempio n. 5
0
 def buy_contracts(self, right):
     action = "BUY"
     contracts = self.find_eligible_contracts(self.SYMBOL, right)
     ticker = self.select_contract(contracts, right)
     if ticker is not None:
         price = midpoint_or_market_price(ticker)
         quantity = (self.config["nope"]["call_quantity"] if right == "C"
                     else self.config["nope"]["put_quantity"])
         if not util.isNan(price) and self.check_acc_balance(
                 price, quantity):
             contract = ticker.contract
             order = LimitOrder(
                 action,
                 quantity,
                 price,
                 algoStrategy="Adaptive",
                 algoParams=[
                     TagValue(tag="adaptivePriority", value="Normal")
                 ],
                 tif="DAY",
             )
             self.cancel_order_type("SELL", "STP")
             trade = self.ib.placeOrder(contract, order)
             trade.filledEvent += log_fill
             trade.filledEvent += self.on_buy_fill
             self.log_order(contract, quantity, price, action)
         else:
             with open("logs/errors.txt", "a") as f:
                 f.write(
                     f"Error buying {right} at {self._nope_value} | {self._underlying_price}\n"
                 )
Esempio n. 6
0
 def buy_contracts(self, right):
     action = "BUY"
     contracts = self.find_eligible_contracts(self.SYMBOL, right)
     # TODO: Improve contract selection https://github.com/ajhpark/ib_nope/issues/21
     offset = (self.config["nope"]["call_strike_offset"] if right == "C"
               else -self.config["nope"]["put_strike_offset"] - 1)
     contract_to_buy = contracts[offset]
     qualified_contracts = self.ib.qualifyContracts(contract_to_buy)
     tickers = self.ib.reqTickers(*qualified_contracts)
     if len(tickers) > 0:
         price = midpoint_or_market_price(tickers[0])
         if not util.isNan(price):
             contract = qualified_contracts[0]
             quantity = (self.config["nope"]["call_quantity"] if right
                         == "C" else self.config["nope"]["put_quantity"])
             order = LimitOrder(
                 action,
                 quantity,
                 price,
                 algoStrategy="Adaptive",
                 algoParams=[
                     TagValue(tag="adaptivePriority", value="Normal")
                 ],
                 tif="DAY",
             )
             trade = self.ib.placeOrder(contract, order)
             trade.filledEvent += log_fill
             self.log_order(contract, quantity, price, action)
         else:
             with open("logs/errors.txt", "a") as f:
                 f.write(
                     f"Error buying {right} at {self._nope_value} | {self._underlying_price}\n"
                 )
Esempio n. 7
0
    def write_calls(self, symbol, primary_exchange, quantity, strike_limit):
        sell_ticker = self.find_eligible_contracts(symbol, primary_exchange,
                                                   "C", strike_limit)

        if not self.wait_for_midpoint_price(sell_ticker):
            click.secho(
                "Couldn't get midpoint price for contract={sell_ticker}, skipping for now",
                fg="red",
            )
            return

        # Create order
        order = LimitOrder(
            "SELL",
            quantity,
            round(get_highest_price(sell_ticker), 2),
            algoStrategy="Adaptive",
            algoParams=[TagValue("adaptivePriority", "Patient")],
            tif="DAY",
        )

        # Submit order
        try:
            trade = self.ib.placeOrder(sell_ticker.contract, order)
            self.orders.append(trade)
            click.echo()
            click.secho("Order submitted", fg="green")
            click.secho(f"{trade}", fg="green")
        except:
            click.echo()
            click.secho(
                "Order trade submission seems to have failed, or a response wasn't received in time. Continuing anyway...",
                fg="yellow",
            )
Esempio n. 8
0
    def roll_positions(self, positions, right):
        for position in positions:
            symbol = position.contract.symbol

            sell_ticker = self.find_eligible_contracts(symbol, right)
            self.wait_for_midpoint_price(sell_ticker)

            quantity = abs(position.position)

            position.contract.exchange = "SMART"
            [buy_ticker] = self.ib.reqTickers(position.contract)
            self.wait_for_midpoint_price(buy_ticker)

            price = midpoint_or_market_price(
                buy_ticker) - midpoint_or_market_price(sell_ticker)

            # Create combo legs
            comboLegs = [
                ComboLeg(
                    conId=position.contract.conId,
                    ratio=1,
                    exchange="SMART",
                    action="BUY",
                ),
                ComboLeg(
                    conId=sell_ticker.contract.conId,
                    ratio=1,
                    exchange="SMART",
                    action="SELL",
                ),
            ]

            # Create contract
            combo = Contract(
                secType="BAG",
                symbol=symbol,
                currency="USD",
                exchange="SMART",
                comboLegs=comboLegs,
            )

            # Create order
            order = LimitOrder(
                "BUY",
                quantity,
                round(price, 2),
                algoStrategy="Adaptive",
                algoParams=[TagValue("adaptivePriority", "Patient")],
                tif="DAY",
            )

            # Submit order
            trade = self.wait_for_trade_submitted(
                self.ib.placeOrder(combo, order))
            click.secho("Order submitted", fg="green")
            click.secho(f"{trade}", fg="green")
Esempio n. 9
0
    def sell_held_contracts(self, right):
        portfolio = self.get_portfolio()
        trades = self.get_trades()
        action = "SELL"

        held_contracts_info = self.get_held_contracts_info(portfolio, right)
        existing_contract_order_ids = self.get_existing_order_ids(
            trades, right, action)
        remaining_contracts_info = list(
            filter(
                lambda c: c["contract"].conId not in
                existing_contract_order_ids,
                held_contracts_info,
            ))

        if len(remaining_contracts_info) > 0:
            remaining_contracts_info.sort(key=lambda c: c["contract"].conId)
            remaining_contracts = [
                c["contract"] for c in remaining_contracts_info
            ]
            qualified_contracts = self.ib.qualifyContracts(
                *remaining_contracts)
            tickers = self.ib.reqTickers(*qualified_contracts)
            tickers.sort(key=lambda t: t.contract.conId)
            for idx, ticker in enumerate(tickers):
                price = midpoint_or_market_price(ticker)
                avg = remaining_contracts_info[idx]["avg"]
                if not util.isNan(price):
                    quantity = remaining_contracts_info[idx]["position"]
                    order = LimitOrder(
                        action,
                        quantity,
                        price,
                        algoStrategy="Adaptive",
                        algoParams=[
                            TagValue(tag="adaptivePriority", value="Normal")
                        ],
                        tif="DAY",
                    )
                    contract = ticker.contract
                    trade = self.ib.placeOrder(contract, order)
                    trade.filledEvent += log_fill
                    self.log_order(contract, quantity, price, action, avg)
                else:
                    with open("logs/errors.txt", "a") as f:
                        f.write(
                            f"Error selling {right} at {self._nope_value} | {self._underlying_price}\n"
                        )
Esempio n. 10
0
    def ib_submit_order(
        self,
        contract_object_with_ib_data,
        trade_list,
        account="",
        order_type="market",
        limit_price=None,
    ):

        if contract_object_with_ib_data.is_spread_contract():
            ibcontract_with_legs = self.ib_futures_contract(
                contract_object_with_ib_data,
                trade_list_for_multiple_legs=trade_list,
                return_leg_data=True,
            )
            ibcontract = ibcontract_with_legs.ibcontract
        else:
            ibcontract = self.ib_futures_contract(contract_object_with_ib_data)
            ibcontract_with_legs = ibcontractWithLegs(ibcontract)

        if ibcontract is missing_contract:
            return missing_order

        ib_BS_str, ib_qty = resolveBS_for_list(trade_list)

        if order_type == "market":
            ib_order = MarketOrder(ib_BS_str, ib_qty)
        elif order_type == "limit":
            if limit_price is None:
                self.log.critical("Need to have limit price with limit order!")
                return missing_order
            else:
                ib_order = LimitOrder(ib_BS_str, ib_qty, limit_price)
        else:
            self.log.critical("Order type %s not recognised!" % order_type)
            return missing_order

        if account != "":
            ib_order.account = account

        order_object = self.ib.placeOrder(ibcontract, ib_order)

        # for consistency with spread orders
        trade_with_contract = tradeWithContract(ibcontract_with_legs,
                                                order_object)

        return trade_with_contract
Esempio n. 11
0
    def write_puts(self, symbol, quantity):
        sell_ticker = self.find_eligible_contracts(symbol, "P")

        # Create order
        order = LimitOrder(
            "SELL",
            quantity,
            round(sell_ticker.marketPrice(), 2),
            algoStrategy="Adaptive",
            algoParams=[TagValue("adaptivePriority", "Patient")],
            tif="DAY",
        )

        # Submit order
        trade = self.ib.placeOrder(sell_ticker.contract, order)
        click.echo()
        click.secho("Order submitted", fg="green")
        click.secho(f"{trade}", fg="green")
Esempio n. 12
0
    def write_calls(self, symbol, quantity, min_strike):
        sell_ticker = self.find_eligible_contracts(symbol, "C", min_strike)

        self.wait_for_midpoint_price(sell_ticker)

        # Create order
        order = LimitOrder(
            "SELL",
            quantity,
            round(midpoint_or_market_price(sell_ticker), 2),
            algoStrategy="Adaptive",
            algoParams=[TagValue("adaptivePriority", "Patient")],
            tif="DAY",
        )

        # Submit order
        trade = self.wait_for_trade_submitted(
            self.ib.placeOrder(sell_ticker.contract, order))
        click.echo()
        click.secho("Order submitted", fg="green")
        click.secho(f"{trade}", fg="green")
Esempio n. 13
0
    def enter_positions(self):
        portfolio = self.get_portfolio()
        trades = self.get_trades()
        action = 'BUY'

        if self._nope_value < self.config["nope"]["long_enter"]:
            held_calls = self.get_total_position(portfolio, 'C')
            existing_order_quantity = self.get_total_buys(trades, 'C')
            total_buys = held_calls + existing_order_quantity
            if total_buys < self.config["nope"]["call_limit"]:
                contracts = self.find_eligible_contracts(self.SYMBOL, 'C')
                # TODO: Implement contract selection from eligible candidiates
                contract_to_buy = contracts[self.config["nope"]
                                            ["call_strike_offset"]]
                qualified_contracts = self.ib.qualifyContracts(contract_to_buy)
                tickers = self.ib.reqTickers(*qualified_contracts)
                if len(tickers) > 0:
                    price = midpoint_or_market_price(tickers[0])
                    call_contract = qualified_contracts[0]
                    if not util.isNan(price):
                        quantity = self.config["nope"]["call_quantity"]
                        order = LimitOrder(action,
                                           quantity,
                                           price,
                                           algoStrategy="Adaptive",
                                           algoParams=[
                                               TagValue(tag='adaptivePriority',
                                                        value='Normal')
                                           ],
                                           tif="DAY")
                        trade = self.ib.placeOrder(call_contract, order)
                        trade.filledEvent += log_fill
                        self.log_order(call_contract, quantity, price, action)
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(
                                f'Error buying call at {self._nope_value} | {self._underlying_price}\n'
                            )
        elif self._nope_value > self.config["nope"]["short_enter"]:
            held_puts = self.get_total_position(portfolio, 'P')
            existing_order_quantity = self.get_total_buys(trades, 'P')
            total_buys = held_puts + existing_order_quantity
            if total_buys < self.config["nope"]["put_limit"]:
                contracts = self.find_eligible_contracts(self.SYMBOL, 'P')
                # TODO: Implement contract selection from eligible candidates
                contract_to_buy = contracts[
                    -self.config["nope"]["put_strike_offset"] - 1]
                qualified_contracts = self.ib.qualifyContracts(contract_to_buy)
                tickers = self.ib.reqTickers(*qualified_contracts)
                if len(tickers) > 0:
                    price = midpoint_or_market_price(tickers[0])
                    put_contract = qualified_contracts[0]
                    if not util.isNan(price):
                        quantity = self.config["nope"]["put_quantity"]
                        order = LimitOrder(action,
                                           quantity,
                                           price,
                                           algoStrategy="Adaptive",
                                           algoParams=[
                                               TagValue(tag='adaptivePriority',
                                                        value='Normal')
                                           ],
                                           tif="DAY")
                        trade = self.ib.placeOrder(put_contract, order)
                        trade.filledEvent += log_fill
                        self.log_order(put_contract, quantity, price, action)
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(
                                f'Error buying put at {self._nope_value} | {self._underlying_price}\n'
                            )
Esempio n. 14
0
    def exit_positions(self):
        portfolio = self.get_portfolio()
        trades = self.get_trades()
        action = 'SELL'

        if self._nope_value > self.config["nope"]["long_exit"]:
            held_calls = self.get_held_contracts(portfolio, 'C')
            existing_call_order_ids = self.get_existing_order_ids(
                trades, 'C', 'SELL')
            remaining_calls = list(
                filter(
                    lambda c: c['contract'].conId not in
                    existing_call_order_ids, held_calls))

            if len(remaining_calls) > 0:
                remaining_calls.sort(key=lambda c: c['contract'].conId)
                remaining_call_contracts = [
                    c['contract'] for c in remaining_calls
                ]
                qualified_contracts = self.ib.qualifyContracts(
                    *remaining_call_contracts)
                tickers = self.ib.reqTickers(*qualified_contracts)
                tickers.sort(key=lambda t: t.contract.conId)
                for idx, ticker in enumerate(tickers):
                    price = midpoint_or_market_price(ticker)
                    if not util.isNan(price):
                        quantity = remaining_calls[idx]['position']
                        order = LimitOrder(action,
                                           quantity,
                                           price,
                                           algoStrategy="Adaptive",
                                           algoParams=[
                                               TagValue(tag='adaptivePriority',
                                                        value='Normal')
                                           ],
                                           tif="DAY")
                        call_contract = ticker.contract
                        trade = self.ib.placeOrder(call_contract, order)
                        trade.filledEvent += log_fill
                        self.log_order(call_contract, quantity, price, action,
                                       remaining_calls[idx]['avg'])
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(
                                f'Error selling call at {self._nope_value} | {self._underlying_price}\n'
                            )
        if self._nope_value < self.config["nope"]["short_exit"]:
            held_puts = self.get_held_contracts(portfolio, 'P')
            existing_put_order_ids = self.get_existing_order_ids(
                trades, 'P', 'SELL')
            remaining_puts = list(
                filter(
                    lambda c: c['contract'].conId not in
                    existing_put_order_ids, held_puts))

            if len(remaining_puts) > 0:
                remaining_puts.sort(key=lambda c: c['contract'].conId)
                remaining_put_contracts = [
                    c['contract'] for c in remaining_puts
                ]
                qualified_contracts = self.ib.qualifyContracts(
                    *remaining_put_contracts)
                tickers = self.ib.reqTickers(*qualified_contracts)
                tickers.sort(key=lambda t: t.contract.conId)
                for idx, ticker in enumerate(tickers):
                    price = midpoint_or_market_price(ticker)
                    if not util.isNan(price):
                        quantity = remaining_puts[idx]['position']
                        order = LimitOrder(action,
                                           quantity,
                                           price,
                                           algoStrategy="Adaptive",
                                           algoParams=[
                                               TagValue(tag='adaptivePriority',
                                                        value='Normal')
                                           ],
                                           tif="DAY")
                        put_contract = ticker.contract
                        trade = self.ib.placeOrder(put_contract, order)
                        trade.filledEvent += log_fill
                        self.log_order(put_contract, quantity, price, action,
                                       remaining_puts[idx]['avg'])
                    else:
                        with open("logs/errors.txt", "a") as f:
                            f.write(
                                f'Error selling put at {self._nope_value} | {self._underlying_price}\n'
                            )
Esempio n. 15
0
    def roll_positions(self, positions, right, portfolio_positions={}):
        for position in positions:
            symbol = position.contract.symbol
            strike_limit = get_strike_limit(self.config, symbol, right)
            if right.startswith("C"):
                strike_limit = math.ceil(
                    max([strike_limit or 0] + [
                        p.averageCost for p in portfolio_positions[symbol]
                        if isinstance(p.contract, Stock)
                    ]))

            sell_ticker = self.find_eligible_contracts(
                symbol,
                self.get_primary_exchange(symbol),
                right,
                strike_limit,
                excluded_expirations=[
                    position.contract.lastTradeDateOrContractMonth
                ],
            )
            self.wait_for_midpoint_price(sell_ticker)

            quantity = abs(position.position)

            position.contract.exchange = "SMART"
            [buy_ticker] = self.ib.reqTickers(position.contract)
            self.wait_for_midpoint_price(buy_ticker)

            price = midpoint_or_market_price(
                buy_ticker) - midpoint_or_market_price(sell_ticker)

            # Create combo legs
            comboLegs = [
                ComboLeg(
                    conId=position.contract.conId,
                    ratio=1,
                    exchange="SMART",
                    action="BUY",
                ),
                ComboLeg(
                    conId=sell_ticker.contract.conId,
                    ratio=1,
                    exchange="SMART",
                    action="SELL",
                ),
            ]

            # Create contract
            combo = Contract(
                secType="BAG",
                symbol=symbol,
                currency="USD",
                exchange="SMART",
                comboLegs=comboLegs,
            )

            # Create order
            order = LimitOrder(
                "BUY",
                quantity,
                round(price, 2),
                algoStrategy="Adaptive",
                algoParams=[TagValue("adaptivePriority", "Patient")],
                tif="DAY",
            )

            # Submit order
            trade = self.ib.placeOrder(combo, order)
            self.orders.append(trade)
            click.echo()
            click.secho("Order submitted", fg="green")
            click.secho(f"{trade}", fg="green")
Esempio n. 16
0
    def open_strategy(self, strategy: Strategy) -> None:
        """Place a new strategy at the market
        """

        ownership = "BUY" if strategy.ownership == OwnershipType.Buyer else "SELL"
        reverse_ownership = "BUY" if ownership == "SELL" else "SELL"

        contract = Contract()
        contract.symbol = strategy.code
        contract.secType = "BAG"
        contract.exchange = "SMART"
        contract.currency = strategy.currency.value
        order_comboLegs = []
        tp_sl_comboLegs = []

        for leg in strategy.legs.values():
            leg_order = ComboLeg()
            leg_order.conId = leg.option.contract.conId
            leg_order.ratio = leg.ratio
            leg_order.action = "BUY" if leg.ownership == OwnershipType.Buyer else "SELL"
            # contract.comboLegs.append(leg_order)
            order_comboLegs.append(leg_order)

        for leg in strategy.legs.values():
            leg_tp_sl = ComboLeg()
            leg_tp_sl.conId = leg.option.contract.conId
            leg_tp_sl.ratio = leg.ratio
            leg_tp_sl.action = (
                "SELL" if leg.ownership == OwnershipType.Buyer else "BUY"
            )  # reverse
            # contract.comboLegs.append(leg_order)
            tp_sl_comboLegs.append(leg_tp_sl)

        contract.comboLegs = order_comboLegs
        order = LimitOrder(
            action="BUY"
            if strategy.ownership == OwnershipType.Buyer else "SELL",
            totalQuantity=strategy.quantity,
            lmtPrice=strategy.entry_price,
            orderRef=strategy.strategy_id,
            orderId=self._broker.client.getReqId(),
            tif="GTC",
            transmit=True,
        )  # Must be False
        print("ORDER SENDED")
        self._broker.placeOrder(contract, order)

        # contract.comboLegs = tp_sl_comboLegs

        # print('take_profit_order', strategy.take_profit_price)
        take_profit = LimitOrder(
            action="SELL"
            if strategy.ownership == OwnershipType.Buyer else "BUY",  # reverse
            totalQuantity=strategy.quantity,
            lmtPrice=strategy.take_profit_price,
            # lmtPrice = -0.1,
            orderRef=strategy.strategy_id + "_TP",
            orderId=self._broker.client.getReqId(),
            tif="GTC",
            transmit=True,
            parentId=order.orderId,
        )
        self._broker.placeOrder(contract, take_profit)
Esempio n. 17
0
    def roll_positions(self,
                       positions,
                       right,
                       account_summary,
                       portfolio_positions={}):
        for position in positions:
            try:
                symbol = position.contract.symbol
                strike_limit = get_strike_limit(self.config, symbol, right)
                if right.startswith("C"):
                    strike_limit = math.ceil(
                        max([strike_limit or 0] + [
                            p.averageCost for p in portfolio_positions[symbol]
                            if isinstance(p.contract, Stock)
                        ]))

                sell_ticker = self.find_eligible_contracts(
                    symbol,
                    self.get_primary_exchange(symbol),
                    right,
                    strike_limit,
                    exclude_expirations_before=position.contract.
                    lastTradeDateOrContractMonth,
                    exclude_first_exp_strike=position.contract.strike,
                )

                qty_to_roll = abs(position.position)
                maximum_new_contracts = self.get_maximum_new_contracts_for(
                    symbol,
                    self.get_primary_exchange(symbol),
                    account_summary,
                )
                from_dte = option_dte(
                    position.contract.lastTradeDateOrContractMonth)
                roll_when_dte = self.config["roll_when"]["dte"]
                if from_dte > roll_when_dte:
                    qty_to_roll = min([qty_to_roll, maximum_new_contracts])

                position.contract.exchange = "SMART"
                buy_ticker = self.get_ticker_for(position.contract,
                                                 midpoint=True)

                price = midpoint_or_market_price(
                    buy_ticker) - midpoint_or_market_price(sell_ticker)

                # Create combo legs
                comboLegs = [
                    ComboLeg(
                        conId=position.contract.conId,
                        ratio=1,
                        exchange="SMART",
                        action="BUY",
                    ),
                    ComboLeg(
                        conId=sell_ticker.contract.conId,
                        ratio=1,
                        exchange="SMART",
                        action="SELL",
                    ),
                ]

                # Create contract
                combo = Contract(
                    secType="BAG",
                    symbol=symbol,
                    currency="USD",
                    exchange="SMART",
                    comboLegs=comboLegs,
                )

                # Create order
                order = LimitOrder(
                    "BUY",
                    qty_to_roll,
                    round(price, 2),
                    algoStrategy="Adaptive",
                    algoParams=[TagValue("adaptivePriority", "Patient")],
                    tif="DAY",
                )

                to_dte = option_dte(
                    sell_ticker.contract.lastTradeDateOrContractMonth)
                from_strike = position.contract.strike
                to_strike = sell_ticker.contract.strike

                # Submit order
                trade = self.ib.placeOrder(combo, order)
                self.orders.append(trade)
                click.echo()
                click.secho(
                    f"Order submitted, current position={abs(position.position)}, qty_to_roll={qty_to_roll}, from_dte={from_dte}, to_dte={to_dte}, from_strike={from_strike}, to_strike={to_strike}, price={round(price,2)}, trade={trade}",
                    fg="green",
                )
            except RuntimeError as e:
                click.echo()
                click.secho(str(e), fg="red")
                click.secho(
                    "Error occurred when trying to roll position. Continuing anyway...",
                    fg="yellow",
                )