def get_account_update(acctCode):
    """ Calls reqAccountUpdates(subscribe=False) then listens for accountAccountTime/AccountValue/Portfolio messages
    """
    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]
    client_id = client.clientId
    g.account_update_resp = dict(accountDownloadEnd=False,
                                 updateAccountValue=dict(),
                                 updatePortfolio=[])
    log.debug('Requesting account updates for {}'.format(acctCode))
    client.reqAccountUpdates(subscribe=False, acctCode=acctCode)
    timeout = g.timeout
    while g.account_update_resp[
            'accountDownloadEnd'] is False and client.isConnected(
            ) is True and timeout > 0:
        # log.debug("Waiting for responses on client {}...".format(client.clientId))
        time.sleep(.25)
        timeout -= 1
        log.debug('Current update {}'.format(g.account_update_resp))
    client.cancelAccountSummary(client_id)
    connection.close_client(client)
    return g.account_update_resp
def get_executions(args):
    """Gets all (filtered) executions from last 24hrs """
    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    g.executions_resp = dict(execDetailsEnd=False,
                             execDetails=[],
                             commissionReport=dict())
    log.debug('Requesting executions for filter {}'.format(args))
    filter = ExecutionFilter()
    for attr in dir(filter):
        if attr[:2] == 'm_' and attr[2:] in args:
            setattr(filter, attr, args[attr[2:]])
    log.debug('Filter: {}'.format(filter.__dict__))
    filter.m_clientId = 0
    client.reqExecutions(1, filter)
    timeout = g.timeout / 2
    while g.executions_resp['execDetailsEnd'] is False and client.isConnected(
    ) is True and timeout > 0:
        # log.debug("Waiting for responses on client {}...".format(client.clientId))
        time.sleep(.25)
        timeout -= 1
        log.debug('Current executions {}'.format(g.executions_resp))
    connection.close_client(client)
    return g.executions_resp
Exemple #3
0
def get_market_data(symbol, args):
    """ The m_symbol for the contract is all our API takes from user (for now).
    User must have appropriate IB subscriptions.
    https://www.interactivebrokers.com/en/software/api/apiguide/java/reqmktdata.htm
    """
    # TODO consider taking more args to get our market data with: filter (price, size, optionComputation, etc) and desired length of data.  Also, tick lists
    log.debug('Getting market data for {}'.format(symbol))
    # Connect to TWS
    client = get_client()
    if client.isConnected() is False:
        return {'error': 'Not connected to TWS'}
    log.debug('Creating Contract for symbol {}'.format(symbol))
    contract = make_contract(str(symbol), args)  # , prim_exch='NASDAQ')

    our_tickerId = get_tickerId()
    g.market_resp[our_tickerId] = []
    log.info('Requesting market data')
    client.reqMktData(our_tickerId, contract, '', False)
    timeout = g.timeout
    while len(g.market_resp[our_tickerId]) < 5 and client.isConnected(
    ) is True and timeout > 0:
        log.info("Waiting for responses on {}...".format(client))
        time.sleep(0.25)
        timeout -= 1
    client.cancelMktData(our_tickerId)
    log.debug('Disconnected Market client {}'.format(close_client(client)))
    return g.market_resp.pop(our_tickerId)
def cancel_order(orderId):
    """ Uses cancelOrder to cancel an order.  The only response is what comes back right away (no EWrapper messages)
    """
    g.error_resp[orderId] = None  # Reset our error for later

    client = connection.get_client(0)
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    log.info('Cancelling order {}'.format(orderId))
    # Reset our order resp to prepare for new data
    g.order_resp_by_order[orderId] = dict(openOrder=dict(), orderStatus=dict())
    client.cancelOrder(int(orderId))
    timeout = g.timeout
    while len(g.order_resp_by_order[orderId]['orderStatus']
              ) == 0 and client.isConnected() is True and timeout > 0:
        # log.debug("Waiting for Cancel Order responses on client {}...".format(client.clientId))
        if g.error_resp[orderId] is not None:
            connection.close_client(client)
            return g.error_resp[orderId]
        time.sleep(0.25)
        timeout -= 1
    connection.close_client(client)
    resp = g.order_resp.copy()
    # Cancelling an order also produces an error, we'll capture that here too
    resp['error'] = g.error_resp[orderId]
    return resp
def get_portfolio_positions():
    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]
    g.portfolio_positions_resp = dict(positionEnd=False, positions=[])
    client.reqPositions()
    timeout = g.timeout
    while g.portfolio_positions_resp[
            'positionEnd'] is False and client.isConnected(
            ) is True and timeout > 0:
        # log.debug("Waiting for Portfolio Positions responses on client {}...".format(client.clientId))
        time.sleep(0.25)
        timeout -= 1
    client.cancelPositions()
    connection.close_client(client)
    return g.portfolio_positions_resp
def get_open_orders():
    """ Uses reqAllOpenOrders to get all open orders from
    """
    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    # Reset our order resp to prepare for new data
    g.order_resp = dict(openOrderEnd=False, openOrder=[], orderStatus=[])
    client.reqAllOpenOrders()
    timeout = g.timeout
    while g.order_resp['openOrderEnd'] is False and client.isConnected(
    ) is True and timeout > 0:
        # log.debug("Waiting for Open Orders responses on client {}...".format(client.clientId))
        time.sleep(0.25)
        timeout -= 1
    connection.close_client(client)
    return g.order_resp
def get_account_summary(tags):
    """ Calls reqAccountSummary() then listens for accountSummary messages()
    """
    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]
    client_id = client.clientId
    g.account_summary_resp[client_id] = dict(accountSummaryEnd=False)
    client.reqAccountSummary(client_id, 'All', tags)
    timeout = g.timeout
    while g.account_summary_resp[client_id]['accountSummaryEnd'] is False \
            and client.isConnected() is True \
            and timeout > 0:
        # log.debug("Waiting for Account Summary responses on client {}...".format(client.clientId))
        time.sleep(0.25)
        timeout -= 1
    # time.sleep(1)
    client.cancelAccountSummary(client_id)
    connection.close_client(client)
    return g.account_summary_resp[client_id]
def place_order_oca(order_list):
    """ Places a Bracket-like OCA set of orders.

    The 1st item in `order_list` is to open a position, and all remaining orders in list
    are an OCA group to close the position.  IBREST creates the OCA group name by using the orderId.

    Auto-detects which args should be assigned to a new Contract or Order, then use to place order.
    Makes use of globals to set initial values, but allows args to override (ie clientId)

    To modify and order, the following parameters are needed (IB won't complain if some of these are missing, but the
    order update won't succeed):
    * orderId
    * exchange
    * totalQuantity
    * secType
    * action
    * orderType AND related paramters (ie TRAIL needs trailingPercent)
    * symbol
    * currency
    * exchange


    Setting `oca` to True implies
    """
    log.debug('Starting place_order_oca with args_list: {}'.format(order_list))
    client = connection.get_client(0)
    if client is None:
        connection.close_client(client)
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    # To allow for bracketed orders (or processing a string of orders in a single request), we expect args to be a list
    if not isinstance(order_list, list):
        log.error('place_order_oca requires list of orders')
        return

    # Our 1st order in the list opens a position.  The rest close it, but are only placed once the 1st order is Filled.
    oca_list = []
    ocaGroup = None
    order_ids = set()
    dont_wait_order_ids = set(
    )  # Some orders aren't worth waiting for responses on
    for args in order_list:
        # If an orderId was provided, we'll be updating an existing order, so only send attributes which are updateable:
        # totalQuantity, orderType, symbol, secType, action
        # TODO consider casting unicode to utf-8 here.  Otherwise we get error(id=1, errorCode=512, errorMsg=Order Sending Error - char format require string of length 1)
        # log.debug('Processing args from order_list: {}'.format(args))
        orderId = args.get('orderId', None)
        if orderId is None:
            orderId = g.orderId
            g.orderId += 1
        if 'goodAfterTime' in args:
            dont_wait_order_ids.add(orderId)
        contract = Contract()
        order = Order()

        # Populate contract with appropriate args
        for attr in dir(contract):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(contract, attr, args[attr[2:]])
        # Populate order with appropriate
        order.m_clientId = client.clientId
        for attr in dir(order):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(order, attr, args[attr[2:]])

        # If this is a bracketed order, we'll need to add in the ocaGroup for children orders
        if ocaGroup:
            # Use our ocaGroup as the OCA group name.
            # The 1st order won't have this because its an Open order
            # All remaining orders are Close orders in an OCA group, which we'll store to file for later use
            order_ids.add(orderId)
            order.m_ocaType = 1
            order.m_ocaGroup = str(ocaGroup)
            oca_list.append((orderId, contract, order))
            # Don't actually place this OCA order just yet
            continue

        log.debug(
            'Placing Open order # {} on client # {} (connected={}): {}'.format(
                orderId, client.clientId, client.isConnected(), args))
        client.placeOrder(orderId, contract, order)
        # Assume our 1st order in the list is the parent.  Use this for remaining bracket orders and also error handling
        if not ocaGroup:
            ocaGroup = orderId
            log.debug('Setting ocaGroup={}'.format(ocaGroup))

    # The only response for placing an order is an error, so we'll check for open orders and wait for this orderId or
    # and error to show up.

    # At this point, our Open order has been placed.  Look for it to be Filled, then place OCA orders.
    # The User must set a goodTillDate on their open order to keep it from filling >1min into the future, or else this
    # function will have given up waiting for it to be filled, and not set the closing OCA group.
    resp = dict()

    timeout = 60 / 0.25

    order_ids = order_ids - dont_wait_order_ids
    # Make a 1-item set representing our Open postion order
    oca_set = set([ocaGroup])
    resp['open_resp'] = wait_for_responses(oca_set, client, timeout,
                                           ['Filled'])
    # Our open order is filled, so now place our OCA group close orders
    log.debug(
        'Placing OCA group of {} orders, ignoring responses for these orderIds: {}'
        .format(len(oca_list), dont_wait_order_ids))
    for o in oca_list:
        client.placeOrder(*o)
    # Now get responses for these new OCA orders
    resp['close_resp'] = wait_for_responses(order_ids, client, timeout)
    connection.close_client(client)
    return resp
def place_order(order_list):
    """ Auto-detects which args should be assigned to a new Contract or Order, then use to place order.
    Makes use of globals to set initial values, but allows args to override (ie clientId)

    To modify and order, the following parameters are needed (IB won't complain if some of these are missing, but the
    order update won't succeed):
    * orderId
    * exchange
    * totalQuantity
    * secType
    * action
    * orderType AND related paramters (ie TRAIL needs trailingPercent)
    * symbol
    * currency
    * exchange

    When an object in `order_list` has secType = 'BAG', it implies an Options combo order will be placed, requiring
    comboLegs: a JSON list of details required for this function to fetch the conId to then build the ComboLeg.
    """
    log.debug('Starting place_order with args_list: {}'.format(order_list))
    client = connection.get_client()
    if client is None:
        connection.close_client(client)
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    # To allow for bracketed orders (or processing a string of orders in a single request), we expect args to be a list
    if not isinstance(order_list, list):
        order_list = [order_list]

    parentId = None
    order_ids = set()
    dont_wait_order_ids = set(
    )  # Some orders aren't worth waiting for responses on
    for args in order_list:
        # If an orderId was provided, we'll be updating an existing order, so only send attributes which are updatable:
        # totalQuantity, orderType, symbol, secType, action
        # TODO consider casting unicode to utf-8 here.  Otherwise we get error(id=1, errorCode=512, errorMsg=Order Sending Error - char format require string of length 1)
        # log.debug('Processing args from order_list: {}'.format(args))
        orderId = args.get('orderId', None)
        if orderId is None:
            orderId = g.orderId
            g.orderId += 1
        order_ids.add(orderId)
        if 'goodAfterTime' in args:
            dont_wait_order_ids.add(orderId)
        contract = Contract()
        order = Order()

        # Populate contract with appropriate args
        for attr in dir(contract):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(contract, attr, args[attr[2:]])
        # Populate order with appropriate
        order.m_clientId = client.clientId
        for attr in dir(order):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(order, attr, args[attr[2:]])

        # Option Combo Orders need the comboLegs details turned into actual ComboLeg objects
        comboLegs = args.get('comboLegs', None)
        if comboLegs:
            # We need to build ComboLegs by first fetching the conId from the contract details
            all_legs = []
            req_ids = []
            # Clear out our global ContractDetails so our handler can repopulate them
            g.contract_resp['contractDetails'] = dict()
            g.contract_resp['contractDetailsEnd'] = False

            # Request new ContractDetails so we can get the conIds needed for our legs
            for idx, leg in enumerate(comboLegs):
                # Each leg is a dict of details needed to make a ComboLeg object
                leg_contract = Contract()

                # Populate leg_contract with appropriate args
                for attr in dir(leg_contract):
                    if attr[:2] == 'm_' and attr[2:] in leg:
                        setattr(leg_contract, attr, leg[attr[2:]])

                # Fetch conId for leg_contract
                client.reqContractDetails(idx, leg_contract)
                req_ids.append(idx)

            # We've now requested ContractDetails for all legs.  Wait to get their async responses.
            timeout = g.timeout
            while g.contract_resp[
                    'contractDetailsEnd'] is False and client.isConnected(
                    ) is True and timeout > 0:
                time.sleep(0.25)
                timeout -= 1

            # Create our ComboLegs for our order
            for idx, leg in enumerate(comboLegs):
                combo_leg = ComboLeg()
                # Populate combo_leg with appropriate args
                for attr in dir(combo_leg):
                    if attr[:2] == 'm_' and attr[2:] in leg:
                        setattr(combo_leg, attr, leg[attr[2:]])
                combo_leg.m_conId = g.contract_resp['contractDetails'][idx][
                    'm_summary'].m_conId
                all_legs.append(combo_leg)
            contract.m_comboLegs = all_legs

        # If this is a bracketed order, we'll need to add in the parentId for children orders
        if parentId:
            order.m_parentId = parentId

        log.debug(
            'Placing order # {} on client # {} (connected={}): {}'.format(
                orderId, client.clientId, client.isConnected(), args))
        client.placeOrder(orderId, contract, order)
        # Assume our 1st order in the list is the parent.  Use this for remaining bracket orders and also error handling
        if not parentId:
            parentId = orderId
            log.debug('Setting child order parentId={}'.format(parentId))

    log.debug('Ignoring responses for these orderIds: {}'.format(
        dont_wait_order_ids))
    order_ids = order_ids - dont_wait_order_ids

    # Don't look for order status or errors until we actually transmit the last order, but then look for status for
    # all order_ids
    timeout = g.timeout
    resp = wait_for_responses(order_ids, client, timeout)
    connection.close_client(client)
    return resp
Exemple #10
0
def get_history(symbol, args):
    """ Args may be any of those in reqHistoricalData()
    https://www.interactivebrokers.com/en/software/api/apiguide/java/reqhistoricaldata.htm
    """
    log.debug('history symbol {}, args: {}'.format(symbol, args))

    client = connection.get_client()
    if client is None:
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    # Populate contract with appropriate
    contract = utils.make_contract(str(symbol), args)

    # log.debug('contract: {}'.format(contract))

    our_tickerId = get_tickerId()
    g.history_resp[our_tickerId] = dict()
    g.error_resp[our_tickerId] = None
    # endtime = (datetime.now() - timedelta(minutes=15)).strftime('%Y%m%d %H:%M:%S')
    log.debug('requesting historical data')
    req_dict = dict(tickerId=our_tickerId,
                    contract=contract,
                    endDateTime=str(
                        args.get('endDateTime',
                                 datetime.now().strftime('%Y%m%d %H:%M:%S'))),
                    durationStr=str(args.get('durationStr', '1 D')),
                    barSizeSetting=str(args.get('barSizeSetting', '1 min')),
                    whatToShow=args.get('whatToShow', 'TRADES'),
                    useRTH=int(args.get('useRTH', 0)),
                    formatDate=int(args.get('formatDate', 2)))
    log.debug('req_dict {}'.format(req_dict))
    client.reqHistoricalData(**req_dict)
    """
    durationStr='60 S',
    barSizeSetting='1 min',
    whatToShow='TRADES',
    useRTH=0,
    formatDate=1)
    """
    log.debug('waiting for historical data)')
    timeout = g.timeout
    while not any([
            "finished" in h for h in g.history_resp[our_tickerId].keys()
    ]) and client.isConnected() and timeout > 0:
        log.debug("Waiting for History responses on client {}...".format(
            client.clientId))
        if g.error_resp.get(our_tickerId, None) is not None:
            # An errorCode of 366 seen on IBGW logs is often meaningless since it shows up for every history call several
            # seconds after it's already found data and receive the "finished" message.  If data
            # did exist, then it would be returned before the error message was generated
            connection.close_client(client)
            return g.error_resp[our_tickerId]
        elif client.isConnected() is False:
            return {'errorMsg': 'Connection lost'}
        time.sleep(0.25)
        timeout -= 1
    # log.debug('history: {}'.format(g.history_resp))
    log.debug('closing historical data stream')
    client.cancelHistoricalData(our_tickerId)
    connection.close_client(client)
    return g.history_resp.pop(our_tickerId)
Exemple #11
0
def place_order(order_list):
    """ Auto-detects which args should be assigned to a new Contract or Order, then use to place order.
    Makes use of globals to set initial values, but allows args to override (ie clientId)

    To modify and order, the following parameters are needed (IB won't complain if some of these are missing, but the
    order update won't succeed):
    * orderId
    * exchange
    * totalQuantity
    * secType
    * action
    * orderType AND related paramters (ie TRAIL needs trailingPercent)
    * symbol
    * currency
    * exchange
    """
    log.debug('Starting place_order with args_list: {}'.format(order_list))
    client = connection.get_client(0)
    if client is None:
        connection.close_client(client)
        return g.error_resp[-2]
    elif client.isConnected() is False:
        return g.error_resp[-1]

    # To allow for bracketed orders (or processing a string of orders in a single request), we expect args to be a list
    if not isinstance(order_list, list):
        order_list = [order_list]

    parentId = None
    order_ids = set()
    dont_wait_order_ids = set(
    )  # Some orders aren't worth waiting for responses on
    for args in order_list:
        # If an orderId was provided, we'll be updating an existing order, so only send attributes which are updatable:
        # totalQuantity, orderType, symbol, secType, action
        # TODO consider casting unicode to utf-8 here.  Otherwise we get error(id=1, errorCode=512, errorMsg=Order Sending Error - char format require string of length 1)
        # log.debug('Processing args from order_list: {}'.format(args))
        orderId = args.get('orderId', None)
        if orderId is None:
            orderId = g.orderId
            g.orderId += 1
        order_ids.add(orderId)
        if 'goodAfterTime' in args:
            dont_wait_order_ids.add(orderId)
        contract = Contract()
        order = Order()

        # Populate contract with appropriate args
        for attr in dir(contract):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(contract, attr, args[attr[2:]])
        # Populate order with appropriate
        order.m_clientId = client.clientId
        for attr in dir(order):
            if attr[:2] == 'm_' and attr[2:] in args:
                setattr(order, attr, args[attr[2:]])

        # If this is a bracketed order, we'll need to add in the parentId for children orders
        if parentId:
            order.m_parentId = parentId

        log.debug(
            'Placing order # {} on client # {} (connected={}): {}'.format(
                orderId, client.clientId, client.isConnected(), args))
        client.placeOrder(orderId, contract, order)
        # Assume our 1st order in the list is the parent.  Use this for remaining bracket orders and also error handling
        if not parentId:
            parentId = orderId
            log.debug('Setting child order parentId={}'.format(parentId))

    log.debug('Ignoring responses for these orderIds: {}'.format(
        dont_wait_order_ids))
    order_ids = order_ids - dont_wait_order_ids

    # Don't look for order status or errors until we actually transmit the last order, but then look for status for
    # all order_ids
    timeout = g.timeout
    resp = wait_for_responses(order_ids, client, timeout)
    connection.close_client(client)
    return resp