예제 #1
0
    def get_realtime_bars(self, assets, frequency):
        if frequency == '1m':
            resample_freq = '1 Min'
        elif frequency == '1d':
            resample_freq = '24 H'
        else:
            raise ValueError("Invalid frequency specified: %s" % frequency)

        df = pd.DataFrame()
        for asset in assets:
            self.subscribe_to_market_data(asset)

            ib_symbol = self._asset_symbol(asset)
            if ib_symbol in self._tws.bars:
                trade_prices = self._tws.bars[ib_symbol]['last_trade_price']
                trade_sizes = self._tws.bars[ib_symbol]['last_trade_size']
            else:
                log.warning("No tws bar for '%s'." % ib_symbol)
                trade_prices = pd.Series([1.0], index=[pd.to_datetime('now')])
                trade_sizes = pd.Series([1], index=[pd.to_datetime('now')])
            ohlcv = trade_prices.resample(resample_freq).ohlc()
            ohlcv['volume'] = trade_sizes.resample(resample_freq).sum()

            # Add asset as level 0 column; ohlcv will be used as level 1 cols
            ohlcv.columns = pd.MultiIndex.from_product([[
                asset,
            ], ohlcv.columns])

            df = pd.concat([df, ohlcv], axis=1)

        return df
예제 #2
0
        def _update_from_order_status(zp_order, ib_order_id):
            if ib_order_id in self._tws.open_orders:
                open_order_state = self._tws.open_orders[ib_order_id]['state']

                zp_status = self._ib_to_zp_status(open_order_state.status)
                if zp_status is None:
                    log.warning("Order-{order_id}: "
                                "unknown order status: {order_status}.".format(
                                    order_id=ib_order_id,
                                    order_status=open_order_state.status))
                else:
                    zp_order.status = zp_status

            if ib_order_id in self._tws.order_statuses:
                order_status = self._tws.order_statuses[ib_order_id]

                zp_order.filled = order_status['filled']

                zp_status = self._ib_to_zp_status(order_status['status'])
                if zp_status is None:
                    log.warning("Order-{order_id}: "
                                "unknown order status: {order_status}.".format(
                                    order_id=ib_order_id,
                                    order_status=order_status['status']))
                else:
                    zp_order.status = zp_status
예제 #3
0
    def _parse_order_ref(cls, ib_order_ref):
        if not ib_order_ref or \
                not ib_order_ref.endswith(cls._zl_order_ref_magic):
            return None

        try:
            action, qty, order_type, limit_price, stop_price, dt, _ = \
                ib_order_ref.split(' ')

            if not all([
                    action.startswith('A:'),
                    qty.startswith('Q:'),
                    order_type.startswith('T:'),
                    limit_price.startswith('L:'),
                    stop_price.startswith('S:'),
                    dt.startswith('D:')
            ]):
                return None

            return {
                'action': action[2:],
                'qty': int(qty[2:]),
                'order_type': order_type[2:].replace('_', ' '),
                'limit_price': float(limit_price[2:]),
                'stop_price': float(stop_price[2:]),
                'dt': pd.to_datetime(dt[2:], unit='s', utc=True)
            }

        except ValueError:
            log.warning(
                "Error parsing order metadata: {}".format(ib_order_ref))
            return None
예제 #4
0
    def subscribe_to_market_data(self, asset):
        if asset not in self.subscribed_assets:
            ib_symbol = self._asset_symbol(asset)

            self._tws.subscribe_to_market_data(ib_symbol)
            self._subscribed_assets.append(asset)
            try:
                polling.poll(
                    lambda: ib_symbol in self._tws.bars,
                    timeout=_max_wait_subscribe,
                    step=_poll_frequency)
            except polling.TimeoutException as te:
                log.warning('Cannot subscribe market data for %s.' % ib_symbol)
            else:
                log.debug("Subscription completed")
예제 #5
0
    def tickSnapshotEnd(self, ticker_id):
        key = "SYMBOL_" + str(ticker_id)
        if key not in self.tick_dict:
            return

        ib_symbol = self.tick_dict[key]
        try:
            last_trade_price = float(self.tick_dict["LAST_" + str(ticker_id)])
            last_trade_size = int(self.tick_dict["LAST_SIZE_" +
                                                 str(ticker_id)])
            last_trade_time = float(self.tick_dict["LAST_TIMESTAMP_" +
                                                   str(ticker_id)])
            last_trade_dt = pd.to_datetime(last_trade_time, unit='s', utc=True)
        except KeyError:
            log.warning('Cannot subscribe market data for %s.' % ib_symbol)
            return

        self._add_bar(ib_symbol, last_trade_price, last_trade_size,
                      last_trade_dt)
예제 #6
0
    def _get_positions_from_broker(self):
        """
        get the positions from the broker and update zipline objects ( the ledger )
        should be used once at startup and once every time we want to refresh the positions array
        """
        cur_pos_in_tracker = self.metrics_tracker.positions
        for ib_symbol in self._tws.ib_positions:
            ib_position = self._tws.ib_positions[ib_symbol]

            equity = self._safe_symbol_lookup(ib_symbol)
            if not equity:
                log.warning(
                    'Wanted to subscribe to %s, but this asset is probably not ingested'
                    % ib_symbol)
                continue

            zp_position = zp.Position(zp.InnerPosition(equity))
            editable_position = MutableView(zp_position)

            editable_position._underlying_position.amount = int(
                ib_position.position)
            editable_position._underlying_position.cost_basis = float(
                ib_position.average_cost)
            editable_position._underlying_position.last_sale_price = ib_position.market_price
            last_close = self.metrics_tracker._trading_calendar.session_close(
                self.metrics_tracker._last_session)
            editable_position._underlying_position.last_sale_date = last_close

            self.metrics_tracker.update_position(
                zp_position.asset,
                amount=zp_position.amount,
                last_sale_price=zp_position.last_sale_price,
                last_sale_date=zp_position.last_sale_date,
                cost_basis=zp_position.cost_basis)
        for asset in cur_pos_in_tracker:
            ib_symbol = self._asset_symbol(asset)
            if ib_symbol not in self._tws.ib_positions:
                # deleting object from the metrcs_tracker as its not in the portfolio
                self.metrics_tracker.update_position(asset, amount=0)

        self.metrics_tracker._ledger._portfolio.positions = zp.Positions(
            self.metrics_tracker.positions)
예제 #7
0
    def subscribe_to_market_data(self, asset):
        if asset not in self.subscribed_assets:
            ib_symbol = self._asset_symbol(asset)
            exchange = 'SMART'
            primaryExchange = 'ISLAND'
            secType = 'STK'
            currency = 'USD'

            self._tws.subscribe_to_market_data(ib_symbol, exchange,
                                               primaryExchange, secType,
                                               currency)
            self._subscribed_assets.append(asset)
            try:
                polling.poll(lambda: ib_symbol in self._tws.bars,
                             timeout=_max_wait_subscribe,
                             step=_poll_frequency)
            except polling.TimeoutException as te:
                log.warning('Cannot subscribe market data for %s.' % ib_symbol)
            else:
                log.debug("Subscription completed")
예제 #8
0
    def _update_transactions(self):
        all_orders = list(self.orders.values())

        for ib_order_id, executions in iteritems(self._tws.executions):
            orders = [
                order for order in all_orders
                if order.broker_order_id == ib_order_id
            ]

            if not orders:
                log.warning(
                    "No order found for executions: {}".format(executions))
                continue

            assert len(orders) == 1
            order = orders[0]

            for exec_id, execution in iteritems(executions):
                if exec_id in self._transactions:
                    continue

                try:
                    commission = self._tws.commissions[ib_order_id][
                        exec_id].commission
                except KeyError:
                    log.warning(
                        "Commission not found for execution: {}".format(
                            exec_id))
                    commission = 0

                exec_detail = execution['exec_detail']
                is_buy = order.amount > 0
                amount = (exec_detail.shares if is_buy else -1 *
                          exec_detail.shares)
                tx = Transaction(asset=order.asset,
                                 amount=amount,
                                 dt=pd.to_datetime(exec_detail.time, utc=True),
                                 price=exec_detail.price,
                                 order_id=order.id)
                self._transactions[exec_id] = tx
예제 #9
0
    def _get_or_create_zp_order(self,
                                ib_order_id,
                                ib_order=None,
                                ib_contract=None):
        zp_order_id = self._ib_to_zp_order_id(ib_order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        # Try to reconstruct the order from the given information:
        # open order state and execution state
        ib_symbol, order_details = None, None

        if ib_order and ib_contract:
            ib_symbol = ib_contract.symbol
            order_details = self._parse_order_ref(ib_order.orderRef)

        if not order_details and ib_order_id in self._tws.open_orders:
            open_order = self._tws.open_orders[ib_order_id]
            ib_symbol = open_order['contract'].symbol
            order_details = self._parse_order_ref(open_order['order'].orderRef)

        if not order_details and ib_order_id in self._tws.executions:
            executions = self._tws.executions[ib_order_id]
            last_exec_detail = list(executions.values())[-1]['exec_detail']
            last_exec_contract = list(executions.values())[-1]['contract']
            ib_symbol = last_exec_contract.symbol
            order_details = self._parse_order_ref(last_exec_detail.orderRef)

        asset = self._safe_symbol_lookup(ib_symbol)
        if not asset:
            log.warning("Ignoring symbol {symbol} which has associated "
                        "order but it is not registered in bundle".format(
                            symbol=ib_symbol))
            return None

        if order_details:
            amount = self._action_qty_to_amount(order_details['action'],
                                                order_details['qty'])
            stop_price = order_details['stop_price']
            limit_price = order_details['limit_price']
            dt = order_details['dt']
        else:
            dt = pd.to_datetime('now', utc=True)
            amount, stop_price, limit_price = 0, None, None
            if ib_order_id in self._tws.open_orders:
                open_order = self._tws.open_orders[ib_order_id]['order']
                amount = self._action_qty_to_amount(open_order.action,
                                                    open_order.totalQuantity)
                stop_price = open_order.auxPrice
                limit_price = open_order.lmtPrice

        stop_price = None if stop_price == 0 else stop_price
        limit_price = None if limit_price == 0 else limit_price

        self._orders[zp_order_id] = ZPOrder(dt=dt,
                                            asset=asset,
                                            amount=amount,
                                            stop=stop_price,
                                            limit=limit_price,
                                            id=zp_order_id)
        self._orders[zp_order_id].broker_order_id = ib_order_id

        return self._orders[zp_order_id]
 def hold(self, order_id, reason=''):
     log.warning("Unexpected hold request for {}: '{}'".format(
         order_id, reason))