def sell(self, contract, position):
        
        self.ib.qualifyContracts(contract)
        if position.position>0:
            order = 'Sell'
        else:
            order = 'Buy'

        marketorder = MarketOrder(order, abs(position.position))

        if self.tradeTime!=0:
            timeDelta = datetime.datetime.now() - self.tradeTime
            if timeDelta.seconds > self.waitTimeInSeconds:
                marketTrade, contract, self.tradeTime = self.placeOrder(contract, marketorder)
        else:
            marketTrade, contract, tradeTime = self.placeOrder(contract, marketorder)
        condition = marketTrade.isDone
        timeout = 20
        for c in self.ib.loopUntil(condition=condition, timeout=timeout):
            marketorder = MarketOrder('Sell', position.position)
            marketTrade = self.ib.placeOrder(contract, marketorder)

        if not condition == 'Filled':
            self.ib.cancelOrder(marketorder)
            marketorder = MarketOrder('Sell', position.position)
            marketTrade = self.ib.placeOrder(contract, marketorder)
Beispiel #2
0
 def order_send(self, type, lots, sl=0, tp=0, comment=''):
     market_order = MarketOrder(type, lots)
     #initial_margin, maintenance_margin = self.get_margins(market_order)
     self.ib.placeOrder(self.contract, market_order)
     id = market_order.orderId
     
     self.number += 1
     price = 0
     while price == 0:
         self.ib.sleep(1)
         price, commission = self.order_values(id)
     profit = self.calculate_profit(type, price, lots)
     trade = {'date':str(self.date)+' '+str(self.hour), 'id':id, 'type':type, 'lots':lots, 'price':price, 
              'S/L':sl, 'T/P':tp, 'commission':commission, 'comment':comment, 'profit':profit}
     self.save_trade(trade)
     self.pool = pd.concat([self.pool,pd.DataFrame(trade,index=[self.number])], sort=False)
     self.history = pd.concat([self.history,pd.DataFrame(trade,index=[self.number])], sort=False)
     mult = (lambda dir: 1 if dir == 'BUY' else -1)(type)
     self.position += (mult*lots)
     self.pool_check()
     if self.verbose:
         print('%s %s | %sING %d units at %5.5f in %s (market)' % (str(self.date), str(self.hour), type, lots, price, self.symbol))
     if self.notification:
         if self.position != 0:
             self.send_message_in(type, price, sl, tp, lots)
         else:
             self.send_message_out(type, price, lots, profit, commission, commission)
 def place_market_order(self, contract, qty, fn_on_filled, orderType):
     order = MarketOrder(order_util.get_order_action(qty),
                         abs(qty),
                         openClose=orderType)
     trade = self.ib.placeOrder(contract, order)
     self.loggerOrderHistory.info('\nOpened\n' + str(trade) + '\n\n')
     trade.filledEvent += fn_on_filled
     return trade
 def buy(self, contract):
     self.ib.qualifyContracts(contract)
     marketorder = MarketOrder('Buy', 1)
     if self.tradeTime!=0:
         timeDelta = datetime.datetime.now() - self.tradeTime
         if timeDelta.seconds > self.waitTimeInSeconds:
             marketTrade, contract, self.tradeTime = self.placeOrder(contract, marketorder)
     else:
         marketTrade, contract, tradeTime = self.placeOrder(contract, marketorder)
     condition = marketTrade.isDone
     timeout = 10
     for c in self.ib.loopUntil(condition=condition, timeout=timeout):
         marketorder = MarketOrder('Buy', 1)
         marketTrade = self.ib.placeOrder(contract, marketorder)
     if not condition == 'Filled':
         self.ib.cancelOrder(marketorder)
         marketorder = MarketOrder('Buy', 1)
         marketTrade = self.ib.placeOrder(contract, marketorder)
Beispiel #5
0
 def entry_order(action: str, quantity: int) -> Order:
     """
     Return order to be used for entry transactions.
     """
     return MarketOrder(action, quantity,
                        algoStrategy='Adaptive',
                        algoParams=[
                            TagValue('adaptivePriority', 'Normal')],
                        tif='Day')
Beispiel #6
0
 def trade(self, contract: Contract, signal: int,
           amount: int) -> Trade:
     direction = {1: 'BUY', -1: 'SELL'}
     order = MarketOrder(direction[signal], amount, algoStrategy='Adaptive',
                         algoParams=[TagValue('adaptivePriority', 'Normal')])
     message = (f'entering {direction[signal]} order for {amount} '
                f'{contract.localSymbol}')
     log.debug(message)
     return self.ib.placeOrder(contract, order)
Beispiel #7
0
    def _create_fx_market_order_for_submission(
            self,
            trade: float,
            account_id: str = arg_not_supplied) -> MarketOrder:

        ib_BS_str, ib_qty = resolveBS(trade)
        ib_order = MarketOrder(ib_BS_str, ib_qty)
        if account_id is not arg_not_supplied:
            ib_order.account = account_id

        return ib_order
Beispiel #8
0
 def reqCommissionsFromIB(self, contracts: List) -> Dict:
     order = MarketOrder('BUY', 1)
     commissions = {contract.symbol: self.read_from_file_or_ib(
         'commission',  'whatIfOrder', contract, order)
         for contract in contracts}
     missing_commissions = []
     for contract, commission in commissions.copy().items():
         if not commission:
             missing_commissions.append(contract)
             del commissions[contract]
     commissions.update(self.getCommissionBySymbol(missing_commissions))
     return commissions
Beispiel #9
0
def update_details(ib: IB, store: AbstractBaseStore,
                   keys: Optional[Union[str, List[str]]] = None) -> None:
    """
    Pull contract details from ib and update metadata in store.

    Args:
    ib: connected IB instance
    store: datastore instance, for which data will be updated
    keys (Optional): keys in datastore, for which data is to be updated,
                     if not given, update all keys
    """
    if keys is None:
        keys = store.keys()
    elif isinstance(keys, str):
        keys = [keys]

    contracts = {}
    for key in keys:
        try:
            contract = eval(store.read_metadata(key)['repr'])
        except TypeError:
            log.error(f'Metadata missing for {key}')
            continue
        contract.update(includeExpired=True)
        contracts[key] = contract
    ib.qualifyContracts(*contracts.values())
    details = {}
    for k, v in contracts.copy().items():
        try:
            details[k] = ib.reqContractDetails(v)[0]
        except IndexError:
            log.error(f'Contract unavailable: {k}')
            del contracts[k]

    # get commission levels
    order = MarketOrder('BUY', 1)
    commissions = {}
    for k, v in contracts.items():
        try:
            commissions[k] = ib.whatIfOrder(v, order).commission
        except AttributeError:
            log.error(f'Commission unavailable for: {k}')
            commissions[k] = np.nan

    for c, d in details.items():
        _d = {'name': d.longName,
              'min_tick': d.minTick,
              'commission': commissions[c]
              }
        store.write_metadata(c, _d)

    log.info('Data written to store.')
Beispiel #10
0
    def sell(self, contract, position):
        self.ib.qualifyContracts(contract)
        if position.position > 0:
            order = 'Sell'
        else:
            order = 'Buy'

        marketorder = MarketOrder(order, abs(position.position))
        marketTrade, contract, tradeTime = self.placeOrder(
            contract, marketorder)
        while self.ib.position.position != 0:
            self.ib.sleep(1)
        self.mySemaphore.release()
Beispiel #11
0
    def sell(self, ticker, rank, order_type):
        log_start = datetime.datetime.now()
        log = logging_.Logging(
            self.runtime_tm, log_start,
            str(self.__class__.__name__ + ',' +
                sys._getframe().f_code.co_name))
        self.hlprs.add_to_manager(self.strat_name, *log.monitor())
        order_log_msg = None
        symbol = ticker.contract.symbol
        try:
            ix = self.portfolio_instr.index(symbol)
        except ValueError:
            status = -1
            print(
                'not quite sure why this error sometimes occurs and if this is maybe to early to leave?'
            )
            return status

        # if isinstance(ticker.domBids, str) == True:
        #     offer_price = ticker.domAsks.price
        #     offer_size = ticker.domAsks.size
        # else:
        #     offer_price = ticker.domAsks[rank].price
        #     offer_size = ticker.domAsks[rank].size
        price_ix = 2
        size_ix = 3
        # held_price = self.held[ix][price_ix]
        held_size = self.portfolio[ix][size_ix]

        cnt = 0
        max_order_filled_cnts = int(ORDER_CANCEL_IF_NOT_FILLED_SECS /
                                    ORDER_FILLED_CHECKED_CYCLE_SECS)
        if not self.debugging.dummy_data:
            if order_type == 'MKT':
                order = MarketOrder('SELL', held_size)
                # https://github.com/erdewit/ib_insync/blob/master/notebooks/ordering.ipynb
                trade = self.ib.placeOrder(ticker.contract, order)
                while cnt < max_order_filled_cnts:
                    order_log_msg = trade.log
                    self.ib.sleep(ORDER_FILLED_CHECKED_CYCLE_SECS)
                    cnt += 1
                    if trade.orderStatus.status == 'Filled':
                        order_success = True
                        break
                self.ib.cancelOrder(trade)
                while not trade.isDone():
                    print("not sure if this makes sense")
                    self.ib.waitOnUpdate()
            elif order_type == 'LMT':
                raise Exception("order type not defined")
            else:
                raise Exception("order type not defined")
        else:
            order_success = True
        order_success = True
        if order_success:
            status = 0
            del self.portfolio[ix]
            self.hlprs.add_to_manager(self.strat_name, 'portfolio',
                                      self.portfolio)
            del self.portfolio_instr[ix]
            # self.add_to_monitor('portfolio_instr', self.portfolio_instr)
            print('not sure if this works')
            self.cnt_trades_per_instr_per_day[ticker.contract.symbol] += 1
            self.hlprs.add_to_manager(self.strat_name,
                                      'cnt_trades_per_instr_per_day',
                                      self.cnt_trades_per_instr_per_day)
            self.heartbeat_q.put([
                self.strat_name, 'cnt_trades_per_instr_per_day',
                self.cnt_trades_per_instr_per_day
            ])
            self.hlprs.add_to_manager(
                self.strat_name, 'cap_usd',
                self.cash.available_funds(self.report.pnl(),
                                          self.account_curr))
        else:
            status = 1
        log.log(self.portfolio, self.portfolio_instr,
                self.cnt_trades_per_instr_per_day, order_log_msg)
        return status
Beispiel #12
0
    def buy(self, ticker, rank, size, order_type):
        log_start = datetime.datetime.now()
        log = logging_.Logging(
            self.runtime_tm, log_start,
            str(self.__class__.__name__ + ',' +
                sys._getframe().f_code.co_name))
        self.hlprs.add_to_manager(self.strat_name, *log.monitor())
        order_log_msg = None
        symbol = ticker.contract.symbol
        if self._ticker_len_n_type_check(ticker.domBids) > 1:
            offer_price = ticker.domBids[rank].price
            # offer_size = ticker.domBids[rank].size
        else:
            offer_price = ticker.domBids.price
            # offer_size = ticker.domBids.size
        cnt = 0
        max_order_filled_cnts = int(ORDER_CANCEL_IF_NOT_FILLED_SECS /
                                    ORDER_FILLED_CHECKED_CYCLE_SECS)
        if self.debugging.dummy_data:
            order_success = True
        else:
            if order_type == 'MKT':
                order = MarketOrder('BUY', size)
                trade = self.ib.placeOrder(ticker.contract, order)
                while cnt < max_order_filled_cnts:  # a bit complicated but it does actually make sense
                    order_log_msg = trade.log
                    self.ib.sleep(ORDER_FILLED_CHECKED_CYCLE_SECS)
                    cnt += 1
                    if not trade.orderStatus.status != 'Filled':
                        # PendingSubmit = 'PendingSubmit'
                        # PendingCancel = 'PendingCancel'
                        # PreSubmitted = 'PreSubmitted'
                        # Submitted = 'Submitted'
                        # ApiPending = 'ApiPending'  # undocumented, can be returned from req(All)OpenOrders
                        # ApiCancelled = 'ApiCancelled'
                        # Cancelled = 'Cancelled'
                        # Filled = 'Filled'
                        # Inactive = 'Inactive'
                        order_success = True
                        break
                else:
                    self.ib.cancelOrder(trade)
                # while not trade.isDone():
                #     print("not sure if this makes sense")
                #     self.ib.waitOnUpdate()
            elif order_type == 'LMT':
                raise Exception("order type not defined")
            else:
                raise Exception("order type not defined")
        if order_success:
            if self.debugging.dummy_time:
                _now = self._manipulated_time(datetime.datetime.now())
            else:
                _now = datetime.datetime.now()

            filled_tm = self.us_tz_op(_now)
            status = 0
            self.portfolio.append([symbol, filled_tm, offer_price, size])
            self.hlprs.add_to_manager(self.strat_name, 'portfolio',
                                      self.portfolio)

            self.portfolio_instr.append(symbol)
            # self.add_to_monitor('portfolio_instr', 'self.portfolio_instr')

            print('not sure if this works')
            self.cnt_trades_per_instr_per_day[ticker.contract.symbol] += 1
            self.hlprs.add_to_manager(self.strat_name,
                                      'cnt_trades_per_instr_per_day',
                                      self.cnt_trades_per_instr_per_day)
            self.heartbeat_q.put([
                self.strat_name, 'cnt_trades_per_instr_per_day',
                self.cnt_trades_per_instr_per_day
            ])
            self.hlprs.add_to_manager(
                self.strat_name, 'cap_usd',
                self.cash.available_funds(self.report.pnl(),
                                          self.account_curr))
        else:
            status = 1
        log.log(self.portfolio, self.portfolio_instr,
                self.cnt_trades_per_instr_per_day, order_log_msg)
        return status
Beispiel #13
0
 async def buy(self, contract):
     await self.semaphore.acquire()
     self.ib.qualifyContracts(contract)
     marketorder = MarketOrder('Buy', 1)
     marketTrade = self.ib.placeOrder(contract, marketorder)
Beispiel #14
0
 def close_order(action: str, quantity: int) -> Order:
     return MarketOrder(action, quantity, tif='GTC')
Beispiel #15
0
 def place_market_order(self, contract, qty, fn_on_filled):
     order = MarketOrder(order_util.get_order_action(qty), abs(qty))
     trade = self.ib.placeOrder(contract, order)
     trade.filledEvent += fn_on_filled
     return trade
Beispiel #16
0
def main():
    # query config
    config = db.collection('config').document('paper' if TRADING_MODE == 'local' else TRADING_MODE).get().to_dict()

    # activity log for Firestore
    activity_log = {
        'agent': (re.match('([\\w-]+)-([0-9]+|manual-[0-9a-z]+)-[0-9a-z]+$', HOSTNAME)).group(1) if HOSTNAME is not None else 'localhost',
        'environment': {'DRY_RUN': DRY_RUN, 'ORDER_PROPERTIES': ORDER_PROPERTIES, 'STRATEGIES': STRATEGIES, 'TRADING_MODE': TRADING_MODE},
        'config': config,
        'exception': None
    }

    main_e = None
    try:
        strategies = STRATEGIES.split(',') if STRATEGIES is not None else []
        gateway = 'localhost' if TRADING_MODE == 'local' else 'ib-gw-' + TRADING_MODE
        order_properties = json.loads(ORDER_PROPERTIES)

        logger.info('Running allocator for {}...'.format(strategies))

        # get signals for all strategies
        signals = {s: get_signal('localhost' if TRADING_MODE == 'local' else s) for s in strategies}
        activity_log['signals'] = signals
        # scale w/ exposure
        scaled_signals = [
            {
                instr: alloc * config['exposure']['strategies'][strat]
                for instr, alloc in sig.items()
            } for strat, sig in signals.items()
        ]
        activity_log['scaledSignals'] = scaled_signals

        # consolidate strategies
        allocation = make_allocation(scaled_signals)
        activity_log['allocation'] = allocation
        logger.info('Allocation: {}'.format(activity_log['allocation']))

        # connect to IB gateway
        ib_gw.connect(gateway, 4003, 1)

        # get net liquidation value
        account_values = get_account_values(config['account'])
        base_currency = list(account_values['NetLiquidation'].keys())[0]
        net_liquidation = float(account_values['NetLiquidation'][base_currency])
        activity_log['netLiquidation'] = net_liquidation

        # get positions
        positions = {item.contract.conId: item.position for item in ib_gw.positions(config['account'])}
        activity_log['positions'] = positions

        # get contract details
        contract_data = get_contract_data(set(list(allocation.keys()) + list(positions.keys())))
        # build contractId->symbol lookup dict
        symbol_map = {k: v['contract'].localSymbol for k, v in contract_data.items()}
        activity_log['contractIds'] = {v['contract'].localSymbol: k for k, v in contract_data.items()}
        # replace dict keys
        activity_log['signals'] = {k: {symbol_map[k]: v for k, v in v.items()} for k, v in signals.items()}
        activity_log['scaledSignals'] = [{symbol_map[k]: v for k, v in s.items()} for s in scaled_signals]
        activity_log['allocation'] = {symbol_map[k]: v for k, v in allocation.items()}
        activity_log['positions'] = {symbol_map[k]: v for k, v in positions.items()}

        # get relevant currencies and corresponding FX ratese
        currencies = {v['contract'].currency for v in contract_data.values()}
        fx = {
            c: 1 if c == base_currency else get_tickers(Forex(c + base_currency))
            for c in currencies
        }
        activity_log['fx'] = {
            v.contract.symbol + v.contract.currency: v.midpoint()
            if v.midpoint() == v.midpoint() else v.close
            for v in fx.values()
        }

        # calculate target positions
        target_positions = {
            k: round(config['exposure']['overall'] * v * net_liquidation
                     / (contract_data[k]['ticker'].close
                        * int(contract_data[k]['contract'].multiplier)
                        * (fx[contract_data[k]['contract'].currency].midpoint()
                           if fx[contract_data[k]['contract'].currency].midpoint() == fx[contract_data[k]['contract'].currency].midpoint()
                           else fx[contract_data[k]['contract'].currency].close)))
            for k, v in allocation.items()
        }

        for k in target_positions.keys():
            if k not in positions:
                positions[k] = 0
        for k in positions.keys():
            if k not in target_positions:
                target_positions[k] = 0
        activity_log['positions'] = {symbol_map[k]: v for k, v in positions.items()}
        activity_log['targetPositions'] = {symbol_map[k]: v for k, v in target_positions.items()}

        # calculate trade
        trades = {k: target_positions[k] - positions[k] for k in target_positions.keys()}
        trades = {k: int(v) for k, v in trades.items() if v != 0}
        activity_log['trades'] = {symbol_map[k]: v for k, v in trades.items()}
        logger.info('Trades: {}'.format(activity_log['trades']))

        perm_ids = []
        if not DRY_RUN:
            # place orders
            for k, v in trades.items():
                order = ib_gw.placeOrder(contract_data[k]['contract'],
                                         MarketOrder(action='BUY' if v > 0 else 'SELL',
                                                     totalQuantity=abs(v)).update(**order_properties))
                perm_ids.append(order.order.permId)
        ib_gw.sleep(5)  # give the IB Gateway a couple of seconds to digest orders and to raise possible errors
        activity_log['orders'] = {
            t.contract.localSymbol: {
                'order': {
                    k: v
                    for k, v in t.order.nonDefaults().items()
                    if isinstance(v, (int, float, str))
                },
                'orderStatus': {
                    k: v
                    for k, v in t.orderStatus.nonDefaults().items()
                    if isinstance(v, (int, float, str))
                },
                'isActive': t.isActive()
            } for t in ib_gw.trades() if t.order.permId in perm_ids
        }
        logging.info('Orders placed: {}'.format(activity_log['orders']))

    except Exception as e:
        logger.error(e)
        activity_log['exception'] = str(e)
        main_e = e

    finally:
        ib_gw.disconnect()

        try:
            activity_log['timestamp'] = datetime.now(timezone.utc)
            db.collection('activity').document().set(activity_log)
        except Exception as e:
            logger.error(e)
            logger.info(activity_log)

    if main_e is not None:
        # raise main exception so that CronJob is restarted
        raise main_e

    logger.info('Done.')
Beispiel #17
0
 def close_order(action: str, quantity: int) -> Order:
     """
     Return order to be used for close transactions.
     """
     return MarketOrder(action, quantity, tif='GTC')