from ib_insync import *
util.startLoop()
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=13)
# util.logToConsole()
<IB connected to 127.0.0.1:7497 clientId=13>
Create a contract and a market order:
contract = Forex('EURUSD')
ib.qualifyContracts(contract)
order = LimitOrder('SELL', 20000, 1.11)
placeOrder will place the order order and return a Trade
object right away (non-blocking):
trade = ib.placeOrder(contract, order)
trade
contains the order and everything related to it, such as order status, fills and a log.
It will be live updated with every status change or fill of the order.
ib.sleep(1)
trade.log
[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 96198, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 283531, tzinfo=datetime.timezone.utc), status='PreSubmitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 323689, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='Fill 20000.0@1.12245'), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 323689, tzinfo=datetime.timezone.utc), status='Filled', message='')]
trade
will also available from ib.trades()
:
assert trade in ib.trades()
Likewise for order
:
assert order in ib.orders()
Now let's create a limit order with an unrealistic limit:
limitOrder = LimitOrder('BUY', 20000, 0.05)
limitTrade = ib.placeOrder(contract, limitOrder)
limitTrade
Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, action='BUY', totalQuantity=20000, lmtPrice=0.05), orderStatus=OrderStatus(orderId=0, status='PendingSubmit', filled=0, remaining=0, avgFillPrice=0.0, permId=0, parentId=0, lastFillPrice=0.0, clientId=0, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message='')])
status
will change from "PendingSubmit" to "Submitted":
ib.sleep(1)
assert limitTrade.orderStatus.status == 'Submitted'
assert limitTrade in ib.openTrades()
Let's modify the limit price and resubmit:
limitOrder.lmtPrice = 0.10
ib.placeOrder(contract, limitOrder)
Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, permId=1710981560, action='BUY', totalQuantity=20000.0, lmtPrice=0.1, auxPrice=0.0, tif='DAY', ocaType=3, trailStopPrice=1.05, volatilityType=0, deltaNeutralOrderType='None', referencePriceType=0, account='DU772802', clearingIntent='IB', adjustedOrderType='None', cashQty=0.0, dontUseAutoPriceForHedge=True), orderStatus=OrderStatus(orderId=0, status='Submitted', filled=0.0, remaining=20000.0, avgFillPrice=0.0, permId=1710981560, parentId=0, lastFillPrice=0.0, clientId=13, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify')])
And now cancel it:
ib.cancelOrder(limitOrder)
Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, permId=1710981560, action='BUY', totalQuantity=20000.0, lmtPrice=0.1, auxPrice=0.0, tif='DAY', ocaType=3, trailStopPrice=1.05, volatilityType=0, deltaNeutralOrderType='None', referencePriceType=0, account='DU772802', clearingIntent='IB', adjustedOrderType='None', cashQty=0.0, dontUseAutoPriceForHedge=True), orderStatus=OrderStatus(orderId=0, status='PendingCancel', filled=0.0, remaining=20000.0, avgFillPrice=0.0, permId=1710981560, parentId=0, lastFillPrice=0.0, clientId=13, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify'), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 183117, tzinfo=datetime.timezone.utc), status='PendingCancel', message='')])
limitTrade.log
[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify'), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 183117, tzinfo=datetime.timezone.utc), status='PendingCancel', message='')]
placeOrder is not blocking and will not wait on what happens with the order. To make the order placement blocking, that is to wait until the order is either filled or canceled, consider the following:
%%time
order = MarketOrder('BUY', 100)
trade = ib.placeOrder(contract, order)
while not trade.isDone():
ib.waitOnUpdate()
CPU times: user 5.87 ms, sys: 486 µs, total: 6.35 ms Wall time: 163 ms
What are our positions?
ib.positions()
[Position(account='DU772802', contract=Stock(conId=9579970, symbol='IWM', exchange='ARCA', currency='USD', localSymbol='IWM', tradingClass='IWM'), position=600.0, avgCost=149.368), Position(account='DU772802', contract=Forex('USDCHF', conId=12087820, localSymbol='USD.CHF', tradingClass='USD.CHF'), position=20.0, avgCost=0.98545), Position(account='DU772802', contract=Forex('EURUSD', conId=12087792, localSymbol='EUR.USD', tradingClass='EUR.USD'), position=165700.0, avgCost=1.1247148664589277), Position(account='DU772802', contract=Stock(conId=265598, symbol='AAPL', exchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS'), position=2551.0, avgCost=187.1202698)]
What's the total of commissions paid today?
sum(fill.commissionReport.commission for fill in ib.fills())
11.607050000000001
whatIfOrder can be used to see the commission and the margin impact of an order without actually sending the order:
order = MarketOrder('SELL', 20000)
ib.whatIfOrder(contract, order)
OrderState(status='PreSubmitted', initMarginBefore='188130.0', maintMarginBefore='188130.0', equityWithLoanBefore='1126836.45', initMarginChange='0.0', maintMarginChange='0.0', equityWithLoanChange='-1.790000000037253', initMarginAfter='188130.0', maintMarginAfter='188130.0', equityWithLoanAfter='1126834.66', commission=1.7857, minCommission=1.7976931348623157e+308, maxCommission=1.7976931348623157e+308, commissionCurrency='EUR', warningText='', completedTime='', completedStatus='')
ib.disconnect()