erdewit / ib_insync

Python sync/async framework for Interactive Brokers API
BSD 2-Clause "Simplified" License
2.8k stars 743 forks source link

Positions: Current State vs Request #575

Closed houseofai closed 1 year ago

houseofai commented 1 year ago

During a session, I want to get my current positions, so I use the ib.positions() to do so. But I never get the positions opened by orders in the same session. Take a simple example where I connect, place a market order, and request the position on the Current State and the position through the request:

client = IB()
client.connect('127.0.0.1', 7497, clientId=11)

contract = Stock("AAPL", 'SMART', 'USD')
order = MarketOrder("BUY", totalQuantity=1)
client.placeOrder(contract, order)

time.sleep(10)

print("Positions")
for position in client.positions():
    print(position)

print("Req Positions")
for position in client.reqPositions():
    if position.position > 0:
        print(position)
Positions
Req Positions
Position(account='DUxxxxxx', contract=Stock(conId=265598, symbol='AAPL', exchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS'), position=1.0, avgCost=160.18)
Position(account='DUxxxxxx', contract=Stock(conId=265598, symbol='AAPL', exchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS'), position=1.0, avgCost=161.18)
Position(account='DUxxxxxx', contract=Stock(conId=265598, symbol='AAPL', exchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS'), position=1.0, avgCost=161.18)

client.positions() call doesn't return any position, while client.reqPositions() does return three positions. (Why three?)

Why is client.positions() not returning the market order position? Should the current state have been updated after 10secs?

mattsta commented 1 year ago

I think portfolio() is more useful than positions().

portfolio() also returns much more useful data and is automatically kept up to date by the library while your session is active:

To your original question, .positions() doesn't provide any data until after a call to .reqPositions(), then it will be updated by the library. But portfolio() gives you more information without the extra setup, so it's better overall.

houseofai commented 1 year ago

Thanks for the tip @mattsta, indeed the portfolio gives more info, but the problem remains the same: it is based on the current state.

contract = Stock("AAPL", 'SMART', 'USD')
order = MarketOrder("BUY", totalQuantity=1)
client.placeOrder(contract, order)

time.sleep(10)

print("Portfolio")
for portfolio in client.portfolio():
    print(portfolio)

prints:

Portfolio
houseofai commented 1 year ago

Interestingly, the example on the Ordering workbook forces the update:

contract = Stock("AMD", 'SMART', 'USD')
order = MarketOrder("BUY", totalQuantity=1)
trade = client.placeOrder(contract, order)

while not trade.isDone():
    client.waitOnUpdate()

print("Positions")
for position in client.positions():
    print(position)

prints the opened trade:

Position(account='DUxxxxx', contract=Stock(conId=4391, symbol='AMD', exchange='NASDAQ', currency='USD', localSymbol='AMD', tradingClass='NMS'), position=1.0, avgCost=93.3644)
erdewit commented 1 year ago

time.sleep(10)

ALLWAYS USE ib.sleep(...) NOT time.sleep(...) !!!!!!!!!!!!!